【发布时间】:2015-07-26 12:25:54
【问题描述】:
John Heyes 的 ANS Forth 测试套件包含以下定义:
: IFFLOORED [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ;
然后根据我们使用的是地板除法还是对称除法,有条件地定义各种单词:
IFFLOORED : T/MOD >R S>D R> FM/MOD ;
所以IFFLOORED 的行为类似于noop 或\,具体取决于表达式的结果。美好的。这样做很容易在我的线程解释器上实现:
: POSTPONE ' , ; IMMEDIATE
...现在IFFLOORED 有效;定义等同于: IFFLOORED -1 IF ['] \ EXECUTE THEN ;。
不幸的是,测试套件的下方是以下代码:
: GT1 123 ;
: GT4 POSTPONE GT1 ; IMMEDIATE
: GT5 GT4 ;
\ assertion here that the stack is empty
同样的实现在这里不起作用。如果POSTPONE 编译了对其单词的引用,那么GT4 就相当于: GT4 123 ;... 但GT4 是立即。所以当GT5 被定义时,123 被压入编译器的堆栈并且GT5 变成了一个noop。但这是不对的;测试套件期望调用GT5 将 123 留在堆栈上。所以要让它工作,POSTPONE 必须生成生成代码的代码:
: POSTPONE ' LITERAL ['] , LITERAL ;
事实上,如果我使用 gForth,我会发现 POSTPONE 实际上是这样工作的:
: GT1 123 ;
: GT4 POSTPONE GT1 ; IMMEDIATE
SEE GT4
<long number> compile, ;
但是这两个定义是不兼容的。如果我使用第二个定义,第一个测试会失败(因为现在 IFFLOORED 尝试编译 \ 而不是执行它)。如果我使用第一个定义,则第二个测试失败(因为 GT4 推送到编译器堆栈而不是编译文字推送)。
...但是两个测试都通过了 gForth。
那么发生了什么?
【问题讨论】:
-
POSTPONE \ THEN ... 推迟评论。我确定这不是你的意思。您能否修复该列表?
标签: forth