在Warren的抽象机中,如果其中一个参数是寄存器,绑定是如何工作的?

时间:2015-02-23 01:33:52

标签: prolog unification warren-abstract-machine

我正在尝试创建自己的WAM实施,并且我被困在the exercise 2.4

我无法理解如何在图2.4中执行指令unify_value X4

据我了解,该指令应该从查询中用程序中的f(W)统一Y.

unify_value X4调用unify (X4,S),其中S = 2(参见图2.1),相应的堆单元格为" REF 2",X4为" STR 5&#34 ;

Unify(图2.7)应bind这些值,但我不明白如何deref注册。

" REF 2"在堆中," STR 5"是在一个登记册。你如何bind注册的东西?

1 个答案:

答案 0 :(得分:5)

我们谈论的是沃伦的“新”引擎,WAM而不是旧引擎,即PLM。

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

  1. 本地堆栈(环境堆栈)

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

    与您的问题很相关的是WAM维持此订单的非常巧妙的方式,同时具有非常便宜的最后通话优化。在(确定的)最后一次调用的时间点,必须以某种方式移动作为最后一次调用的参数的局部变量。在像ZIP这样的传统Prolog机器中,这是一项非常费力的工作,它基本上需要扫描环境框架中的变量。

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

    考虑WAM中的安全变量:

    1. 头部出现的所有变数

    2. 所有显示为结构参数的变量

    3. 因此,只有在目标和最后一个目标中首先出现并且未出现在某个结构中的变量必须具有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)]).