Search code examples
prologsicstus-prologwarren-abstract-machine

How can I inspect WAM code in SICStus Prolog


In the context of hacking on I want to glimpse at the code generated by SICStus Prolog. As an example, let's dissect the following predicate!

is_list([]).
is_list([_|Es]) :- is_list(Es).

Here's what I'm doing now:

  1. Split the 2 clauses of is_list/1 into 2 separate predicates and prepend 2 dummy clauses:

    is_list__clause1(dummy1).                  % dummy clause
    is_list__clause1([]).
    
    is_list__clause2(dummy2).                  % dummy clause
    is_list__clause2([_|Es]) :- is_list(Es).
    
  2. (Ab-)use the SICStus like so:

    | ?- 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
    …

This output—albeit somewhat cryptic—is giving me a feel of what's going on at the WAM level. I like!

But there has got to a simpler way... please help!


Solution

  • There is a simpler way: the undocumented, unsupported, library(disassembler).

    You can use this for programmatically getting information about first-argument indexing in addition to the WAM instructions. See the source for more information.

    | ?- 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
    | ?-