top-loop.red 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. %
  2. % TOP-LOOP.RED - Generalized top loop construct
  3. %
  4. % Author: Eric Benson and M. L. Griss
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 19 October 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.KERNEL>TOP-LOOP.RED.6, 5-Oct-82 11:02:29, Edit by BENSON
  12. % Added EvalInitForms, changed SaveSystem to 3 args
  13. % <PSL.KERNEL>TOP-LOOP.RED.5, 4-Oct-82 18:09:33, Edit by BENSON
  14. % Added GCTime!*
  15. % $pi/top-loop.red, Mon Jun 28 10:54:19 1982, Edit by Fish
  16. % Conditional output: !*Output, Semic!*, !*NoNil.
  17. % <PSL.INTERP>TOP-LOOP.RED.13, 30-Apr-82 14:32:20, Edit by BENSON
  18. % Minor change to !*DEFN processing
  19. % <PSL.INTERP>TOP-LOOP.RED.5, 29-Apr-82 03:56:06, Edit by GRISS
  20. % Initial attempt to add !*DEFN processing
  21. %<PSL.INTERP>TOP-LOOP.RED.18 24-Nov-81 15:22:25, Edit by BENSON
  22. % Changed Standard!-Lisp to StandardLisp
  23. CompileTime flag('(NthEntry DefnPrint DefnPrint1 HistPrint),
  24. 'InternalFunction);
  25. fluid '(TopLoopRead!* % reading function
  26. TopLoopPrint!* % printing function
  27. TopLoopEval!* % evaluation function
  28. TopLoopName!* % short name to put in prompt
  29. TopLoopLevel!* % depth of top loop invocations
  30. HistoryCount!* % number of entries read so far
  31. HistoryList!* % list of entries read and evaluated
  32. PromptString!* % input prompt
  33. LispBanner!* % Welcome banner printed in StandardLisp
  34. !*EMsgP % whether to print error messages
  35. !*BackTrace % whether to print backtrace
  36. !*Time % whether to print timing of evaluation
  37. GCTime!* % Time spent in garbage collection
  38. !*Defn % To "output" rather than process
  39. DFPRINT!* % Alternate DEFN print function
  40. !*Output % Whether to print output.
  41. Semic!* % Input terminator when in Rlisps.
  42. !*NoNil % Whether to supress NIL value print.
  43. InitForms!* % Forms to be evaluated at startup
  44. );
  45. LoadTime <<
  46. TopLoopLevel!* := -1;
  47. HistoryCount!* := 0;
  48. LispBanner!* := "Portable Standard LISP";
  49. !*Output := T; % Output ON by default.
  50. >>;
  51. lisp procedure TopLoop(TopLoopRead!*, %. Generalized top-loop mechanism
  52. TopLoopPrint!*, %.
  53. TopLoopEval!*, %.
  54. TopLoopName!*, %.
  55. WelcomeBanner); %.
  56. begin scalar PromptString!*, Semic!*, LevelPrompt, ThisGCTime,
  57. InputValue, OutputValue, TimeCheck;
  58. Semic!* := '!; ; % Output when semicolon terminator for rlisps.
  59. (lambda TopLoopLevel!*;
  60. begin
  61. TimeCheck := 0;
  62. ThisGCTime := GCTime!*;
  63. LevelPrompt := MkString(TopLoopLevel!*, char '!> );
  64. Prin2T WelcomeBanner;
  65. LoopStart:
  66. HistoryCount!* := IAdd1 HistoryCount!*;
  67. HistoryList!* := (NIL . NIL) . HistoryList!*;
  68. PromptString!* := BldMsg("%w %w%w ",
  69. HistoryCount!*,
  70. TopLoopName!*,
  71. LevelPrompt);
  72. InputValue := ErrorSet(quote Apply(TopLoopRead!*, NIL), T, !*Backtrace);
  73. if InputValue eq '!$ExitTopLoop!$ then goto LoopExit;
  74. if not PairP InputValue then
  75. goto LoopStart;
  76. InputValue := car InputValue;
  77. if InputValue eq '!$ExitTopLoop!$ then goto LoopExit;
  78. if InputValue eq !$EOF!$ then goto LoopExit;
  79. Rplaca(car HistoryList!*, InputValue);
  80. if !*Time then
  81. << TimeCheck := Time();
  82. ThisGCTime := GCTime!* >>;
  83. if !*Defn then
  84. OutputValue := DefnPrint InputValue
  85. else
  86. OutputValue := ErrorSet(list('Apply, MkQuote TopLoopEval!*,
  87. MkQuote list InputValue),
  88. T,
  89. !*Backtrace);
  90. if not PairP OutputValue then
  91. goto LoopStart;
  92. OutputValue := car OutputValue;
  93. if !*Time then
  94. << TimeCheck := Time() - TimeCheck;
  95. ThisGCTime := GCTime!* - ThisGCTime >>;
  96. Rplacd(car HistoryList!*, OutputValue);
  97. if !*Output and Semic!* eq '!;
  98. and not (!*NoNil and OutputValue eq NIL) then
  99. ErrorSet(list('Apply,
  100. MkQuote TopLoopPrint!*,
  101. MkQuote list OutputValue), T, !*Backtrace);
  102. if !*Time then
  103. if ThisGCTime = 0 then
  104. PrintF("Cpu time: %w ms%n", TimeCheck)
  105. else
  106. PrintF("Cpu time: %w ms, GC time: %w ms%n",
  107. TimeCheck - ThisGCTime, ThisGCTime);
  108. goto LoopStart;
  109. LoopExit:
  110. PrintF("Exiting %w%n", TopLoopName!*);
  111. end)(IAdd1 TopLoopLevel!*);
  112. end;
  113. lisp procedure DefnPrint U; % handle case of !*Defn:=T
  114. %
  115. % Looks for special action on a form, otherwise prettyprints it;
  116. % Adapted from DFPRINT
  117. %
  118. if PairP U and FlagP(car U, 'Ignore) then DefnPrint1 U
  119. else % So 'IGNORE is EVALED, not output
  120. << if DfPrint!* then Apply(DfPrint!*, list U)
  121. else PrettyPrint U; % So 'EVAL gets EVALED and Output
  122. if PairP U and FlagP(car U, 'Eval) then DefnPrint1 U >>;
  123. lisp procedure DefnPrint1 U;
  124. ErrorSet(list('Apply, MkQuote TopLoopEval!*,
  125. MkQuote list U),
  126. T,
  127. !*Backtrace);
  128. fluid '(!*Break);
  129. lisp procedure NthEntry N;
  130. begin scalar !*Break;
  131. return if IGEQ(N, HistoryCount!*) then
  132. StdError BldMsg("No history entry %r", N)
  133. else car PNth(cdr HistoryList!*, IDifference(HistoryCount!*, N));
  134. end;
  135. lisp procedure Inp N; %. Return Nth input
  136. car NthEntry N;
  137. expr procedure ReDo N; %. Re-evaluate Nth input
  138. Apply(TopLoopEval!*, list car NthEntry N);
  139. lisp procedure Ans N; %. return Nth output
  140. cdr NthEntry N;
  141. nexpr procedure Hist AL; %. Print history entries
  142. begin scalar I1, I2, L;
  143. if ILessP(HistoryCount!*, 2) then return NIL;
  144. I1 := 1;
  145. I2 := ISub1 HistoryCount!*;
  146. if PairP AL then
  147. << if car AL = 'CLEAR then
  148. << HistoryCount!* := 1;
  149. HistoryList!* := NIL . NIL;
  150. return NIL >>;
  151. if IMinusP car AL then return
  152. HistPrint(cdr HistoryList!*,
  153. ISub1 HistoryCount!*,
  154. IMinus car AL);
  155. I1 := Max(I1, car AL);
  156. AL := cdr AL >>;
  157. if PairP AL then I2 := Min(I2, car AL);
  158. return HistPrint(PNTH(cdr HistoryList!*,
  159. IDifference(HistoryCount!*, I2)),
  160. I2,
  161. IAdd1 IDifference(I2, I1));
  162. end;
  163. lisp procedure HistPrint(L, N, M);
  164. if IZeroP M then NIL else
  165. << HistPrint(cdr L, ISub1 N, ISub1 M);
  166. PrintF("%w Inp: %p%n Ans: %p%n",
  167. N, car first L, cdr first L) >>;
  168. lisp procedure Time(); %. Get run-time in milliseconds
  169. Sys2Int TimC(); % TimC is primitive runtime function
  170. lisp procedure StandardLisp(); %. Lisp top loop
  171. (lambda (CurrentReadMacroIndicator!*, CurrentScanTable!*);
  172. TopLoop('READ, 'PrintWithFreshLine, 'EVAL, "lisp", LispBanner!*)
  173. )('LispReadMacro, LispScanTable!*);
  174. lisp procedure PrintWithFreshLine X;
  175. PrintF("%f%p%n", X);
  176. lisp procedure SaveSystem(Banner, File, InitForms);
  177. begin scalar SavedHistoryList, SavedHistoryCount;
  178. SavedHistoryCount := HistoryCount!*;
  179. SavedHistoryList := HistoryList!*;
  180. HistoryList!* := NIL;
  181. HistoryCount!* := 0;
  182. LispBanner!* := BldMsg("%w, %w", Banner, Date());
  183. !*UserMode := T;
  184. InitForms!* := InitForms;
  185. DumpLisp File;
  186. InitForms!* := NIL;
  187. HistoryCount!* := SavedHistoryCount;
  188. HistoryList!* := SavedHistoryList;
  189. end;
  190. lisp procedure EvalInitForms(); %. Evaluate and clear InitForms!*
  191. << for each X in InitForms!* do Eval X;
  192. InitForms!* := NIL >>;
  193. END;