Editing, apropos/1, trace/1, spy/1, nospy/1

To edit a file and then compile it use:

?- edit(<editor>,<file>).

To edit and recompile the currently compiled file using the emacs editor type:

?- ed.

To edit and recompile the currently compiled file using the edit editor (under DOS) type:

?- edit.

To simply recompile the last file type:

?- co.

The debugger/tracer
uses R.A. O'Keefe's public domain meta-interpreter. You can modify it in the file "extra.pl".
DCG-expansion
is supported by the public domain file dcg.pl.

To debug a file type:

?- reconsult(FileName).

and then

?- trace(Goal).

For
interactivity, both the toplevel and the debugger depend on

?-interactive(yes).

or

?-interactive(no).

My personal preference is using
interactive(no) within a scrollable window. However, as traditionally all Prologs hassle the user after each answer BinProlog 3.30 will do the same by default.

If you forget the name of some builtin, apropos/1 (or help/1) will give you some (flexible up to one misspelled or missing letter) matches with their arities.

You can use the debugger to debug compiled code with the following trick if you always debug bottom-up i.e. if you ensure that tools work before to using them. For example, on top of the compiled file allperms.pl you can temporarily interpret perm/2, insert/3 etc. to be able to trace them while keeping uninteresting predicates compiled. By the way, this allows, to trace/debug parts of the kernel itself in particular.

The following terminal session shows an example:

?- [allperms].
compiling(to(mem),progs/allperms.pl,...)
compile_time(230)
?- consult(user).
% using compile/1 is MUCH faster
reconsulting(user)
g0(N):-nats(1,N,Ns),perm(Ns,_),fail.
g0(_).
WARNING: redefining compiled predicate(g0/1)
perm([],[]).
perm([X|Xs],Zs):-
	perm(Xs,Ys),
	insert(X,Ys,Zs).

insert(X,Ys,[X|Ys]).
insert(X,[Y|Ys],[Y|Zs]):-
	insert(X,Ys,Zs).
WARNING: redefining compiled predicate(perm/2)
WARNING: redefining compiled predicate(insert/3)
reconsulted(user,time = 20)
yes
?- interactive(no).
yes
?- trace(g0(3)).
Call: g0(3)
 Call: nats(1,3,_645)
  compiled(nats(1,3,_645))
 Exit: nats(1,3,[1,2,3])
 Call: perm([1,2,3],_648)
  Call: perm([2,3],_1095)
   Call: perm([3],_1362)
    Call: perm([],_1629)
    Exit: perm([],[])
    Call: insert(3,[],_1362)
    Exit: insert(3,[],[3])
   Exit: perm([3],[3])
   Call: insert(2,[3],_1095)
   Exit: insert(2,[3],[2,3])
  Exit: perm([2,3],[2,3])
  Call: insert(1,[2,3],_648)
  Exit: insert(1,[2,3],[1,2,3])
 Exit: perm([1,2,3],[1,2,3])
 Call: fail
  compiled(fail)
 Fail: fail
 Redo: perm([1,2,3],[1,2,3])
  Redo: insert(1,[2,3],[1,2,3])
   Call: insert(1,[3],_2683)
   Exit: insert(1,[3],[1,3])
  Exit: insert(1,[2,3],[2,1,3])
 Exit: perm([1,2,3],[2,1,3])
 Call: fail
  compiled(fail)
 Fail: fail
 Redo: perm([1,2,3],[2,1,3])
  Redo: insert(1,[2,3],[2,1,3])
   Redo: insert(1,[3],[1,3])
    Call: insert(1,[],_2945)
    Exit: insert(1,[],[1])
   Exit: insert(1,[3],[3,1])
  Exit: insert(1,[2,3],[2,3,1])
 Exit: perm([1,2,3],[2,3,1])
 Call: fail
  compiled(fail)
 Fail: fail
 Redo: perm([1,2,3],[2,3,1])
  Redo: insert(1,[2,3],[2,3,1])
   Redo: insert(1,[3],[3,1])
    Redo: insert(1,[],[1])
    Fail: insert(1,[],_2945)
   Fail: insert(1,[3],_2683)
  Fail: insert(1,[2,3],_648)
  Redo: perm([2,3],[2,3])
   Redo: insert(2,[3],[2,3])
    Call: insert(2,[],_2421)
    Exit: insert(2,[],[2])
   Exit: insert(2,[3],[3,2])
  Exit: perm([2,3],[3,2])
  Call: insert(1,[3,2],_648)
  Exit: insert(1,[3,2],[1,3,2])
 Exit: perm([1,2,3],[1,3,2])
 Call: fail
  compiled(fail)
 Fail: fail
 Redo: perm([1,2,3],[1,3,2])
  Redo: insert(1,[3,2],[1,3,2])
   Call: insert(1,[2],_2945)
   Exit: insert(1,[2],[1,2])
  Exit: insert(1,[3,2],[3,1,2])
 Exit: perm([1,2,3],[3,1,2])
 Call: fail
  compiled(fail)
 Fail: fail
 Redo: perm([1,2,3],[3,1,2])
  Redo: insert(1,[3,2],[3,1,2])
   Redo: insert(1,[2],[1,2])
    Call: insert(1,[],_3207)
    Exit: insert(1,[],[1])
   Exit: insert(1,[2],[2,1])
  Exit: insert(1,[3,2],[3,2,1])
 Exit: perm([1,2,3],[3,2,1])
 Call: fail
  compiled(fail)
 Fail: fail
 Redo: perm([1,2,3],[3,2,1])
  Redo: insert(1,[3,2],[3,2,1])
   Redo: insert(1,[2],[2,1])
    Redo: insert(1,[],[1])
    Fail: insert(1,[],_3207)
   Fail: insert(1,[2],_2945)
  Fail: insert(1,[3,2],_648)
  Redo: perm([2,3],[3,2])
   Redo: insert(2,[3],[3,2])
    Redo: insert(2,[],[2])
    Fail: insert(2,[],_2421)
   Fail: insert(2,[3],_1095)
   Redo: perm([3],[3])
    Redo: insert(3,[],[3])
    Fail: insert(3,[],_1362)
    Redo: perm([],[])
    Fail: perm([],_1629)
   Fail: perm([3],_1362)
  Fail: perm([2,3],_1095)
 Fail: perm([1,2,3],_648)
 Redo: nats(1,3,[1,2,3])
 Fail: nats(1,3,_645)
Exit: g0(3)

Starting with version 3.08 spy/1 and nospy/1 allow to watch entry and exit from compiled predicates. Note that they should be in the file to be compiled, before any use of the predicate to be spied on as in:

% FILE: jbond.pl
:-spy a/1.
:-spy c/1.

b(X):-a(X),c(X).

a(1).
a(2).

c(2).
c(3).

This
gives the following interaction:

?-[jbond].
......
?- b(X).

Call: a(_2158) <enter=call, other=trace>: ;
 !!! compiled(a/1)
Exit: a(1)
Call: c(1) <enter=call, other=trace>: ;
 !!! compiled(c/1)
Fail: c(1)
Redo: a(1)
Exit: a(2)
Call: c(2) <enter=call, other=trace>: ;
 !!! compiled(c/1)
Exit: c(2)
X=2;

Redo: c(2)
Fail: c(2)
Redo: a(2)
Fail: a(_2158)
no

Although
these are very basic debugging facilities you can enhance them at your will and with some discipline in programming they may be all you really need. Anyway, future of debugging is definitely not by tracing. One thing is to have stronger static checking. In dynamic debugging the way go is to have a database of trace-events and then query it with high level tools. We plan to add some non-tracing database-oriented debugging facilities in the future.

You
can generate a kind of intermediate WAM-assembler by

  ?- compile(asm,[file1,file2,...],'huge_file.asm').

A
convenient way to see interactively the sequence of program transformations BinProlog is based on is:

?- asm.
a-->b,c,d.
^D

DEFINITE:
a(A,B) :- 
        b(A,C),
        c(C,D),
        d(D,B).

BINARY:
a(A,B,C) :- 
        b(A,D,c(D,E,d(E,B,C))).

WAM-ASSEMBLER:
clause_? a,3
firstarg_? _/0,6
put_structure d/3,var(4-4/11,1/2)
write_variable put,var(5-5/10,1/2)
write_value put,var(2-2/6,2/2)
write_value put,var(3-3/7,2/2)
put_structure c/3,var(3-8/14,1/2)
write_variable put,var(2-9/13,1/2)
write_value put,var(5-5/10,2/2)
write_value put,var(4-4/11,2/2)
execute_? b,3