|
nedoPC.orgElectronics hobbyists community established in 2002 |
|
PDFORTH = Public Domain FORTH для PIC16F87X
Author |
Message |
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Возвращаясь к нашим ламповым экскрементам - нашёл кстати очень удобное описание ключевых слов стандарта 83
Итак, компилятор, встречая IF, должен скомпилить его вот в такой код: при этом запоминая на стеке адресов адрес, где сидит GOTO 0, чтобы потом подменить его на нужный GOTO с адресом, идущим после ELSE или THEN (который в Форте обозначает ENDIF). Далее компилируем как обычно и при нахождении ELSE пишем:
корректируя при этом GOTO по сохранённому ранее адресу на стеке адресов, прописывая туда адрес метки, идущей за GOTO, и сохраняя адрес нового GOTO на этом самом стеке для будущей коррекции - назвать его чтоли "system stack"?
Потом добираясь таки до THEN (по русски говоря ENDIF), просто вытаскиваем из системного стека адрес GOTO и корректируем его, прописывая в нём текущий адрес компиляции. Такой подход позволяет обработать оба случая - и с ELSE, и без.
P.S. Так как адреса у нас короче 64K, то старшие биты сохраняемых на стеке адресов (которых при 13-битном адресе имеется целых 3) можно использовать для тегирования сохраняемого, чтобы вылавливать случаи, когда юзер запутавшись пишет LOOP после IF или THEN без IF...
|
10 Dec 2014 22:26 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
На самом деле первую часть вот этого:
можно было бы затолкать в подпрограмму: и тогда IF скомпилируется вот в это:
что уменьшит размер кода (если IF-ов будет много), но замедлит программу чуть ли не в 2 раза...
P.S. по идее можно научить компилятор самостоятельно делать "inline" компиляцию вставляя внутренности подпрограммы вместо её вызова и делать это пользуясь неким порогом, если длина подпрограммы короче порога, то вставлять текст подпрограммы вместо CALL - порог можно завести как переменную, которую пользователь может менять...
|
10 Dec 2014 23:12 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Проверил в gforth - меняя VALUE меняется и программа, её использующая, а вот пересозданная CONSTANT поведение ранее откомпилированной программы НЕ меняет - т.е. установка константы на стек по сути компилируется прямо так - без CALL (как и чисел). Также вставку кода подпрограммы использующей VALUE непосредственно в код вместо CALL для оптимизации надо запретить, т.к. в таком случае невозможно будет изменить значение VALUE с помощью TO - запрещать оптимизацию некоторых подпрограмм можно путём их маркирования, например расположив NOP в конце (перед RETURN) мы сообщим оптимизирующему компилятору о том, что вызов этой подпрограммы оптимизировать ненадо. Аналогичным образом можно реализовать IMMEDIATE-слова (которые не компилируются, а вызываются сразу после ввода юзером) путём пометки подпрограммы NOP-ом вначале - таким образом можно реализовать FORGET и MARKER, а то и :
|
10 Dec 2014 23:49 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Например можно задействовать 2 старших бита (оставив остальные 14 для представления адресов в пределах 16K):
00 - IF...ELSE...THEN
01 - BEGIN ... AGAIN / UNTIL / WHILE
10 - WHILE ... REPEAT
11 - DO ... LOOP (LEAVE, UNLOOP, +LOOP, ?DO, I, J)
Для сложного случая BEGIN ... WHILE ... REPEAT придётся заюзать 2 разных тэга - 01 для первой половины (до WHILE) и 10 - для второй (после WHILE)
P.S. По идее UNLOOP нужен только чтобы прекратить выполнение цикла перед EXIT (которое покидает описание слова - будет компилироваться в RETURN) - это было сделано для тех форт-систем, которые совмещали стек возвратов и стек адресов для циклов - в нашем случае этого не понадобиться (т.к. в стек возвратов пика всё равно не залезешь), но для совместимости можно и поддержать...
|
11 Dec 2014 00:31 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
На самом деле gforth отказывается интерактивно выполнять программы, в которых есть компилируемые слова типа IF и DO - можно по идее тоже самое сделать, но тогда нужно как-то отличать такие слова от обычных - например если они все будут IMMEDIATE (NOP как первая инструкция в коде слова) - т.е. интерактивный интерпретатор будет выполнять слова, пока не встретит первое IMMEDIATE слово, на котором он остановится и сбросит состояние в начало (освободит стек и т.д.).
|
11 Dec 2014 01:15 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Итак, при включении форт-система ждёт команды от юзера на последовательном порту - если это : то это ввод нового слова - компилируем его строка за строкой пока не встретим ; либо ; IMMEDIATE. Теперь о том как лучше маркировать IMMEDIATE - т.к. до самого последнего момента форт не знает будет это слово IMMEDIATE или нет мы должны маркировать его в конце (либо ставить этот флаг в заголовке уже после компиляции). Предположим, что кроме длины слова и самого слова мы в заголовок ещё воткнём размер слова (для того чтобы оптимизатор мог заранее понять, надо ли при компиляции копировать содержимое слова либо воткнуть CALL) и флаги (один из которых будет IMMEDIATE). Например описание слова DROP может выглядеть так:
Сразу за именем идёт 14-битный описатель где старшие 6 бит это флаги, а младшие 8 - размер (соответственно размер не должен быть больше 255 пико-слов). Флаги могут быть такими:
bit 13 - immediate
bit 12 - never inline
bit 11 - always inline (хотя это наверное можно сделать через immediate?)
|
12 Dec 2014 07:30 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Тут выходит, что IMMEDIATE для компилятора тоже будет (TO, VALUE, CONSTANT) т.е. флаги надо делать так:
bit 13 - immediate for compiler
bit 12 - immediate for interpreter
bit 11 - never inline
bit 10 - always inline
bit 9 - reserved
bit 8 - reserved
Два резервных бита можно заюзать для представления длин до 1K (вместе со следущим байтом).
P.S. Длина подпрограммы будет использоваться для того, чтобы перескочить на начало следующей при поиске слов.
P.P.S. Одновременное взведение флагов "never inline" и "always inline" может быть использовано для запрещения отдельных слов (или новых версий слов, чтобы при компиляции использовать старые).
|
13 Dec 2014 09:08 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Вроде всё хорошо получается - по идее и для других платформ можно сделать имплементацию, включая 8080, 8086 и RW0 (чем не платформа? ; )
|
14 Dec 2014 21:54 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 873
|
В режиме интерпретации абсолютно все слова выполняются, этот флаг не нужен. После выполнения ":" устанавливается переменная state, и интерпретатор (он же и компилятор) выполняет только слова, помеченные immediate, остальные он складывает по адресу here. Слово ";" (кстати помеченное immediate) сбрасывает переменную state. Вот и весь секрет.
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
18 Dec 2014 05:47 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 873
|
Т.к. это immediate-слова, они, как и все остальные immediate-слова, проверяют в самом начале переменную state, и если выполнение в данном контексте не имеет смысла, вываливаются по ошибке (очищается входной буфер, стек).
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
18 Dec 2014 06:40 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
А как же IF и DO? Они в режиме интерпретации НЕ выполняются, во всяком случае на gforth...
|
18 Dec 2014 07:55 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22811 Location: Silicon Valley
|
Я тоже про это думал, но тогда в каждую подпрограмму таких слов придётся вставлять проверку флага - а тут как бы интерпретатор/компилятор эту проверку делает сам и сам ругается, если слово не подразумевается быть интерпретируемым или наоборот - компилируемым, т.е. на лицо экономия в размерах программного кода...
|
18 Dec 2014 11:45 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 873
|
В таком случае интерпретация будет медленнее. В форте цикл интерпретатора используется даже при загрузке из файла, а в этом случае скорость интерпретации очень даже критична. Хотя, по сравнению с поиском слова в словаре, проверка флага - просто пшик. Какой-нибудь хеш по первым двум буквам с лихвой окупит эти затраты
Если очень хочется, можно сделать флаг "compiler only".
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
18 Dec 2014 12:43 |
|
|
forthuser
Senior
Joined: 12 Jan 2023 07:26 Posts: 165
|
И чем эпопея с Форт для PIC16F87X закончилась? Для более продвинутых PIC есть FlashForth
|
12 Jan 2023 09:06 |
|
|
forthuser
Senior
Joined: 12 Jan 2023 07:26 Posts: 165
|
|
12 Jan 2023 09:36 |
|
|
Who is online |
Users browsing this forum: No registered users and 1 guest |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum
|
|