home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / lifeos2.zip / LIFE-1.02 / TOOLS / PROFILER.LF < prev    next >
Text File  |  1996-06-04  |  51KB  |  1,960 lines

  1. %    $Id: profiler.lf,v 1.2 1994/12/08 23:52:18 duchier Exp $    
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %
  4. %
  5. %
  6. %  Profiler for predicates by source code transformation
  7. %  -----------------------------------------------------
  8. %
  9. %
  10. %  Author : Arnaud Venet.
  11. %
  12. %  Last modification : February 19th 1994
  13. %
  14. %
  15. %
  16. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  17. %
  18. %  
  19. %  USE : see "small presentation for the user" below.
  20. %
  21. %  PRECAUTIONS : _ dynamic predicates and functions will be corrupted
  22. %                _ profiling is only possible, when using modules, for public 
  23. %                  functions and predicates
  24. %
  25. %
  26. %  Read section 5 of document 'profiler.doc': "What the profiler does", to 
  27. %  get detailed description of the rewriting rules.
  28. %
  29. %
  30. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  31. %
  32. % (C) Digital Equipment Corporation 1993 - 1994
  33. %
  34. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  35. %
  36.  
  37.  
  38.  
  39.  
  40. module("profiler")?
  41.  
  42. public(profile, unprofile, clear_stats, profile_stats, profile_help,
  43.        write_stats, profile_backtracking, profile_fail_occured, 
  44.        goal, call, normal, titles_for_predicates, titles_for_functions)?
  45.  
  46.  
  47.  
  48. %
  49. % --------------------------------------------------------------------------
  50. % -
  51. % -  Persistent and global variables
  52. % -
  53. % --------------------------------------------------------------------------
  54. %
  55.  
  56.  
  57.  
  58. persistent(profile_old_clauses)?
  59.  
  60. profile_old_clauses <<- store? 
  61.  
  62. persistent(profile_stats)?
  63.  
  64. profile_stats <<- data?
  65.  
  66. persistent(profile_backtracking)?
  67.  
  68. profile_backtracking <<- false?
  69.  
  70. persistent(profile_fail_occured)?
  71.  
  72. profile_fail_occured <<- false?
  73.  
  74. persistent(column_width)?
  75.  
  76. column_width <<- 1?
  77.  
  78. persistent(columns_number)?
  79.  
  80. columns_number <<- 5?
  81.  
  82. persistent(titles_for_predicates)?
  83.  
  84. titles_for_predicates <<- ["Tries", "Entries", "Success", 
  85.                            "%Tot.fail", "%Expl.fail"]?
  86.  
  87. persistent(titles_for_functions)?
  88.  
  89. titles_for_functions <<-  ["Tries", "Match", "%Eval", 
  90.                            "Successes", "%Tot.fail"]?
  91.  
  92. global(string_storage)?
  93.  
  94. string_storage <- cache?
  95.  
  96.  
  97.  
  98. %
  99. % --------------------------------------------------------------------------
  100. % -
  101. % -  Output parameters : they are used for the display of the statistics,
  102. % -  -----------------   feel free to change them at your convenience.
  103. % -
  104. % --------------------------------------------------------------------------
  105. %
  106.  
  107.  
  108.  
  109. no_value -> "---".
  110.  
  111. extension_for_log_files -> "log".
  112.  
  113. big_separation :- iter_string("*", 50).
  114.  
  115. small_separation :- iter_string("-", 40).
  116.  
  117. minimal_column_width -> 11.
  118.  
  119. maximal_column_width -> 23.
  120.  
  121.  
  122.  
  123. %
  124. % --------------------------------------------------------------------------
  125. % -
  126. % -  A small presentation for the user
  127. % -
  128. % --------------------------------------------------------------------------
  129. %
  130.  
  131.  
  132.  
  133. write("
  134. Type 'profile_help ?' to get some help about the profiler
  135.  
  136. ")?
  137.  
  138.  
  139. profile_help :-
  140.   write("
  141. PROFILER: source transformation to provide information about predicates and
  142.           functions use.
  143.  
  144. Use:
  145.       > import(""profiler"")?
  146.  
  147.       > profile(Name1, Name2, ... , NameN, level => Level)?
  148.  
  149.           Name1, ... NameN are names of functions or predicates to profile
  150.           Level := {call; clause; goal}
  151.  
  152.       > write_stats(Name1, Name2, ... , NameN, verbosity => Verbosity, 
  153.                     file => Where)?
  154.  
  155.           --> Display the statistics for Name1, ..., NameN.
  156.  
  157.           Name1, ... NameN are names of functions or predicates registered
  158.           for profiling.
  159.           Verbosity := {normal; verbose}
  160.           Where = . a string specifying the name of the file where to put
  161.                     the statistics. The extension '", extension_for_log_files,
  162.                     "' will be added to it.
  163.                   . @ (displays statistics on the standard output)
  164.  
  165.       > clear_stats(Name1, Name2, ... , NameN)?
  166.  
  167.           --> Resets the statistics for Name1, ..., NameN.
  168.  
  169.         If no name is specified, the statistics of all the predicates 
  170.         and functions registered for profiling are cleared.
  171.  
  172.       > unprofile(Name1, Name2, ... , NameN)?
  173.  
  174.           --> Restores the original clauses of Name1, ..., NameN.
  175.  
  176.           If no name is specified, all the predicates and functions 
  177.           registered for profiling are restored.
  178.  
  179.  
  180. WARNING : 'profile_stats', 'profile_backtracking' and 'profile_fail_occured' 
  181. -------   are reserved names of persistent variables exported by the module. 
  182.           DO NOT try to modify them.
  183.  
  184. <MORE>"), 
  185.   get(X),
  186.   write("
  187.  
  188. CUSTOMIZATION :
  189. ---------------
  190. You can customize the column titles which are displayed when you choose the 
  191. 'normal' verbosity for 'write_stats'. For this purpose you are provided with 
  192. two persistent variables : 'titles_for_predicates' and 'titles_for_functions'
  193. in which you can store a list of strings representing the titles of the
  194. corresponding columns. It's useful when you want the display to fit a given
  195. format. Each list must contain exactly FIVE strings.
  196. Default is :
  197.  
  198. titles_for_predicates : ", titles_for_predicates, "
  199.  
  200. titles_for_functions  : ", titles_for_functions, "
  201.  
  202.  
  203. Read: '~venet/LIFE/PROFILER/profiler.doc' for more information.
  204.  
  205. ").
  206.  
  207.  
  208.  
  209. %
  210. % --------------------------------------------------------------------------
  211. % -
  212. % -  Interface predicates & related code
  213. % -
  214. % --------------------------------------------------------------------------
  215. %
  216.  
  217.  
  218. P : profile :-
  219.   F = features(P),
  220.   retrieve_profile_features(P, F, Level, LNames),
  221.   private_profile(LNames, Level).
  222.  
  223.  
  224. %
  225. % --------------------------------------------------------------------------
  226. %
  227.  
  228.  
  229. retrieve_profile_features(Term, [level | LFeatures], Level : Term.level, 
  230.                           LNames) :-
  231.   !,
  232.   retrieve_profile_features(Term, LFeatures, Level, LNames).
  233.  
  234.  
  235. retrieve_profile_features(Term, [Feature | LFeatures], Level,
  236.                           [Term.Feature | LNames]) :-
  237.   !,
  238.   retrieve_profile_features(Term, LFeatures, Level, LNames).
  239.  
  240.  
  241. retrieve_profile_features(Term, [], Level, []).
  242.  
  243.  
  244. %
  245. % --------------------------------------------------------------------------
  246. %
  247.  
  248.  
  249. private_profile([], Level) :- !.
  250.  
  251.  
  252. private_profile([Name | LNames], Level) :-
  253.   !,
  254.   (
  255.     private_profile(Name, Level)
  256.   ;
  257.     succeed
  258.   ),
  259.   private_profile(LNames, Level).
  260.  
  261.  
  262.  
  263. private_profile(What, Level) :-
  264.   Level = {call; clause; goal},
  265.   !,
  266.   cond(is_function(What),
  267.     (
  268.       Type = function,
  269.       RW = rewrite_function
  270.     ),
  271.     cond(is_predicate(What),
  272.       (
  273.         Type = predicate,
  274.         RW = rewrite_predicate
  275.       ),
  276.       (
  277.         write_err("*** Profile : ", What, " is not a predicate or a function"),
  278.         nl_err,
  279.         fail
  280.       )
  281.     )
  282.   ),
  283.   dynamic(What),
  284.   retrieve_old_clauses_of(What, Type, OldClauses),
  285.   cond(OldClauses :== [],
  286.     (
  287.       extract_clauses_of(What, Type, Clauses),
  288.       cond(Clauses :== [],
  289.         (
  290.           write_err("*** Profile : ", Type, " '", What, "' has no clauses"), 
  291.           nl_err
  292.         ),
  293.         (
  294.           save_clauses(What, Type, Level, Clauses),
  295.           add_stats_for(What, Clauses, Level),
  296.           RW=@(What, Clauses, Level),
  297.           RW,
  298.           write("Profile : Added profiling code to ", Type, " '", What, "' at ",
  299.                 Level, " level"),
  300.           nl
  301.         )
  302.       )
  303.     ),    
  304.     (
  305.       cond(Level :== profile_old_clauses.What.level,
  306.         (
  307.           write_err("*** Profile : ", Type, " '", What,  
  308.                     "' already modified at this level"),
  309.           nl_err,
  310.           save_clauses(What, Type, Level, OldClauses)
  311.         ),
  312.         (      
  313.           extract_clauses_of(What, Type, ModifiedClauses),
  314.           remove_stats_for(What),
  315.           assert_list(OldClauses),
  316.           private_profile(What, Level)
  317.         )
  318.       )
  319.     )
  320.   ).
  321.  
  322.  
  323. %
  324. % --------------------------------------------------------------------------
  325. %
  326.  
  327.  
  328. U : unprofile :-
  329.   F = features(U),
  330.   cond(F :== [],
  331.     private_unprofile,
  332.     (
  333.       retrieve_name_features(U, F, LNames),
  334.       private_unprofile(LNames)
  335.     )
  336.   ).
  337.   
  338.  
  339. %
  340. % --------------------------------------------------------------------------
  341. %
  342.  
  343.  
  344. retrieve_name_features(Term, [Feature | LFeatures], 
  345.                         [Term.Feature | LNames]) :-
  346.   !,
  347.   retrieve_name_features(Term, LFeatures, LNames).
  348.  
  349.  
  350. retrieve_name_features(@, [], []).
  351.  
  352.  
  353. %
  354. % --------------------------------------------------------------------------
  355. %
  356.  
  357.  
  358. private_unprofile(Top) :-
  359.   Top :== @,
  360.   !,
  361.   ListOfNames = features(profile_old_clauses, current_module),
  362.   private_unprofile(ListOfNames).
  363.  
  364. private_unprofile([]) :- !.
  365.  
  366. private_unprofile([Name | LNames]) :-
  367.   !,
  368.   private_unprofile(Name),
  369.   private_unprofile(LNames).
  370.  
  371. private_unprofile(What) :-
  372.   retrieve_old_clauses_of(What, Type, OldClauses),
  373.   cond(OldClauses :\== [],
  374.     (
  375.       extract_clauses_of(What, Type, ModifiedClauses),
  376.       remove_stats_for(What),
  377.       assert_list(OldClauses),
  378.       write("Profile : restored original clauses for ", Type, " '", What,"'"),
  379.       nl
  380.     )
  381.   ).
  382.  
  383.  
  384. %
  385. % --------------------------------------------------------------------------
  386. %
  387.  
  388.  
  389. extract_clauses_of(What, Type, [Cl | LCl]) :- 
  390.   Cl = sort_of(Type),
  391.   R = root_sort(What),
  392.   Cl.1 = R,
  393.   Cl.2 = @,
  394.   clause(Cl),
  395.   !,
  396.   retract(Cl),
  397.   extract_clauses_of(What, Type, LCl).
  398.  
  399. extract_clauses_of(What, Type, []).
  400.  
  401.  
  402. %
  403. % --------------------------------------------------------------------------
  404. %
  405.  
  406.  
  407. sort_of(function) -> root_sort(->).
  408.  
  409. sort_of(predicate) -> root_sort(:-).
  410.  
  411.  
  412. %
  413. % --------------------------------------------------------------------------
  414. %
  415.  
  416.  
  417. save_clauses(What, Type, Level, Clauses) :-
  418.   profile_old_clauses.What <<- 
  419.     pack_of_clauses(level => Level, type => Type, clauses => Clauses).
  420.  
  421.  
  422. %
  423. % --------------------------------------------------------------------------
  424. %
  425.  
  426.  
  427. retrieve_old_clauses_of(What, Type, Clauses) :-
  428.   (
  429.     has_feature(What,profile_old_clauses, Pack),
  430.     !,
  431.     Type = Pack.type,
  432.     Cl = Pack.clauses,
  433.     Clauses = copy_term(Cl),
  434.     Cl <<- []
  435.   ;
  436.     Clauses = []
  437.   ).
  438.  
  439.  
  440. %
  441. % --------------------------------------------------------------------------
  442. %
  443.  
  444.  
  445. assert_list([C | LC]) :-
  446.   !,
  447.   assert(C),
  448.   assert_list(LC).
  449.  
  450. assert_list([]).
  451.  
  452.  
  453.  
  454. %
  455. % --------------------------------------------------------------------------
  456. % -
  457. % -  Predicates for the display of the profiling statistics
  458. % -
  459. % --------------------------------------------------------------------------
  460. %
  461.  
  462.  
  463.  
  464. W : write_stats :-
  465.   F = features(W),
  466.   retrieve_write_features(W, F, Verbosity, FileName, LNames, false),
  467.   private_write_stats(LNames, Verbosity, FileName).
  468.  
  469.  
  470. %
  471. % --------------------------------------------------------------------------
  472. %
  473.  
  474.  
  475. retrieve_write_features(Term, [verbosity | LFeatures],
  476.                         Verbosity : (Term.verbosity),
  477.                         FileName, LNames, ThereWasAName) :-
  478.   !,
  479.   retrieve_write_features(Term, LFeatures, Verbosity, FileName, LNames,
  480.                           ThereWasAName).
  481.  
  482. retrieve_write_features(Term, [file | LFeatures], Verbosity,
  483.                         FileName : (Term.file), LNames, ThereWasAName) :-
  484.   !,
  485.   retrieve_write_features(Term, LFeatures, Verbosity, FileName, LNames,
  486.                           ThereWasAName).
  487.  
  488. retrieve_write_features(Term, [Feature | LFeatures], Verbosity, FileName,
  489.                         [Term.Feature | LNames]) :-
  490.   !,
  491.   retrieve_write_features(Term, LFeatures, Verbosity, FileName, LNames,
  492.                           true).
  493.  
  494. retrieve_write_features(Term, [], Verbosity, FileName, LNames, 
  495.                         ThereWasAName) :-
  496.   cond(ThereWasAName,
  497.     LNames = []
  498.   ).
  499.  
  500.  
  501. %
  502. % --------------------------------------------------------------------------
  503. %
  504.  
  505.  
  506. private_write_stats(Top, Verbosity, FileName) :-
  507.   Top :== @,
  508.   !,
  509.   private_write_stats(features(profile_stats), Verbosity, FileName).  
  510.  
  511.  
  512. private_write_stats(ListOfNames:list, Verbosity:{normal; verbose}, 
  513.                     FileName:string) :-
  514.   !,
  515.   (
  516.     FileName :\== string,
  517.     !,
  518.     CompleteFileName = strcon(strcon(FileName, "."),
  519.                               extension_for_log_files),
  520.     open_out(CompleteFileName, Stream)
  521.   ;
  522.     succeed
  523.   ),
  524.   separate(ListOfNames, ListOfFunctionsNames, ListOfFunctionsStats,
  525.            ListOfPredicatesNames, ListOfPredicatesStats),
  526.  
  527.   sort_by(tries, ListOfFunctionsNames, ListOfFunctionsStats, 
  528.           ListOfFunctionsNamesSortedByTry, ListOfFunctionsStatsSortedByTry),
  529.  
  530.   sort_by(tries, ListOfPredicatesNames, ListOfPredicatesStats, 
  531.           ListOfPredicatesNamesSortedByTry, ListOfPredicatesStatsSortedByTry),
  532.   nl,
  533.   cond(ListOfPredicatesNamesSortedByTry :\== [],
  534.     (
  535.       write("Profiling statistics for predicates :"), nl,
  536.       write("-----------------------------------"), nl,
  537.       nl,
  538.       cond(Verbosity :== normal,
  539.         (
  540.           display_titles_for(predicates, 1),
  541.           write_stats_list(normal, ListOfPredicatesNamesSortedByTry,
  542.                            ListOfPredicatesStatsSortedByTry), 
  543.           nl,
  544.           display_titles_for(predicates, 1),
  545.           write_clauses_stats_list(tries, ListOfPredicatesNames, 
  546.                                    ListOfPredicatesStats), 
  547.           nl,
  548.           display_titles_for(predicates, 2),
  549.           write_clauses_stats_list(head_unifications, ListOfPredicatesNames, 
  550.                                    ListOfPredicatesStats), 
  551.           nl,
  552.           display_titles_for(predicates, 3),
  553.           write_clauses_stats_list(successes, ListOfPredicatesNames, 
  554.                                    ListOfPredicatesStats), 
  555.           nl
  556.         ),
  557.         (
  558.           write_stats_list(verbose, ListOfPredicatesNamesSortedByTry,
  559.                            ListOfPredicatesStatsSortedByTry), 
  560.           nl,
  561.           nl
  562.         )
  563.       )
  564.     )
  565.   ),
  566.   cond(ListOfFunctionsNamesSortedByTry :\== [],
  567.     (
  568.       write("Profiling statistics for functions :"), nl,
  569.       write("----------------------------------"), nl,
  570.       nl,
  571.       cond(Verbosity :== normal,
  572.         (
  573.           display_titles_for(functions, 1),
  574.           write_stats_list(normal, ListOfFunctionsNamesSortedByTry,
  575.                            ListOfFunctionsStatsSortedByTry), 
  576.           nl,
  577.           display_titles_for(functions, 2),
  578.           write_clauses_stats_list(pattern_matchings, ListOfFunctionsNames, 
  579.                                    ListOfFunctionsStats), 
  580.           nl
  581.         ),
  582.         (
  583.           write_stats_list(verbose, ListOfFunctionsNamesSortedByTry,
  584.                            ListOfFunctionsStatsSortedByTry),
  585.           nl
  586.         )
  587.       )
  588.     )
  589.   ),
  590.   cond(FileName :\== string, 
  591.     close(Stream)
  592.   ).
  593.  
  594.  
  595. private_write_stats(Name, Verbosity, FileName) :-
  596.   private_write_stats([Name], Verbosity, FileName).
  597.  
  598.  
  599. %
  600. % --------------------------------------------------------------------------
  601. %
  602.  
  603.  
  604. separate([Name | LNames], [Name | LFunctionsNames], [Stats | LFunctionsStats], 
  605.          LPredicatesNames, LPredicatesStats) :-
  606.   has_feature(Name, profile_stats, Stats),
  607.   profile_old_clauses.Name.type :== function,
  608.   !,
  609.   separate(LNames, LFunctionsNames, LFunctionsStats, LPredicatesNames, 
  610.            LPredicatesStats).
  611.  
  612. separate([Name | LNames], LFunctionsNames, LFunctionsStats, 
  613.          [Name | LPredicatesNames], [Stats | LPredicatesStats]) :-
  614.   has_feature(Name, profile_stats, Stats),
  615.   profile_old_clauses.Name.type :== predicate,
  616.   !,
  617.   separate(LNames, LFunctionsNames, LFunctionsStats, LPredicatesNames, 
  618.            LPredicatesStats).
  619.  
  620. separate([], [], [], [], []) :- !.
  621.  
  622. separate([Name | LNames], LFunctionsNames, LFunctionsStats, 
  623.          LPredicatesNames, LPredicatesStats) :-
  624.   write_err("*** Profile : '", Name, "' not registered for profiling"),
  625.   nl_err,
  626.   separate(LNames, LFunctionsNames, LFunctionsStats, LPredicatesNames, 
  627.            LPredicatesStats).
  628.  
  629.  
  630. %
  631. % --------------------------------------------------------------------------
  632. %
  633.  
  634.  
  635. sort_by(Criterion, [Name | LNames], [Stats | LStats], SortedNames, 
  636.         SortedStats) :-
  637.   !,
  638.   sort_by(Criterion, LNames, LStats, SortedLNames, SortedLStats),
  639.   insert_by(Criterion, Name, Stats, SortedLNames, SortedNames, SortedLStats,
  640.             SortedStats).
  641.  
  642. sort_by(Criterion, [], [], [], []).
  643.  
  644.  
  645. %
  646. % --------------------------------------------------------------------------
  647. %
  648.  
  649.  
  650. insert_by(Criterion, What, StatsForWhat, [Name | LNames], SortedNames, 
  651.           [Stats | LStats], SortedStats) :-
  652.   !,
  653.   cond(StatsForWhat.Criterion >= Stats.Criterion,
  654.     (
  655.       SortedNames = [What, Name | LNames],
  656.       SortedStats = [StatsForWhat, Stats | LStats]
  657.     ),
  658.     (
  659.       SortedNames = [Name | LNamesWithWhat],
  660.       SortedStats = [Stats | LStatsWithStatsForWhat],
  661.       insert_by(Criterion, What, StatsForWhat, LNames, LNamesWithWhat,
  662.                 LStats, LStatsWithStatsForWhat)
  663.     )
  664.   ).
  665.  
  666. insert_by(Criterion, What, StatsForWhat, [], [What], [], [StatsForWhat]).
  667.  
  668.  
  669. %
  670. % --------------------------------------------------------------------------
  671. %
  672.  
  673.  
  674. write_stats_list(Verbosity, [Name | LNames], [Stats | LStats]) :-
  675.   !,
  676.   cond(Verbosity :== verbose,
  677.     verbose_write_stats_for(Name, Stats),
  678.     write_the_stats_in(Stats, Name)
  679.   ),
  680.   write_stats_list(Verbosity, LNames, LStats).
  681.  
  682. write_stats_list(Verbosity, [], []).
  683.  
  684.  
  685.  
  686. %
  687. % --------------------------------------------------------------------------
  688. % -
  689. % -  Normal display of the profiling statistics
  690. % -
  691. % --------------------------------------------------------------------------
  692. %
  693.  
  694.  
  695.  
  696. write_the_stats_in(Clauses:clauses(tries => Tries,
  697.                           total_failures => TotalFailures,
  698.                           explicit_failures => ExplicitFailures,
  699.                           successes => Successes), 
  700.                           Name) :-
  701.   !,
  702.   format([Tries, @, Successes,
  703.          rate(TotalFailures, Tries), rate(ExplicitFailures, Tries)]),
  704.   write(Name),
  705.   nl.
  706.  
  707.  
  708. write_the_stats_in(Clauses:rules(tries => Tries,
  709.                           total_failures => TotalFailures, 
  710.                           successes => Successes), Name) :-
  711.   format([Tries, @, @, Successes, rate(TotalFailures, Tries)]),
  712.   write(Name),
  713.   nl.
  714.  
  715.  
  716. %
  717. % --------------------------------------------------------------------------
  718. %
  719.  
  720.  
  721. write_clauses_stats_list(Criterion, [Name | LNames], [Stats | LStats]) :-
  722.   !,
  723.   cond(profile_old_clauses.Name.level :\== call,
  724.     (
  725.       generate_clauses_names(Name, L:length(profile_old_clauses.Name.clauses),
  726.                              ClausesNames, 1),
  727.       generate_stats_list(Stats, L, StatsList, 1),
  728.       sort_by(Criterion, ClausesNames, StatsList, SortedNames, SortedStats),
  729.       cond(profile_old_clauses.Name.type :== predicate,
  730.         write_clauses_stats(SortedStats, SortedNames),
  731.         write_rules_stats(SortedStats, SortedNames)
  732.       )
  733.     )
  734.   ),
  735.   write_clauses_stats_list(Criterion, LNames, LStats).
  736.  
  737. write_clauses_stats_list(Criterion, [], []).
  738.  
  739.  
  740. %
  741. % --------------------------------------------------------------------------
  742. %
  743.  
  744.  
  745. generate_clauses_names(Name, NumberOfClauses, [NameOfClause | LNames],
  746.                        ClauseNumber) :-
  747.   ClauseNumber =< NumberOfClauses,
  748.   !,
  749.   NameOfClause = strcon(strcon(psi2str(Name), "#"), int2str(ClauseNumber)),
  750.   generate_clauses_names(Name, NumberOfClauses, LNames, ClauseNumber + 1).
  751.  
  752.  
  753. generate_clauses_names(Name, NumberOfClauses, [], ClauseNumber).
  754.  
  755.  
  756. %
  757. % --------------------------------------------------------------------------
  758. %
  759.  
  760.  
  761. generate_stats_list(StatsForClauses, NumberOfClauses, [Stats | LStats],
  762.                     ClauseNumber) :-
  763.   ClauseNumber =< NumberOfClauses,
  764.   !,  
  765.   Stats = StatsForClauses.ClauseNumber,
  766.   generate_stats_list(StatsForClauses, NumberOfClauses, LStats, 
  767.                       ClauseNumber + 1).
  768.  
  769.  
  770. generate_stats_list(StatsForClauses, NumberOfClauses, [], ClauseNumber).
  771.  
  772.  
  773. %
  774. % --------------------------------------------------------------------------
  775. %
  776.  
  777.  
  778. write_clauses_stats([Stats | LStats], [Name | LNames]) :-
  779.   !,
  780.   format([Stats.tries, Unify:(Stats.head_unifications), 
  781.           Stats.successes, rate(Stats.total_failures, Unify),
  782.           rate(Stats.explicit_failures, Unify)]),
  783.   write(Name), nl,
  784.   write_clauses_stats(LStats, LNames).
  785.  
  786.  
  787. write_clauses_stats([], []).
  788.  
  789.  
  790. %
  791. % --------------------------------------------------------------------------
  792. %
  793.  
  794.  
  795. write_rules_stats([Stats | LStats], [Name | LNames]) :-
  796.   !,
  797.   format([@, PatternMatchings:(Stats.pattern_matchings), 
  798.           rate(Stats.evaluations, PatternMatchings), Stats.successes,
  799.           rate(Stats.total_failures, PatternMatchings)]),
  800.   write(Name), nl,
  801.   write_rules_stats(LStats, LNames).
  802.  
  803.  
  804. write_rules_stats([], []).
  805.  
  806.  
  807. %
  808. % --------------------------------------------------------------------------
  809. %
  810.  
  811.  
  812. display_titles_for(What, ColumnNumber) :-
  813.   TitlesForWhat = cond(What :== functions,
  814.     titles_for_functions,
  815.     titles_for_predicates
  816.   ),
  817.   cond(length(TitlesForWhat) =\= columns_number,
  818.     (
  819.       write_err("*** Profile : ",
  820.                 "Incorrect specifications for titles_for_", psi2str(What)),
  821.       nl_err,
  822.       fail
  823.     )
  824.   ),
  825.   make_quotation(TitlesForWhat, OldTitle, ColumnNumber, 1),
  826.   column_width <<- adjust(max_size_of_names_in(TitlesForWhat)),
  827.   format(TitlesForWhat),
  828.   write(psi2str(What)),
  829.   nl,
  830.   restore_quotation(TitlesForWhat, OldTitle, ColumnNumber, 1).
  831.  
  832.  
  833. %
  834. % --------------------------------------------------------------------------
  835. %
  836.  
  837.  
  838. make_quotation(L:[Title | LTitles], OldTitle, ColumnNumber, ColumnNumber) :-
  839.   !,
  840.   OldTitle = copy_term(Title),
  841.   L.1 <<- strcon("*", strcon(Title, "*")).
  842.  
  843. make_quotation([Title | LTitles], OldTitle, ColumnNumber, CurrentColumn) :-
  844.   make_quotation(LTitles , OldTitle, ColumnNumber, CurrentColumn + 1).
  845.  
  846.  
  847. %
  848. % --------------------------------------------------------------------------
  849. %
  850.  
  851.  
  852. restore_quotation(L:[Title | LTitles], OldTitle, ColumnNumber, ColumnNumber) :-
  853.   !,
  854.   L.1 <<- OldTitle.
  855.  
  856. restore_quotation([Title | LTitles], OldTitle, ColumnNumber, CurrentColumn) :-
  857.   restore_quotation(LTitles , OldTitle, ColumnNumber, CurrentColumn + 1).
  858.  
  859.  
  860. %
  861. % --------------------------------------------------------------------------
  862. %
  863.  
  864.  
  865. max_size_of_names_in([Name]) -> strlen(Name).
  866.  
  867. max_size_of_names_in([Name | LNames]) -> 
  868.   max(strlen(Name), max_size_of_names_in(LNames)).
  869.  
  870.  
  871. %
  872. % --------------------------------------------------------------------------
  873. %
  874.  
  875.  
  876. adjust(0) -> minimal_column_width.
  877.  
  878. adjust(N) -> AdjustedN
  879.   | AdjustedN = cond(N < minimal_column_width,
  880.       minimal_column_width,
  881.       cond(N > maximal_column_width,
  882.         @  | (
  883.                write_err("*** Profile : Column title too long"),
  884.                nl_err,
  885.                fail
  886.         ),
  887.         cond((N - 2 * (N / 2)) =:= 0,
  888.           N + 1,
  889.           N
  890.         )
  891.       )
  892.     ).
  893.  
  894.  
  895.  
  896. %
  897. % --------------------------------------------------------------------------
  898. % -
  899. % -  Verbose display of the profiling statistics
  900. % -
  901. % --------------------------------------------------------------------------
  902. %
  903.  
  904.  
  905. verbose_write_stats_for(Name, Stats) :-
  906.   write("Profile statistics for ", profile_old_clauses.Name.type, 
  907.         " '", Name, "' :"),
  908.   nl,
  909.   small_separation, nl,
  910.   Level = profile_old_clauses.Name.level,
  911.   verbose_write_the_stats_in(Stats, Level),
  912.   nl,
  913.   big_separation,
  914.   nl,
  915.   nl.
  916.  
  917.  
  918. %
  919. % --------------------------------------------------------------------------
  920. %
  921.  
  922.  
  923. verbose_write_the_stats_in(Clauses:clauses(tries => Tries, 
  924.                            total_failures => TotalFailures,
  925.                            explicit_failures => ExplicitFailures,
  926.                            successes => Successes),
  927.                            Level) :-
  928.   !,
  929.   write("+ Number of tries : ", Tries), nl,
  930.   write("+ Number of explicit failures : ", ExplicitFailures), nl,
  931.   write("+ Total number of failures : ", TotalFailures), nl, 
  932.   write("+ Number of successes : ", Successes), nl,
  933.   write("+ Success rate : ", rate(Successes, Tries), " %"), nl,
  934.   nl,
  935.   cond(Level :\== call,
  936.     verbose_write_stats_for_clauses(Clauses, 1, Level)).
  937.  
  938.  
  939. verbose_write_the_stats_in(Rules:rules(tries => Tries,
  940.                            total_failures => TotalFailures,
  941.                            successes => Successes), Level) :-
  942.   write("+ Number of tries : ", Tries), nl, 
  943.   write("+ Number of failures : ", TotalFailures), nl, 
  944.   write("+ Number of successes : ", Successes), nl,
  945.   write("+ Success rate : ", rate(Successes, Tries), " %"), nl,
  946.   nl,
  947.   cond(Level :\== call,
  948.     verbose_write_stats_for_clauses(Rules, 1, Level)).
  949.   
  950.  
  951. %
  952. % --------------------------------------------------------------------------
  953. %
  954.  
  955.  
  956. verbose_write_stats_for_clauses(Clauses, ClauseNumber, Level) :-
  957.   root_sort(Clauses) :== clauses,
  958.   !,
  959.   write("CLAUSE #", ClauseNumber, " :"), nl,
  960.   small_separation, nl,
  961.   Clause = Clauses.ClauseNumber,
  962.   write("+ Number of tries : ", Clause.tries), nl,
  963.   write("+ Number of explicit failures : ", Clause.explicit_failures), nl,
  964.   write("+ Total number of failures : ", Clause.total_failures), nl, 
  965.   write("+ Number of head unifications : ", Unify:(Clause.head_unifications)), nl,
  966.   write("+ Number of successes : ", Successes:(Clause.successes)), nl,
  967.   write("+ Success rate : ", rate(Successes, Unify), " %"), nl,
  968.   cond(Level :== goal,
  969.     (
  970.       Goals = Clause.goals,
  971.       nl,
  972.       write("Statistics for the goals :"), nl,
  973.       small_separation, nl,
  974.       verbose_write_stats_for_goals(Goals, 1, 1),
  975.       nl
  976.     )
  977.   ),
  978.   nl,
  979.   cond(has_feature(ClauseNumber + 1, Clauses),
  980.     verbose_write_stats_for_clauses(Clauses, ClauseNumber + 1, Level)
  981.   ).
  982.  
  983.  
  984. verbose_write_stats_for_clauses(Rules, RuleNumber, Level) :-
  985.   root_sort(Rules) :== rules,
  986.   !,
  987.   write("RULE #", RuleNumber, " :"), nl,
  988.   small_separation, nl,
  989.   Rule = Rules.RuleNumber,  
  990.   write("+ Number of pattern matchings : ", PatternMatchings:(Rule.pattern_matchings)), nl,
  991.   write("+ Number of failures : ", Rule.total_failures), nl,
  992.   write("+ Number of successful evaluations : ", Rule.evaluations), nl,
  993.   write("+ Number of successes : ", Successes:(Rule.successes)), nl,
  994.   write("+ Success rate : ", rate(Successes, PatternMatchings), " %"), nl,
  995.   (  
  996.     Level :== goal,
  997.     has_feature(body, Rule, Body),
  998.     !,
  999.     nl,
  1000.     write("Statistics for the body :"), nl,
  1001.     small_separation, nl,
  1002.     write("+ Number of tries : ", BodyTries:(Body.tries)), nl,
  1003.     write("+ Number of successes : ", BodySuccesses:(Body.successes)), nl,
  1004.     write("+ Number of failures : ", Body.total_failures), nl,
  1005.     write("+ Success rate : ", rate(BodySuccesses, BodyTries), "%"), nl,
  1006.     nl,   
  1007.     verbose_write_stats_for_goals(Body, 1, 1)
  1008.   ;
  1009.     succeed
  1010.   ),
  1011.   nl,
  1012.   cond(has_feature(RuleNumber + 1, Rules),
  1013.     verbose_write_stats_for_clauses(Rules, RuleNumber + 1, Level)
  1014.   ).  
  1015.  
  1016.  
  1017. %
  1018. % --------------------------------------------------------------------------
  1019. %
  1020.  
  1021.  
  1022. verbose_write_stats_for_goals(Goals, GoalNumber, Indentation) :-
  1023.   indent(Indentation),
  1024.   Goal = Goals.GoalNumber,
  1025.   verbose_write_stats_for_the_goal(Goal, GoalNumber, Indentation),
  1026.   cond(has_feature(GoalNumber + 1, Goals),
  1027.     verbose_write_stats_for_goals(Goals, GoalNumber + 1, Indentation)).
  1028.  
  1029.  
  1030. %
  1031. % --------------------------------------------------------------------------
  1032. %
  1033.  
  1034.  
  1035. verbose_write_stats_for_the_goal(call(tries => Tries, successes => Successes),
  1036.                          GoalNumber, Indentation) :-
  1037.   !,
  1038.   write("G#", GoalNumber, " <CALL> ", 
  1039.         "Tries: ", Tries, ", Successes: ", Successes), nl.
  1040.  
  1041.  
  1042. verbose_write_stats_for_the_goal(disjunction(tries => Tries, successes => Successes,
  1043.                                  1 => First, 2 => Second),
  1044.                                  GoalNumber, Indentation) :-
  1045.   !,
  1046.   write("G#", GoalNumber, " <DISJUNCTION> " ,
  1047.         "Tries: ", Tries, ", Successes: ", Successes), nl,
  1048.   indent(Indentation),
  1049.   write("<FIRST TERM> "), 
  1050.   write("Tries: ", First.tries, ", Successes: ", First.successes),
  1051.   nl,
  1052.   verbose_write_stats_for_goals(First, 1, Indentation + 1),
  1053.   indent(Indentation),
  1054.   write("<SECOND TERM> "), 
  1055.   write("Tries: ", Second.tries, ", Successes: ", Second.successes),
  1056.   nl,
  1057.   verbose_write_stats_for_goals(Second, 1, Indentation + 1).
  1058.  
  1059.  
  1060. verbose_write_stats_for_the_goal(C:condition(tries => Tries, successes => Successes),
  1061.                          GoalNumber, Indentation) :-
  1062.   !,
  1063.   write("G#", GoalNumber, " <CONDITION> " ,
  1064.         "Tries: ", Tries, ", Successes: ", Successes), nl,
  1065.   cond(has_feature(true, C, True),
  1066.     (
  1067.       indent(Indentation),
  1068.       write("<CONDITION SATISFIED> "), 
  1069.       write("Tries: ", True.tries, ", Successes: ", True.successes),
  1070.       nl,
  1071.       verbose_write_stats_for_goals(True, 1, Indentation + 1)
  1072.     )
  1073.   ),
  1074.   cond(has_feature(false, C, False),
  1075.     (
  1076.       indent(Indentation),
  1077.       write("<CONDITION NOT SATISFIED> "), 
  1078.       write("Tries: ", False.tries, ", Successes: ", False.successes),
  1079.       nl,
  1080.       verbose_write_stats_for_goals(False, 1, Indentation + 1)
  1081.     )
  1082.   ).
  1083.  
  1084.  
  1085. verbose_write_stats_for_the_goal(cut(tries => Tries), GoalNumber, Indentation) :- 
  1086.   write("G#", GoalNumber, " <CUT> Tries: ", Tries),
  1087.   nl. 
  1088.  
  1089.  
  1090.  
  1091. %
  1092. % --------------------------------------------------------------------------
  1093. % -
  1094. % -  Miscellaneous predicates used for the display of the profiling 
  1095. % -  statistics
  1096. % -
  1097. % --------------------------------------------------------------------------
  1098. %
  1099.  
  1100.  
  1101. rate(Value, Tries) -> Result
  1102.   | Result = cond(Tries =\= 0,
  1103.       ((Value / Tries) * 100),
  1104.       no_value
  1105.     ).
  1106.  
  1107.  
  1108. %
  1109. % --------------------------------------------------------------------------
  1110. %
  1111.  
  1112.  
  1113. format([What | LThings]) :-
  1114.   !,
  1115.   DisplayValueOfWhat = cond(What :== @,
  1116.     no_value,
  1117.     What
  1118.   ),
  1119.   write_centered(DisplayValueOfWhat),
  1120.   format(LThings).
  1121.  
  1122. format([]) :-
  1123.   write_space(2).
  1124.  
  1125.  
  1126. %
  1127. % --------------------------------------------------------------------------
  1128. %
  1129.  
  1130.  
  1131. write_centered(String:string) :-
  1132.   !,
  1133.   Length = strlen(String),
  1134.   NumberOfSpaces = floor(Difference:((column_width - Length) / 2)),
  1135.   write_space(NumberOfSpaces),
  1136.   write(String), 
  1137.   write_space(NumberOfSpaces),
  1138.   cond((Difference - NumberOfSpaces) =\= 0,
  1139.     write(" ")
  1140.   ).
  1141.  
  1142. write_centered(N:int) :- 
  1143.   !,
  1144.   Difference = (column_width - 1) / 2,
  1145.   StringOfN = int2str(N),
  1146.   write_space(Difference - strlen(StringOfN) + 1),
  1147.   write(StringOfN),
  1148.   write_space(Difference).
  1149.  
  1150. write_centered(X:real) :-
  1151.   IntOfX = int2str(Int:floor(X)),
  1152.   FractOfX = int2str(Fract:floor((X - Int) * 100)),
  1153.   cond(Fract =:= 0,
  1154.     write_centered(Int),
  1155.     (
  1156.       Difference = (column_width - 1) / 2,
  1157.       write_space(Difference - strlen(IntOfX)),
  1158.       write(IntOfX),
  1159.       write("."),
  1160.       write(FractOfX),
  1161.       write_space(Difference - strlen(FractOfX))
  1162.     )
  1163.   ).
  1164.  
  1165.  
  1166. %
  1167. % --------------------------------------------------------------------------
  1168. %
  1169.  
  1170.  
  1171. iter_string(S, 0) :- !.
  1172.  
  1173. iter_string(S, N) :-
  1174.   StringStorageForS = string_storage.S,
  1175.   (
  1176.     has_feature(N, StringStorageForS, NStrings),
  1177.     !,
  1178.     write(NStrings)
  1179.   ;
  1180.     StringStorageForS.N = Str:(get_mult_string(N, S)),
  1181.     write(Str)
  1182.   ).
  1183.  
  1184. get_mult_string(0, S) -> "".
  1185.  
  1186. get_mult_string(N, S) -> strcon(S, get_mult_string(N - 1, S)).
  1187.  
  1188.  
  1189. %
  1190. % --------------------------------------------------------------------------
  1191. %
  1192.  
  1193. write_space(N) :- iter_string(" ", N).
  1194.  
  1195. indent(N) :- iter_string("| ", N).
  1196.  
  1197.  
  1198.  
  1199. %
  1200. % --------------------------------------------------------------------------
  1201. % -
  1202. % -  Initialization and clearing of the profiling statistics
  1203. % -
  1204. % --------------------------------------------------------------------------
  1205. %
  1206.  
  1207.  
  1208. C : clear_stats :-
  1209.   F = features(C),
  1210.   cond(F :== [],
  1211.     private_clear_stats,
  1212.     (
  1213.       retrieve_name_features(C, F, LNames),
  1214.       private_clear_stats(LNames)
  1215.     )
  1216.   ).
  1217.  
  1218.  
  1219. %
  1220. % --------------------------------------------------------------------------
  1221. %
  1222.  
  1223.  
  1224. private_clear_stats(Top) :-
  1225.   Top :== @,
  1226.   !,
  1227.   Names = features(profile_stats),
  1228.   clear_stats_for_list_of(Names).
  1229.  
  1230. private_clear_stats([Name | LNames]) :-
  1231.   !,
  1232.   private_clear_stats(Name),
  1233.   private_clear_stats(LNames).
  1234.  
  1235. private_clear_stats([]) :- !.
  1236.  
  1237. private_clear_stats(What) :-
  1238.   has_feature(What, profile_stats, Stats),
  1239.   !,
  1240.   cond(Stats :\== @,
  1241.     (
  1242.       Store = profile_old_clauses.What,
  1243.       cond(profile_old_clauses.What.type :== predicate,
  1244.         Stats.explicit_failures <<- 0
  1245.       ),
  1246.       Stats.tries <<- 0,
  1247.       Stats.successes <<- 0,
  1248.       Stats.total_failures <<- 0,
  1249.       cond(Level:(profile_old_clauses.What.level) :\== call,
  1250.         (
  1251.           Clauses = Store.clauses,
  1252.           empty_references_of_clauses(Stats, Clauses, Level, 1)
  1253.         )
  1254.       )
  1255.     )
  1256.   ).
  1257.  
  1258. private_clear_stats(What) :-
  1259.   write_err("*** Profile : '", What, "' not registered for profiling"),
  1260.   nl_err.
  1261.  
  1262.  
  1263. %
  1264. % --------------------------------------------------------------------------
  1265. %
  1266.  
  1267.  
  1268. clear_stats_for_list_of([Name | LNames]) :-
  1269.   !,
  1270.   clear_stats(Name),
  1271.   clear_stats_for_list_of(LNames).
  1272.  
  1273. clear_stats_for_list_of([]).
  1274.  
  1275.  
  1276. %
  1277. % --------------------------------------------------------------------------
  1278. %
  1279.     
  1280.  
  1281. remove_stats_for(What) :-
  1282.   AllNames = features(profile_stats, current_module),
  1283.   NewStats = data,
  1284.   copy_stats_and_remove(AllNames, What, NewStats),
  1285.   profile_stats <<- NewStats.
  1286.  
  1287.  
  1288. %
  1289. % --------------------------------------------------------------------------
  1290. %
  1291.  
  1292.  
  1293. copy_stats_and_remove([Name | LNames], What, NewStats) :-
  1294.   Name :== What,
  1295.   !,
  1296.   copy_stats_and_remove(LNames, What, NewStats).
  1297.  
  1298. copy_stats_and_remove([Name | LNames], What, NewStats) :-
  1299.   !,
  1300.   NewStats.Name = profile_stats.Name,
  1301.   copy_stats_and_remove(LNames, What, NewStats).
  1302.  
  1303. copy_stats_and_remove([], What).
  1304.  
  1305.  
  1306. %
  1307. % --------------------------------------------------------------------------
  1308. %
  1309.  
  1310.  
  1311. add_stats_for(What, Clauses, Level) :-
  1312.   Stats = @(successes => 0, tries => 0, total_failures => 0),
  1313.   cond(profile_old_clauses.What.type :== function,
  1314.     NameOfStats = rules,
  1315.     (
  1316.       NameOfStats = clauses,
  1317.       Stats.tries <<- 0,
  1318.       Stats.explicit_failures <<- 0
  1319.     )
  1320.   ),
  1321.   StatsForWhat:(profile_stats.What) <<- (Stats & NameOfStats),
  1322.   cond(Level :\== call,
  1323.     empty_references_of_clauses(StatsForWhat, Clauses, Level, 1)).
  1324.  
  1325.  
  1326. %
  1327. % --------------------------------------------------------------------------
  1328. %
  1329.  
  1330.  
  1331. empty_references_of_clauses(Stats, [Cl | LCl], Level, ClauseNumber) :-
  1332.   !,
  1333.   StatsForClause = Stats.ClauseNumber,
  1334.   StatsForClause <<- stats(successes => 0, total_failures => 0),
  1335.   cond(root_sort(Stats) :== rules,
  1336.     (
  1337.       StatsForClause.pattern_matchings <<- 0,
  1338.       StatsForClause.evaluations <<- 0
  1339.     ),
  1340.     (
  1341.       StatsForClause.head_unifications <<- 0,
  1342.       StatsForClause.tries <<- 0,
  1343.       StatsForClause.explicit_failures <<- 0
  1344.     )
  1345.   ),
  1346.   cond(Level :== goal,
  1347.     empty_goals_for(StatsForClause, Cl)),
  1348.   empty_references_of_clauses(Stats, LCl, Level, ClauseNumber + 1).
  1349.  
  1350. empty_references_of_clauses(StatsForClauses, [], Level, ClauseNumber).
  1351.  
  1352.  
  1353. %
  1354. % --------------------------------------------------------------------------
  1355. %
  1356.  
  1357.  
  1358. non_strict(empty_goals_for)?
  1359.  
  1360.  
  1361. empty_goals_for(StatsForClause, (Head :- Body)) :-
  1362.   !,
  1363.   StatsForGoals = StatsForClause.goals,
  1364.   StatsForGoals <<- sequence,
  1365.   empty_goals(StatsForGoals, Body, 1, NumberOfGoals).
  1366.  
  1367.  
  1368. empty_goals_for(StatsForRule, (Pattern -> Result)) :-
  1369.   (
  1370.     Result :== `(|),
  1371.     !,
  1372.     Body = Result.2,
  1373.     StatsForGoals = StatsForRule.body,
  1374.     StatsForGoals <<- 
  1375.       sequence(tries => 0, successes => 0, total_failures => 0),
  1376.     empty_goals(StatsForGoals, Body, 1, NumberOfGoals)
  1377.   ;
  1378.     succeed
  1379.   ).
  1380.  
  1381.  
  1382. non_strict(empty_goals)?
  1383.  
  1384.  
  1385. empty_goals(StatsForGoals, Top, GoalNumber, GoalNumber) :-
  1386.   Top :== @,
  1387.   !.
  1388.  
  1389.  
  1390. empty_goals(StatsForGoals, (A, B), GoalNumber, NewGoalNumber) :-
  1391.   !,
  1392.   empty_goals(StatsForGoals, A, GoalNumber, NumberOfGoalsOfA),
  1393.   GoalNumberAfterA = NumberOfGoalsOfA + 1,
  1394.   empty_goals(StatsForGoals, B, GoalNumberAfterA, NewGoalNumber).
  1395.  
  1396.  
  1397. empty_goals(StatsForGoals, (A ; B), GoalNumber, GoalNumber) :-
  1398.   !,
  1399.   FirstTerm <<- sequence(tries => 0, successes => 0),
  1400.   SecondTerm <<- sequence(tries => 0, successes => 0),
  1401.   empty_goals(FirstTerm, A, 1, NumberOfGoalsOfA),
  1402.   empty_goals(SecondTerm, B, 1, NumberOfGoalsOfB),
  1403.   Disjunction = StatsForGoals.GoalNumber,
  1404.   Disjunction <<-
  1405.     disjunction(tries => 0, successes => 0,
  1406.                 1 => FirstTerm, 2 => SecondTerm).
  1407.  
  1408.  
  1409. empty_goals(StatsForGoals, C:cond(Test), GoalNumber, GoalNumber) :-
  1410.   !,
  1411.   Cond = StatsForGoals.GoalNumber,
  1412.   Cond <<- condition(tries => 0, successes => 0),
  1413.   cond(has_feature(2, C, TermWhenTrue),
  1414.     (
  1415.       True = Cond.true,
  1416.       True <<- sequence(tries => 0, successes => 0),
  1417.       empty_goals(True, TermWhenTrue, 1, NumberOfGoalsWhenTrue)
  1418.     )
  1419.   ),
  1420.   cond(has_feature(3, C, TermWhenFalse),
  1421.     (
  1422.       False = Cond.false,
  1423.       False <<- sequence(tries => 0, successes => 0),
  1424.       empty_goals(False, TermWhenFalse, 1, NumberOfGoalsWhenFalse)
  1425.     )
  1426.   ).
  1427.  
  1428.  
  1429. empty_goals(StatsForGoals, !, GoalNumber, GoalNumber) :- 
  1430.   !,
  1431.   StatsForGoals.GoalNumber <<- cut(tries => 0).
  1432.  
  1433.  
  1434. empty_goals(StatsForGoals, A, GoalNumber, GoalNumber) :-
  1435.   !,
  1436.   StatsForGoals.GoalNumber <<- call(tries => 0, successes => 0).
  1437.  
  1438.  
  1439.  
  1440. %
  1441. % --------------------------------------------------------------------------
  1442. % -
  1443. % -  Rewriting rules for predicates
  1444. % -
  1445. % --------------------------------------------------------------------------
  1446. %
  1447.  
  1448.  
  1449.  
  1450. rewrite_predicate(Predicate, Clauses, Level) :-
  1451.   TryBody = ( 
  1452.     T:`(profile_stats.Predicate.tries) <<- `(+) & @(T, 1),
  1453.     fail
  1454.   ),
  1455.   assert(Predicate :- TryBody),
  1456.   rewrite_clauses(Predicate, Clauses, Level, 1),
  1457.   !,
  1458.   CondForFailure = `cond(profile_backtracking :== false),
  1459.   CondForFailure.2 = (
  1460.     EF1:(StatsForPred.explicit_failures) <<- `(+) & @(EF1, 1)
  1461.   ),
  1462.   CondForFailure.3 = CondForFailOccurence & `cond(profile_fail_occured),
  1463.   CondForFailOccurence.2 = (
  1464.     EF2:(StatsForPred.explicit_failures) <<- `(+) & @(EF2, 1)
  1465.   ),
  1466.   BodyFail = (
  1467.     StatsForPred = `(profile_stats.Predicate),
  1468.     CondForFailure,
  1469.     TF:(StatsForPred.total_failures) <<- `(+) & @(TF, 1),
  1470.     `profile_backtracking <<- false,
  1471.     `profile_fail_occured <<- false,
  1472.     fail
  1473.   ),
  1474.   assert(Predicate :- BodyFail).
  1475.  
  1476. rewrite_predicate(Predicate, Clauses, Level) :-
  1477.   write_err("*** Profile : Unable to add profiling code for predicate ", 
  1478.             Predicate, ": program corrupted"),
  1479.   nl_err,
  1480.   fail.
  1481.  
  1482.  
  1483. %
  1484. % --------------------------------------------------------------------------
  1485. %
  1486.  
  1487.  
  1488. non_strict(clean_body)?
  1489.  
  1490.  
  1491. clean_body((succeed, B), CleanedB) :-
  1492.   !,
  1493.   clean_body(B, CleanedB).
  1494.  
  1495. clean_body((A, succeed), CleanedA) :-
  1496.   !,
  1497.   clean_body(A, CleanedA).
  1498.  
  1499. clean_body((A, B), (CleanedA, CleanedB)) :-
  1500.   !,
  1501.   clean_body(A, CleanedA),
  1502.   clean_body(B, CleanedB).
  1503.  
  1504. clean_body((A ; B), (CleanedA ; CleanedB)) :-
  1505.   !,
  1506.   clean_body(A, CleanedA),
  1507.   clean_body(B, CleanedB).
  1508.  
  1509. clean_body(cond(Test, Term), cond(Test, CleanedTerm)) :-
  1510.   !,
  1511.   clean_body(Term, CleanedTerm).
  1512.  
  1513. clean_body(cond(Test, Term1, Term2), cond(Test, CleanedTerm1, CleanedTerm2)) :-
  1514.   !,
  1515.   clean_body(Term1, CleanedTerm1),
  1516.   clean_body(Term2, CleanedTerm2).
  1517.  
  1518. clean_body(A, A).
  1519.  
  1520.  
  1521. %
  1522. % --------------------------------------------------------------------------
  1523. %
  1524.  
  1525.  
  1526. rewrite_clauses(Predicate, [(Head :- Body) | LCl], Level, ClauseNumber) :-
  1527.   !,
  1528.   TryBody = (
  1529.     T:`(profile_stats.Predicate.ClauseNumber.tries) <<- `(+) & @(T, 1),
  1530.     fail      
  1531.   ),
  1532.   cond(Level :\== call,
  1533.     assert(Predicate :- TryBody)
  1534.   ),
  1535.   Stats = cond(Level :== goal,
  1536.     StatsForClause.goals
  1537.   ),
  1538.   rewrite_body(Predicate, Body, RewrittenBody, Stats,
  1539.                Backtrack, Fail, Level, ClauseNumber, 1),
  1540.   HeadUnify = cond(Level :\== call,
  1541.     (
  1542.       StatsForClause = StatsForPredicate.ClauseNumber,
  1543.       HU:(StatsForClause.head_unifications) <<- `(+) & @(HU, 1)
  1544.     ),
  1545.     succeed
  1546.   ),
  1547.   cond(Level :\== call,
  1548.     (
  1549.       CondForFailure = `cond(Backtrack :== false),
  1550.       CondForFailure.2 = (
  1551.         EF1:(StatsForClause.explicit_failures) <<- `(+) & @(EF1, 1)
  1552.       ),   
  1553.       CondForFailure.3 = CondForFailOccurence & `cond(Fail),
  1554.       CondForFailOccurence.2 = (
  1555.         EF2:(StatsForClause.explicit_failures) <<- `(+) & @(EF2, 1)
  1556.       ),
  1557.       Failure = (
  1558.         succeed
  1559.       ;
  1560.         CondForFailure,
  1561.         TF:(StatsForClause.total_failures) <<- `(+) & @(TF, 1),
  1562.         `profile_backtracking <<- Backtrack,
  1563.         `profile_fail_occured <<- Fail,
  1564.         fail
  1565.       )
  1566.     ),
  1567.     Failure = (
  1568.       succeed
  1569.     ;
  1570.       `profile_backtracking <<- Backtrack,
  1571.       `profile_fail_occured <<- Fail,
  1572.        fail
  1573.     )
  1574.   ),
  1575.   Success =
  1576.     cond(Level :\== call,
  1577.       (
  1578.         CS:(StatsForClause.successes) <<- `(+) & @(CS, 1)
  1579.       ),
  1580.       succeed
  1581.   ),
  1582.   ModifiedBody = (
  1583.     StatsForPredicate = `(profile_stats.Predicate),
  1584.     Fail <<- false,
  1585.     Backtrack <<- false,
  1586.     HeadUnify,
  1587.     Failure,
  1588.     RewrittenBody,
  1589.     (
  1590.       Success,
  1591.       PS:(StatsForPredicate.successes) <<- `(+) & @(PS, 1),
  1592.       `profile_backtracking <<- false,
  1593.       `profile_fail_occured <<- false
  1594.     ;
  1595.       Backtrack <<- true,
  1596.       fail
  1597.     )
  1598.   ),
  1599.   clean_body(ModifiedBody, CleanedModifiedBody),
  1600.   assert(Head :- CleanedModifiedBody),
  1601.   rewrite_clauses(Predicate, LCl, Level, ClauseNumber + 1).           
  1602.  
  1603. rewrite_clauses(Pred, [], Level, ClauseNumber).         
  1604.  
  1605.  
  1606. %
  1607. % --------------------------------------------------------------------------
  1608. %
  1609.  
  1610.  
  1611. non_strict(rewrite_body)?
  1612.  
  1613.  
  1614. rewrite_body(Predicate, Top, Top, Stats, Backtrack, Fail, Level, ClauseNumber, 
  1615.              GoalNumber, GoalNumber) :-
  1616.   Top :== @,
  1617.   !.
  1618.  
  1619.  
  1620. rewrite_body(Predicate, (A, B), (NewA, NewB), Stats, Backtrack, Fail, Level, 
  1621.              ClauseNumber, GoalNumber, NewGoalNumber) :-
  1622.   !,
  1623.   rewrite_body(Predicate, A, NewA, Stats, Backtrack, Fail, Level, 
  1624.                ClauseNumber, GoalNumber, NumberOfGoalsOfA),
  1625.   GoalsAfterA = NumberOfGoalsOfA + 1,
  1626.   rewrite_body(Predicate, B, NewB, Stats, Backtrack, Fail, Level, 
  1627.                ClauseNumber, GoalsAfterA, NewGoalNumber).
  1628.  
  1629.  
  1630. rewrite_body(Predicate, (A ; B), NewDisjunction, Stats, Backtrack, Fail, goal, 
  1631.              ClauseNumber, GoalNumber, GoalNumber) :-
  1632.   !,
  1633.   rewrite_body(Predicate, A, NewA, Disjunction1, Backtrack, Fail, goal, 
  1634.                ClauseNumber, 1, ANumber),
  1635.   rewrite_body(Predicate, B, NewB, Disjunction2, Backtrack, Fail, goal, 
  1636.                ClauseNumber, 1, BNumber),
  1637.   NewDisjunction = (
  1638.     DisjunctionStats = Stats.GoalNumber,
  1639.     Disjunction1 = DisjunctionStats.1,
  1640.     Disjunction2 = DisjunctionStats.2,
  1641.     (
  1642.       TA:(DisjunctionStats.tries) <<- `(+) & @(TA, 1),
  1643.       T1:(Disjunction1.tries) <<- `(+) & @(T1, 1),
  1644.       NewA,
  1645.       SA:(DisjunctionStats.successes) <<- `(+) & @(SA, 1),
  1646.       S1:(Disjunction1.successes) <<- `(+) & @(S1, 1)
  1647.     ;
  1648.       T2:(Disjunction2.tries) <<- `(+) & @(T2, 1),
  1649.       NewB,
  1650.       SB:(DisjunctionStats.successes) <<- `(+) & @(SB, 1),
  1651.       S2:(Disjunction2.successes) <<- `(+) & @(S2, 1)
  1652.     )
  1653.   ).
  1654.  
  1655.  
  1656. rewrite_body(Predicate, C:cond(Test), NewCond, Stats, Backtrack, Fail, goal, 
  1657.              ClauseNumber, GoalNumber, GoalNumber) :-
  1658.   !,
  1659.   RewrittenCond = `cond(Test),
  1660.   cond(has_feature(2, C, TermWhenTrue),
  1661.     (
  1662.       rewrite_body(Predicate, TermWhenTrue, RewrittenTermWhenTrue, 
  1663.                    StatsForTrue, Backtrack, Fail, goal,
  1664.                    ClauseNumber, 1, NumberOfGoalsWhenTrue),
  1665.       RewrittenCond.2 = (
  1666.         StatsForTrue = CondStats.true,
  1667.         TT:(StatsForTrue.tries) <<- `(+) & @(TT, 1),
  1668.         RewrittenTermWhenTrue,
  1669.         ST:(StatsForTrue.successes) <<- `(+) & @(ST, 1)
  1670.       )
  1671.     )
  1672.   ),
  1673.   cond(has_feature(3, C, TermWhenFalse),
  1674.     (
  1675.       rewrite_body(Predicate, TermWhenFalse, RewrittenTermWhenFalse, 
  1676.                    StatsForFalse, Backtrack, Fail, goal,
  1677.                    ClauseNumber, 1, NumberOfGoalsWhenFalse),
  1678.       RewrittenCond.3 = (
  1679.         StatsForFalse = CondStats.false,
  1680.         TF:(StatsForFalse.tries) <<- `(+) & @(TF, 1),
  1681.         RewrittenTermWhenFalse,
  1682.         SF:(StatsForFalse.successes) <<- `(+) & @(SF, 1)
  1683.       )
  1684.     )
  1685.   ),
  1686.   NewCond = (
  1687.     CondStats = Stats.GoalNumber,
  1688.     TC:(CondStats.tries) <<- `(+) & @(TC, 1),
  1689.     RewrittenCond,
  1690.     SC:(CondStats.successes) <<- `(+) & @(SC, 1)
  1691.   ).
  1692.  
  1693.  
  1694. rewrite_body(What, !, NewCut, Stats, Backtrack, Fail, call, ClauseNumber, 
  1695.              GoalNumber, GoalNumber) :-
  1696.   !,
  1697.   cond(profile_old_clauses.What.type :== predicate,
  1698.     (
  1699.       CondForFailure = `cond(Backtrack :== false),
  1700.       CondForFailure.2 = (
  1701.         EF1:(StatsForWhat.explicit_failures) <<- `(+) & @(EF1, 1)
  1702.       ),
  1703.       CondForFailure.3 = CondForFailOccurence & `cond(Fail),
  1704.       CondForFailOccurence.2 = (
  1705.         EF2:(StatsForWhat.explicit_failures) <<- `(+) & @(EF2, 1)
  1706.       ),
  1707.       FailOnBacktrack = (
  1708.         CondForFailure,
  1709.         `profile_backtracking <<- false,
  1710.         `profile_fail_occured <<- false
  1711.       )
  1712.     ),
  1713.     FailOnBacktrack = succeed
  1714.   ),   
  1715.   NewCut = (
  1716.     !,
  1717.     StatsForWhat = `(profile_stats.What),
  1718.     (
  1719.       succeed
  1720.     ;
  1721.       FailOnBacktrack,
  1722.       TF:(StatsForWhat.total_failures) <<- `(+) & @(TF, 1),
  1723.       fail
  1724.     )
  1725.   ).
  1726.  
  1727.  
  1728. rewrite_body(What, !, NewCut, Stats, Backtrack, Fail, Level, ClauseNumber,
  1729.              GoalNumber, GoalNumber) :-
  1730.   !,
  1731.   (
  1732.     profile_old_clauses.What.type :== function,
  1733.     !,
  1734.     BodyFail = cond(Level :== goal,
  1735.       (BF:(StatsForRule.body.total_failures) <<- `(+) & @(BF, 1)),
  1736.       succeed
  1737.     ),
  1738.     RewrittenCut = ( 
  1739.       !,
  1740.       StatsForFunction = `(profile_stats.`What),
  1741.       StatsForRule = StatsForFunction.ClauseNumber,
  1742.       (
  1743.         succeed
  1744.       ;
  1745.         RTF:(StatsForRule.total_failures) <<- `(+) & @(RTF, 1),
  1746.         FTF:(StatsForFunction.total_failures) <<- `(+) & @(FTF, 1),
  1747.         BodyFail,
  1748.         fail
  1749.       )
  1750.     )
  1751.   ;
  1752.     CondForFailure = `cond(Backtrack :== false),
  1753.     CondForFailure.2 = (
  1754.       CEF1:(StatsForClause.explicit_failures) <<- `(+) & @(CEF1, 1),
  1755.       PEF1:(StatsForWhat.explicit_failures) <<- `(+) & @(PEF1, 1)
  1756.     ),
  1757.     CondForFailure.3 = CondForFailOccurence & `cond(Fail),
  1758.     CondForFailOccurence.2 = (
  1759.       CEF2:(StatsForClause.explicit_failures) <<- `(+) & @(CEF2, 1),
  1760.       PEF2:(StatsForWhat.explicit_failures) <<- `(+) & @(PEF2, 1)    
  1761.     ),
  1762.     RewrittenCut = (   
  1763.       !,
  1764.       StatsForWhat = `(profile_stats.What),
  1765.       StatsForClause = StatsForWhat.ClauseNumber,
  1766.       (
  1767.         succeed
  1768.       ;
  1769.         CondForFailure,
  1770.         CTF:(StatsForClause.total_failures) <<- `(+) & @(CTF, 1),
  1771.         CPF:(StatsForWhat.total_failures) <<- `(+) & @(CPF, 1),
  1772.         `profile_backtracking <<- false,
  1773.         `profile_fail_occured <<- false,
  1774.         fail
  1775.       )
  1776.     )
  1777.   ),
  1778.   NewCut = cond(Level :== goal,
  1779.     (
  1780.       GT:(Stats.GoalNumber.tries) <<- `(+) & @(GT, 1),
  1781.       RewrittenCut
  1782.     ),
  1783.     RewrittenCut
  1784.   ).
  1785.  
  1786.  
  1787. rewrite_body(What, Body, NewBody, Stats, Backtrack, Fail, Level,
  1788.              ClauseNumber, GoalNumber, GoalNumber) :-
  1789.   RewrittenBody = cond(Body :== fail,
  1790.     cond(profile_old_clauses.What.type :== predicate,
  1791.       (
  1792.         Fail <<- true,
  1793.         fail
  1794.       ),
  1795.       fail
  1796.     ),
  1797.     Body
  1798.   ),  
  1799.   NewBody = cond(Level :== goal,
  1800.     (
  1801.       GT:(Stats.GoalNumber.tries) <<- `(+) & @(GT, 1), 
  1802.       RewrittenBody,
  1803.       GS:(Stats.GoalNumber.successes) <<- `(+) & @(GS, 1)
  1804.     ),
  1805.     RewrittenBody
  1806.   ).
  1807.  
  1808.  
  1809. %
  1810. % --------------------------------------------------------------------------
  1811. % -
  1812. % -  Rewriting rules for functions
  1813. % -
  1814. % --------------------------------------------------------------------------
  1815. %
  1816.  
  1817.  
  1818. non_strict(rewrite_function)?
  1819.  
  1820.  
  1821. rewrite_function(Function, Rules, Level) :-
  1822.   rewrite_rules(Function, Rules, Level, 1),
  1823.   !,
  1824.   BodyFail = (
  1825.     FunctionStats = `(profile_stats.Function),
  1826.     F:(FunctionStats.total_failures) <<- `(+) & @(F, 1),
  1827.     T:(FunctionStats.tries) <<- `(+) & @(T, 1),
  1828.     fail
  1829.   ),
  1830.   assert((Function -> @ | BodyFail)).
  1831.  
  1832.   
  1833. rewrite_function(Function, Rules, Level) :-
  1834.   write_err("*** Profile : Unable to add profiling code for function ", 
  1835.             Function, ": program corrupted"),
  1836.   nl_err.
  1837.  
  1838.  
  1839. %
  1840. % --------------------------------------------------------------------------
  1841. %
  1842.  
  1843.  
  1844. non_strict(rewrite_rules)?
  1845.  
  1846.  
  1847. rewrite_rules(Function, [(Pattern -> ExpressionResult) | LRules], Level, 
  1848.               RuleNumber) :-
  1849.   !,
  1850.   cond(ExpressionResult :== `(|),
  1851.     true | (ExpressionResult = `(Value | Body)),
  1852.     true | (Value = ExpressionResult)
  1853.   ),
  1854.   PatternMatchesForRule = cond(Level :\== call,
  1855.     (
  1856.       StatsForRule = StatsForFunction.RuleNumber,
  1857.       PMR:(StatsForRule.pattern_matchings) <<- `(+) & @(PMR, 1)
  1858.     ),
  1859.     succeed
  1860.   ),
  1861.   FailureForRule = cond(Level :\== call,
  1862.     (FR:(StatsForRule.total_failures) <<- `(+) & @(FR, 1)),
  1863.     succeed
  1864.   ),
  1865.   EvaluationFailedForRule = cond(Level :\== call,
  1866.     (EF1:(StatsForRule.total_failures) <<- `(+) & @(EF1, 1)),
  1867.     succeed
  1868.   ),
  1869.   EvaluationSucceededForRule = cond(Level :\== call,
  1870.     (
  1871.       EF2:(StatsForRule.total_failures) <<- `(-) & @(EF2, 1),
  1872.       EV:(StatsForRule.evaluations) <<- `(+) & @(EV, 1)
  1873.     ),
  1874.     succeed
  1875.   ),
  1876.   SuccessForRule = cond(Level :\== call,
  1877.     (SR:(StatsForRule.successes) <<- `(+) & @(SR, 1)),
  1878.     succeed
  1879.   ),
  1880.   CommonCodeForBodyTry = (
  1881.     succeed
  1882.   ;
  1883.     F1:(StatsForFunction.total_failures) <<- `(+) & @(F1, 1),
  1884.     FailureForRule,
  1885.     fail          
  1886.   ),
  1887.   cond(Body :== @,
  1888.     (
  1889.       BodyTry = CommonCodeForBodyTry,
  1890.       RewrittenBody = succeed,
  1891.       BodySuccess = succeed
  1892.     ),
  1893.     (
  1894.       rewrite_body(Function, Body, RewrittenBody, StatsForBody, @, @,
  1895.                    Level, RuleNumber, 1, NumberOfGoalsOfBody),
  1896.       BodyTry = cond(Level :== goal,
  1897.         (
  1898.           StatsForBody = StatsForRule.body,
  1899.           (
  1900.             BT:(StatsForBody.tries) <<- `(+) & @(BT, 1)
  1901.           ;
  1902.             BF:(StatsForBody.total_failures) <<- `(+) & @(BF, 1),
  1903.             F2:(StatsForFunction.total_failures) <<- `(+) & @(F2, 1),
  1904.             FailureForRule,
  1905.             fail
  1906.           )
  1907.         ),
  1908.         CommonCodeForBodyTry
  1909.       ),
  1910.       BodySuccess = cond(Level :== goal,
  1911.         (BS:(StatsForBody.successes) <<- `(+) & @(BS, 1)),
  1912.         succeed
  1913.       )
  1914.     )
  1915.   ),
  1916.   NewBody = (
  1917.     StatsForFunction = `(profile_stats.(`Function)),
  1918.     T:(StatsForFunction.tries) <<- `(+) & @(T, 1),
  1919.     PatternMatchesForRule,
  1920.     %%% We suppose that the evaluation fails
  1921.     SEF:(StatsForFunction.total_failures) <<- `(+) & @(SEF, 1),
  1922.     EvaluationFailedForRule,
  1923.     Result = Value,
  1924.     %%% The evaluation succeeded, we restore the previous number of failures
  1925.     ES:(StatsForFunction.total_failures) <<- `(-) & @(ES, 1),
  1926.     EvaluationSucceededForRule,
  1927.     BodyTry,
  1928.     RewrittenBody,
  1929.     BodySuccess,
  1930.     SuccessForRule,
  1931.     SF:(StatsForFunction.successes) <<- `(+) & @(SF, 1)
  1932.   ),
  1933.   clean_body(NewBody, CleanedNewBody),
  1934.   assert((Pattern -> Result | CleanedNewBody)),
  1935.   NewRuleNumber = RuleNumber + 1,
  1936.   rewrite_rules(Function, LRules, Level, NewRuleNumber).
  1937.   
  1938.  
  1939. rewrite_rules(Function, [], Level, RuleNumber).
  1940.  
  1941.  
  1942.  
  1943. %
  1944. %
  1945. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1946. %
  1947. %
  1948.  
  1949.  
  1950.  
  1951.  
  1952.  
  1953.  
  1954.  
  1955.  
  1956.  
  1957.  
  1958.  
  1959.  
  1960.