next up previous contents
Next: References Up: RFM Manual: Compiling RELFUN Previous: 7.5.2 The debugger display

8 A sample session

  We consult and compile the well-known naive reverse benchmark, run an nrev-query and then demonstrate the usage of the debugger using a simple append-query. Except from the explicit true values for successful queries, this does not differ from PROLOG's semantics permitting an easy comparison. Once the debugging principles are thus understood, the reader can also debug functional programs.

rfi-p> emul
Collecting modules for the emulator:
sortbase workspace
rfe-p> consult "exa/bench"
Reading file "/home/perling/RELFUN/RFM/demo/exa/bench.rfp"

rfe-p> listing
app([],L,L).
app([H|L1],L2,[H|L3]) :- app(L1,L2,L3).
nrev([],[]).
nrev([H|L1],L3) :- nrev(L1,L2), app(L2,[H],L3).

rfe-p> style lisp
rfe-l> listing
(hn (app (tup) _l _l))
(hn (app (tup _h | _l1) _l2 (tup _h | _l3))
    (app _l1 _l2 _l3) )
(hn (nrev (tup) (tup)))
(hn (nrev (tup _h | _l1) _l3)
    (nrev _l1 _l2)
    (app _l2 `(tup _h) _l3) )

The database has been consulted and listed. In the following we do some horizontal transformations and list the result.

rfe-l> style prolog
rfe-p> horizon
rfe-p> listing
app(nil,L,L).
app(_1,L2,_2) :- _2 is cns[H,L3], _1 is cns[H,L1], app(L1,L2,L3) & true.
nrev(nil,nil).
nrev(_1,L3) :-
         _1 is cns[H,L1],
         nrev(L1,L2),
         _2 is cns[H,nil],
         app(L2,_2,L3) &
         true.

rfe-p> style lisp
rfe-l> listing
(hn (app nil _l _l))
(ft (app _1 _l2 _2)
    (is _2 `(cns _h _l3))
    (is _1 `(cns _h _l1))
    (app _l1 _l2 _l3)
    true )
(hn (nrev nil nil))
(ft (nrev _1 _l3)
    (is _1 `(cns _h _l1))
    (nrev _l1 _l2)
    (is _2 `(cns _h nil))
    (app _l2 _2 _l3)
    true )

The horizontal transformations are followed by the vertical transformations into WAM code. The resulting code is shown by the listcode command. If you want to see the classified clauses, type listclass.

rfe-l> style prolog
rfe-p> verti
rfe-p> listcode app/3
((set_index_number 1)
 (switch_on_term nil nil 2 1 "label38")
 "label38"
 (set_index_number 3)
 (switch_on_term 1 1 "label39" 1 "label39")
 "label39"
 (try 1 3)
 (trust 2 3)
 1
 (get_nil 1)
 (get_x_value 2 3)
 (put_constant true 1)
 (proceed)
 2
 (allocate 0)
 (get_list 3)
 (unify_x_variable 4)
 (unify_x_variable 5)
 (get_list 1)
 (unify_x_value 4)
 (unify_x_variable 6)
 (put_x_value 6 1)
 (put_x_value 5 3)
 (call app/3 0)
 (put_constant true 1)
 (deallocate)
 (proceed) )

rfe-p> listcode nrev/2
((set_index_number 1)
 (switch_on_term nil nil 2 1 "label28")
 "label28"
 (set_index_number 2)
 (switch_on_term 2 2 2 "label29" "label29")
 "label29"
 (try 1 2)
 (trust 2 2)
 1
 (get_nil 1)
 (get_nil 2)
 (put_constant true 1)
 (proceed)
 2
 (allocate 3)
 (get_y_variable 3 2)
 (get_list 1)
 (unify_y_variable 2)
 (unify_x_variable 3)
 (put_y_variable 1 2)
 (put_x_value 3 1)
 (call nrev/2 3)
 (put_list 2)
 (unify_y_value 2)
 (unify_nil)
 (put_unsafe_value 1 1)
 (put_y_value 3 3)
 (call app/3 0)
 (put_constant true 1)
 (deallocate)
 (proceed) )

We are now finished compiling the database. Next we perform an nrev-query.

rfe-p> nrev([1,2,3],X)
true
X=[3,2,1]
rfe-p> more
unknown

Now we are interested in obtaining a trace of a simple query, displaying the internal structures when something interesting happens. The query is compiled and then the debugger is invoked.

rfe-p> spy
rfe-p> app([1],[2],X)

((MAIN (VARI X)) (IS (VARI 1) (INST (CNS 1 NIL)))
 (IS (VARI 2) (INST (CNS 2 NIL))) (APP (VARI 1) (VARI 2) (VARI X)))

((PROC MAIN/1 1 (INDEXING)
  (FUN1EVA (CUT-INFO NIL) (PERM)
   (TEMP ((VARI X) (3 (1) (3))) ((VARI 1) (4 NIL (1))) ((VARI 2) (2 NIL (2))))
   (CHUNK
    ((USRLIT (MAIN ((VARI X) (FIRST SAFE TEMP))) (1 0 (1)))
     (IS ((VARI 1) (FIRST UNSAFE TEMP)) (INST (CNS 1 NIL)))
     (IS ((VARI 2) (FIRST UNSAFE TEMP)) (INST (CNS 2 NIL)))
     (USRLIT
      (APP ((VARI 1) (NONFIRST UNSAFE TEMP)) ((VARI 2) (NONFIRST UNSAFE TEMP))
       ((VARI X) (NONFIRST SAFE TEMP)))
      (3 0 (1 3))))
    (4 NIL)))))

((GET_X_VARIABLE 3 1) (PUT_LIST 4) (UNIFY_CONSTANT 1) (UNIFY_NIL) (PUT_LIST 2)
 (UNIFY_CONSTANT 2) (UNIFY_NIL) (PUT_X_VALUE 4 1) (EXECUTE APP/3))

The following is a debugger trace.

 [260932] = (GWAM.TRY 260934 0) : v

 Value of? s

 [160930] = unused-stack-cell <== E <== B

Initially there is not much on the stack. Registers E and B point to the beginning of the stack. The next instruction creates a choicepoint and the registers are set appropriately. This is the standard choicepoint which is responsible for the output of unknown/success messages, having the next clause entry pointing to code causing the output of the user's variables.

 [260932] = (GWAM.TRY 260934 0) : s

 [260934] = (GWAM.CALL/DY QUERY@[30514] 0) : v

 Value of? s

 [160930] = unused-stack-cell <== E
 [160931] = (ref 160930)
 [160932] = 260935
 [160933] = (ref 160930)
 [160934] = 260933
 [160935] = (trail nil)
 [160936] = (ref 60931) <== B
 [260934] = (GWAM.CALL/DY QUERY@[30514] 0) : s
 [264018] = (GWAM.GET_X_VARIABLE 3 1) : s
 [264019] = (GWAM.PUT_LIST 4) : s
 [264020] = (GWAM.UNIFY_CONSTANT 1) : s
 [264021] = (GWAM.UNIFY_NIL) : s
 [264022] = (GWAM.PUT_LIST 2) : s
 [264023] = (GWAM.UNIFY_CONSTANT 2) : s
 [264024] = (GWAM.UNIFY_NIL) : s
 [264025] = (GWAM.PUT_X_VALUE 4 1) : s
 [264026] = (GWAM.EXECUTE/DY APP/3@[23842]) : v

 Value of? a

 Number of argument registers: 3

 A(1) = (LIST 60932)
 A(2) = (LIST 60934)
 A(3) = (REF 60931)
 [264026] = (GWAM.EXECUTE/DY APP/3@[23842]) : v

 Value of? h

 [60930] = unused-heap-cell <== S
 [60931] = (ref 60931) <== HB
 [60932] = (const 1)
 [60933] = (const nil)
 [60934] = (const 2)
 [60935] = (const nil) <== H
 [264026] = (GWAM.EXECUTE/DY APP/3@[23842]) : s

The code above allocates the structures for the query in the data space and sets the argument registers accordingly. Register X1 points to a list at memory locations 2 and 3, representing the list (1 . nil), and register X2 points to the list at memory locations 4 and 5. The third argument (X3) is a reference to memory location 1, whose contents points to the same location. This is the representation of a free variable.

 [263895] = (GWAM.SET_INDEX_NUMBER 1) : s
 [263896] = (GWAM.SWITCH_ON_TERM 260931 260931 263905 263901 263897) : s
 [263905] = (GWAM.ALLOCATE 0) : s
 [263906] = (GWAM.GET_LIST 3) : s

Note that indexing leads the program flow immediately to the second clause of append/3.

 [263907] = (GWAM.UNIFY_X_VARIABLE 4) : v

 Value of? s

 [160930] = unused-stack-cell
 [160931] = (ref 160930)
 [160932] = 260935
 [160933] = (ref 160930)
 [160934] = 260933
 [160935] = (trail nil)
 [160936] = (ref 60931) <== E <== B
 [160937] = (ref 160930)
 [160938] = 260935
 [160939] = unused-stack-cell
 [263908] = (GWAM.UNIFY_X_VARIABLE 5) : s
 [263909] = (GWAM.GET_LIST 1) : s
 [263910] = (GWAM.UNIFY_X_VALUE 4) : s
 [263911] = (GWAM.UNIFY_X_VARIABLE 6) : s
 [263912] = (GWAM.PUT_X_VALUE 6 1) : s
 [263913] = (GWAM.PUT_X_VALUE 5 3) : s
 [263914] = (GWAM.CALL/DY APP/3@[23842] 0) : v

 Value of? a

 Number of argument registers: 3

 A(1) = (CONST NIL)
 A(2) = (LIST 60934)
 A(3) = (REF 60937)
 [263914] = (GWAM.CALL/DY APP/3@[23842] 0) : v

 [60930] = unused-heap-cell
 [60931] = (list 60936) <== HB
 [60932] = (const 1)
 [60933] = (const nil) <== S
 [60934] = (const 2)
 [60935] = (const nil)
 [60936] = (const 1)
 [60937] = (ref 60937) <== H
 [263914] = (GWAM.CALL/DY APP/3@[23842] 0) : s

Now app/3 is called with the following arguments: X1 is nil, X2 is (2.nil) and X3 is a free variable. Clearly, the first clause of app/3 must be applied.

 [263895] = (GWAM.SET_INDEX_NUMBER 1) : s
 [263896] = (GWAM.SWITCH_ON_TERM 260931 260931 263905 263901 263897) : s
 [263901] = (GWAM.GET_NIL 1) : s
 [263902] = (GWAM.GET_X_VALUE 2 3) : s
 [263903] = (GWAM.PUT_CONSTANT TRUE 1) : s
 [263904] = (GWAM.PROCEED) : s
 [263915] = (GWAM.PUT_CONSTANT TRUE 1) : s
 [263916] = (GWAM.DEALLOCATE) : s
 [263917] = (GWAM.PROCEED) : s
 [260935] = (GWAM.HAS-SUCCEEDED) : v

 Value of? s


 [160930] = unused-stack-cell <== E
 [160931] = (ref 160930)
 [160932] = 263915
 [160933] = (ref 160930)
 [160934] = 260933
 [160935] = (trail nil)
 [160936] = (ref 60931) <== B
 [260935] = (GWAM.HAS-SUCCEEDED) : s

true
X=[1,2]
rfe-p> more

Indexing has pruned the search space for backtracking so that after the user's more request no other possibilities need be tested and the unknown message is generated.

 [260933] = (GWAM.TRUST 260930 0) : s
 [260930] = (GWAM.HAS-FAILED) : s

unknown
rfe-p>


next up previous contents
Next: References Up: RFM Manual: Compiling RELFUN Previous: 7.5.2 The debugger display

Harold Boley (boley@informatik.uni-kl.de)