cslrend.red 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  1. module cslrend; % CSL REDUCE "back-end".
  2. % Authors: Martin L. Griss and Anthony C. Hearn.
  3. % Modified by Arthur Norman for use with CSL.
  4. create!-package('(cslrend csl),'(build));
  5. fluid '(!*break
  6. !*echo
  7. !*eolinstringok
  8. !*int
  9. !*mode
  10. !*raise
  11. !*lower
  12. !*keepsqrts);
  13. global '(!$eol!$
  14. !*extraecho
  15. cr!*
  16. crchar!*
  17. date!*
  18. esc!*
  19. ff!*
  20. ifl!*
  21. ipl!*
  22. largest!-small!-modulus
  23. ofl!*
  24. spare!*
  25. statcounter
  26. crbuflis!*
  27. tab!*
  28. version!*
  29. symchar!*);
  30. % Constants used in scanner.
  31. flag('(define!-constant),'eval);
  32. cr!* := compress(list('!!, special!-char 6)); % carriage return
  33. ff!* := compress(list('!!, special!-char 5)); % form feed
  34. tab!*:= compress(list('!!, special!-char 3)); % tab key
  35. % One inessential reference to REVERSIP in this module (left unchanged).
  36. % This file defines the system dependent code necessary to run REDUCE
  37. % under CSL.
  38. Comment The following functions, which are referenced in the basic
  39. REDUCE source (RLISP, ALG1, ALG2, MATR and PHYS) should be defined to
  40. complete the definition of REDUCE:
  41. BYE
  42. EVLOAD
  43. ERROR1
  44. FILETYPE
  45. MKFIL
  46. ORDERP
  47. QUIT
  48. SEPRP
  49. SETPCHAR.
  50. Prototypical descriptions of these functions are as follows;
  51. remprop('bye,'stat);
  52. symbolic procedure bye;
  53. %Returns control to the computer's operating system command level.
  54. %The current REDUCE job cannot be restarted;
  55. <<close!-output!-files(); stop 0>>;
  56. deflist('((bye endstat)),'stat);
  57. remprop('quit,'stat);
  58. symbolic procedure quit;
  59. %Returns control to the computer's operating system command level.
  60. %The current REDUCE job cannot be restarted;
  61. <<close!-output!-files(); stop 0>>;
  62. deflist('((quit endstat)),'stat);
  63. % evload is now defined in cslprolo.red - this has to be the case
  64. % so it can be used (via load_package) to load rlisp and cslrend.
  65. % symbolic procedure evload l;
  66. % for each m in l do load!-module m;
  67. symbolic procedure seprp u;
  68. % Returns true if U is a blank, end-of-line, tab, carriage return or
  69. % form feed. This definition replaces the one in the BOOT file.
  70. u eq '! or u eq tab!* or u eq !$eol!$ or u eq ff!* or u eq cr!*;
  71. symbolic procedure filetype u;
  72. % Determines if string U has a specific file type.
  73. begin scalar v,w;
  74. v := cdr explode u;
  75. while v and not(car v eq '!.) do
  76. <<if car v eq '!< then while not(car v eq '!>) do v := cdr v;
  77. v := cdr v>>;
  78. if null v then return nil;
  79. v := cdr v;
  80. while v and not(car v eq '!") do <<w := car v . w; v := cdr v>>;
  81. return intern compress reversip w
  82. end;
  83. symbolic procedure mkfil u;
  84. % Converts file descriptor U into valid system filename.
  85. if stringp u then u
  86. else if not idp u then typerr(u,"file name")
  87. else string!-downcase u;
  88. Comment The following functions are only referenced if various flags are
  89. set, or the functions are actually defined. They are defined in another
  90. module, which is not needed to build the basic system. The name of the
  91. flag follows the function name, enclosed in parentheses:
  92. CEDIT (?)
  93. COMPD (COMP)
  94. EDIT1 This function provides a link to an editor. However, a
  95. definition is not necessary, since REDUCE checks to see
  96. if it has a function value.
  97. EMBFN (?)
  98. EZGCDF (EZGCD)
  99. PRETTYPRINT (DEFN --- also called by DFPRINT)
  100. This function is used in particular for output of RLISP
  101. expressions in LISP syntax. If that feature is needed,
  102. and the prettyprint module is not available, then it
  103. should be defined as PRINT
  104. RPRINT (PRET)
  105. TIME (TIME) returns elapsed time from some arbitrary initial
  106. point in milliseconds;
  107. Comment The following operator is used to save a REDUCE session as a
  108. file for later use;
  109. symbolic procedure savesession u;
  110. preserve('begin);
  111. flag('(savesession),'opfn);
  112. flag('(savesession),'noval);
  113. Comment make "system" available as an operator;
  114. flag('(system),'opfn);
  115. flag('(system),'noval);
  116. Comment to make "faslend" an endstat;
  117. put('faslend,'stat,'endstat);
  118. Comment The current REDUCE model allows for the availability of fast
  119. arithmetical operations on small integers (called "inums"). All modern
  120. LISPs provide such support. However, the program will still run without
  121. these constructs. The relevant functions that should be defined for
  122. this purpose are as follows;
  123. flag('(iplus itimes iplus2 itimes2 iadd1 isub1 iminus iminusp
  124. idifference iquotient iremainder ilessp igreaterp ileq igeq
  125. izerop ionep), 'lose);
  126. Comment There are also a number of system constants required for each
  127. implementation. In systems that don't support inums, the equivalent
  128. single precision integers should be used;
  129. % LARGEST!-SMALL!-MODULUS is the largest power of two that can
  130. % fit in the fast arithmetic (inum) range of the implementation.
  131. % This is constant for the life of the system and could be
  132. % compiled in-line if the compiler permits it.
  133. largest!-small!-modulus := 2**24 - 1; % I could use up to 2^27-1, but
  134. % stick to 2^24-1 since that's what Cambridge Lisp used to use.
  135. flag('(modular!-difference modular!-minus modular!-number
  136. modular!-plus modular!-quotient modular!-reciprocal
  137. modular!-times modular!-expt set!-small!-modulus), 'lose);
  138. % See comments about gensym() below - which apply also to the
  139. % effects of having different random number generators in different
  140. % host Lisp systems.
  141. % From 3.5 onwards (with a new random generator built into the
  142. % REDUCE sources) I am happy to use the portable version.
  143. % flag('(random next!-random!-number), 'lose);
  144. set!-small!-modulus 3;
  145. % The following are now built into CSL, where by using the C library
  146. % and (hence?) maybe low level tricks or special floating point
  147. % microcode things can go fast.
  148. flag('(acos acosd acosh acot acotd acoth acsc acscd acsch asec asecd
  149. asech asin asind asinh atan atand atan2 atan2d atanh cbrt cos
  150. cosd cosh cot cotd coth csc cscd csch exp expt hypot ln log
  151. logb log10 sec secd sech sin sind sinh sqrt tan tand tanh fix
  152. ceiling floor round clrhash puthash gethash remhash), 'lose);
  153. symbolic procedure int!-gensym1 u;
  154. % in Codemist Lisp compress interns - hence version in int.red is bad;
  155. gensym1 u;
  156. Comment We need to define a function BEGIN, which acts as the top-level
  157. call to REDUCE, and sets the appropriate variables;
  158. remflag('(begin),'go);
  159. global '(patchdate!*);
  160. symbolic procedure begin;
  161. begin
  162. scalar w;
  163. !*int := not batchp();
  164. !*echo := not !*int;
  165. !*extraecho := t;
  166. ifl!* := ipl!* := ofl!* := nil;
  167. if date!* then <<
  168. verbos nil;
  169. % The linelength may need to be adjusted if we are running in a window.
  170. linelength 80;
  171. % The next four lines have been migrated into the C code in "restart.c"
  172. % so that some sort of information gets back to the user nice an early...
  173. % prin2 version!*;
  174. % prin2 ", ";
  175. % prin2 date!*;
  176. % prin2t " ...";
  177. !*mode := if getd 'addsq then 'algebraic else 'symbolic;
  178. %since most REDUCE users won't use LISP
  179. date!* := nil >>;
  180. % crchar!* := '! ;
  181. % If there is a patches module that is later than one that I currently have
  182. % installed then load it up now.
  183. w := modulep 'patches;
  184. if w and (null patchdate!* or datelessp(patchdate!*, w)) then begin
  185. scalar !*redefmsg; % Avoid silly messages
  186. load!-module 'patches;
  187. patchdate!* := w end;
  188. while errorp errorset('(begin1), !*backtrace, !*backtrace) do nil;
  189. prin2t "Leaving REDUCE ... "
  190. end;
  191. flag('(begin),'go);
  192. % The following function is used in some CSL-specific operations. It is
  193. % also defined in util/rprint, but is repeated here to avoid loading
  194. % that module unnecessarily, and because the definition given there is
  195. % rather PSL specific.
  196. remflag('(string!-downcase),'lose);
  197. symbolic procedure string!-downcase u;
  198. compress('!" . append(explode2lc u,'(!")));
  199. flag('(string!-downcase),'lose);
  200. % This function is used in Rlisp '88.
  201. symbolic procedure igetv(u,v); getv(u,v);
  202. % The following functions are NOT in Standard Lisp and should NOT be used
  203. % anywhere in the REDUCE sources, but the amount of trouble I have had with
  204. % places where they do creep in has encouraged me to define them here anyway
  205. % and put up with the (small) waste of space.
  206. symbolic procedure first x; car x;
  207. symbolic procedure second x; cadr x;
  208. symbolic procedure third x; caddr x;
  209. symbolic procedure fourth x; cadddr x;
  210. symbolic procedure rest x; cdr x;
  211. Comment Initial setups for REDUCE;
  212. spare!* := 11; % We need this for bootstrapping.
  213. symchar!* := t; % Changed prompt when in symbolic mode.
  214. % PSL has gensyms with names g0001, g0002 etc., and in a few places
  215. % REDUCE will insert gensyms into formulae in such a way that their
  216. % names can influence the ordering of terms. The next fragment of
  217. % commented out code make CSL use similar names (but interned). This
  218. % is not sufficient to guarantee a match with PSL though, since in (for
  219. % instance) the code
  220. % list(gensym(), gensym(), gensym())
  221. % there is no guarantee which gensym will have the smallest serial
  222. % number. Also if !*comp is true and the user defines a procedure it is
  223. % probable that the compiler does a number (just how many we do not
  224. % wish to say) of calls to gensym, upsetting the serial number
  225. % sequence. Thus other ways of ensuring consistent output from REDUCE
  226. % are needed.
  227. %- global '(gensym!-counter);
  228. %- gensym!-counter := 1;
  229. %- symbolic procedure reduce!-gensym();
  230. %- begin
  231. %- scalar w;
  232. %- w := explode gensym!-counter;
  233. %- gensym!-counter := gensym!-counter+1;
  234. %- while length w < 4 do w := '!0 . w;
  235. %- return compress ('g . w)
  236. %- end;
  237. %- remflag('(gensym), 'lose);
  238. %- remprop('gensym, 's!:builtin0);
  239. %- smacro procedure gensym();
  240. %- reduce!-gensym();
  241. symbolic procedure initreduce;
  242. initrlisp(); % For compatibility.
  243. symbolic procedure initrlisp;
  244. % Initial declarations for REDUCE
  245. <<statcounter := 0;
  246. %- gensym!-counter := 1;
  247. crbuflis!* := nil;
  248. spare!* := 11;
  249. !*int := not batchp()>>;
  250. symbolic procedure rlispmain;
  251. lispeval '(begin);
  252. flag('(rdf preserve reclaim),'opfn);
  253. flag('(rdf preserve),'noval);
  254. remflag('(showtime), 'lose);
  255. symbolic procedure showtime;
  256. begin scalar x,y;
  257. x := otime!*;
  258. otime!* := time();
  259. x := otime!* - x;
  260. y := ogctime!*;
  261. ogctime!* := gctime();
  262. y := ogctime!* - y;
  263. % x := x - y;
  264. terpri();
  265. prin2 "Time: "; prin2 x; prin2 " ms";
  266. if y = 0 then return terpri();
  267. prin2 " plus GC time: "; prin2 y; prin2 " ms"
  268. end;
  269. flag('(showtime), 'lose);
  270. flag('(load reload),'noform);
  271. deflist('((load rlis) (reload rlis)),'stat);
  272. symbolic macro procedure load x; PSL!-load(cdr x, nil);
  273. symbolic macro procedure reload x; PSL!-load(cdr x, t);
  274. global '(PSL!-loaded!*);
  275. PSL!-loaded!* := nil;
  276. symbolic procedure PSL!-load(mods, reloadp);
  277. for each x in mods do <<
  278. if reloadp or not member(x, PSL!-loaded!*) then <<
  279. load!-module x;
  280. PSL!-loaded!* := union(list x, PSL!-loaded!*) >> >>;
  281. symbolic macro procedure tr x;
  282. list('trace, list('quote, cdr x));
  283. symbolic macro procedure untr x;
  284. list('untrace, list('quote, cdr x));
  285. symbolic macro procedure trst x;
  286. list('traceset, list('quote, cdr x));
  287. symbolic macro procedure untrst x;
  288. list('untraceset, list('quote, cdr x));
  289. flag('(tr untr
  290. trst untrst
  291. ),'noform);
  292. deflist('((tr rlis) (trst rlis)
  293. (untr rlis) (untrst rlis)
  294. ),'stat);
  295. symbolic procedure prop x; plist x; % Yukky PSL compatibility.
  296. Comment The following declarations are needed to build various modules;
  297. flag('(mkquote spaces subla boundp error1),'lose);
  298. % The exact order of items in the lists produced by these is important
  299. % to REDUCE.
  300. flag('(union intersection), 'lose);
  301. flag('(safe!-fp!-plus safe!-fp!-times safe!-fp!-quot
  302. safe!-fp!-pl safe!-fp!-pl0), 'lose);
  303. flag('(threevectorp ordp), 'lose);
  304. deflist('((imports rlis)),'stat);
  305. endmodule;
  306. module csl; % Support for fast floating point arithmetic in CSL.
  307. imports ash, ash1, logand, msd;
  308. exports msd!:;
  309. fluid '(!!nbfpd);
  310. remflag ('(fl2bf msd!: fix2 rndpwr timbf),'lose);
  311. symbolic smacro procedure fix2 u; fix u;
  312. symbolic smacro procedure lshift(m,d); ash(m,d);
  313. symbolic smacro procedure ashift(m,d); ash1(m,d);
  314. symbolic smacro procedure land(a,b); logand(a,b);
  315. symbolic smacro procedure msd!: u; msd u;
  316. symbolic smacro procedure make!:ibf (mt, ep);
  317. '!:rd!: . (mt . ep);
  318. fluid '(!:bprec!:);
  319. symbolic smacro procedure rndpwr j;
  320. begin
  321. scalar !#w; % I use an odd name here to avoid clashes (smacro)
  322. !#w := mt!: j;
  323. if !#w = 0 then return make!:ibf(0, 0);
  324. !#w := inorm(!#w, !:bprec!:);
  325. return make!:ibf(car !#w, cdr !#w + ep!: j)
  326. end;
  327. % This is introduced as a privately-named function and an associated
  328. % smacro to avoid unwanted interactions between 3 versions of this
  329. % function: the one here, the version of this code compiled into C, and
  330. % the original version in arith.red. Note thus that CSL_normbf is not
  331. % flagged as 'lose here (but it will be when a version compiled into
  332. % C exists), and the standard version of normbf will still get compiled
  333. % in arith.red, but all references to it will get turned into calls
  334. % to CSL_normbf. The SMACRO does not need a 'lose flag either.
  335. symbolic procedure CSL_normbf x;
  336. begin
  337. scalar mt,s;
  338. integer ep;
  339. % Note I write out mt!: and ep!: here because the smacros for them are
  340. % not yet available.
  341. if (mt := cadr x)=0 then return '(!:rd!: 0 . 0);
  342. if mt<0 then <<mt := -mt; s := t>>;
  343. ep := lsd mt;
  344. mt := lshift(mt, -ep);
  345. if s then mt := -mt;
  346. ep := ep + cddr x;
  347. return make!:ibf(mt,ep)
  348. end;
  349. symbolic smacro procedure normbf x; CSL_normbf x;
  350. symbolic procedure CSL_timbf(u, v);
  351. begin
  352. scalar m;
  353. m := mt!: u * mt!: v;
  354. if m = 0 then return '(!:rd!: 0 . 0);
  355. m := inorm(m, !:bprec!:);
  356. return make!:ibf(car m, cdr m + ep!: u + ep!: v)
  357. end;
  358. symbolic smacro procedure timbf(u, v); CSL_timbf(u, v);
  359. symbolic procedure fl2bf x;
  360. begin scalar u;
  361. u := frexp x;
  362. x := cdr u; % mantissa between 0.5 and 1
  363. u := car u; % exponent
  364. x := fix(x*2**!!nbfpd);
  365. return normbf make!:ibf(x,u-!!nbfpd)
  366. end;
  367. flag ('(fl2bf msd!: fix2 rndpwr timbf), 'lose);
  368. set!-print!-precision 14;
  369. % The following definition is appropriate for MSDOS, and the value of
  370. % !!maxbflexp should be OK for all IEEE systems. BEWARE if you have a
  371. % computer with non-IEEE arithmetic, and worry a bit about !!flexperr
  372. % (which is hardly ever used anyway...).
  373. % I put this here to avoid having arith.red do a loop that is terminated
  374. % by a floating point exception, since as of Nov 1994 CSL built using
  375. % Watcom C 10.0a can not recover from such errors more than (about) ten times
  376. % in any one run - this avoids that during system building.
  377. global '(!!flexperr !!!~xx !!maxbflexp);
  378. remflag('(find!!maxbflexp), 'lose);
  379. symbolic procedure find!!maxbflexp();
  380. << !!flexperr := t;
  381. !!!~xx := expt(2.0, 1023);
  382. !!maxbflexp := 1022 >>;
  383. flag('(find!!maxbflexp), 'lose);
  384. remflag('(copyd), 'lose);
  385. symbolic procedure copyd(new,old);
  386. % Copy the function definition from old id to new.
  387. begin scalar x;
  388. x := getd old;
  389. % If loading with !*savedef = '!*savedef then the actual definitions
  390. % do not get loaded, but the source forms do...
  391. if null x then <<
  392. if not (!*savedef = '!*savedef)
  393. then rerror('rlisp,1,list(old,"has no definition in copyd")) >>
  394. else << putd(new,car x,cdr x);
  395. if flagp(old, 'lose) then flag(list new, 'lose) >>;
  396. % The transfer of the saved definition is needed if the REDUCE "patch"
  397. % mechanism is to work fully properly.
  398. if (x := get(old, '!*savedef)) then put(new, '!*savedef, x);
  399. return new
  400. end;
  401. flag('(copyd), 'lose);
  402. smacro procedure int2id x; compress list('!!, x);
  403. smacro procedure id2int x; car explode2n x;
  404. smacro procedure bothtimes x; eval!-when((compile load eval), x);
  405. smacro procedure compiletime x; eval!-when((compile eval), x);
  406. smacro procedure loadtime x; eval!-when((load eval), x);
  407. smacro procedure csl x; x;
  408. smacro procedure psl x; nil;
  409. symbolic macro procedure printf u;
  410. list('printf1, cadr u, 'list . cddr u);
  411. symbolic procedure printf1(fmt, args);
  412. % this is the inner works of print formatting.
  413. % the special sequences that can occur in format strings are
  414. % %b do that many spaces
  415. % %c next arg is a numeric character code. display character
  416. % * %f do a terpri() unless posn()=0
  417. % %l prin2 items from given list, blank separated
  418. % * %n do a terpri()
  419. % %o print in octal
  420. % %p print using prin1
  421. % %t do a ttab to move to given column
  422. % %w use prin2
  423. % %x print in hexadecimal
  424. % * %% print a '%' character (items marked * do not use an arg).
  425. begin
  426. scalar a, c;
  427. fmt := explode2 fmt;
  428. while fmt do <<
  429. c := car fmt;
  430. fmt := cdr fmt;
  431. if c = '!% then <<
  432. c := car fmt;
  433. fmt := cdr fmt;
  434. if c = '!f then << if not zerop posn() then terpri() >>
  435. else if c = '!n then terpri()
  436. else if c = '!% then prin2 c
  437. else <<
  438. a := car args;
  439. args := cdr args;
  440. if c = '!b then spaces a
  441. else if c = '!c then tyo a
  442. else if c = '!l then <<
  443. if not atom a then <<
  444. prin2 car a;
  445. for each w in cdr a do << prin2 " "; prin2 w >> >> >>
  446. else if c = '!o then prinoctal a
  447. else if c = '!p then prin1 a
  448. else if c = '!t then ttab a
  449. else if c = '!w then prin2 a
  450. else if c = '!x then prinhex a
  451. else rerror('cslrend,1,list(c,"bad format character")) >> >>
  452. else prin2 c >>
  453. end;
  454. symbolic macro procedure bldmsg u;
  455. list('bldmsg1, cadr u, 'list . cddr u);
  456. symbolic procedure bldstring r;
  457. begin
  458. scalar w;
  459. w := '(!");
  460. while r do <<
  461. w := car r . w;
  462. if car r eq '!" then w := '!" . w;
  463. r := cdr r >>;
  464. return compress ('!" . w)
  465. end;
  466. symbolic procedure bldcolumn(s, n);
  467. if null s or eqcar(s, !$eol!$) then n
  468. else bldcolumn(cdr s, n+1);
  469. symbolic procedure bldmsg1(fmt, args);
  470. begin
  471. scalar a, c, r;
  472. fmt := explode2 fmt;
  473. while fmt do <<
  474. c := car fmt;
  475. fmt := cdr fmt;
  476. if c = '!% then <<
  477. c := car fmt;
  478. fmt := cdr fmt;
  479. if c = '!f then <<
  480. if not zerop bldcolumn(r, 0) then r := !$eol!$ . r >>
  481. else if c = '!n then r := !$eol!$ . r
  482. else if c = '!% then r := c . r
  483. else <<
  484. a := car args;
  485. args := cdr args;
  486. if c = '!b then for i := 1:a do r := '! . r
  487. else if c = '!c then r := a . r
  488. else if c = '!l then <<
  489. if not atom a then <<
  490. r := append(reverse explode2 car a, r);
  491. for each w in cdr a do <<
  492. r := '! . r;
  493. r := append(reverse explode2 w, r) >> >> >>
  494. else if c = '!o then r := append(reverse explodeoctal a, r)
  495. else if c = '!p then r := append(reverse explode a, r)
  496. else if c = '!t then while bldcolumn(r, 0)<a do r := '! . r
  497. else if c = '!w then r := append(reverse explode2 a, r)
  498. else if c = '!x then r := append(reverse explodehex a, r)
  499. else rerror('cslrend,1,list(c,"bad format character")) >> >>
  500. else r := c . r >>;
  501. return bldstring r
  502. end;
  503. endmodule;
  504. end;