调用堆栈?retainstack?namestack?

Pub*_*bby 6 continuations concatenative-language factor-lang

因子手册的这一页讨论了存储在continuation中的这些类型的堆栈:

  • datastack
  • retainstack
  • 调用堆栈
  • namestack
  • catchstack

这些堆栈究竟拥有什么?对我来说最令人困惑的三个是callstack,retainstack和namestack.

小智 8

我当然不是因素大师,但因为他们的名字似乎意味着他们的使用:

  • datastack:用于通常推送和弹出值.3 4 +使用数据包推送'3',然后按'4'.运行'+'会从数据包中弹出2个值,并将答案5推回到数据包.运行因子的交互式会话(至少在Linux上)在每次交互后打印此堆栈的内容:

    $> 1
    --- Data stack:
    1
    $> 2
    --- Data stack:
    1
    2
    $> +
    --- Data stack:
    3
    $> .
    3
    $>
    
    Run Code Online (Sandbox Code Playgroud)
  • callstack:用于存储正在运行的单词以及它们的组成单词执行时的个别进度.想象一下,你已经定义了一个更好的总和版本:( : sum' ( seq-of-int -- summmation ) 0 [ + ] reduce 20 + ;它更好,因为你免费得到额外的20!).想要重用代码,你已经利用了reduce标准因素带来的词.当运行时正在执行时,sum'它调用实​​现reduce.但是,由于我们仍然需要添加额外的20,所以有人必须记录reduce返回时再次启动的位置.这些注释存储在callstack中,很可能在调试运行期间有一些辅助数据,以帮助调试器了解正在发生的事情.

  • retainstack:用于保留某种辅助数据包的值.在Forth中,可以滥用返回堆栈(Forth的模拟到callstack)来充当retainstack.这种方法的一个问题是,从你的单词返回而不清理你的脏黑客会让你跳到不正确的位置并造成一般的破坏.Forth的运行时会看到你的值,期望它们在调用单词时会产生很好的音符并且会混淆.通过使用单独的堆栈作为返回地址,Factor可以避免这种情况.

  • namestack:用于保存实现动态变量所必需的数据.通过使用堆栈,您可以在执行子例程时使用新的名称隐藏旧名称,然后弹出绑定并恢复旧名称.

  • catchstack:用于支持异常处理.通过使用堆栈,子例程可以为异常和阴影默认行为注册自己的专业处理程序.然后,一旦单词返回,旧的处理程序可以通过从堆栈弹出来轻松恢复.