rlisp-support.red 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. % <PSL.UTIL>RLISP-SUPPORT.RED.8, 13-Oct-82 10:21:02, Edit by BENSON
  2. % !*INT is globally T
  3. % <PSL.UTIL>RLISP-SUPPORT.RED.5, 5-Oct-82 11:05:30, Edit by BENSON
  4. % Changed SaveSystem to 3 arguments
  5. % <PSL.UTIL>RLISP-SUPPORT.RED.3, 20-Sep-82 11:57:21, Edit by BENSON
  6. % Added Begin1 and BeginRlisp to IgnoredInBacktrace!*
  7. CompileTime REMPROP('SHOWTIME,'STAT);
  8. %*********************************************************************
  9. % RLISP and REDUCE Support Code for NEW-RLISP / On PSL
  10. %********************************************************************;
  11. GLOBAL '(FLG!*);
  12. GLOBAL '(BLOCKP!* CMSG!* ERFG!* INITL!* LETL!*
  13. PRECLIS!* VARS!* !*FORCE
  14. CLOC!*
  15. !*DEMO
  16. !*QUIET
  17. OTIME!* !*SLIN LREADFN!* TSLIN!*
  18. !*NAT NAT!*!* CRCHAR!* IFL!* IPL!* KEY!* KEY1!*
  19. OFL!* OPL!* PROGRAM!* PROGRAML!* SEMIC!*
  20. !*OUTPUT EOF!* TECHO!* !*INT !*MODE
  21. !*CREF !*MSG !*PRET !*EXTRAECHO);
  22. FLUID '(!*DEFN !*ECHO DFPRINT!* !*TIME !*BACKTRACE CURSYM!*);
  23. % These global variables divide into two classes. The first
  24. %class are those which must be initialized at the top level of the
  25. %program. These are as follows;
  26. BLOCKP!* := NIL; %keeps track of which block is active;
  27. CMSG!* := NIL; %shows that continuation msg has been printed;
  28. EOF!* := NIL; %flag indicating an end-of-file;
  29. ERFG!* := NIL; %indicates that an input error has occurred;
  30. INITL!* := '(BLOCKP!* VARS!*);
  31. %list of variables initialized in BEGIN1;
  32. KEY!* := 'SYMBOLIC; %stores first word read in command;
  33. LETL!* := NIL; %used in algebraic mode for special delimiters;
  34. LREADFN!* := NIL; %used to define special reading function;
  35. %OUTL!* := NIL; %storage for output of input line;
  36. PRECLIS!*:= '(OR AND NOT MEMBER MEMQ EQUAL NEQ EQ GEQ GREATERP LEQ
  37. LESSP PLUS DIFFERENCE TIMES QUOTIENT EXPT CONS);
  38. %precedence list of infix operators;
  39. TECHO!* := NIL; %terminal echo status;
  40. VARS!* := NIL; %list of current bound variables during parse;
  41. !*BACKTRACE := NIL; %if ON, prints a LISP backtrace;
  42. !*CREF := NIL; %used by cross-reference program;
  43. !*DEMO := NIL; % causes a PAUSE (READCH) in COMMAND loop
  44. !*ECHO := NIL; %indicates echoing of input;
  45. !*FORCE := NIL; %causes all macros to expand;
  46. !*INT := T; % system is interactive
  47. %!*LOSE := T; %determines whether a function flagged LOSE
  48. %is defined;
  49. %!*MSG:=NIL; %flag to indicate whether messages should be
  50. %printed;
  51. !*NAT := NIL; %used in algebraic mode to denote 'natural'
  52. %output. Must be on in symbolic mode to
  53. %ensure input echoing;
  54. NAT!*!* := NIL; %temporary variable used in algebraic mode;
  55. !*OUTPUT := T; %used to suppress output;
  56. !*SLIN := NIL; %indicates that LISP code should be read;
  57. !*TIME := NIL; %used to indicate timing should be printed;
  58. % The second class are those global variables which are
  59. %initialized within some function, although they do not appear in that
  60. %function's variable list. These are;
  61. % CRCHAR!* next character in input line
  62. % CURSYM!* current symbol (i. e. identifier, parenthesis,
  63. % delimiter, e.t.c,) in input line
  64. % FNAME!* name of a procedure being read
  65. % FTYPES!* list of regular procedure types
  66. % IFL!* input file/channel pair - set in BEGIN to NIL
  67. % IPL!* input file list- set in BEGIN to NIL
  68. % KEY1!* current key-word being analyzed - set in RLIS1;
  69. % NXTSYM!* next symbol read in TOKEN
  70. % OFL!* output file/channel pair - set in BEGIN to NIL
  71. % OPL!* output file list- set in BEGIN to NIL
  72. % PROGRAM!* current input program
  73. % PROGRAML!* stores input program when error occurs for a
  74. % later restart
  75. % SEMIC!* current delimiter character (used to decide
  76. % whether to print result of calculation)
  77. % TTYPE!* current token type;
  78. % WS used in algebraic mode to store top level value
  79. % !*FORT used in algebraic mode to denote FORTRAN output
  80. % !*INT indicates interactive system use
  81. % !*MODE current mode of calculation
  82. % !*PRET indicates REDUCE prettyprinting of input;
  83. fluid '(IgnoredInBacktrace!*);
  84. IgnoredInBacktrace!* := Append(IgnoredInBacktrace!*, '(Begin1 BeginRlisp));
  85. CompileTime flag('(FlagP!*!* CondTerPri
  86. LispFileNameP MkFil SetLispScanTable SetRlispScanTable
  87. ProgVr),
  88. 'InternalFunction);
  89. CompileTime <<
  90. macro procedure PgLine U; % needed for LOCN
  91. ''(1 . 1);
  92. >>;
  93. %*********************************************************************
  94. % REDUCE SUPERVISOR
  95. %********************************************************************;
  96. % The true REDUCE supervisory function is BEGIN, again defined in
  97. %the system dependent part of this program. However, most of the work
  98. %is done by BEGIN1, which is called by BEGIN for every file
  99. %encountered on input;
  100. SYMBOLIC PROCEDURE FLAGP!*!*(U,V);
  101. IDP U AND FLAGP(U,V);
  102. FLUID '(PROMPTSTRING!*);
  103. fluid '(STATCOUNTER!*);
  104. STATCOUNTER!* := 0;
  105. lisp procedure RlispPrompt();
  106. BldMsg("[%w] ", StatCounter!*);
  107. put('Symbolic, 'PromptFn, 'RlispPrompt);
  108. SYMBOLIC PROCEDURE BEGIN1;
  109. BEGIN SCALAR MODE,PARSERR,RESULT,PROMPT,WRKSP,MODEPRINT,PROMPTFN,RESULTL,
  110. PROMPTSTRING!*;
  111. A0: CURSYM!* := '!*SEMICOL!*;
  112. OTIME!* := TIME();
  113. GO TO A1;
  114. A: %IF NULL IFL!* AND !*INT
  115. % THEN <<%/CRBUFLIS!* := (STATCOUNTER!* . CRBUF!*) . CRBUFLIS!*;
  116. % CRBUF!* := NIL>>;
  117. A1: IF NULL IFL!* AND !*INT THEN STATCOUNTER!* := STATCOUNTER!* + 1;
  118. IF PROMPTFN := GET(!*MODE,'PROMPTFN) THEN
  119. PROMPTSTRING!* := APPLY(PROMPTFN,NIL);
  120. A2: PARSERR := NIL;
  121. % IF !*OUTPUT AND !*INT AND NULL IFL!* AND NULL OFL!*
  122. % AND NULL !*DEFN
  123. % THEN TERPRI();
  124. IF !*TIME THEN SHOWTIME();
  125. IF TSLIN!*
  126. THEN PROGN(!*SLIN := CAR TSLIN!*,
  127. LREADFN!* := CDR TSLIN!*,
  128. TSLIN!* := NIL);
  129. MAPC(INITL!*,FUNCTION SINITL);
  130. IF !*INT THEN ERFG!* := NIL; %to make editing work properly;
  131. IF CURSYM!* EQ 'END THEN GO TO ND0;
  132. PROGRAM!* := ERRORSET('(COMMAND),T,!*BACKTRACE);
  133. CONDTERPRI();
  134. IF ATOM PROGRAM!* OR CDR PROGRAM!* THEN GO TO ERR1;
  135. PROGRAM!* := CAR PROGRAM!*;
  136. IF PROGRAM!* EQ !$EOF!$ THEN GO TO ND1
  137. ELSE IF EQCAR(PROGRAM!*,'!*COMMA!*) THEN GO TO ER
  138. ELSE IF CURSYM!* EQ 'END THEN GO TO ND0
  139. ELSE IF EQCAR(PROGRAM!*,'RETRY) THEN PROGRAM!* := PROGRAML!*
  140. ;% ELSE IF PROGRAM!* EQ 'ED
  141. % THEN PROGN(CEDIT NIL,GO TO A2)
  142. % ELSE IF EQCAR(PROGRAM!*,'ED)
  143. % THEN PROGN(CEDIT CDR PROGRAM!*,GO TO A2);
  144. IF !*DEFN THEN GO TO D;
  145. B: %IF !*OUTPUT AND IFL!* AND !*ECHO THEN TERPRI();
  146. RESULTL := ERRORSET(PROGRAM!*,T,!*BACKTRACE);
  147. IF ATOM RESULTL OR CDR RESULTL OR ERFG!* THEN GO TO ERR2
  148. ELSE IF !*DEFN THEN GO TO A;
  149. RESULT := CAR RESULTL;
  150. IF IDP KEY!* AND GET(KEY!*,'STAT) EQ 'MODESTAT
  151. THEN MODE := KEY!*
  152. ELSE MODE := !*MODE;
  153. IF NULL !*OUTPUT OR IFL!* AND !*QUIET THEN GO TO C;
  154. IF SEMIC!* EQ '!; THEN <<
  155. MODEPRINT := GET(MODE,'MODEPRINFN) OR 'PrintWithFreshLine;
  156. % IF NOT FLAGP(MODE,'NOTERPRI) THEN
  157. % TERPRI();
  158. APPLY(MODEPRINT,RESULTL) >>;
  159. C: IF WRKSP := GET(MODE,'WORKSPACE) THEN
  160. SET(WRKSP,RESULT);
  161. GO TO A;
  162. D: IF ERFG!* THEN GO TO A
  163. ELSE IF FLAGP!*!*(KEY!*,'IGNORE) OR EQCAR(PROGRAM!*,'QUOTE)
  164. THEN GO TO B;
  165. IF PROGRAM!* THEN DFPRINT PROGRAM!*;
  166. IF FLAGP!*!*(KEY!*,'EVAL) THEN GO TO B ELSE GO TO A;
  167. ND0:COMM1 'END;
  168. ND1: EOF!* := NIL;
  169. IF NULL IPL!* %terminal END;
  170. THEN BEGIN
  171. IF OFL!* THEN WRS NIL;
  172. AA: IF NULL OPL!* THEN RETURN(OFL!* := NIL);
  173. CLOSE CDAR OPL!*;
  174. OPL!* := CDR OPL!*;
  175. GO TO AA
  176. END;
  177. RETURN NIL;
  178. ERR1:
  179. IF EOF!* OR PROGRAM!* EQ !$EOF!$ THEN GO TO ND1
  180. ELSE IF PROGRAM!* EQ 'EXTRA! BEGIN THEN GO TO A
  181. % ELSE IF PROGRAM!* EQ !*!*ESC THEN GO TO A0
  182. ELSE GO TO ER1;
  183. ER: LPRIE IF NULL ATOM CADR PROGRAM!*
  184. THEN LIST(CAADR PROGRAM!*,"UNDEFINED")
  185. ELSE "SYNTAX ERROR";
  186. ER1:
  187. PARSERR := T;
  188. GO TO ERR3;
  189. ERR2:
  190. PROGRAML!* := PROGRAM!*;
  191. ERR3:
  192. RESETPARSER();
  193. % IF NULL ERFG!* OR ERFG!* EQ 'HOLD
  194. % THEN LPRIE "ERROR TERMINATION *****";
  195. ERFG!* := T;
  196. IF NULL !*INT THEN GO TO E;
  197. RESULT := PAUSE1 PARSERR;
  198. IF RESULT THEN RETURN NULL EVAL RESULT;
  199. ERFG!* := NIL;
  200. GO TO A;
  201. E: !*DEFN := T; %continue syntax analyzing but not evaluation;
  202. !*ECHO := T;
  203. IF NULL CMSG!* THEN LPRIE "CONTINUING WITH PARSING ONLY ...";
  204. CMSG!* := T;
  205. GO TO A
  206. END;
  207. SYMBOLIC PROCEDURE CONDTERPRI;
  208. !*OUTPUT AND !*ECHO AND !*EXTRAECHO AND (NULL !*INT OR IFL!*)
  209. AND NULL !*DEFN AND POSN() > 0 AND TERPRI();
  210. CommentOutCode <<
  211. SYMBOLIC PROCEDURE ASSGNL U;
  212. IF ATOM U OR NULL (CAR U MEMQ '(SETK SETQ SETEL))
  213. THEN NIL
  214. ELSE IF ATOM CADR U THEN MKQUOTE CADR U . ASSGNL CADDR U
  215. ELSE CADR U . ASSGNL CADDR U;
  216. >>;
  217. SYMBOLIC PROCEDURE DFPRINT U;
  218. %Looks for special action on a form, otherwise prettyprints it;
  219. IF DFPRINT!* THEN APPLY(DFPRINT!*,LIST U)
  220. % ELSE IF CMSG!* THEN NIL
  221. ELSE IF NULL EQCAR(U,'PROGN) THEN
  222. << PRINTF "%f";
  223. PRETTYPRINT U >>
  224. ELSE BEGIN
  225. A: U := CDR U;
  226. IF NULL U THEN RETURN NIL;
  227. DFPRINT CAR U;
  228. GO TO A
  229. END;
  230. SYMBOLIC PROCEDURE SHOWTIME;
  231. BEGIN SCALAR X;
  232. X := OTIME!*;
  233. OTIME!* := TIME();
  234. X := OTIME!*-X;
  235. % TERPRI();
  236. PRIN2 "TIME: "; PRIN2 X; PRIN2T " MS";
  237. END;
  238. SYMBOLIC PROCEDURE SINITL U;
  239. SET(U,GET(U,'INITL));
  240. FLAG ('(IN OUT ON OFF SHUT),'IGNORE);
  241. %*********************************************************************
  242. % IDENTIFIER AND RESERVED CHARACTER READING
  243. %********************************************************************;
  244. % The function TOKEN defined below is used for reading
  245. %identifiers and reserved characters (such as parentheses and infix
  246. %operators). It is called by the function SCAN, which translates
  247. %reserved characters into their internal name, and sets up the output
  248. %of the input line. The following definitions of TOKEN and SCAN are
  249. %quite general, but also inefficient. THE READING PROCESS CAN OFTEN
  250. %BE SPEEDED UP BY A FACTOR OF AS MUCH AS FIVE IF THESE FUNCTIONS
  251. %(ESPECIALLY TOKEN) ARE CODED IN ASSEMBLY LANGUAGE;
  252. CommentOutCode <<
  253. SYMBOLIC PROCEDURE PRIN2X U;
  254. OUTL!*:=U . OUTL!*;
  255. SYMBOLIC PROCEDURE PTOKEN;
  256. BEGIN SCALAR X;
  257. X := TOKEN();
  258. IF X EQ '!) AND EQCAR(OUTL!*,'! ) THEN OUTL!*:= CDR OUTL!*;
  259. %an explicit reference to OUTL!* used here;
  260. PRIN2X X;
  261. IF NULL ((X EQ '!() OR (X EQ '!))) THEN PRIN2X '! ;
  262. RETURN X
  263. END;
  264. >>;
  265. SYMBOLIC PROCEDURE MKEX U;
  266. IF NOT(!*MODE EQ 'ALGEBRAIC) OR EQCAR(U,'AEVAL) THEN U
  267. ELSE NIL;%APROC(U,'AEVAL);
  268. SYMBOLIC PROCEDURE MKSETQ(U,V);
  269. LIST('SETQ,U,V);
  270. SYMBOLIC PROCEDURE MKVAR(U,V); U;
  271. SYMBOLIC PROCEDURE RPLCDX(U,V); IF CDR U=V THEN U ELSE RPLACD(U,V);
  272. SYMBOLIC PROCEDURE REFORM U;
  273. IF ATOM U OR CAR U EQ 'QUOTE THEN U
  274. ELSE IF CAR U EQ 'COND THEN 'COND . REFORM CDR U
  275. ELSE IF CAR U EQ 'PROG
  276. THEN PROGN(RPLCDX(CDR U,MAPCAR(CDDR U,FUNCTION REFORM)),U)
  277. ELSE IF CAR U EQ 'LAMBDA
  278. THEN PROGN(RPLACA(CDDR U,REFORM CADDR U),U)
  279. ELSE IF CAR U EQ 'FUNCTION AND ATOM CADR U
  280. THEN BEGIN SCALAR X;
  281. IF NULL !*CREF AND (X:= GET(CADR U,'SMACRO))
  282. THEN RETURN LIST('FUNCTION,X)
  283. ELSE IF GET(CADR U,'NMACRO) OR MACROP CADR U
  284. THEN REDERR "MACRO USED AS FUNCTION"
  285. ELSE RETURN U END
  286. % ELSE IF CAR U EQ 'MAT THEN RPLCDX(U,MAPC2(CDR U,FUNCTION REFORM))
  287. ELSE IF ATOM CAR U
  288. THEN BEGIN SCALAR X,Y;
  289. IF (Y := GETD CAR U) AND CAR Y EQ 'MACRO
  290. AND EXPANDQ CAR U
  291. THEN RETURN REFORM APPLY(CDR Y,LIST U);
  292. X := REFORMLIS CDR U;
  293. IF NULL IDP CAR U THEN RETURN(CAR U . X)
  294. ELSE IF (NULL !*CREF OR EXPANDQ CAR U)
  295. AND (Y:= GET(CAR U,'NMACRO))
  296. THEN RETURN
  297. APPLY(Y,IF FLAGP(CAR U,'NOSPREAD) THEN LIST X ELSE X)
  298. ELSE IF (NULL !*CREF OR EXPANDQ CAR U)
  299. AND (Y:= GET(CAR U,'SMACRO))
  300. THEN RETURN SUBLIS(PAIR(CADR Y,X),CADDR Y)
  301. %we could use an atom SUBLIS here (eg, SUBLA);
  302. ELSE RETURN PROGN(RPLCDX(U,X),U)
  303. END
  304. ELSE REFORM CAR U . REFORMLIS CDR U;
  305. SYMBOLIC PROCEDURE REFORMLIS U;
  306. IF ATOM U THEN U ELSE REFORM CAR U . REFORMLIS CDR U;
  307. SYMBOLIC PROCEDURE EXPANDQ U;
  308. %determines if macro U should be expanded in REFORM;
  309. FLAGP(U,'EXPAND) OR !*FORCE AND NULL FLAGP(U,'NOEXPAND);
  310. CommentOutCode <<
  311. SYMBOLIC PROCEDURE ARRAYP U;
  312. GET(U,'ARRAY);
  313. SYMBOLIC PROCEDURE GETTYPE U;
  314. %it might be better to use a table here for more generality;
  315. IF NULL ATOM U THEN 'FORM
  316. ELSE IF NUMBERP U THEN 'NUMBER
  317. ELSE IF ARRAYP U THEN 'ARRAY
  318. ELSE IF GETD U THEN 'PROCEDURE
  319. ELSE IF GLOBALP U THEN 'GLOBAL
  320. ELSE IF FLUIDP U THEN 'FLUID
  321. ELSE IF GET(U,'MATRIX) THEN 'MATRIX
  322. ELSE IF GET(U,'SIMPFN) OR GET(U,'MSIMPFN) THEN 'OPERATOR
  323. ELSE IF FLAGP(U,'PARM) THEN 'PARAMETER
  324. ELSE NIL;
  325. SYMBOLIC PROCEDURE GETELS U;
  326. GETEL(CAR U . EVLIS(CDR U));
  327. SYMBOLIC PROCEDURE SETELS(U,V);
  328. SETEL(CAR U . EVLIS(CDR U),V);
  329. >>;
  330. %. Top Level Entry Function
  331. %. --- Special Flags -----
  332. % !*DEMO -
  333. SYMBOLIC PROCEDURE COMMAND;
  334. BEGIN SCALAR X,Y;
  335. IF !*DEMO AND (X := IFL!*)
  336. THEN PROGN(TERPRI(),RDS NIL,READCH(),RDS CDR X);
  337. % IF EDIT!* THEN EDITLINE() ELSE IF FLG!* THEN GO TO A;
  338. IF !*SLIN THEN
  339. <<KEY!* := SEMIC!* := '!;;
  340. CLOC!* := IF IFL!* THEN CAR IFL!* . PGLINE() ELSE NIL;
  341. X := IF LREADFN!* THEN APPLY(LREADFN!*,NIL) ELSE READ();
  342. IF KEY!* EQ '!; THEN KEY!* := IF ATOM X THEN X ELSE CAR X>>
  343. ELSE <<SetRlispScanTable(); MakeInputAvailable(); SCAN();
  344. CLOC!* := IF IFL!* THEN CAR IFL!* . PGLINE() ELSE NIL;
  345. KEY!* := CURSYM!*; X := XREAD1 NIL>>;
  346. IF !*PRET THEN PROGN(TERPRI(),RPRINT X);
  347. X := REFORM X;
  348. IF CLOC!* AND NOT ATOM X AND CAR X MEMQ '(DE DF DM)
  349. THEN PUT(CADR X,'LOCN,CLOC!*)
  350. ELSE IF CLOC!* AND EQCAR(X,'PROGN)
  351. AND CDDR X AND NOT ATOM CADDR X
  352. AND CAADDR X MEMQ '(DE DF DM)
  353. THEN PUT(CADR CADDR X,'LOCN,CLOC!*);
  354. % IF IFL!*='(DSK!: (INPUT . TMP)) AND
  355. % (Y:= PGLINE()) NEQ '(1 . 0)
  356. % THEN LPL!*:= Y; %use of IN(noargs);
  357. IF NULL IDP KEY!* OR NULL(GET(KEY!*,'STAT) EQ 'MODESTAT)
  358. AND NULL(KEY!* EQ 'ED)
  359. THEN X := MKEX X;
  360. A: IF FLG!* AND IFL!* THEN BEGIN
  361. CLOSE CDR IFL!*;
  362. IPL!* := DELETE(IFL!*,IPL!*);
  363. IF IPL!* THEN RDS CDAR IPL!* ELSE RDS NIL;
  364. IFL!* := NIL END;
  365. FLG!* := NIL;
  366. RETURN X
  367. END;
  368. OFF R2I;
  369. SYMBOLIC PROCEDURE RPRINT U; % Autoloading stub
  370. << LOAD RPRINT;
  371. RPRINT U >>;
  372. ON R2I;
  373. %*********************************************************************
  374. % GENERAL FUNCTIONS
  375. %********************************************************************;
  376. %SYMBOLIC PROCEDURE MAPC2(U,V);
  377. % %this very conservative definition is to allow for systems with
  378. % %poor handling of functional arguments, and because of bootstrap-
  379. % %ping difficulties;
  380. % BEGIN SCALAR X,Y,Z;
  381. % A: IF NULL U THEN RETURN REVERSIP Z;
  382. % X := CAR U;
  383. % Y := NIL;
  384. % B: IF NULL X THEN GO TO C;
  385. % Y := APPLY(V,LIST CAR X) . Y;
  386. % X := CDR X;
  387. % GO TO B;
  388. % C: U := CDR U;
  389. % Z := REVERSIP Y . Z:
  390. % GO TO A
  391. % END;
  392. %*********************************************************************
  393. % FUNCTIONS FOR PRINTING DIAGNOSTIC AND ERROR MESSAGES
  394. %********************************************************************;
  395. SYMBOLIC PROCEDURE LPRIE U;
  396. << ERRORPRINTF("***** %L", U);
  397. ERFG!* := T >>;
  398. SYMBOLIC PROCEDURE LPRIM U;
  399. !*MSG AND ERRORPRINTF("*** %L", U);
  400. SYMBOLIC PROCEDURE REDERR U;
  401. BEGIN %TERPRI();
  402. LPRIE U; ERROR(99,NIL) END;
  403. SYMBOLIC PROCEDURE PROGVR VAR;
  404. IF NOT ATOM VAR THEN NIL
  405. ELSE IF NUMBERP VAR OR FLAGP(VAR,'SHARE)
  406. OR NOT(!*MODE EQ 'ALGEBRAIC) AND FLUIDP VAR THEN T
  407. ELSE BEGIN SCALAR X;
  408. IF X := GET(VAR,'DATATYPE) THEN RETURN CAR X END;
  409. SYMBOLIC PROCEDURE MKARG U;
  410. IF NULL U THEN NIL
  411. ELSE IF ATOM U THEN IF PROGVR U THEN U ELSE MKQUOTE U
  412. ELSE IF CAR U EQ 'QUOTE THEN MKQUOTE U
  413. ELSE IF FLAGP!*!*(CAR U,'NOCHANGE) AND NOT FLAGP(KEY1!*,'QUOTE)
  414. THEN U
  415. ELSE 'LIST . MAPCAR(U,FUNCTION MKARG);
  416. SYMBOLIC PROCEDURE MKPROG(U,V);
  417. 'PROG . (U . V);
  418. CommentOutCode <<
  419. SYMBOLIC PROCEDURE SETDIFF(U,V);
  420. IF NULL V THEN U ELSE SETDIFF(DELETE(CAR V,U),CDR V);
  421. SYMBOLIC PROCEDURE REMTYPE VARLIS;
  422. BEGIN SCALAR X,Y;
  423. VARS!* := SETDIFF(VARS!*,VARLIS);
  424. A: IF NULL VARLIS THEN RETURN NIL;
  425. X := CAR VARLIS;
  426. Y := CDR GET(X,'DATATYPE);
  427. IF Y THEN PUT(X,'DATATYPE,Y)
  428. ELSE PROGN(REMPROP(X,'DATATYPE),REMFLAG(LIST X,'PARM));
  429. VARLIS := CDR VARLIS;
  430. GO TO A
  431. END;
  432. >>;
  433. DEFLIST('((LISP SYMBOLIC)),'NEWNAM);
  434. FLAG('(FOR),'NOCHANGE);
  435. FLAG('(REPEAT),'NOCHANGE);
  436. FLAG('(WHILE),'NOCHANGE);
  437. CommentOutCode <<
  438. COMMENT LISP arrays built with computed index into a vector;
  439. % FLUID '(U V X Y N); %/ Fix for MAPC closed compile
  440. SYMBOLIC PROCEDURE ARRAY U;
  441. FOR EACH X IN U DO
  442. BEGIN INTEGER Y;
  443. IF NULL CDR X OR NOT IDP CAR X
  444. THEN REDERR LIST(X,"CANNOT BECOME AN ARRAY");
  445. Y:=1;
  446. FOR EACH V IN CDR X DO Y:=Y*(V+1);
  447. PUT(CAR X,'ARRAY,MKVECT(Y-1));
  448. PUT(CAR X,'DIMENSION,ADD1LIS CDR X);
  449. END;
  450. SYMBOLIC PROCEDURE CINDX!* U;
  451. BEGIN SCALAR V; INTEGER N;
  452. N:=0;
  453. IF NULL(V:=DIMENSION CAR U)
  454. THEN REDERR LIST(CAR U,"NOT AN ARRAY");
  455. FOR EACH Y IN CDR U DO
  456. <<IF NULL V THEN REDERR LIST(U,"TOO MANY INDICES");
  457. IF Y<0 OR Y>CAR V-1
  458. THEN REDERR LIST(U,"INDEX OUT OF RANGE");
  459. N:=Y+N*CAR V;
  460. V:=CDR V>>;
  461. IF V THEN REDERR LIST(U,"TOO FEW INDICES");
  462. RETURN N
  463. END;
  464. %UNFLUID '(U V X Y N); %/ Fix for MAPC closed compile
  465. SYMBOLIC PROCEDURE GETEL U;
  466. GETV(ARRAYP CAR U,CINDX!* U);
  467. SYMBOLIC PROCEDURE SETEL(U,V);
  468. PUTV(ARRAYP CAR U,CINDX!* U,V);
  469. SYMBOLIC PROCEDURE DIMENSION U;
  470. GET(U,'DIMENSION);
  471. COMMENT further support for REDUCE arrays;
  472. SYMBOLIC PROCEDURE TYPECHK(U,V);
  473. BEGIN SCALAR X;
  474. IF (X := GETTYPE U) EQ V OR X EQ 'PARAMETER
  475. THEN LPRIM LIST(U,"ALREADY DEFINED AS",V)
  476. ELSE IF X THEN REDERR LIST(X,U,"INVALID AS",V)
  477. END;
  478. SYMBOLIC PROCEDURE NUMLIS U;
  479. NULL U OR (NUMBERP CAR U AND NUMLIS CDR U);
  480. CompileTime REMPROP('ARRAY,'STAT); %for bootstrapping purposes;
  481. SYMBOLIC PROCEDURE ARRAYFN U;
  482. BEGIN SCALAR X,Y;
  483. A: IF NULL U THEN RETURN;
  484. X := CAR U;
  485. IF ATOM X THEN REDERR "SYNTAX ERROR"
  486. ELSE IF TYPECHK(CAR X,'ARRAY) THEN GO TO B;
  487. Y := IF NOT(!*MODE EQ 'ALGEBRAIC) THEN !*EVLIS CDR X
  488. ELSE REVLIS CDR X;
  489. IF NOT NUMLIS Y
  490. THEN LPRIE LIST("INCORRECT ARRAY ARGUMENTS FOR",CAR X);
  491. ARRAY LIST (CAR X . Y);
  492. B: U := CDR U;
  493. GO TO A
  494. END;
  495. SYMBOLIC PROCEDURE ADD1LIS U;
  496. IF NULL U THEN NIL ELSE (CAR U+1) . ADD1LIS CDR U;
  497. >>;
  498. %*********************************************************************
  499. %*********************************************************************
  500. % REDUCE FUNCTIONS FOR HANDLING INPUT AND OUTPUT OF FILES
  501. %*********************************************************************
  502. %********************************************************************;
  503. GLOBAL '(CONTL!*);
  504. MACRO PROCEDURE IN U;
  505. LIST('EVIN, MKQUOTE CDR U);
  506. SYMBOLIC PROCEDURE EVIN U;
  507. BEGIN SCALAR CHAN,ECHO,ECHOP,EXTN,OSLIN,OLRDFN,OTSLIN;
  508. ECHOP := SEMIC!* EQ '!;;
  509. ECHO := !*ECHO;
  510. IF NULL IFL!* THEN TECHO!* := !*ECHO; %terminal echo status;
  511. OSLIN := !*SLIN;
  512. OLRDFN := LREADFN!*;
  513. OTSLIN := TSLIN!*;
  514. TSLIN!* := NIL;
  515. FOR EACH FL IN U DO
  516. <<CHAN := OPEN(FL,'INPUT); IFL!* := FL . CHAN;
  517. IPL!* := IFL!* . IPL!*;
  518. RDS (IF IFL!* THEN CDR IFL!* ELSE NIL);
  519. !*ECHO := ECHOP;
  520. !*SLIN := T;
  521. IF LISPFILENAMEP FL THEN LREADFN!* := NIL
  522. ELSE !*SLIN := OSLIN;
  523. BEGIN1();
  524. IF !*SLIN THEN RESETPARSER();
  525. IF CHAN THEN CLOSE CHAN;
  526. LREADFN!* := OLRDFN;
  527. !*SLIN := OSLIN;
  528. IF FL EQ CAAR IPL!* THEN IPL!* := CDR IPL!*
  529. ELSE REDERR LIST("FILE STACK CONFUSION",FL,IPL!*)>>;
  530. !*ECHO := ECHO; %restore echo status;
  531. TSLIN!* := OTSLIN;
  532. IF IPL!* AND NULL CONTL!* THEN IFL!* := CAR IPL!*
  533. ELSE IFL!* := NIL;
  534. RDS(IF IFL!* THEN CDR IFL!* ELSE NIL);
  535. RETURN NIL
  536. END;
  537. CommentOutCode <<
  538. lisp procedure RedIN F;
  539. begin scalar !*Echo, !*Output, !*SLIN, Chan;
  540. IPL!* := (IFL!* := (F . (Chan := Open(F, 'Input)))) . IPL!*;
  541. RDS Chan;
  542. Begin1();
  543. IPL!* := cdr IPL!*;
  544. RDS(if not null IPL!* then cdr first IPL!* else NIL);
  545. end;
  546. >>;
  547. SYMBOLIC PROCEDURE LISPFILENAMEP S; %. Look for ".SL" or ".LSP"
  548. BEGIN SCALAR C, I, SS;
  549. SS := SIZE S;
  550. IF SS < 3 THEN RETURN NIL;
  551. I := SS;
  552. LOOP:
  553. IF I < 0 THEN RETURN NIL;
  554. IF INDX(S, I) = CHAR '!. THEN GOTO LOOPEND;
  555. I := I - 1;
  556. GOTO LOOP;
  557. LOOPEND:
  558. I := I + 1;
  559. C := SS - I;
  560. IF NOT (C MEMBER '(1 2)) THEN RETURN NIL;
  561. C := SUBSEQ(S, I, SS + 1);
  562. RETURN IF C MEMBER '("SL" "sl" "LSP" "lsp" "Sl" "Lsp") THEN T ELSE NIL;
  563. END;
  564. MACRO PROCEDURE OUT U;
  565. LIST('EVOUT, MKQUOTE CDR U);
  566. SYMBOLIC PROCEDURE EVOUT U;
  567. %U is a list of one file;
  568. BEGIN SCALAR CHAN,FL,X;
  569. IF NULL U THEN RETURN NIL
  570. ELSE IF CAR U EQ 'T THEN RETURN <<WRS(OFL!* := NIL); NIL>>;
  571. FL := MKFIL CAR U;
  572. IF NOT (X := ASSOC(FL,OPL!*))
  573. THEN <<CHAN := OPEN(FL,'OUTPUT);
  574. OFL!* := FL . CHAN;
  575. OPL!* := OFL!* . OPL!*>>
  576. ELSE OFL!* := X;
  577. WRS CDR OFL!*
  578. END;
  579. MACRO PROCEDURE SHUT U;
  580. LIST('EVSHUT, MKQUOTE CDR U);
  581. SYMBOLIC PROCEDURE EVSHUT U;
  582. %U is a list of names of files to be shut;
  583. BEGIN SCALAR FL,FL1;
  584. A: IF NULL U THEN RETURN NIL
  585. ELSE IF FL1 := ASSOC((FL := MKFIL CAR U),OPL!*) THEN GO TO B
  586. ELSE IF NOT (FL1 := ASSOC(FL,IPL!*))
  587. THEN REDERR LIST(FL,"NOT OPEN");
  588. IF FL1 NEQ IFL!*
  589. THEN <<CLOSE CDR FL1; IPL!* := DELETE(FL1,IPL!*)>>
  590. ELSE REDERR LIST("CANNOT CLOSE CURRENT INPUT FILE",CAR FL);
  591. GO TO C;
  592. B: OPL!* := DELETE(FL1,OPL!*);
  593. IF FL1=OFL!* THEN <<OFL!* := NIL; WRS NIL>>;
  594. CLOSE CDR FL1;
  595. C: U := CDR U;
  596. GO TO A
  597. END;
  598. %/ removed STAT property
  599. %*********************************************************************
  600. % FUNCTIONS HANDLING INTERACTIVE FEATURES
  601. %********************************************************************;
  602. %GLOBAL Variables referenced in this Section;
  603. CONTL!* := NIL;
  604. SYMBOLIC PROCEDURE PAUSE;
  605. PAUSE1 NIL;
  606. SYMBOLIC PROCEDURE PAUSE1 BOOL;
  607. BEGIN
  608. % IF BOOL THEN
  609. % IF NULL IFL!*
  610. % THEN RETURN IF !*INT AND GETD 'CEDIT AND YESP 'EDIT!?
  611. % THEN CEDIT() ELSE
  612. % NIL
  613. % ELSE IF GETD 'EDIT1 AND ERFG!* AND CLOC!* AND YESP 'EDIT!?
  614. % THEN RETURN <<CONTL!* := NIL;
  615. % IF OFL!* THEN <<LPRIM LIST(CAR OFL!*,'SHUT);
  616. % CLOSE CDR OFL!*;
  617. % OPL!* := DELETE(OFL!*,OPL!*);
  618. % OFL!* := NIL>>;
  619. % EDIT1(CLOC!*,NIL)>>
  620. % ELSE IF FLG!* THEN RETURN (EDIT!* := NIL);
  621. IF NULL IFL!* OR YESP 'CONT!? THEN RETURN NIL;
  622. CONTL!* := IFL!* . !*ECHO . CONTL!*;
  623. RDS (IFL!* := NIL);
  624. !*ECHO := TECHO!*
  625. END;
  626. SYMBOLIC PROCEDURE CONT;
  627. BEGIN SCALAR FL,TECHO;
  628. IF IFL!* THEN RETURN NIL %CONT only active from terminal;
  629. ELSE IF NULL CONTL!* THEN REDERR "NO FILE OPEN";
  630. FL := CAR CONTL!*;
  631. TECHO := CADR CONTL!*;
  632. CONTL!* := CDDR CONTL!*;
  633. IF FL=CAR IPL!* THEN <<IFL!* := FL;
  634. RDS IF FL THEN CDR FL ELSE NIL;
  635. !*ECHO := TECHO>>
  636. ELSE <<EOF!* :=T; LPRIM LIST(FL,"NOT OPEN"); ERROR(99,NIL)>>
  637. END;
  638. %/DEFLIST ('((PAUSE ENDSTAT) (CONT ENDSTAT) (RETRY ENDSTAT)),'STAT);
  639. %/PUT('RETRY,'STAT,'ENDSTAT);
  640. FLAG ('(CONT),'IGNORE);
  641. %******** "rend" fixups
  642. GLOBAL '(!*INT CONTL!* DATE!* !*MODE
  643. IMODE!* CRCHAR!* !*SLIN LREADFN!*);
  644. REMFLAG('(BEGINRLISP),'GO);
  645. %---- Merge into XREAD1 in command ----
  646. % Shouldnt USE Scan in COMMAND, since need change Parser first
  647. FLUID '(!*PECHO);
  648. Symbolic Procedure XREAD1 x; %. With Catches
  649. Begin scalar Form!*;
  650. Form!*:=PARSE0(0, NIL);
  651. If !*PECHO then PRIN2T LIST("parse>",Form!*);
  652. Return Form!*
  653. end;
  654. lisp procedure Xread X;
  655. Begin scalar Form!*;
  656. MakeInputAvailable();
  657. Form!*:=PARSE0(0, T);
  658. If !*PECHO then PRIN2T LIST("parse>",Form!*);
  659. Return Form!*
  660. end;
  661. !*PECHO:=NIL;
  662. SYMBOLIC PROCEDURE BEGINRLISP;
  663. BEGIN SCALAR A,B,PROMPTSTRING!*;
  664. %/ !*BAKGAG := NIL;
  665. !*INT := T;
  666. !*ECHO := NIL;
  667. A := !*SLIN;
  668. !*SLIN := LREADFN!* := NIL;
  669. CONTL!* := IFL!* := IPL!* := OFL!* := OPL!* := NIL;
  670. !*MODE := IMODE!*;
  671. CRCHAR!* := '! ;
  672. %/ RDSLSH NIL;
  673. %/ SETPCHAR '!*;
  674. SetRlispScanTable();
  675. % IF SYSTEM!* NEQ 0 THEN CHKLEN();
  676. IF DATE!* EQ NIL
  677. THEN IF A THEN <<PRIN2 "Entering RLISP..."; GO TO B>>
  678. ELSE GO TO A;
  679. %/ IF FILEP '((REDUCE . INI)) THEN <<IN REDUCE.INI; TERPRI()>>;
  680. %/ ERRORSET(QUOTE LAPIN "PSL.INI", NIL, NIL); % no error if not there
  681. PRIN2 DATE!*;
  682. DATE!* := NIL;
  683. % IF SYSTEM!* NEQ 1 THEN GO TO A;
  684. % IF !*HELP THEN PRIN2 "For help, type HELP()";
  685. B: TERPRI();
  686. A: BEGIN1();
  687. % TERPRI();
  688. !*SLIN := T;
  689. %/ RDSLSH NIL;
  690. SetLispScanTable();
  691. PRIN2T "Entering LISP..."
  692. END;
  693. FLAG('(BEGINRLISP),'GO);
  694. PUTD('BEGIN,'EXPR, CDR GETD 'BEGINRLISP);
  695. SYMBOLIC PROCEDURE MKFIL U;
  696. %converts file descriptor U into valid system filename;
  697. U;
  698. SYMBOLIC PROCEDURE NEWMKFIL U;
  699. %converts file descriptor U into valid system filename;
  700. U;
  701. lisp procedure SetPChar C; %. Set prompt, return old one
  702. begin scalar OldPrompt;
  703. OldPrompt := PromptString!*;
  704. PromptString!* := if StringP C then C
  705. else if IDP C then CopyString ID2String C
  706. else BldMsg("%w", C);
  707. return OldPrompt;
  708. end;
  709. COMMENT Some Global Variables required by REDUCE;
  710. %GLOBAL '(!*!*ESC);
  711. %
  712. %!*!*ESC := 'ESC!.NOT!.NEEDED!.NOW; %to make it user settable (used to be a NEWNAM);
  713. COMMENT The remaining material in this file introduces extensions
  714. or redefinitions of code in the REDUCE source files, and
  715. is not really necessary to run a basic system;
  716. lisp procedure SetRlispScanTable();
  717. << CurrentReadMacroIndicator!* :='RLispReadMacro;
  718. CurrentScanTable!* := RLispScanTable!* >>;
  719. lisp procedure SetLispScanTable();
  720. << CurrentReadMacroIndicator!* :='LispReadMacro;
  721. CurrentScanTable!* := LispScanTable!* >>;
  722. PutD('LispSaveSystem, 'EXPR, cdr GetD 'SaveSystem);
  723. lisp procedure SaveSystem(S, F, I); %. Set up for saving EXE file
  724. << StatCounter!* := 0;
  725. RemD 'Main;
  726. Copyd('Main, 'RlispMain);
  727. Date!* := BldMsg("%w, %w", S, Date());
  728. LispSaveSystem("PSL", F, I) >>;
  729. lisp procedure RlispMain();
  730. << BeginRlisp();
  731. StandardLisp() >>;
  732. lisp procedure Rlisp(); % Uses new top loop
  733. << SetRlispScanTable();
  734. TopLoop('ReformXRead, 'PrintWithFreshLine, 'Eval, "rlisp", "PSL Rlisp") >>;
  735. lisp procedure ReformXRead();
  736. Reform XRead T;
  737. !*RAISE := T;
  738. %IF GETD 'ADDSQ THEN IMODE!* := 'ALGEBRAIC ELSE IMODE!* := 'SYMBOLIC;
  739. IMODE!* := 'SYMBOLIC;
  740. TSLIN!* := NIL;
  741. !*MSG := T;
  742. END;