DEFER

Материал из ПМК вики
Перейти к: навигация, поиск

DEFER — фортовское порождающее слово Каллисто. Определение переменной действия.

DEFER          ( −− )                               Определить следующее слово, как действие
                                                    с начальным значением НОП (нет операции).

При исполнении переменной действия будет исполнено то слово, токен которого ей присвоен с помощью слова TO. DEFER позволяет определять слова, значения которых меняются во время работы приложения.

Слова, исполняемые переменной действия, могут вызывать авост.

Пример[править]

В следующем примере скомпилированное слово TELLANIMAL обращается то к ANIMAL1, то к ANIMAL2 — в зависимости от содержимого переменной действия ANIMAL:

DEFER ANIMAL
: TELLANIMAL ANIMAL ;

: ANIMAL1 ." кот" ;
: ANIMAL2 ." пёс" ;

' ANIMAL1 TO ANIMAL
TELLANIMAL

' ANIMAL2 TO ANIMAL
TELLANIMAL

Реализация[править]

2566 ;#DEFER
2567 ; DEFER            ( −− )                               Определить следующее слово, как действие с начальным значением НОП (нет операции).
2568 ; Для хранения xt (в виде адреса в единой адресации) используется поле данных DEFER
2569 ; Соглашение по векторному поля кода такое же, как у VALUE −− ведь мы используем одно и то же слово TO
2570 LDEFER:         .DB     5
2571                 .TEXT   "DEFER"                 ; ( "<пр>имя" −− )
2572                 .DW     LVALUE
2573 DEFER:          .DW CALL, CREAT,LITP,SNOP,COMMA ; DEFER инициализируется токеном НОП
2574                 .DW LITP,TODEFER,COMMA, PSCOD   ; TODEFER −− второй элемент векторного поля кода
2575 ; Исполняющая часть DEFER (обычное вхождение слова)
2576                 RM7 M5 KRM5                     ; ( −− ) выполнить сохранённый xt
2577                 KRM5 RME ∗ KRM5 +               ; RX := сохранённый xt
2578                 PGOTO DOEXECRX                  ; W := RX, JMP MEMW[W]
2579 TODEFER:
2580                 RM7 3 − M5                      ; R5 готов к косвенной адресации с предв. автоинкрементом
2581                 RM3 MA 1 + M3                   ; RA содержит номер регистра, в котором хранится новый xt
2582                 KRMA                            ; Получить новый CFA
2583                 ENT RME / FANS <−> KINT KM5     ; Сохранить старший байт нового CFA
2584                 ∗ − KM5  KGOTO9                 ; Сохранить младший байт нового CFA, NEXT

Реализации из SP-Forth 4.20:

0 VALUE VECT-CODE
…
CODE _VECT-CODE
     POP EBX
     JMP [EBX]
END-CODE

' _VECT-CODE TO VECT-CODE
…
         ' _VECT-CODE >VIRT VALUE VECT-CODE
…
: VECT ( -> )
  [T] HEADER [I]
  VECT-CODE COMPILE, NOOP-CODE >VIRT ,
  TOVALUE-CODE COMPILE,
;
: VECT ( -> )
  ( создать слово, семантику выполнения которого можно менять,
    записывая в него новый xt по TO)
  HEADER
  ['] _VECT-CODE COMPILE, ['] NOOP ,
  ['] _TOVALUE-CODE COMPILE,
;
…
: DEFER VECT ;
…
: DEFER CREATE ['] NOOP , DOES> @ EXECUTE ;
: DEFER@ ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE @ ELSE @ THEN ; IMMEDIATE
: IS '  >BODY STATE @ IF POSTPONE LITERAL POSTPONE ! ELSE ! THEN ; IMMEDIATE

: +TO ' >BODY STATE @ IF POSTPONE LITERAL POSTPONE +! ELSE +! THEN ; IMMEDIATE

Примечание[править]

Слова DEFER! и DEFER@ из черновика Forth 2000x в Каллисто отсутствуют. При необходимости их легко определить самостоятельно:

: DEFER! ( xt2 xt1 -- )   >BODY ! ;
: DEFER@ ( xt1 -- xt2 )   >BODY @ ;

Ссылки[править]


  Nopictures-icon.png У этой статьи нет иллюстраций. Вы можете помочь проекту, добавив их.


  Stub-icon-48px.png Это заготовка статьи. Вы можете помочь проекту, дополнив её.