Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Чт мар 28, 2024 18:34

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Ответить
Имя пользователя:
Заголовок:
Текст сообщения:
Введите текст вашего сообщения. Длина сообщения в символах не более: 60000

Размер шрифта:
Цвет шрифта
Настройки:
BBCode ВКЛЮЧЕН
[img] ВЫКЛЮЧЕН
[flash] ВЫКЛЮЧЕН
[url] ВКЛЮЧЕН
Смайлики ВЫКЛЮЧЕНЫ
Отключить в этом сообщении BBCode
Не преобразовывать адреса URL в ссылки
Вопрос
Теперь гостю придется вводить здесь пароль. Не от своей учетной записи, а ПАРОЛЬ ДЛЯ ГОСТЯ, получить который можно после регистрации на форуме через ЛС.:
Этот вопрос предназначен для выявления и предотвращения автоматических регистраций.
   

Обзор темы - [BF] структуры управления в старом ЦК
Автор Сообщение
  Заголовок сообщения:   Ответить с цитатой
Ну все, получили самый маленький язык программирования, теперь можно на этом рисовать программки.
Для удобства надо еще добавить многозадачность (хотя бы параллельное выполенние нескольких нитей -- адресное пространство кода и данных одно и то же, но для каждой нити отдельные стеки).
Так вот при запуске таких нитей нам нужно будет для команды ( cfa-addr ) thread ( pid ) указывать адрес слова, с которого будет стартовать потом нить командой ( pid ) start ( -- ) .
Для этого нам в ЦК нужно слово ['] которое будет каким-то образом лезть внутрь CREATE-DOES {слова} и вытаскивать из него адрес, который это {слово} использует при компиляции call {слово-addr}.
Самым простым мне показалось сначала дать этому {слову} отработать, то есть скомпилить call, а потом пропатчить этот call заменив на lit. Чтобы сохранить традиционный префиксный синтаксис ['] , используется поиск имени {слова} по словарю и запуск еще через EXECUTE, хотя более красивым и простым было бы использование постфиксной формы.
Код:
: [']      
     BL WORD FIND IF EXECUTE ELSE ABORT THEN \ лезем в поток SOURCE выцепляя имя, делаем поиск и запуск (или аборт)
     0x05 ( lit-op) THERE _cell - ( call-op-addr ) b! \ патчим опкод call на опкод lit
;
Сообщение Добавлено: Вс июн 03, 2007 11:48
  Заголовок сообщения:   Ответить с цитатой
буфер
Код:
: buffer ( n )   CREATE THERE , ( n ) 0 DO 0 b, LOOP DOES> @ lit ;
запоминаем адрес (текущее значение THERE), компилим n нулевых байт, при упоминании имени буфера компилим литерал адрес буфера
Код:
512 buffer FLOPPY_SECTOR
... z1 ... FLOPPY_SECTOR ... z2 ...
компилится в
Код:
...
@FLOPPY_SECTOR: db 0 times 512
...
z1
...
lit @FLOPPY_SECTOR
...
z2
...
Сообщение Добавлено: Вс июн 03, 2007 11:36
  Заголовок сообщения:   Ответить с цитатой
переменные -- компилируем в байт-код начальное значение, его адрес запоминаем через CREATE-DOES,
Код:
: var    ( n )   CREATE THERE , ( n ) cell,          DOES> @ lit ;
при упоминании имени переменной в коде
Код:
0x1234 var SDKJSDJ

.... z1 ... SDKJSDJ @ ... z2 ...

компилируем запомненный адрес переменной литералом:
Код:
...
@SDKJSDJ: dcell 0x1234
...
z1
...
lit @SDKJSDJ
@
...
z2
...
Сообщение Добавлено: Вс июн 03, 2007 11:31
  Заголовок сообщения:   Ответить с цитатой
ну и структуры управления.
если словарную структуру не создаем, то делаем просто:
константы реализуем как CREATE-DOES слова, в целевой код компилируем литералом inline:
Код:
: const  ( n )   CREATE ( n ) ,                      DOES> @ lit ;

код
Код:
0x1234 const KDSKSDKJ

.... z1 ... KDSKSDKJ ... z2 ...
компилится
Код:
....
z1
....
lit 0x1234
...
z2
...
Сообщение Добавлено: Вс июн 03, 2007 11:27
  Заголовок сообщения:   Ответить с цитатой
и наконец аналогично
Код:
.... z1 begin z2 ( flag ) until z3 ...
компилится в
Код:
     ...
     z1
@BEGIN:
     z2
( flag )
@UNTIL: ?jmp @BEGIN
     z3
     ...

как и с begin/again никаких фиктивных jmpов, компилим
Код:
?jmp @BEGIN
и все
Сообщение Добавлено: Вс июн 03, 2007 11:24
  Заголовок сообщения:   Ответить с цитатой
Код:
... z1 begin z2 ( flag ) while z3 repeat z4 ...
компилится в
Код:
     ...
     z1
@BEGIN: \ begin положил адрес
     z2
( flag )
@WHILE: ?jmp 0xFFFF --patched--> @REPEAT \ while положил адрес и скомпилил фиктивный ?jmp
     z3
jmp @WHILE \ это
@REPEAT: \ и это скомпилил repeat используя со стека адреса положенные begin и while
     z4
     ...
Сообщение Добавлено: Вс июн 03, 2007 11:19
  Заголовок сообщения:   Ответить с цитатой
совсем просто реализуются циклы do/loop:

Код:
.... z1 ( n1 n2 ) do z2 i z3 loop z4 ...


компилится используя спец.команды для таких циклов, которые используют собственный стек

Код:
     ...
     z1
( n1 n2 ) do
     z2
     i
     z3
loop
     z4
     ...
Сообщение Добавлено: Вс июн 03, 2007 11:16
  Заголовок сообщения:   Ответить с цитатой
Код:
.... z1 begin z2 again z3 ...
проще всего:
Код:
     ...
     z1
@BEGIN:
     z2
@AGAIN: jmp @BEGIN
     z3
     ...

никакого геморроя -- тупо взяли адрес, положенный begin, и скомпилили на него jmp
Сообщение Добавлено: Вс июн 03, 2007 11:14
  Заголовок сообщения:   Ответить с цитатой
код
Код:
... z1 if z2 else z3 endif z4 ...

компилится более сложно:
Код:
     ...
     z1
@IF: ?jmp 0xFFFF --patched--> @ELSE \ скомпилилось ifом
     z2
     jmp 0xFFFF --patched--> @ENDIF \ это
@ELSE:  \ и это скомпилилось elseом, на стеке данных была подмена адресов для endifа
     z3
@ENDIF: \ отработал endif но пропатчил не ifный ?jmp а elseный jmp (адреса параметров на стеке были подменены elseом)
     z4
     ...
Сообщение Добавлено: Вс июн 03, 2007 11:09
  Заголовок сообщения:   Ответить с цитатой
код
Код:
... z1 ( n1 n2 n3 flag ) if z2 endif z3 ...

скомпилируется в байт-код
Код:
     ...
     z1 ( n1 n2 n3 flag )
@IF: ?jmp 0xFFFF --patched--> label@ENDIF \ здесь работало слово if компилируя фиктивный jmp
     z2
label@ENDIF: \ здесь работало слово endif которое взяло THERE=label@ENDIF и пропатчило фиктивный jmp
     z3
     ...
Сообщение Добавлено: Вс июн 03, 2007 11:02
  Заголовок сообщения:   Ответить с цитатой
чтобы врубиться в работу слов типа if else begin while ... имхо лучше всего посмотреть в какой код компилируются эти конструкции, и попытаться реализовать их самостоятельно (в итоге получится практически тот же самый код что и у меня 8-)
Сообщение Добавлено: Вс июн 03, 2007 10:59
  Заголовок сообщения:   Ответить с цитатой
С реализацией конструкций типа if/else/endif все очень запутанно. Если кратко, то используется принцип -- в местах где нам нужно скомпилировать безусловный или условный переход, компилируем фиктивный (?)jmp 0xFFFF(FFFF) , запоминая в стеке данных адрес параметра этого (?)jmpа. Далее в процессе работы ЦК мы выясняем необходимые реальные значения этого параметра, и патчим параметры ранее скомпилированных jmpов (так называемая методика backpatching, используется практически во всех однопроходных компиляторах).
Сообщение Добавлено: Вс июн 03, 2007 10:57
  Заголовок сообщения:   Ответить с цитатой
совсем по-простому: словом { NEWWORD мы добавляем в ЦК слово NEWWORD компилирующее call на значение THERE в момент своего создания,
} вообще тупо компилирует ret.
Сообщение Добавлено: Вс июн 03, 2007 10:50
  Заголовок сообщения:  Re: [BF] структуры управления в старом ЦК  Ответить с цитатой
forth@km.ru писал(а):
Код:
: {      THERE _entry cell! CREATE THERE , DOES> @ call ;
: }      ret ;


Эти два слова используются для определения слов (процедур) в целевом коде (vs макросы определенные как обычно через : ; и компилирующиеся в целевой код inline).

Код:
THERE _entry cell!
берет текущее значение указателя ЦК, и патчит параметрт стартого jmpа в стартовом коде (см. самый конец исходника цк), устанавливая точку входа программы на определяемое через { } слово. Учтите что словарная структура в целевом коде не создается, так что это значение фактически является CFA нового слова. Если все же понадобится создание словарной структуры, слово HEADER, компилирующее заголовок словарной статьи, должно выполняться до этого кода.

Код:
CREATE THERE , DOES> @ call
в словаре инструментальной форт-системы (в нашем случае это SPF) создается CREATE-DOESнутое слово с именем слова, которое мы сейчас определяем через { }. Это слово при своем выполнении будет компилировать команду call на запомненное текущее значение THERE.

Таким образом, когда при работе ЦК мы выполняем (в режиме интерпретации) слово { NEWWORD. оно добавляет в ЦК слово NEWWORD, которое уже в свою очередь будет компилировать call на текущий адрес.
Сообщение Добавлено: Вс июн 03, 2007 10:48
  Заголовок сообщения:  [BF] структуры управления в старом ЦК  Ответить с цитатой
Код:
\ структуры управления

: {      THERE _entry cell! CREATE THERE , DOES> @ call ;
: }      ret ;

: if      -1 ?jmp THERE _cell - ;
: endif      THERE SWAP cell! ;
: else      -1 jmp THERE _cell - SWAP endif ;

: begin      THERE ;
: again      jmp ;
: until      ?jmp ;
: while      if ;
: repeat   SWAP jmp THERE SWAP cell! ;

: const  ( n )   CREATE ( n ) ,                      DOES> @ lit ;
: var    ( n )   CREATE THERE , ( n ) cell,          DOES> @ lit ;
: buffer ( n )   CREATE THERE , ( n ) 0 DO 0 b, LOOP DOES> @ lit ;
Сообщение Добавлено: Вс июн 03, 2007 10:38

Часовой пояс: UTC + 3 часа [ Летнее время ]


cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB