/*

   Author:    Gerhard Röhner
   E-Mail:    GRoehner@t-online.de

   Zweck      : Erzeugt für eine Anfrage eine Verfolgungsspur.
                Die CALL-Ports werden entsprechend der Aufruf-
                tiefe eingerückt angezeigt.
   Autor      : Gerhard Röhner
   Literatur  : N. Fuchs: Kurs in logischer Programmierung
   Version    : 1.0, 16.11.1991, Urfassung
                1.1, 05.12.1991, Berücksichtigung von not
                2.0, 13.01.1992, Berücksichtigung von Cut
                2.1, 03.02.1992, Berücksichtigung von ;
                2.2, 14.12.1995, Version für Swing-Prolog
                2.3, 03.01.1996, Library-Version
                2.4, 15.09.2013, mit meta_predicate
                
   In das Library-Verzeichnis kopieren, in Prolog öffen und speichern
   und dann "make." aufrufen.
   
*/

:- module(spur, [spur/1]).
:- meta_predicate spur(:).


spur(Ziel):-
  spur(Ziel, 0, Ergebnis),
  (Ergebnis == fail, !, fail; true).

spur(true, _Tiefe, true):-                          /* facts  */
  !.

spur(!, Tiefe, true):-                              /* Cut     */
  writeline(!, Tiefe).
spur(!, Tiefe, fail):-
  !,
  writeline('Cut!', Tiefe).

spur((A, B), Tiefe, Ergebnis):-                     /* rules  */
  !,
  spur(A, Tiefe, ErgebnisA), 
  (ErgebnisA  == true, spur(B, Tiefe, Ergebnis); 
   ErgebnisA \== true, Ergebnis = ErgebnisA).
   
spur((A; B), Tiefe, Ergebnis):-
  !,
  (spur(A, Tiefe, Ergebnis);
  spur(B, Tiefe, Ergebnis)).

spur(A, Tiefe, true):- 
  predicate_property(A, built_in),
  !,
  call(A),
  writeline(A, Tiefe).
                       
spur(not(A), Tiefe, true):-
  !,
  writeline(not, Tiefe),
  \+ spur(A, Tiefe, _).

spur(A, Tiefe, Ergebnis):- 
  clause(user:A, B),
  writeline(A, Tiefe), 
  Tiefe1 is Tiefe + 3,
  spur(B, Tiefe1, Ergebnis),
  (Ergebnis == fail, !, fail; true).
                       
spur(A, Tiefe, true):-               /* keine weitere Regel für A */
  \+ clause(user:A, _),
  tab(Tiefe), write(A), write('    nein'), nl,
  fail.

writeline(_:A, Tiefe):-
  !,
  writeline(A, Tiefe).
writeline(A, Tiefe):-
  tab(Tiefe), write(A), nl.


