Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/user-interface/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
User interface 第四:推迟——它是如何工作的?_User Interface_Forth - Fatal编程技术网

User interface 第四:推迟——它是如何工作的?

User interface 第四:推迟——它是如何工作的?,user-interface,forth,User Interface,Forth,John Heyes的第四套测试套件包含以下定义: : IFFLOORED [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ; 然后,根据我们使用的是floored还是对称除法,它被用于有条件地定义各种单词: IFFLOORED : T/MOD >R S>D R> FM/MOD ; 因此,ifflored的作用类似于noop或\,具体取决于表达式的结果。好的通过执行以下操作,可以在我的线程解释器上轻松实现: : POST

John Heyes的第四套测试套件包含以下定义:

: IFFLOORED [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ;
然后,根据我们使用的是floored还是对称除法,它被用于有条件地定义各种单词:

IFFLOORED : T/MOD  >R S>D R> FM/MOD ;
因此,
ifflored
的作用类似于noop或
\
,具体取决于表达式的结果。好的通过执行以下操作,可以在我的线程解释器上轻松实现:

: POSTPONE ' , ; IMMEDIATE
…现在,
ifflored
工作了;该定义相当于
:ifflored-1 IF[']\EXECUTE THEN

不幸的是,测试套件的下面是以下代码:

: GT1 123 ;
: GT4 POSTPONE GT1 ; IMMEDIATE
: GT5 GT4 ;
\ assertion here that the stack is empty
同样的实现在这里不起作用。如果
delay
编译了对其单词的引用,那么
GT4
就相当于
:GT4 123。。。但是GT4是即时的。因此,当定义
GT5
时,123被推到编译器堆栈上,
GT5
成为noop。但这是不对的;测试套件期望调用
GT5
将123留在堆栈上。因此,要使其工作,
delay
必须生成生成代码的代码:

: POSTPONE  ' LITERAL  ['] , LITERAL ;
事实上,如果我玩gForth,我会发现
delay
实际上是这样工作的:

: GT1 123 ;
: GT4 POSTPONE GT1 ; IMMEDIATE
SEE GT4

<long number> compile, ;
:GT1 123;
:GT4推迟GT1;立即的
见GT4
编译;
但这两个定义并不兼容。如果使用第二个定义,第一个测试将失败(因为现在
ifflored
尝试编译
\
,而不是执行它)。如果使用第一个定义,第二个测试将失败(因为
GT4
将推送到编译器堆栈上,而不是编译文本推送)

…但这两项测试都通过了


发生了什么事?

您引用的代码片段做了以下事情:

  • 计算-3/2(在编译时),并检查它是否为-2
  • 如果是,则存储一个0(false),否则将-1(true)存储在
    ifflored
    中,因此在对其求值时,它会将该值放在堆栈上。(这是
    LITERAL
    的效果)
  • 计算
    IFFLOORED
    时,在堆栈上按下值后,会出现
    IF
    -
    然后
    表达式。当该值为true时,意味着我们不在一个铺满地板的环境中,因此我们希望注释掉该行的其余部分,这就是
    \
    所做的

  • 所以这里有一个棘手的部分-
    \
    立即的
    ,也就是说,您不能在冒号定义中使用它,因为它会注释掉行的其余部分。您必须明确地告诉编译器您想要编译这个函数,而不是执行它,这就是
    推迟
    所做的。

    让我在这里回答,因为问题发生了很大的变化。不过,我仍然不确定我是否理解这个问题:)

    在您的示例中,您定义了

    : GT4 POSTPONE GT1 ; IMMEDIATE
    
    这里发生的情况如下:

  • 执行
    ,读取
    GT4
    并创建新词
  • 执行
    delay
    的编译语义,即编译
    GT1
    的编译语义,如您在GForth中所看到的
  • ,结束定义
  • 执行
    IMMEDIATE
    ,将最后定义的单词标记为IMMEDIATE
  • 只有在编译
    GT4
    时才调用
    delay
    ,它不会出现在编译后的代码中。因此,当以后在
    GT5
    的定义中使用这个直接词时,不需要
    delay
    的解释语义

    顺便说一下,根据,
    delay
    只有编译语义,而解释语义是未定义的

    另请参见中的
    推迟
    教程

    编辑解释和编译语义示例:

    : TEST1 ." interpretation" ;  => ok
    : TEST2 ." compilation" ; IMMEDIATE  => ok
    : TEST3 TEST1 TEST2 ;  => compilation ok
    TEST3  => interpretation ok
    : TEST4 POSTPONE TEST1 ; IMMEDIATE  => ok
    : TEST5 TEST4 ;  => ok
    TEST5  => interpretation ok
    : TEST6 POSTPONE TEST2 ; IMMEDIATE  => ok
    TEST6  => compilation ok
    

    如果您还有任何问题,您可以参考这些测试。

    很抱歉,您完全错过了我问题的重点---我理解
    iFloored
    的工作原理;这是我感到困惑的事。我更新了这个问题,希望能让它更清楚我想知道什么。是的,我都知道!我不明白的是
    delay
    在这种情况下和
    ifflored
    情况下是如何工作的
    GT4
    最终成为一个单词,当调用它时,编译对
    GT1
    的调用。但是
    ifflored
    最终成为一个单词,当被调用时,它执行对\的调用。
    delay
    如何同时做到这两个呢?
    delay
    总是编译单词的编译语义。在
    GT1
    的情况下,它的编译语义是编译对
    GT1
    的调用。而在\的情况下,作为一个
    立即
    单词,它的编译语义是将行的其余部分视为注释。因此,本质上,
    delay
    延迟下一个单词的执行-如果它是立即的,那么它编译一个对它的简单调用;如果它是一个简单的调用,那么它会编译代码来编译它。哦,它会看看它是什么类型的单词!这完全有道理(一旦我完成了实现,它甚至可以工作)。谢谢