home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / CLIPPER / MISC / AIE8907.ZIP / TOOLBOX.CDE < prev   
Encoding:
Text File  |  1988-05-04  |  7.5 KB  |  208 lines

  1. LISTING 1.
  2. Bug finding strategy in PROLOG.
  3. find_failing_subgoal( Given_goal, Subgoal_which_is_bug) :-
  4.       this_is_the_problem( Subgoal_which_is_bug), !.
  5. find_failing_subgoal( Given_goal, Subgoal_which_is_bug) :-
  6.       find_failing_subgoal_of_my_clauses(  Given_goal,
  7.                              Intermediate_problem_goal),
  8.       find_failing_subgoal( Intermediate_problem_goalGiven_goal,
  9.                              Subgoal_which_is_bug).
  10.  
  11. LISTING 2.
  12. Testing for a list of integers
  13. with bug.
  14. integers( []) :-
  15.     !,
  16.     fail.
  17. integers( [H|T]) :-
  18.     integer(H),
  19.     integers(T).
  20.  
  21. LISTING 3.
  22. Report on bug in Listing 2.
  23. HERE IS THE BUG ANALYSIS :
  24. THE TOP LEVEL BUG...
  25.      The user-supplied goal integers([1]) failed.
  26.  
  27. GOING DOWN A LEVEL,
  28.   The goal at this level is integers([1]) which failed.
  29.   Clause 2 of integers / 1 failed.
  30.   Here it is with the failing subgoal marked.
  31.  
  32.   integers([A|B]) :-
  33.         integer(A),
  34. FAILS==>integers(B).
  35.  
  36.   Instantiated, this subgoal is integers([]).
  37.  
  38. GOING DOWN A LEVEL,
  39.   The goal at this level is integers([]) which failed.
  40.   Clause 1 of integers / 1 failed.
  41.   Here it is with the failing subgoal marked.
  42.  
  43.   integers([]) :-
  44.         !,
  45. FAILS==>fail.
  46.   Instantiated, this subgoal is fail.
  47. GOING DOWN A LEVEL,
  48.   You deliberately called the predicate 'fail'.
  49.      -- ( end of this particular possible bug explanation ) --
  50.  
  51. LISTING 4.
  52. Finding information about the current level bug.
  53.           % reports what has happened at current level,
  54.           % produces a report frame
  55. current_level_bug_report( Goal,
  56.                           Current_level_report) :-
  57.           % see why each clause of the Goal predicate failed
  58.     clause_reports( Goal,
  59.                     Clause_report_list) ,!,
  60.           % produce a bug report from the clause info
  61.     current_level_bug_report_hlpr( Goal,
  62.                                    Clause_report_list,
  63.                                    Current_level_report) .
  64.  
  65. LISTING 5.
  66. Reporting clause failures.
  67.  
  68.     % maps a Goal into a list of reports on what happened when you
  69.     % tried to satisfy the Goal using the various clauses of the
  70.     % Goal's predicate
  71. clause_reports( Goal, Clause_report_list) :-
  72.             % get functor and arity from Goal
  73.       functor( Goal, Functor, Arity),    !,
  74.             % get generalized rule head
  75.       functor( Head, Functor, Arity),    !,
  76.             % get clauses which have this functor as head
  77.       findall( X,
  78.                ( clause( Head, Body),
  79.                  X = ( Head :- Body)),
  80.                Clauses),                  !,
  81.             % clean up database
  82.       retractall(zzz_current_goal( _   )),
  83.             % store goal to protect it from unification
  84.       asserta( zzz_current_goal( Goal)),
  85.       gen_clause_reports( Clauses, 1, Clause_report_list),
  86.             % clean up database
  87.       retractall(zzz_current_goal( _   )).
  88.  
  89. LISTING 6.
  90. Clause-level bug reporting.
  91.  
  92. clause_report_hlpr(   Clause,  Report ):-
  93.          % get fresh copy of Goal, unaffected by any unifications
  94.          % done in computing previous clause reports
  95.    call( zzz_current_goal( Goal)),
  96.          % get head of rule
  97.    Clause = ( Head :- Body),  !,
  98.           % if the Head matches the Goal...
  99.    (  Head = Goal,
  100.           % stay with this branch
  101.       !,
  102.           % save the fact that the heads match
  103.       Report0 =  [ head_matched : true],
  104.           % collect more info about trying the clause body
  105.       clause_report_hlpr_on_body( Body, 1, Report0, Report)
  106.     ;
  107.           % else if Head does not match Goal
  108.       !,
  109.           % report out that fact
  110.       Report =  [ head_matched : fail ]).
  111. /** clause_report_hlpr_on_body finds info on where the body of a
  112.     rule fails **/
  113.          % debug rule
  114. clause_report_hlpr_on_body( Body , _, Report, _ ) :-
  115.          clause_level_trace([$e clause_report_hlpr_on_body, Body = $,
  116.                       Body,
  117.                       $ Report = $, Report ]),
  118.          fail.
  119.          % quit when a failure is reported
  120. clause_report_hlpr_on_body( _ , _, Report, Report) :-
  121.          clause_has_already_failed( Report ),  !.
  122.          % increment cut counts for cut terms
  123. clause_report_hlpr_on_body( ( Term , Rest), N, Report0, Report) :-
  124.            Term == !,
  125.            !,
  126.            increment_cut_count( Report0, Report1),
  127.            N1 is N+1,
  128.            clause_report_hlpr_on_body( Rest, N1, Report1, Report).
  129.          % recurse on success with next term
  130. clause_report_hlpr_on_body( ( Term , Rest), N, Report0, Report) :-
  131.            call( Term),
  132.            !,
  133.            N1 is N+1,
  134.            clause_report_hlpr_on_body( Rest, N1, Report0, Report).
  135.          % report term failure
  136. clause_report_hlpr_on_body( ( Term , _   ), N, Report0, Report) :-
  137.            !,
  138.            Term_report = [ result : fail,
  139.                            failing_subgoal_number : N,
  140.                            failing_subgoal : Term ],
  141.            frame_unify( Term_report,
  142.                         Report0,
  143.                         Report  ) .
  144.          % increment cut counts for final cut terms
  145. clause_report_hlpr_on_body( !,  _, Report0, Report) :-
  146.            !,
  147.            increment_cut_count( Report0, Report ).
  148.          % report success for clause if last term succeeds
  149. clause_report_hlpr_on_body(   Term , N, Report0, Report) :-
  150.            call( Term),
  151.            !,
  152.            Term_report = [ result : success,
  153.                            number_of_subgoals  : N],
  154.            frame_unify( Term_report,
  155.                         Report0,
  156.                         Report  ) .
  157.          % report term failure
  158. clause_report_hlpr_on_body(   Term , N, Report0, Report) :-
  159.            !,
  160.            Term_report = [ result : fail,
  161.                            failing_subgoal_number : N,
  162.                            failing_subgoal : Term ],
  163.            frame_unify( Term_report,
  164.                         Report0,
  165.                         Report  ) .
  166.  
  167. LISTING 7.
  168. Example of clause-report analysis.
  169.  
  170.                 % If clause report list is empty,
  171.                 % no rules are defined
  172. current_level_bug_report_hlpr(
  173.             Goal,       % the current goal
  174.             [],         % the list of clause reports
  175.                         % the generated current level bug report
  176.             [goal_report(
  177.                   [ call : Goal,
  178.                     result : fail,
  179.                     reason :
  180.                       no_clauses_defined])]) :- !.
  181.                 % if only 1 head matches , look in there
  182. current_level_bug_report_hlpr( Goal,
  183.                                Clause_report_list,
  184.                                Bug_report) :-
  185.      findall( Clause,
  186.               (  memb( Clause, Clause_report_list),
  187.                  frame_slot_val(head_matched, Clause, true)),
  188.               [ Head_matched ]),
  189.      bug_report_on_clause( Head_matched, Bug_report0 ),
  190.      frame_unify( [ call : Goal], Bug_report0, Bug_report1),
  191.      frame_info( Bug_report1, _, Slots),
  192.      Bug_report = [goal_report( Slots)], !.
  193. bug_report_on_clause( Clause_report , Bug_report) :-
  194.           frame_slot_val( failing_subgoal, Clause_report, Failure),
  195.           remove_if_slot( head_matched,
  196.                           Clause_report ,
  197.                           What_we_need  ) ,
  198.           frame_info( What_we_need , _, Bug_report  ).
  199. 1
  200. LISTING 8.
  201. Backtracking version of member.
  202.  
  203. memb(H,[H|_]).
  204. memb(H,[_|T]) :- memb(H,T).
  205.  
  206. /* Special thanks to Andre Vellino at Bell Northern Research in Ottawa,
  207.    ON, for showing me how useful this simple predicate can be. */
  208. anks to Andre Vellino