Автор |
Сообщение |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Цитата: А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации. Идём в ногу со временем [сарказм] Я бы дал этим словам такой функционал - CLEAR – очистка кэша
- LIST – создание списка
- RUN – запуск сторонней программы из оболочки форта
[quote]А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации.[/quote] Идём в ногу со временем [сарказм]
Я бы дал этим словам такой функционал [list] [*] CLEAR – очистка кэша [*] LIST – создание списка [*] RUN – запуск сторонней программы из оболочки форта[/list]
|
|
|
 |
Добавлено: Ср май 07, 2025 17:27 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Total Vacuum писал(а): Вот есть такое: https://en.wikipedia.org/wiki/Tiny_BASICГрамматика в части операторов там совсем простая: Код: statement ::= PRINT expr-list IF expression relop expression THEN statement GOTO expression INPUT var-list LET var = expression GOSUB expression RETURN CLEAR LIST RUN END А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации. Скорее уж это команды редактора или даже операционной системы, но никак не самого языка. Где-то они могут быть полезны (например, при построчном вводе программы через терминал), а где-то полноценный встроенный редактор и запуск по F9, либо внешний редактор и интерпретация или компиляция файлов через командную строку, и вот здесь-то эти команды точно не нужны. Впрочем, спецификация Tiny BASIC уходит корнями в покрытую мхом почтенную древность, так что простительно.  В этом даже какой-то шарм безвозвратно ушедшей в прошлое 8-битной эпохи. Ну а в текущих реалиях надо отделять мух от котлет: редактор (если он вообще нужен) будет отдельно, а интерпретатор (BASIC, Forth, любой другой или все сразу) - отдельно.
[quote="Total Vacuum"]Вот есть такое: [url]https://en.wikipedia.org/wiki/Tiny_BASIC[/url] Грамматика в части операторов там совсем простая:[code] statement ::= PRINT expr-list IF expression relop expression THEN statement GOTO expression INPUT var-list LET var = expression GOSUB expression RETURN CLEAR LIST RUN END[/code][/quote] А вообще странно, что они сделали CLEAR/LIST/RUN частью спецификации. Скорее уж это команды редактора или даже операционной системы, но никак не самого языка. Где-то они могут быть полезны (например, при построчном вводе программы через терминал), а где-то полноценный встроенный редактор и запуск по F9, либо внешний редактор и интерпретация или компиляция файлов через командную строку, и вот здесь-то эти команды точно не нужны. Впрочем, спецификация Tiny BASIC уходит корнями в покрытую мхом почтенную древность, так что простительно. :) В этом даже какой-то шарм безвозвратно ушедшей в прошлое 8-битной эпохи. Ну а в текущих реалиях надо отделять мух от котлет: редактор (если он вообще нужен) будет отдельно, а интерпретатор (BASIC, Forth, любой другой или все сразу) - отдельно.
|
|
|
 |
Добавлено: Ср май 07, 2025 12:01 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Собственно, лежит тут: http://totalvacuum/UB/ubasic.zipСам ubasic.c компилировал при помощи TCC, но должно любым сишным компилироваться. В скомпилированном виде весит 3K. В папке TEST пара тестов, перекомпилируются при помощи соответствующих *.bat по схеме basic => ef => asm => com, хотя можно и под win сделать, если транслятор ef \ esoteric forth \ подменить. Натравил на него свой сишный транслятор, там меньше 2K исполняемый файл получается, правда это 16-битный com-файл. Для форт-процессора будет и того меньше, раза в 2, наверное. Интерпретатор в 100 строк, скорее всего, не уложится, он будет сложнее компилятора, но точно не в разы. Да, кстати, для добавления poke/peek (а это ведь по сути фортовские !/@) достаточно в stmt() перед label дописать строки Код: if (t("poke")) {expr(); expr(); op(ASSIGN);} else if (t("peek")) {var(); expr(); op(LOAD); op(ASSIGN);} else А, например, для push/pop: Код: if (t("push")) {expr();} else if (t("pop")) {var(); op("!");} else Хотя peek можно оформить в виде функции, чтобы была возможность использования в выражениях. В этом случае нужно добавить в prim() строку Код: else if (t("peek")) {unary(); op(LOAD);} Забавно будет, если по итогу интерпретатор BASIC на борту Форт-процессора в ПЛИС окажется шустрее спектрумовского 
Собственно, лежит тут: [url]http://totalvacuum/UB/ubasic.zip[/url] Сам ubasic.c компилировал при помощи TCC, но должно любым сишным компилироваться. В скомпилированном виде весит 3K. В папке TEST пара тестов, перекомпилируются при помощи соответствующих *.bat по схеме basic => ef => asm => com, хотя можно и под win сделать, если транслятор ef \ esoteric forth \ подменить. Натравил на него свой сишный транслятор, там меньше 2K исполняемый файл получается, правда это 16-битный com-файл. Для форт-процессора будет и того меньше, раза в 2, наверное.
Интерпретатор в 100 строк, скорее всего, не уложится, он будет сложнее компилятора, но точно не в разы.
Да, кстати, для добавления poke/peek (а это ведь по сути фортовские !/@) достаточно в stmt() перед label дописать строки[code] if (t("poke")) {expr(); expr(); op(ASSIGN);} else if (t("peek")) {var(); expr(); op(LOAD); op(ASSIGN);} else[/code] А, например, для push/pop:[code] if (t("push")) {expr();} else if (t("pop")) {var(); op("!");} else[/code] Хотя peek можно оформить в виде функции, чтобы была возможность использования в выражениях. В этом случае нужно добавить в prim() строку[code] else if (t("peek")) {unary(); op(LOAD);}[/code]
Забавно будет, если по итогу интерпретатор BASIC на борту Форт-процессора в ПЛИС окажется шустрее спектрумовского :D
|
|
|
 |
Добавлено: Вт май 06, 2025 01:33 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Hishnik писал(а): Из добавляемого очень уж просятся именованные подпрограммы.  И да, есть возможность использования именованных подпрограмм. Например: Код: let r = 1 let n = 8 gosub fact print r end
fact let r = r * n let n = n - 1 if n > 1 gosub fact return А всё потому, что поленился сделать обработку ошибок. В результате всё непонятное автоматически считается меткой. Лень - двигатель прогресса, однако.  Кроме того, строки не обязаны начинаться с метки, в строке допускается размещать несколько операторов и меток. И наоборот: допускается размещать опкод и операнды на разных строках. Т.е. в каком-то смысле полная свобода в оформлении кода.
[quote="Hishnik"]Из добавляемого очень уж просятся именованные подпрограммы.[/quote] :) И да, есть возможность использования именованных подпрограмм. Например:[code]let r = 1 let n = 8 gosub fact print r end
fact let r = r * n let n = n - 1 if n > 1 gosub fact return[/code]А всё потому, что поленился сделать обработку ошибок. В результате всё непонятное автоматически считается меткой. Лень - двигатель прогресса, однако. :) Кроме того, строки не обязаны начинаться с метки, в строке допускается размещать несколько операторов и меток. И наоборот: допускается размещать опкод и операнды на разных строках. Т.е. в каком-то смысле полная свобода в оформлении кода.
|
|
|
 |
Добавлено: Пн май 05, 2025 23:26 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Платформо-зависимые вещи убраны в отдельный файл в шапке: Код: #include "x86.h"
#include <stdlib.h> #include <stdio.h> #include <string.h> Транслируется в uf \ micro forth \ и ef \ esoteric forth \  При желании можно и напрямую в асм перегонять, достаточно лишь заменить соответствующие дефайны в подключаемом файле. Например, Код: #define ADD "+" заменить на что-то вроде Код: #define ADD "pop ax\npop bx\nadd ax,bx\npush ax\n" и т.д. В сумме 2 файла занимают ровно 100 строк  В версии под ef \ esoteric forth \ нельзя использовать двух- и более- значные числа, а также переменные c/b/h/s/x/o/g (они задействованы в stdio), ну а в остальном отличий нет. Примеры выложу чуть позже здесь: [url]totalvacuum.ru/UB/ubasic.zip[/url]
Платформо-зависимые вещи убраны в отдельный файл в шапке:[code] #include "x86.h"
#include <stdlib.h> #include <stdio.h> #include <string.h>[/code]Транслируется в uf \ micro forth \ и ef \ esoteric forth \ :) При желании можно и напрямую в асм перегонять, достаточно лишь заменить соответствующие дефайны в подключаемом файле. Например,[code]#define ADD "+"[/code]заменить на что-то вроде[code]#define ADD "pop ax\npop bx\nadd ax,bx\npush ax\n"[/code]и т.д. В сумме 2 файла занимают ровно 100 строк :)
В версии под ef \ esoteric forth \ нельзя использовать двух- и более- значные числа, а также переменные c/b/h/s/x/o/g (они задействованы в stdio), ну а в остальном отличий нет. Примеры выложу чуть позже здесь: [url]totalvacuum.ru/UB/ubasic.zip[/url]
|
|
|
 |
Добавлено: Пн май 05, 2025 23:13 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Ну и операторы: Код: /* stmt */
void print () { token(); hold(); if (s[0]=='"') {expr(); op(PUTS);} else {expr(); op(PUTH);} }
int stmt () { if (n("")) return 0; if (t("print")) {print();} else if (t("if")) {cmp(); op(IF); stmt(); op(ENDIF);} else if (t("goto")) {token(); printf(JMP,s);} else /* if (t("input")) {var(); op(INPUT);} else */ if (t("let")) {var(); token(); expr(); op(ASSIGN);} else if (t("gosub")) {token(); printf(CALL,s);} else if (t("return")) {op(RET);} else /* if (t("clear")||t("list")||t("run")) {} else */ if (t("end")) {op(EXIT);} else {printf(LABEL,s); stmt();} return 1; }
void main () {op(TARGET); while (stmt());} clear/list/run в режиме "компиляции" не нужны, поэтому убрал. input тоже убрал, т.к. в ПЛИС реализация будет другая, а проверять пока можно и без него.
Ну и операторы:[code]/* stmt */
void print () { token(); hold(); if (s[0]=='"') {expr(); op(PUTS);} else {expr(); op(PUTH);} }
int stmt () { if (n("")) return 0; if (t("print")) {print();} else if (t("if")) {cmp(); op(IF); stmt(); op(ENDIF);} else if (t("goto")) {token(); printf(JMP,s);} else /* if (t("input")) {var(); op(INPUT);} else */ if (t("let")) {var(); token(); expr(); op(ASSIGN);} else if (t("gosub")) {token(); printf(CALL,s);} else if (t("return")) {op(RET);} else /* if (t("clear")||t("list")||t("run")) {} else */ if (t("end")) {op(EXIT);} else {printf(LABEL,s); stmt();} return 1; }
void main () {op(TARGET); while (stmt());}[/code]clear/list/run в режиме "компиляции" не нужны, поэтому убрал. input тоже убрал, т.к. в ПЛИС реализация будет другая, а проверять пока можно и без него.
|
|
|
 |
Добавлено: Пн май 05, 2025 22:58 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Разбор выражений: Код: /* expr */
void op (char *s) {printf(CMD,s);}
void expr ();
void prim () { if (t("(")) {expr(); token();} else {op(s); if ((s[0]>='a')&&(s[0]<='z')) op(LOAD);} }
void unary () {if (n("-")) {unary(); op(NEGATE);} else prim();}
void mul () { unary(); while (n("*")||t("/")) if (t("*")) {unary(); op(MUL);} else {unary(); op(DIV);} hold(); }
void expr () { mul(); while (n("+")||t("-")) if (t("+")) {mul(); op(ADD);} else {mul(); op(SUB);} hold(); }
void cmp () {char r[3]; expr(); token(); strcpy(r,s); expr(); op(r);}
void var () {token(); op(s);} Это следует читать так: Выражение - это сумма слагаемых, слагаемое - это произведение множителей, множитель - это первичное выражение со знаком или без, а первичное выражение - это выражение в скобках, число или переменная.
Разбор выражений:[code]/* expr */
void op (char *s) {printf(CMD,s);}
void expr ();
void prim () { if (t("(")) {expr(); token();} else {op(s); if ((s[0]>='a')&&(s[0]<='z')) op(LOAD);} }
void unary () {if (n("-")) {unary(); op(NEGATE);} else prim();}
void mul () { unary(); while (n("*")||t("/")) if (t("*")) {unary(); op(MUL);} else {unary(); op(DIV);} hold(); }
void expr () { mul(); while (n("+")||t("-")) if (t("+")) {mul(); op(ADD);} else {mul(); op(SUB);} hold(); }
void cmp () {char r[3]; expr(); token(); strcpy(r,s); expr(); op(r);}
void var () {token(); op(s);}[/code]Это следует читать так: Выражение - это сумма слагаемых, слагаемое - это произведение множителей, множитель - это первичное выражение со знаком или без, а первичное выражение - это выражение в скобках, число или переменная.
|
|
|
 |
Добавлено: Пн май 05, 2025 22:53 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Немного упростил себе жизнь на первом этапе, заменив expr-list и var-list на expr и var соответственно, еще токены пока надо вручную разделять пробелами, ну и then в операторе if убрал за ненадобностью. Все это пока не так принципиально. В итоге набросалось на скорую руку такое: Сканер (потрошит исходник на отдельные лексемы): Код: /* scan */
char h = 0, c, s[32];
int gc () {return c = getchar();}
void hold () {h = 1;}
void token () { if (h) {h = 0; return;} s[0] = 0; while (gc()<'!') if (c==-1) return; s[0] = c; int p = 1; if (c=='"') do s[p++] = gc(); while (c!='"'); else while (gc()>' ') s[p++] = c; s[p] = 0; }
int t (char *x) {return !strcmp(s,x);}
int n (char *x) {token(); return t(x);}
Немного упростил себе жизнь на первом этапе, заменив expr-list и var-list на expr и var соответственно, еще токены пока надо вручную разделять пробелами, ну и then в операторе if убрал за ненадобностью. Все это пока не так принципиально. В итоге набросалось на скорую руку такое:
Сканер (потрошит исходник на отдельные лексемы):[code]/* scan */
char h = 0, c, s[32];
int gc () {return c = getchar();}
void hold () {h = 1;}
void token () { if (h) {h = 0; return;} s[0] = 0; while (gc()<'!') if (c==-1) return; s[0] = c; int p = 1; if (c=='"') do s[p++] = gc(); while (c!='"'); else while (gc()>' ') s[p++] = c; s[p] = 0; }
int t (char *x) {return !strcmp(s,x);}
int n (char *x) {token(); return t(x);}[/code]
|
|
|
 |
Добавлено: Пн май 05, 2025 22:50 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Hishnik писал(а): "не больше 100 строк во всей программе". Не, ну 100 строк, конечно, маловато, но можно и в них транслятор впихнуть, если не сильно переживать по поводу красивости отступов 
[quote="Hishnik"]"не больше 100 строк во всей программе".[/quote]Не, ну 100 строк, конечно, маловато, но можно и в них транслятор впихнуть, если не сильно переживать по поводу красивости отступов :D
|
|
|
 |
Добавлено: Пн май 05, 2025 22:42 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Из добавляемого очень уж просятся именованные подпрограммы. GOSUB по номеру строки - это просто уже что-то... на уровне "не больше 100 строк во всей программе".
Из добавляемого очень уж просятся именованные подпрограммы. GOSUB по номеру строки - это просто уже что-то... на уровне "не больше 100 строк во всей программе".
|
|
|
 |
Добавлено: Чт май 01, 2025 16:26 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
В соседней теме зашла речь про Бейсики. Еще одну тему плодить не хочется, а по смысле эта тема ближе. Вот есть такое: https://en.wikipedia.org/wiki/Tiny_BASICГрамматика в части операторов там совсем простая: Код: statement ::= PRINT expr-list IF expression relop expression THEN statement GOTO expression INPUT var-list LET var = expression GOSUB expression RETURN CLEAR LIST RUN END Понятно, что дословно повторять такое не обязательно, по желанию/необходимости удаляем/меняем/добавляем что угодно. На первый взгляд, оно совсем простое и непригодно для чего-то серьезного, но если добавить хотя бы PEEK/POKE/PUSH/POP/массивы, то сразу же заиграет новыми красками. В идеале на выходе должен получиться готовый рецепт Бейсика на Си (и, как следствие, на Форте). Реализация должна получиться очень простой, но при этом сможет служить неплохой иллюстрацией того, что транслятор своими руками - это достаточно просто, особенно в случае, когда в качестве целевой платформы используется Форт или что-то близкое к нему по духу.
В соседней теме зашла речь про Бейсики. Еще одну тему плодить не хочется, а по смысле эта тема ближе. Вот есть такое: [url]https://en.wikipedia.org/wiki/Tiny_BASIC[/url] Грамматика в части операторов там совсем простая:[code] statement ::= PRINT expr-list IF expression relop expression THEN statement GOTO expression INPUT var-list LET var = expression GOSUB expression RETURN CLEAR LIST RUN END[/code]Понятно, что дословно повторять такое не обязательно, по желанию/необходимости удаляем/меняем/добавляем что угодно. На первый взгляд, оно совсем простое и непригодно для чего-то серьезного, но если добавить хотя бы PEEK/POKE/PUSH/POP/массивы, то сразу же заиграет новыми красками. В идеале на выходе должен получиться готовый рецепт Бейсика на Си (и, как следствие, на Форте). Реализация должна получиться очень простой, но при этом сможет служить неплохой иллюстрацией того, что транслятор своими руками - это достаточно просто, особенно в случае, когда в качестве целевой платформы используется Форт или что-то близкое к нему по духу.
|
|
|
 |
Добавлено: Чт май 01, 2025 14:25 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Hishnik писал(а): В целом да, тут две крайности. Можно последовательно воспроизводить все, "как у всех", постоянно натыкаясь на особенности стека. Можно принципиально не делать ничего "как у всех". Истина где-то посередине, как обычно. Ну я не то, чтобы специально делаю всё нестандартно и наперекор. Но если при реализации какого-то очередного функционала появляется выбор между громоздким, но зато полностью стандартным решением и простым, но не совсем стандартным, то выберу простое. 
[quote="Hishnik"]В целом да, тут две крайности. Можно последовательно воспроизводить все, "как у всех", постоянно натыкаясь на особенности стека. Можно принципиально не делать ничего "как у всех". Истина где-то посередине, как обычно.[/quote]Ну я не то, чтобы специально делаю всё нестандартно и наперекор. Но если при реализации какого-то очередного функционала появляется выбор между громоздким, но зато полностью стандартным решением и простым, но не совсем стандартным, то выберу простое. :)
|
|
|
 |
Добавлено: Чт апр 17, 2025 14:46 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Минутка юмора  Когда начинал делать транслятор, за основу взял грамматику из стандарта C89. Но при этом что-то сразу исключил: - триграфы; - определения функций в старом стиле K&R; А что-то сделал не совсем стандартно: - возможность объявления функций с переменным числом параметров в т.ч. и без обязательного первого (первых) параметра, т.е. вида void f (...); - поддержка в т.ч. двоичных чисел с префиксом 0b; - функции вида f() считаются функциями без параметров, а не функциями с неопределенным числом параметров; - переменные могут объявляться в любом месте блока, а не только в его начале; Ну и сразу заложил по мелочи что-то из того, что может пригодиться в будущем (например, inline). Решил глянуть, что там сейчас стандартописатели напридумывали. После стандарта C89 были C99, C11, C17, ну и вроде как самый свежий на сегодня C23. Понятное дело, что в следующих стандартах добавились inline и возможность объявления переменных в любом месте блока. И будете смеяться, но в C23: - убрали функции в стиле K&R и триграфы; - обязательные параметры в вариадических функциях теперь не требуются, а в макросе va_start второй параметр (как раз тот самый обязательный параметр, про который ломали копья не так давно в этой ветке) не является обязательным, а если даже и указан, то игнорируется; - добавили поддержку двоичных чисел с префиксом 0b (наконец-то!); - и да, функции f() - это теперь официально функции без параметров. Вот и выходит, что пишешь вроде как C89, а получается почему-то C23 
Минутка юмора :) Когда начинал делать транслятор, за основу взял грамматику из стандарта C89. Но при этом что-то сразу исключил: - триграфы; - определения функций в старом стиле K&R; А что-то сделал не совсем стандартно: - возможность объявления функций с переменным числом параметров в т.ч. и без обязательного первого (первых) параметра, т.е. вида void f (...); - поддержка в т.ч. двоичных чисел с префиксом 0b; - функции вида f() считаются функциями без параметров, а не функциями с неопределенным числом параметров; - переменные могут объявляться в любом месте блока, а не только в его начале; Ну и сразу заложил по мелочи что-то из того, что может пригодиться в будущем (например, inline).
Решил глянуть, что там сейчас стандартописатели напридумывали. После стандарта C89 были C99, C11, C17, ну и вроде как самый свежий на сегодня C23. Понятное дело, что в следующих стандартах добавились inline и возможность объявления переменных в любом месте блока. И будете смеяться, но в C23: - убрали функции в стиле K&R и триграфы; - обязательные параметры в вариадических функциях теперь не требуются, а в макросе va_start второй параметр (как раз тот самый обязательный параметр, про который ломали копья не так давно в этой ветке) не является обязательным, а если даже и указан, то игнорируется; - добавили поддержку двоичных чисел с префиксом 0b (наконец-то!); - и да, функции f() - это теперь официально функции без параметров.
Вот и выходит, что пишешь вроде как C89, а получается почему-то C23 :)
|
|
|
 |
Добавлено: Чт апр 17, 2025 14:39 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
В целом да, тут две крайности. Можно последовательно воспроизводить все, "как у всех", постоянно натыкаясь на особенности стека. Можно принципиально не делать ничего "как у всех". Истина где-то посередине, как обычно. Удобство стековой модели для ПЛИС в компактном коде, и можно просто учитывать эту особенность, не создавая много параметров специально. А оно часто так и оказывается в простых приложениях, в ПЛИС в основном нужно манипулировать регистрами IP-ядер, и выжимать максимум из процессора совершенно ни к чему.
В целом да, тут две крайности. Можно последовательно воспроизводить все, "как у всех", постоянно натыкаясь на особенности стека. Можно принципиально не делать ничего "как у всех". Истина где-то посередине, как обычно. Удобство стековой модели для ПЛИС в компактном коде, и можно просто учитывать эту особенность, не создавая много параметров специально. А оно часто так и оказывается в простых приложениях, в ПЛИС в основном нужно манипулировать регистрами IP-ядер, и выжимать максимум из процессора совершенно ни к чему.
|
|
|
 |
Добавлено: Пт апр 11, 2025 16:13 |
|
|
 |
|
|
Заголовок сообщения: |
Re: Трансляторы Си в Форт |
 |
|
Да, безусловно, аппаратно стековый кадр (или кадровый стек  ) можно поддержать, предусмотрев нужный функционал в архитектуре и системе команд. Но когда начинал делать компилятор, исходил из того, что нужно не только максимально простое, но и в каком-то смысле универсальное решение, которое должно работать в т.ч. и в самых запущенных случаях, а именно: - небольшой стек (для локальных переменных в нем просто не хватит места); - запись в стек только через вершину, прочие ячейки недоступны для записи (если локальные переменные разместить в стеке, не сможем менять их значение); - примитивная система команд (отдельным командам для работы с кадром стека и сложным режимам адресации здесь не место). Все написанное выше относится не только к моим Форт-процессорам, но и к разномастным Фортам: если не лезть в бутылку ассемблер и кишки каждой конкретной Форт-системы, то в арсенале у нас лишь небольшое количество милых сердцу каждого фортера слов (dup/drop/...), а стек в общем случае непригоден для хранения локальных переменных. Да, можно было бы программно реализовать стек данных, чтобы в нем было место и для локальных переменных. Но зачем эти гири на ногах Форт-процессору? Через аппаратный стек ему считать быстрее. Да и какой смысл в точности повторять реализацию стекового кадра из условного x86? Главное, что есть агрументы/результаты/локальные переменные, а как оно там под капотом сделано - не принципиально.
Да, безусловно, аппаратно стековый кадр (или кадровый стек :) ) можно поддержать, предусмотрев нужный функционал в архитектуре и системе команд. Но когда начинал делать компилятор, исходил из того, что нужно не только максимально простое, но и в каком-то смысле универсальное решение, которое должно работать в т.ч. и в самых запущенных случаях, а именно: - небольшой стек (для локальных переменных в нем просто не хватит места); - запись в стек только через вершину, прочие ячейки недоступны для записи (если локальные переменные разместить в стеке, не сможем менять их значение); - примитивная система команд (отдельным командам для работы с кадром стека и сложным режимам адресации здесь не место). Все написанное выше относится не только к моим Форт-процессорам, но и к разномастным Фортам: если не лезть в [s]бутылку[/s] ассемблер и кишки каждой конкретной Форт-системы, то в арсенале у нас лишь небольшое количество милых сердцу каждого фортера слов (dup/drop/...), а стек в общем случае непригоден для хранения локальных переменных. Да, можно было бы программно реализовать стек данных, чтобы в нем было место и для локальных переменных. Но зачем эти гири на ногах Форт-процессору? Через аппаратный стек ему считать быстрее. Да и какой смысл в точности повторять реализацию стекового кадра из условного x86? Главное, что есть агрументы/результаты/локальные переменные, а как оно там под капотом сделано - не принципиально.
|
|
|
 |
Добавлено: Пт апр 11, 2025 11:30 |
|
|
 |
|