如何检查 SICStus Prolog 中的 WAM 代码
How can I inspect WAM code in SICStus Prolog
在破解 SICStus Prolog 生成的 clpz on sicstus-prolog I want to glimpse at the warren-abstract-machine 代码的上下文中。
作为例子,让我们剖析以下谓词!
is_list([]).
is_list([_|Es]) :- is_list(Es).
这是我现在正在做的事情:
将 is_list/1
的 2 个子句拆分为 2 个单独的谓词并添加 2 个虚拟子句:
is_list__clause1(dummy1). % dummy clause
is_list__clause1([]).
is_list__clause2(dummy2). % dummy clause
is_list__clause2([_|Es]) :- is_list(Es).
(Ab-)像这样使用 SICStus prolog-toplevel:
| ?- is_list__clause1(X).
X = dummy1 ? t
…
0x7eff37281300: GET_NIL_X0
0x7eff37281304: PROCEED
0x7eff37281308: END_OF_CLAUSEQ user:is_list__clause1/1
…
| ?- is_list__clause2(X).
X = dummy2 ? t
…
0x7eff37281150: GET_LIST_X0
0x7eff37281154: U2_VOID_XVAR 1,x(0)
0x7eff37281160: EXECUTEQ user:is_list/1
0x7eff37281170: END_OF_CLAUSEQ user:is_list__clause2/1
…
这个输出——尽管有点神秘——让我了解了 WAM 级别的情况。我喜欢!
但是有更简单的方法...请帮忙!
有一个更简单的方法:未记录,不受支持,library(disassembler)
。
除了 WAM 指令之外,您还可以使用它以编程方式获取有关第一个参数索引的信息。有关详细信息,请参阅来源。
| ?- use_module(library(disassembler)).
% ...
yes
| ?- [user].
% compiling user...
| foo([],Ys,Ys). foo([X|Xs],Ys,[X|Zs]) :- foo(Xs,Ys,Zs). end_of_file.
% compiled user in module user, 89 msec 599696 bytes
yes
| ?- disassemble(foo/3).
% Predicate: user:foo/3 (user)
% Varcase: [4343940512-4343958960,4346212208-4343221120]
% Lstcase: [4346212212]
% Switch: [[]=4343940516], default: failcode
% clause indexed [var,number,atom,structure] (user)
% 4343940512: 'GET_NIL_X0'
% 4343940516: 'GET_X_VALUE_PROCEED'(x(1),x(2))
% 4343940528: 'END_OF_CLAUSEQ'(user:foo/3)
% clause indexed [var,list] (user)
% 4346212208: 'GET_LIST_X0'
% 4346212212: 'U2_XVAR_XVAR'(x(3,0),x(0,0))
% 4346212224: 'GET_LIST'(x(2))
% 4346212232: 'U2_XVAL_XVAR'(x(3),x(2,0))
% 4346212244: 'EXECUTE'(user:foo/3)
% 4346212256: 'END_OF_CLAUSEQ'(user:foo/3)
yes
| ?-
在破解 SICStus Prolog 生成的 clpz on sicstus-prolog I want to glimpse at the warren-abstract-machine 代码的上下文中。 作为例子,让我们剖析以下谓词!
is_list([]).
is_list([_|Es]) :- is_list(Es).
这是我现在正在做的事情:
将
is_list/1
的 2 个子句拆分为 2 个单独的谓词并添加 2 个虚拟子句:is_list__clause1(dummy1). % dummy clause is_list__clause1([]). is_list__clause2(dummy2). % dummy clause is_list__clause2([_|Es]) :- is_list(Es).
(Ab-)像这样使用 SICStus prolog-toplevel:
| ?- is_list__clause1(X). X = dummy1 ? t … 0x7eff37281300: GET_NIL_X0 0x7eff37281304: PROCEED 0x7eff37281308: END_OF_CLAUSEQ user:is_list__clause1/1 … | ?- is_list__clause2(X). X = dummy2 ? t … 0x7eff37281150: GET_LIST_X0 0x7eff37281154: U2_VOID_XVAR 1,x(0) 0x7eff37281160: EXECUTEQ user:is_list/1 0x7eff37281170: END_OF_CLAUSEQ user:is_list__clause2/1 …
这个输出——尽管有点神秘——让我了解了 WAM 级别的情况。我喜欢!
但是有更简单的方法...请帮忙!
有一个更简单的方法:未记录,不受支持,library(disassembler)
。
除了 WAM 指令之外,您还可以使用它以编程方式获取有关第一个参数索引的信息。有关详细信息,请参阅来源。
| ?- use_module(library(disassembler)).
% ...
yes
| ?- [user].
% compiling user...
| foo([],Ys,Ys). foo([X|Xs],Ys,[X|Zs]) :- foo(Xs,Ys,Zs). end_of_file.
% compiled user in module user, 89 msec 599696 bytes
yes
| ?- disassemble(foo/3).
% Predicate: user:foo/3 (user)
% Varcase: [4343940512-4343958960,4346212208-4343221120]
% Lstcase: [4346212212]
% Switch: [[]=4343940516], default: failcode
% clause indexed [var,number,atom,structure] (user)
% 4343940512: 'GET_NIL_X0'
% 4343940516: 'GET_X_VALUE_PROCEED'(x(1),x(2))
% 4343940528: 'END_OF_CLAUSEQ'(user:foo/3)
% clause indexed [var,list] (user)
% 4346212208: 'GET_LIST_X0'
% 4346212212: 'U2_XVAR_XVAR'(x(3,0),x(0,0))
% 4346212224: 'GET_LIST'(x(2))
% 4346212232: 'U2_XVAL_XVAR'(x(3),x(2,0))
% 4346212244: 'EXECUTE'(user:foo/3)
% 4346212256: 'END_OF_CLAUSEQ'(user:foo/3)
yes
| ?-