Что именно делает слово DOES›?

Я возился и пытался понять это, поэтому я написал простое слово, чтобы проверить это:

: test ." compile time" DOES> ." runtime" ;

Проблема в том, что это слово ведет себя непоследовательно. Его выход, кажется, варьируется в зависимости от ряда факторов, таких как:

  • это первая строка, которую нужно интерпретировать?
  • есть ли другие слова, определенные после него?

Кроме того, иногда он вообще ничего не печатает.

(Используя Гфорт)


person binarycat    schedule 19.11.2020    source источник
comment
Связанный: softwareengineering.stackexchange.com/questions/339283/   -  person Jerry Jeremiah    schedule 20.11.2020
comment
Этот ответ говорит: «Я полагаюсь на спецификацию. в котором говорится, что существует неоднозначное условие, если [самое последнее определение] не было определено с помощью CREATE ... поэтому, поскольку вы не используете CREATE, оно не будет работать так, как вы ожидаете.   -  person Jerry Jeremiah    schedule 20.11.2020
comment
Вот это неоднозначное условие, работающее в спецификации: complang.tuwien.ac.at/forth/ansforth-cvs/documents/html3/core/   -  person Jerry Jeremiah    schedule 20.11.2020
comment
@JerryJeremiah В той же спецификации говорится, что типичное использование также находится в определении двоеточия, так что это продолжает меня смущать.   -  person binarycat    schedule 20.11.2020
comment
Итак, я не являюсь экспертом в FORTH, поэтому я не могу рассказать вам, как он работает, но, похоже, его нужно использовать в определении с двоеточием, чтобы изменить определение слова, созданного CREATE. Поскольку в вашем примере CREATE не используется для создания слова перед использованием DOES›, ваш DOES› вместо этого изменяет последнее созданное слово, что дает вам удивительные результаты.   -  person Jerry Jeremiah    schedule 20.11.2020
comment
Для ознакомления я бы рекомендовал прочитать главу 11 Starting Forth, Расширение компилятора.   -  person Peter Mortensen    schedule 29.07.2021


Ответы (4)


Это ваш код:

: test ." compile time" DOES> ." runtime" ;

После этого я могу использовать ваше слово без двусмысленного поведения, с которым вы столкнулись:

CREATE def 12345 , test \ prints "compile time"

Он печатает compile time, потому что это поведение, которое вы скомпилировали в test до DOES>. Примечание: на самом деле это не выполняется во время компиляции.

DOES> заканчивает определение слова, но изменяет его так, что test также изменяет последнее определенное слово, чтобы оно помещало адрес своего поля данных в стек, а затем выполняет поведение, обнаруженное после DOES>.

Используя слово, которое я создал, оно имеет конкретизированное поведение, которое вы определили, следуя неявному поведению нажатия адреса:

def @ . \ prints runtime 12345

Примечание для Forth 2012. В соответствии с определением DOES> в Forth 2012 это может привести к неоднозначному поведению, если последнее слово не будет определено с помощью CREATE. Однако Gforth позволяет изменять определение любого слова.

Я надеюсь, что этот пример поможет объяснить, почему обычно CREATE используется в определении, использующем DOES>, но это, конечно, не обязательно.

person Veltas    schedule 21.11.2020

ответ ruvim может быть легче понять в Gforth.

В приведенном ниже коде определяется «классическое» определяющее слово, которое создает переменные, инициализируемые элементом в стеке во время компиляции. Я надеюсь, что операторы отслеживания в определениях помогут показать, что происходит.

: var    \ create: n <name> -- ; does>: -- addr ; initialised VARIABLE
  create      \ create a dictionary item for <name>.
  ." HERE at compile time: " HERE .
  ,           \ place n at HERE in the dictionary
  does>       \ Push the HERE as at compile time to the stack
  ." Run time address on the stack:" dup .
;

var теперь можно использовать для определения новых слов, для которых действие во время выполнения определено после DOES›.

10 var init10    \ Use var to define a new word init10
\ HERE at compile time: 135007328

init10 CR DUP . @ .
\ Run time address on the stack:135007328
\ 135007328 10   \ addr of init10, content of that address.

12 var init12    \ Use var to define a new word init12
\ HERE at compile time: 135007376

init12 CR DUP . @ .
\ Run time address on the stack:135007376
\ 135007376 12

100 init10 !    \ Store 100 in init10
\ Run time address on the stack:135007328
init10 @ .
\ Run time address on the stack:135007328  100
\ init10 now contains 100

Надеемся, что ответы послужат основой для изучения определяющих слов и действия ДЕЛАЕТ›.

person Tls Chris    schedule 20.11.2020

Интерактивная игра

В Gforth вы можете играть с does> интерпретируя.

create foo 123 ,

foo @ . \ prints 123

does> ( addr -- ) @ . ;

foo \ prints 123

does> ( addr -- ) @ 1+ . ;

foo \ prints 124

' foo >body @ . \ prints 123

Итак, does> просто изменяет поведение последнего слова, когда это последнее слово определено через create. Будет ошибкой запускать does>, когда последнее слово не было определено через create.

Использование на практике

Обычно does> используется для установки нового поведения только один раз для слова, определенного через create. Возможность изменить это поведение несколько раз — это лишь побочный эффект исторической реализации, и на практике этот эффект почти не используется.


Альтернативные способы

На практике случаи, когда используется does>, могут быть реализованы и без does>.

Например, пусть мы хотим реализовать слово counter, которое создает счетчик, который каждый раз возвращает следующее значение и используется следующим образом:

1 counter x1
x1 . \ prints 1
x1 . \ prints 2
x1 . \ prints 3

Реализация через create does>

: counter ( x0 "ccc" -- ) \ Run-Time: ( -- x )
  create ,  does> ( addr -- x ) dup >r @ dup 1+ r> !
;

Реализация с использованием цитирования

[undefined] lit, [if] : lit, ( x  -- ) postpone lit, ; [then]
[undefined] xt,  [if] : xt,  ( xt -- ) compile, ;      [then]

: counter ( x0 "ccc" -- ) \ Run-Time: ( -- x )
  align here >r , [: ( addr -- x ) dup >r @ dup 1+ r> ! ;] >r
  :  r> r> lit, xt, postpone ;
;

Реализация с использованием макроса (встраивание кода) через слово ]]:

: counter ( x0 "ccc" -- ) \ Run-Time: ( -- x )
  align here >r , 
  :  r> lit, ]] dup >r @ dup 1+ r> ! [[ postpone ; 
;
person ruvim    schedule 20.11.2020

Слово, определяющее слова, выделяющие память, может быть снабжено действием через DOES›, которое задает адрес блока памяти.

Простым примером является CONSTANT, который можно определить как

: CONSTANT ( n -- ) CREATE , DOES› @ ;

person Lehs    schedule 22.02.2021