在沃伦的抽象机中,如果参数之一是寄存器,绑定如何工作?

In a Warren's Abstract Machine, how does bind work, if one of the arguments is a register?

我正在尝试创建自己的 WAM 实现,但我卡在 the exercise 2.4

图2.4中的指令unify_value X4我不明白怎么执行

据我了解,这条指令应该将程序中的 Y 与查询中的 f(W) 统一起来。

unify_value X4调用unify (X4,S),其中S=2(见图2.1)对应的堆单元为"REF 2",X4为"STR 5".

Unify(图2.7)应该是bind那些值,但是我不明白如何deref注册一个。

"REF 2"在堆中,"STR 5"在寄存器中。你如何bind注册一些东西?

我们谈论的是 Warren 的 "New" 引擎,WAM,而不是旧引擎,称为 PLM。

在 WAM 中,变量分配在两个地方。

  1. 本地栈(环境栈)

寄存器不能保存变量。但是,它们可能包含对变量的引用。请注意,堆中的引用仅指向堆中。

与您的问题密切相关的是 WAM 如何维持此顺序并同时具有 非常便宜的最后调用优化 的巧妙方式。在(确定的)最后一次调用的时间点,必须以某种方式移动作为最后一次调用参数的局部变量。在像 ZIP 这样的更传统的 Prolog 机器中,这是一项极其费力的工作,本质上需要扫描环境框架以查找仍然位于其中的变量。

然而,WAM 有一个更好的调用约定:大多数变量已经在一个安全的地方,可以在编译期间轻松分析。剩下的极少数需要一个明确的 PUT_UNSAFE 指令来检查值,并且它仍然是一个局部变量,该变量被转移到堆上。

考虑什么是 WAM 中的安全变量:

  1. 头部出现的所有变量

  2. 作为结构参数出现的所有变量

因此只有在目标中最先出现和在最后一个目标中出现并且未出现在某些结构中的变量必须具有 PUT_UNSAFE。那不是那么多。此外,动态检查可以将实际复制到堆上的次数减少到最少。

起初这PUT_UNSAFE看起来工作量很大,但永远不要忘记 WAM 允许删除许多 PUT,而 ZIP 必须为每个参数至少执行一条指令。

这是一个使用 GNU 的典型示例:

a --> b, c.

扩展到:

a(S0,S) :- b(S0,S1), c(S1,S).

并使用命令pl2wam编译为:

predicate(a/2,1,static,private,monofile,global,[
    allocate(2),
    get_variable(y(0),1),                   % S
    put_variable(y(1),1),                   % S1
    call(b/2),
    put_unsafe_value(y(1),0),               % S1
    put_value(y(0),1),                      % S
    deallocate,
    execute(c/2)]).