0

我正在尝试编写一个 Forth 单词,它将丢弃堆栈中的所有项目。我正在使用一种非常愚蠢的方法,通过使用“drop”运行无限循环并在“drop”失败时捕获错误,因为堆栈为空。

我的话是这样定义的:

( Infinite drop loop)
: droploop begin drop true while drop repeat ;

( Experimental catch with a single drop)
: dropcatcher ['] drop catch drop ;

( Like dropcatcher, but with 'droploop' instead of 'drop')
: dropall  ['] droploop catch drop ;

当我运行 droploop 时,我得到了一个我期望的错误,并且在执行之后,堆栈是空的。当我运行 dropcatcher 时,如果堆栈不为空,它会丢弃,如果堆栈为空,它不会报告任何内容。当我运行 dropall 时,我会在堆栈上得到各种剩余的东西。

它看起来像这样:

2 3 4 5 6 7 8 9 10 dropall .s <9> -1 3 -1 5 -1 7 -1 9 -1 ok

我希望 dropall 会简单地清除堆栈而不会抱怨,因为 droploop 和 dropcatcher 似乎可以自己正常工作,但是唉,我不明白为什么 dropall 不起作用。

为什么 dropall 的工作方式似乎与 droploop 和 dropcatcher 不同?或者,我在这里做错了什么?

4

1 回答 1

2

droploop抛出错误时,它可能会调用ABORTor -1 THROW,根据定义,它会清除数据堆栈。因此,很可能droploop在检测到错误之前没有丢弃正确数量的堆栈项,但系统异常处理程序会为您完成。

当我droploop自己运行时,它要么崩溃,要么挂起。这似乎证实了我的理论,即存在严重的堆栈下溢。

至于 之后的堆栈状态dropall,我的猜测是 gforth 可能没有在正确的时间检测到堆栈下溢,而您看到的是一些半随机垃圾。因此,这是droploop在调用之前留在堆栈中的内容ABORT

旁注:您droploop每次迭代都会丢弃两个堆栈项,这可能是也可能不是您想要的。此外,使用againfor 无限循环而不是true while. IE: droploop begin drop again;

当然,清除堆栈的更好方法是

: clear   depth 0 ?do drop loop ;

或者

: clear   begin depth while drop repeat ;

或者

: clear   sp0 sp! ;
于 2014-11-05T19:18:25.853 回答