调用堆栈?保留堆栈?名称堆栈?

发布于 2025-01-07 21:03:31 字数 290 浏览 0 评论 0原文

Factor 手册的本页讨论了存储在延续中的这些类型的堆栈:

  • datastack
  • 、retainstack
  • callstack
  • namestack
  • catchstack

这些堆栈到底保存什么?对我来说最令人困惑的三个是调用堆栈、保留堆栈和名称堆栈。

This page of the Factor manual talks about these types of stacks stored in continuations:

  • datastack
  • retainstack
  • callstack
  • namestack
  • catchstack

What precisely do these stacks hold? The three most confusing for me are the callstack, retainstack and namestack.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烛影斜 2025-01-14 21:03:31

我当然不是因子大师,但因为它们的名字似乎暗示了它们的用途:

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

    <前><代码>$> 1
    ---数据栈:
    1
    $> 2
    ---数据栈:
    1
    2
    $> +
    ---数据栈:
    3
    $> 。
    3
    $>

  • callstack:用于存储哪些单词正在运行以及它们的组成单词执行时的单独进度。想象一下,您已经定义了 sum 的更好版本: : sum' ( seq-of-int -- summmation ) 0 [ + ] reduce 20 + ; (它更好,因为您免费获得了额外的 20! )。为了重用代码,您利用了标准因子附带的 reduce 一词。当运行时执行 sum' 时,它会调用 reduce 的实现。但是,由于我们仍然需要添加额外的 20 个,因此必须有人记录 reduce 返回后再次启动的位置。这些注释存储在调用堆栈中,很可能在调试运行期间包含一些辅助数据,以帮助调试器了解正在发生的情况。

  • retainstack:用于保留某种辅助数据堆栈上的值。在 Forth 中,人们可以滥用返回堆栈(Forth 类似于调用堆栈)来充当保留堆栈。这种方法的问题之一是,如果不清理你的肮脏黑客行为,就言而无信,会让你跳转到错误的位置并造成严重破坏。 Forth 的运行时会看到你的值,期望它们是它在调用单词时所做的漂亮注释,但会感到困惑。通过使用单独的堆栈作为返回地址,Factor 可以避免这种情况。

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

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

I'm certainly no factor guru, but since their names seem to imply their use:

  • datastack: used for the usual pushing and popping of values. 3 4 + uses the datastack to push a '3', then push a '4'. Running '+' pops 2 values from the datastack and pushes the answer, 5, back to the datastack. Running an interactive session of factor (at least on Linux) prints the contents of this stack after every interaction:

    gt; 1
    --- Data stack:
    1
    
    gt; 2
    --- Data stack:
    1
    2
    
    gt; +
    --- Data stack:
    3
    
    gt; .
    3
    
    gt;
    
  • callstack: used to store which words are running and their individual progress while their component words execute. Imagine you have defined a better version of sum: : sum' ( seq-of-int -- summmation ) 0 [ + ] reduce 20 + ; (it's better because you get an extra 20 for free!). Wanting to reuse code, you've leveraged the reduce word that comes with standard factor. While the runtime is executing sum' it calls the implementation of reduce. But, since we still need to add the extra 20, someone has to record where to startup again once reduce returns. These notes are stored on the callstack, most likely with some ancillary data during debug runs to help debuggers understand what is going on.

  • retainstack: used for retaining values on a sort of ancillary datastack. In Forth, one can abuse the return stack (Forth's analog to the callstack) to act as a retainstack. One of the problems with this approach is that returning from your word without cleaning up your dirty hack will have you jumping to incorrect locations and wreaking general havoc. Forth's runtime will see your values, expecting them to be the nice notes it makes when calling a word and gets confused. By using a separate stack for return addresses, Factor can avoid this.

  • namestack: used to hold the data necessary to implement dynamic variables. By using a stack, you can hide old names with new ones while executing a subroutine, then pop the binding and the old names are restored.

  • catchstack: used to support exception handling. By using a stack, subroutines can register their own specialty handlers for exceptions and shadow default behaviour. Then, once the word returns, the old handlers can be restored easily by popping from the stack.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文