我记得曾经读过,至少还有两个与WAM大致同时发明的替代品。有什么指针吗?
答案 0 :(得分:20)
在WAM之前,有一个由Clocksin提供的ZIP。它的设计仍然非常有趣。 SWI-Prolog使用它。此外,B-Prolog已经从WAM设计慢慢迁移到ZIP。当然,通过这种方式,开发了许多新的创新。另一种选择是VAM。
1993年的比较是:
http://www.complang.tuwien.ac.at/ulrich/papers/PDF/binwam-nov93.pdf
与此同时,最有趣的建筑发展与B-Prolog有关。
WAM和ZIP之间的关键区别在于谓词参数的精确接口。在WAM中,参数都通过寄存器传递,即,实际寄存器或至少内存中的固定位置。 ZIP通过堆栈传递所有参数。
让我们考虑一个最小的例子:
p(R1,R2,R3,L1,L2,L3) :- % WAM % ZIP
% store L1...L3 % nothing
% nothing % push R1..R3
% init X1..X3 % push X1..X3
q(R1,R2,R3,X1,X2,X3),
% put unsafe X1..X3 % push X1..X3
% load L1..L3 % push L1..L3
r(X1,X2,X3,L1,L2,L3).
q
之前: WAM不需要对在相同位置(R1..R3
)传递给第一个目标的参数执行任何操作。这对于二元子句特别有意义 - 也就是说,最后只有一个常规目标的子句。 WAM擅长这里。
其他参数L1..L3
需要存储在本地。所以对于这些参数,寄存器接口没有做任何好事。
另一方面,ZIP不需要保存参数 - 它们已经保存在堆栈中。这不仅适用于具有多个目标的子句,也适用于其他中断目标,如约束或中断。
作为缺点,ZIP必须再次推送R1..R3
。
两者都必须初始化X1..X3
并将它们存储在堆栈中。
q
:调用q
时,WAM必须为X1..X3
和L1..L3
分配6个单元格的堆栈空间,而ZIP需要R1..R3,L1..L3,X1..X3
。所以在这里,WAM更节省空间。此外,WAM允许环境修整(对于更复杂的情况),这对于ZIP来说几乎是不可能的。
r
之前:此r
是最后一次调用,系统会尝试释放此子句的空间,前提是没有选择点。
对于WAM,存在变量X1..X3
have to be checked仍然是未实例化的局部变量(put_unsafe
),如果它们被移到堆上 - 这很昂贵,但很少发生。 L1..L3
刚刚加载。就是这样,WAM现在可以安全地解除分配本地帧。所以最后一次通话优化很便宜。
对于ZIP,一切都必须照常推送。然后,额外的扫描必须检查堆栈上的所有值并相应地移动它们。那相当昂贵。一些优化是可能的,但它仍然是WAM所做的更多。 ((可能的改进是以相反的顺序推送参数。然后变量L1..L3
可能会留在它们的位置。所以这些变量不需要任何处理。我还没有看到这样的实现(还)。) )
答案 1 :(得分:9)
在题为An abstract Prolog instruction set的技术说明中,Warren还引用了Bowen,Byrd和Clocksin的另一个编译器。但是,他说这两种架构有很多共同点,所以我不知道这个编译器是否真的可以作为替代。
答案 2 :(得分:6)
不确定这是不是你的意思,但前两个Prolog实现是由Colmerauer等人用Fortran编写的解释器。和Warren等人的DEC PDP-10原生编译器
沃伦在他的前言中提到了这些WAM的Ait-Kaci Tutorial Reconstruction。如果这不是您的意思,您可以在该文档或其参考文献中找到它。