cslrend.red 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  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),nil);
  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. lispsystem!*
  24. ofl!*
  25. spare!*
  26. statcounter
  27. crbuflis!*
  28. tab!*
  29. version!*
  30. copyright1!*
  31. copyright2!*
  32. loadable!-packages!*
  33. switches!*
  34. symchar!*);
  35. copyright1!* := "Copyright A C Hearn, 1999";
  36. copyright2!* := "Copyright Codemist Ltd, 1999";
  37. loadable!-packages!* := '(
  38. algint applysym arnum assist atensor
  39. avector boolean cali camal cantens
  40. cedit changevr cl compact conlaw
  41. crack cvit defint desir dfpart
  42. dipoly dummy dvfsf eds excalc
  43. ezgcd factor fide fmprint fps
  44. ftr gentran geometry gnuplot groebner
  45. hephys ideals ineq int invbase
  46. laplace lie liepde limits linalg
  47. mathml matrix misc modsr mrvlimit
  48. ncpoly normform numeric odesolve ofsf
  49. orthovec pf physop plot pm
  50. polydiv pretty qsum randpoly rataprx
  51. ratint rcref reacteqn redlog residue
  52. rlfi rlisp88 rltools roots rprint
  53. rsolve rtrace scope sets sfgamma
  54. solve sparse spde specfn sum
  55. support susy2 symmetry taylor tps
  56. tri trigint trigsimp wu xcolor
  57. xideal ztrans);
  58. switches!* := '(
  59. algint adjprec allbranch allfac
  60. arbvars asterisk backtrace balanced_mod
  61. bfspace combineexpt combinelogs comp
  62. complex compxroots cramer cref
  63. defn demo dfprint div
  64. echo errcont evallhseqp exp
  65. expandexpt expandlogs ezgcd factor
  66. fastfor force fort fortupper
  67. fullprec fullprecision fullroots gc
  68. gcd heugcd horner ifactor
  69. int intstr lcm lessspace
  70. limitedfactors list listargs lower
  71. mcd modular msg multiplicities
  72. nat nero noarg noconvert
  73. nonlnr nosplit numval output
  74. period pgwd plap precise
  75. pret pri pwrds quotenewnam
  76. raise rat ratarg rational
  77. rationalize ratpri reduced revpri
  78. rlisp88 rootmsg roundall roundbf
  79. rounded savestructr solvesingular time
  80. trallfac trfac trint trroot);
  81. % Constants used in scanner.
  82. flag('(define!-constant),'eval);
  83. cr!* := compress(list('!!, special!-char 6)); % carriage return
  84. ff!* := compress(list('!!, special!-char 5)); % form feed
  85. tab!*:= compress(list('!!, special!-char 3)); % tab key
  86. % One inessential reference to REVERSIP in this module (left unchanged).
  87. % This file defines the system dependent code necessary to run REDUCE
  88. % under CSL.
  89. Comment The following functions, which are referenced in the basic
  90. REDUCE source (RLISP, ALG1, ALG2, MATR and PHYS) should be defined to
  91. complete the definition of REDUCE:
  92. BYE
  93. EVLOAD
  94. ERROR1
  95. FILETYPE
  96. MKFIL
  97. ORDERP
  98. QUIT
  99. SEPRP
  100. SETPCHAR.
  101. Prototypical descriptions of these functions are as follows;
  102. remprop('bye,'stat);
  103. symbolic procedure bye;
  104. %Returns control to the computer's operating system command level.
  105. %The current REDUCE job cannot be restarted;
  106. <<close!-output!-files(); stop 0>>;
  107. deflist('((bye endstat)),'stat);
  108. remprop('quit,'stat);
  109. symbolic procedure quit;
  110. %Returns control to the computer's operating system command level.
  111. %The current REDUCE job cannot be restarted;
  112. <<close!-output!-files(); stop 0>>;
  113. deflist('((quit endstat)),'stat);
  114. % evload is now defined in cslprolo.red - this has to be the case
  115. % so it can be used (via load_package) to load rlisp and cslrend.
  116. % symbolic procedure evload l;
  117. % for each m in l do load!-module m;
  118. symbolic procedure seprp u;
  119. % Returns true if U is a blank, end-of-line, tab, carriage return or
  120. % form feed. This definition replaces the one in the BOOT file.
  121. u eq '! or u eq tab!* or u eq !$eol!$ or u eq ff!* or u eq cr!*;
  122. symbolic procedure filetype u;
  123. % Determines if string U has a specific file type.
  124. begin scalar v,w;
  125. v := cdr explode u;
  126. while v and not(car v eq '!.) do
  127. <<if car v eq '!< then while not(car v eq '!>) do v := cdr v;
  128. v := cdr v>>;
  129. if null v then return nil;
  130. v := cdr v;
  131. while v and not(car v eq '!") do <<w := car v . w; v := cdr v>>;
  132. return intern compress reversip w
  133. end;
  134. symbolic procedure mkfil u;
  135. % Converts file descriptor U into valid system filename.
  136. if stringp u then u
  137. else if not idp u then typerr(u,"file name")
  138. else string!-downcase u;
  139. Comment The following functions are only referenced if various flags are
  140. set, or the functions are actually defined. They are defined in another
  141. module, which is not needed to build the basic system. The name of the
  142. flag follows the function name, enclosed in parentheses:
  143. CEDIT (?)
  144. COMPD (COMP)
  145. EDIT1 This function provides a link to an editor. However, a
  146. definition is not necessary, since REDUCE checks to see
  147. if it has a function value.
  148. EMBFN (?)
  149. EZGCDF (EZGCD)
  150. PRETTYPRINT (DEFN --- also called by DFPRINT)
  151. This function is used in particular for output of RLISP
  152. expressions in LISP syntax. If that feature is needed,
  153. and the prettyprint module is not available, then it
  154. should be defined as PRINT
  155. RPRINT (PRET)
  156. TIME (TIME) returns elapsed time from some arbitrary initial
  157. point in milliseconds;
  158. Comment The following operator is used to save a REDUCE session as a
  159. file for later use;
  160. symbolic procedure savesession u;
  161. preserve('begin);
  162. flag('(savesession),'opfn);
  163. flag('(savesession),'noval);
  164. Comment make "system" available as an operator;
  165. flag('(system),'opfn);
  166. flag('(system),'noval);
  167. Comment to make "faslend" an endstat;
  168. put('faslend,'stat,'endstat);
  169. Comment The current REDUCE model allows for the availability of fast
  170. arithmetical operations on small integers (called "inums"). All modern
  171. LISPs provide such support. However, the program will still run without
  172. these constructs. The relevant functions that should be defined for
  173. this purpose are as follows;
  174. flag('(iplus itimes iplus2 itimes2 iadd1 isub1 iminus iminusp
  175. idifference iquotient iremainder ilessp igreaterp ileq igeq
  176. izerop ionep), 'lose);
  177. Comment There are also a number of system constants required for each
  178. implementation. In systems that don't support inums, the equivalent
  179. single precision integers should be used;
  180. % LARGEST!-SMALL!-MODULUS is the largest power of two that can
  181. % fit in the fast arithmetic (inum) range of the implementation.
  182. % This is constant for the life of the system and could be
  183. % compiled in-line if the compiler permits it.
  184. largest!-small!-modulus := 2**24 - 1; % I could use up to 2^27-1, but
  185. % stick to 2^24-1 since that's what Cambridge Lisp used to use.
  186. flag('(modular!-difference modular!-minus modular!-number
  187. modular!-plus modular!-quotient modular!-reciprocal
  188. modular!-times modular!-expt set!-small!-modulus), 'lose);
  189. % See comments about gensym() below - which apply also to the
  190. % effects of having different random number generators in different
  191. % host Lisp systems.
  192. % From 3.5 onwards (with a new random generator built into the
  193. % REDUCE sources) I am happy to use the portable version.
  194. % flag('(random next!-random!-number), 'lose);
  195. set!-small!-modulus 3;
  196. % The following are now built into CSL, where by using the C library
  197. % and (hence?) maybe low level tricks or special floating point
  198. % microcode things can go fast.
  199. flag('(acos acosd acosh acot acotd acoth acsc acscd acsch asec asecd
  200. asech asin asind asinh atan atand atan2 atan2d atanh cbrt cos
  201. cosd cosh cot cotd coth csc cscd csch exp expt hypot ln log
  202. logb log10 sec secd sech sin sind sinh sqrt tan tand tanh fix
  203. ceiling floor round clrhash puthash gethash remhash), 'lose);
  204. % remflag('(int!-gensym1),'lose);
  205. % symbolic procedure int!-gensym1 u;
  206. % In Codemist Lisp compress interns - hence version in int.red may
  207. % not work. However, it seems to be ok for now.
  208. % gensym1 u;
  209. % flag('(int!-gensym1),'lose);
  210. Comment We need to define a function BEGIN, which acts as the top-level
  211. call to REDUCE, and sets the appropriate variables;
  212. remflag('(begin),'go);
  213. global '(patchdate!* no_init_file);
  214. symbolic procedure load!-latest!-patches();
  215. begin
  216. scalar w;
  217. w := modulep 'patches;
  218. if w and (null patchdate!* or datelessp(patchdate!*, w)) then
  219. begin scalar !*usermode, !*redefmsg; % Avoid silly messages
  220. load!-module 'patches;
  221. patchdate!* := w;
  222. for each m in loaded!-packages!* do
  223. if (w := get(m, 'patchfn)) then apply(w, nil)
  224. end
  225. end;
  226. symbolic procedure begin;
  227. begin
  228. scalar w;
  229. !*echo := not !*int;
  230. !*extraecho := t;
  231. ifl!* := ipl!* := ofl!* := nil;
  232. if date!* then <<
  233. verbos nil;
  234. % The linelength may need to be adjusted if we are running in a window.
  235. % To cope with this, CSL allows (linelength t) to set a "default" line
  236. % length that can even vary as window sizes are changed. An attempt
  237. % will be made to ensure that it is 80 at the start of a run, but
  238. % (linelength nil) can return varying values as the user re-sizes the
  239. % main window (in some versions of CSL). However this is still not
  240. % perfect! The protocol
  241. % old := linelength nil;
  242. % <do something, possibly changing linelength as you go>
  243. % linelength old;
  244. % can not restore the variability characteristic. However I make
  245. % old := linelength n; % n numeric or T
  246. % ...
  247. % linelength old;
  248. % preserve things by returning T from (linelength n) in relevant cases.
  249. linelength t;
  250. % The next four lines have been migrated into the C code in "restart.c"
  251. % so that some sort of information gets back to the user nice and early.
  252. % prin2 version!*;
  253. % prin2 ", ";
  254. % prin2 date!*;
  255. % prin2t " ...";
  256. if getd 'addsq then <<
  257. % I assume here that this is an algebra system if ADDSQ is defined, and
  258. % in that case process an initialisation file. Starting up without ADDSQ
  259. % defined means I either have just RLISP built or I am in the middle of
  260. % some bootstrap process. Also if a variable no_init_file is set to TRUE
  261. % then I avoid init file processing.
  262. !*mode := 'algebraic;
  263. if null no_init_file then begin
  264. scalar name;
  265. name := assoc('executable, lispsystem!*);
  266. if atom name then name := "reduce"
  267. else name := list!-to!-string explode2lc cdr name;
  268. read!-init!-file name end >>
  269. else !*mode := 'symbolic;
  270. date!* := nil >>;
  271. % If there is a patches module that is later than one that I currently
  272. % have installed then load it up now.
  273. load!-latest!-patches();
  274. w := assoc('opsys, lispsystem!*);
  275. if not atom w then w := cdr w;
  276. % For MOST systems I will let ^G (bell) be the escape character, but
  277. % under win32 I use that as an interrupt character, and so there I go
  278. % back and use ESC instead. I do the check at BEGIN time rather than
  279. % further out so that common checkpoint images can be used across
  280. % systems.
  281. esc!*:= compress list('!!,
  282. special!-char (if w = 'win32 then 10 else 9));
  283. while errorp errorset('(begin1), !*backtrace, !*backtrace) do nil;
  284. prin2t "Leaving REDUCE ... "
  285. end;
  286. flag('(begin),'go);
  287. % The following function is used in some CSL-specific operations. It is
  288. % also defined in util/rprint, but is repeated here to avoid loading
  289. % that module unnecessarily, and because the definition given there is
  290. % rather PSL specific.
  291. remflag('(string!-downcase),'lose);
  292. symbolic procedure string!-downcase u;
  293. compress('!" . append(explode2lc u,'(!")));
  294. % princ!-upcase and princ!-downcase are used for fortran output
  295. flag('(string!-downcase princ!-upcase princ!-downcase),'lose);
  296. % This function is used in Rlisp '88.
  297. symbolic procedure igetv(u,v); getv(u,v);
  298. symbolic procedure iputv(u,v,w); putv(u,v,w);
  299. % The following functions are NOT in Standard Lisp and should NOT be
  300. % used anywhere in the REDUCE sources, but the amount of trouble I have
  301. % had with places where they do creep in has encouraged me to define
  302. % them here anyway and put up with the (small) waste of space.
  303. symbolic procedure first x; car x;
  304. symbolic procedure second x; cadr x;
  305. symbolic procedure third x; caddr x;
  306. symbolic procedure fourth x; cadddr x;
  307. symbolic procedure rest x; cdr x;
  308. flag('(iequal),'lose);
  309. Comment Initial setups for REDUCE;
  310. spare!* := 0; % We need this for bootstrapping.
  311. symchar!* := t; % Changed prompt when in symbolic mode.
  312. % PSL has gensyms with names g0001, g0002 etc., and in a few places
  313. % REDUCE will insert gensyms into formulae in such a way that their
  314. % names can influence the ordering of terms. The next fragment of
  315. % commented out code make CSL use similar names (but interned). This
  316. % is not sufficient to guarantee a match with PSL though, since in (for
  317. % instance) the code
  318. % list(gensym(), gensym(), gensym())
  319. % there is no guarantee which gensym will have the smallest serial
  320. % number. Also if !*comp is true and the user defines a procedure it is
  321. % probable that the compiler does a number (just how many we do not
  322. % wish to say) of calls to gensym, upsetting the serial number
  323. % sequence. Thus other ways of ensuring consistent output from REDUCE
  324. % are needed.
  325. %- global '(gensym!-counter);
  326. %- gensym!-counter := 1;
  327. %- symbolic procedure reduce!-gensym();
  328. %- begin
  329. %- scalar w;
  330. %- w := explode gensym!-counter;
  331. %- gensym!-counter := gensym!-counter+1;
  332. %- while length w < 4 do w := '!0 . w;
  333. %- return compress ('g . w)
  334. %- end;
  335. %- remflag('(gensym), 'lose);
  336. %- remprop('gensym, 's!:builtin0);
  337. %- smacro procedure gensym();
  338. %- reduce!-gensym();
  339. % However, the current CSL gensym uses an upper case G as the root,
  340. % which causes inconsistencies in some tests (e.g., int and qsum).
  341. % This definition cures that.
  342. symbolic smacro procedure gensym; gensym1 'g;
  343. symbolic procedure initreduce;
  344. initrlisp(); % For compatibility.
  345. symbolic procedure initrlisp;
  346. % Initial declarations for REDUCE
  347. <<statcounter := 0;
  348. %- gensym!-counter := 1;
  349. crbuflis!* := nil;
  350. spare!* := 0;
  351. % !*int := not batchp();
  352. !*int := t;
  353. >>;
  354. symbolic procedure rlispmain;
  355. lispeval '(begin);
  356. flag('(rdf preserve reclaim),'opfn);
  357. flag('(rdf preserve),'noval);
  358. flag('(load reload),'noform);
  359. deflist('((load rlis) (reload rlis)),'stat);
  360. symbolic macro procedure load x; PSL!-load(cdr x, nil);
  361. symbolic macro procedure reload x; PSL!-load(cdr x, t);
  362. global '(PSL!-loaded!*);
  363. PSL!-loaded!* := nil;
  364. symbolic procedure PSL!-load(mods, reloadp);
  365. for each x in mods do <<
  366. if reloadp or not member(x, PSL!-loaded!*) then <<
  367. % load!-module x;
  368. load!-package x;
  369. PSL!-loaded!* := union(list x, PSL!-loaded!*) >> >>;
  370. symbolic macro procedure tr x;
  371. list('trace, list('quote, cdr x));
  372. symbolic macro procedure untr x;
  373. list('untrace, list('quote, cdr x));
  374. symbolic macro procedure trst x;
  375. list('traceset, list('quote, cdr x));
  376. symbolic macro procedure untrst x;
  377. list('untraceset, list('quote, cdr x));
  378. flag('(tr untr
  379. trst untrst
  380. ),'noform);
  381. deflist('((tr rlis) (trst rlis)
  382. (untr rlis) (untrst rlis)
  383. ),'stat);
  384. symbolic procedure prop x; plist x; % Yukky PSL compatibility.
  385. Comment The following declarations are needed to build various modules;
  386. flag('(mkquote spaces subla boundp error1),'lose);
  387. % The exact order of items in the lists produced by these is important
  388. % to REDUCE.
  389. flag('(union intersection), 'lose);
  390. flag('(safe!-fp!-plus safe!-fp!-times safe!-fp!-quot), 'lose);
  391. flag('(threevectorp ordp), 'lose);
  392. deflist('((imports rlis)),'stat);
  393. flag('(sort stable!-sort stable!-sortip),'lose);
  394. % We also need this.
  395. flag('(lengthc),'lose);
  396. symbolic procedure concat2(u,v); concat(u,v);
  397. symbolic procedure concat(u,v);
  398. % This would be better supported at a lower level.
  399. compress('!" . append(explode2 u,nconc(explode2 v,list '!")));
  400. % Used by patching mechanism.
  401. %
  402. % Note that DESPITE the name this MUST be an interned symbol not a
  403. % gensym since it will be used as the name of a function written out
  404. % using FASLOUT and later re-loaded: gensym identities can not survive
  405. % this transition. The symbols created by dated!-name are almost
  406. % always going to avoid clashes - see commentary in the CSL source file
  407. % "extras.red" for an explanation.
  408. symbolic procedure dated!-gensym u; dated!-name u;
  409. endmodule;
  410. end;