从循环中捕获异常

时间:2014-11-05 17:23:10

标签: forth gforth

我正在尝试写一个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的工作方式不同?或者,我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

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

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

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

旁注:您的droploop每次迭代都会丢弃两个堆栈项,这可能与您的意图相同或不同。另外,使用again代替true while无限循环。即: droploop begin drop again;

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

: clear   depth 0 ?do drop loop ;

: clear   begin depth while drop repeat ;

: clear   sp0 sp! ;