form.red 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. module form; % Performs a mode analysis of parsed forms.
  2. % Author: Anthony C. Hearn.
  3. % Modifications by: Jed Marti, Arthur C. Norman.
  4. % Copyright (c) 1993 RAND. All rights reserved.
  5. fluid '(!*!*a2sfn !*cref !*defn !*mode !*reduce4 !*rlisp88
  6. current!-modulus fname!* ftype!*);
  7. global '(!*argnochk !*comp !*composites !*force !*micro!-version
  8. !*vars!* cursym!*);
  9. !*!*a2sfn := 'aeval;
  10. flag('(algebraic symbolic),'modefn);
  11. symbolic procedure formcond(u,vars,mode);
  12. 'cond . formcond1(cdr u,vars,mode);
  13. symbolic procedure formcond1(u,vars,mode);
  14. if null u then nil
  15. else list(formbool(caar u,vars,mode),formc(cadar u,vars,mode))
  16. % FORM1 here leaves out top level REVAL.
  17. . formcond1(cdr u,vars,mode);
  18. put('cond,'formfn,'formcond);
  19. symbolic procedure formlamb(u,vars,mode);
  20. list('lambda,cadr u,form1(caddr u,pairvars(cadr u,vars,mode),mode));
  21. put('lambda,'formfn,'formlamb);
  22. symbolic procedure formprogn(u,vars,mode);
  23. 'progn . formclis(cdr u,vars,mode);
  24. put('progn,'formfn,'formprogn);
  25. symbolic procedure expdrmacro u;
  26. % Returns the macro form for U if expansion is permitted.
  27. begin scalar x;
  28. if null(x := getrmacro u) or flagp(u,'noexpand) then return nil
  29. % else if null(null !*cref and (null !*defn or car x eq 'smacro)
  30. % or flagp(u,'expand) or !*force)
  31. else if !*cref and null flagp(u,'expand) and null !*force
  32. then return nil
  33. else return x
  34. end;
  35. symbolic procedure getrmacro u;
  36. %returns a Reduce macro definition for U, if one exists,
  37. %in GETD format;
  38. begin scalar x;
  39. return if not idp u then nil
  40. else if (x := getd u) and car x eq 'macro then x
  41. else if (x := get(u,'smacro)) then 'smacro . x
  42. else nil
  43. end;
  44. symbolic procedure applmacro(u,v,w); apply1(u,w . v);
  45. put('macro,'macrofn,'applmacro);
  46. flag('(ed go quote),'noform);
  47. symbolic procedure set!-global!-mode u;
  48. begin
  49. !*mode := u;
  50. return list('null,list('setq,'!*mode,mkquote u))
  51. end;
  52. symbolic procedure form1(u,vars,mode);
  53. begin scalar x,y;
  54. if atom u
  55. then return if not idp u then u
  56. else if u eq 'ed then list u
  57. else if flagp(u,'modefn) then set!-global!-mode u
  58. else if x:= get(mode,'idfn)
  59. then apply2(x,u,vars)
  60. else u
  61. else if not atom car u then return form2(u,vars,mode)
  62. else if not idp car u then typerr(car u,"operator")
  63. else if flagp(car u,'noform) then return u
  64. else if arrayp car u
  65. % and (mode eq 'symbolic or intexprlisp(cdr u,vars))
  66. and mode eq 'symbolic
  67. then return list('getel,intargfn(u,vars,mode))
  68. else if cdr u and (get(car u,'rtype) eq 'vector
  69. or vectorp cadr u or flagpcar(cadr u,'vecfn))
  70. then return getvect(u,vars,mode)
  71. else if flagp(car u,'modefn)
  72. then return convertmode(cadr u,vars,mode,car u)
  73. else if (x := get(car u,'formfn))
  74. then return macrochk(apply3(x,u,vars,mode),mode)
  75. else if get(car u,'stat) eq 'rlis
  76. then return macrochk(formrlis(u,vars,mode),mode)
  77. % else if (x := getd car u) and eqcar(x, 'macro) and
  78. % not(mode eq 'algebraic) then
  79. % return <<x := apply3(cdr x,u,vars,mode);
  80. % formc(x,vars,mode) >>
  81. % else if flagp(car u,'type) then blocktyperr car u
  82. else if car u eq '!*comma!*
  83. then if not atom cadr u and atom caddr u
  84. and flagp(caadr u,'type)
  85. % and(get(caddr u,'stat) eq 'decstat)
  86. then blocktyperr caadr u
  87. else rerror('rlisp,10,
  88. list("Syntax error: , invalid after",cadr u));
  89. % Exclude algebraic operator with same name as symbolic function.
  90. if mode eq 'symbolic or flagp(car u,'opfn)
  91. then argnochk u;
  92. x := formlis(cdr u,vars,mode);
  93. y := if x=cdr u then u else car u . x;
  94. return if mode eq 'symbolic
  95. or get(car u,'stat)
  96. or cdr u and eqcar(cadr u,'quote)
  97. and null(!*micro!-version and null !*defn)
  98. or intexprnp(y,vars) and null !*composites
  99. and current!-modulus=1
  100. then macrochk(y,mode)
  101. else if not(mode eq 'algebraic)
  102. then convertmode(y,vars,mode,'algebraic)
  103. else ('list . algid(car u,vars) . x)
  104. end;
  105. symbolic procedure form2(u,vars,mode);
  106. begin scalar x;
  107. if x := get(caar u,'form2fn) then return apply3(x,u,vars,mode)
  108. else typerr(car u,"operator")
  109. end;
  110. put('lambda,'form2fn,'formlis);
  111. symbolic procedure argnochk u;
  112. begin scalar x;
  113. if null !*argnochk then return u
  114. else if (x := argsofopr car u) and x neq length cdr u
  115. %% and null get(car u,'simpfn)
  116. and null (get(car u,'simpfn) or get(car u,'psopfn)) % FJW ?????
  117. then rerror('rlisp,11,list(car u,"called with",
  118. length cdr u,
  119. if length cdr u=1 then "argument"
  120. else "arguments",
  121. "instead of",x))
  122. else return u
  123. end;
  124. symbolic procedure argsofopr u;
  125. % This function may be optimizable in various implementations.
  126. get(u,'number!-of!-args);
  127. symbolic procedure intexprnp(u,vars);
  128. %determines if U is an integer expression;
  129. if atom u then if numberp u then fixp u
  130. else if (u := atsoc(u,vars)) then cdr u eq 'integer
  131. else nil
  132. else idp car u and flagp(car u,'intfn) and intexprlisp(cdr u,vars);
  133. symbolic procedure intexprlisp(u,vars);
  134. null u or intexprnp(car u,vars) and intexprlisp(cdr u,vars);
  135. flag('(difference minus plus times),'intfn);
  136. % EXPT is not included in this list, because a negative exponent can
  137. % cause problems (i.e., result can be rational);
  138. symbolic procedure formlis(u,vars,mode);
  139. begin scalar x;
  140. a: if null u then return reversip!* x;
  141. x := form1(car u,vars,mode) . x;
  142. u := cdr u;
  143. go to a
  144. end;
  145. symbolic procedure formclis(u,vars,mode);
  146. begin scalar x;
  147. a: if null u then return reversip!* x;
  148. x := formc(car u,vars,mode) . x;
  149. u := cdr u;
  150. go to a
  151. end;
  152. symbolic procedure form u;
  153. if null atom u and flagp(car u,'always_nform)
  154. then n_form u % REDUCE 4.
  155. else if null !*rlisp88 then form1(u,!*vars!*,!*mode)
  156. else if null(!*mode eq 'symbolic)
  157. or flagp(u,'modefn) and null(u eq 'symbolic)
  158. or flagpcar(u,'modefn) and null(car u eq 'symbolic)
  159. then typerr("algebraic expression","Rlisp88 form")
  160. else form1(u,!*vars!*,!*mode);
  161. symbolic procedure macrochk(u,mode);
  162. begin scalar y;
  163. % Expands U if CAR U is a macro and expansion allowed.
  164. % This model has the problem that nested macros are not expanded
  165. % at this point (but they will be in the compiler).
  166. if atom u then return u
  167. else if (y := expdrmacro car u)
  168. and (mode eq 'symbolic or idp car u and flagp(car u,'opfn))
  169. then return apply3(get(car y,'macrofn),cdr y,cdr u,car u)
  170. else return u
  171. end;
  172. put('symbolic,'idfn,'symbid);
  173. symbolic procedure symbid(u,vars);
  174. <<if fname!* and null(ftype!* memq '(macro smacro))
  175. and not(atsoc(u,vars) or fluidp u or globalp u
  176. or null u or u eq t or flagp(u,'share) or !*comp)
  177. then lprim list("nonlocal use of undeclared variable",u,
  178. "in procedure",fname!*);
  179. u>>;
  180. put('algebraic,'idfn,'algid);
  181. symbolic procedure algid(u,vars);
  182. if atsoc(u,vars) or flagp(u,'share) then u else mkquote u;
  183. put('integer,'idfn,'intid);
  184. symbolic procedure intid(u,vars);
  185. begin scalar x,y;
  186. return if (x := atsoc(u,vars))
  187. then if cdr x eq 'integer then u
  188. else if y := get(cdr x,'integer)
  189. then apply2(y,u,vars)
  190. else if cdr x eq 'scalar then !*!*a2i(u,vars)
  191. else rerror('rlisp,12,
  192. list(cdr x,"not convertable to INTEGER"))
  193. else !*!*a2i(mkquote u,vars)
  194. end;
  195. symbolic procedure convertmode(exprn,vars,target,source);
  196. convertmode1(form1(exprn,vars,source),vars,target,source);
  197. symbolic procedure convertmode1(exprn,vars,target,source);
  198. begin scalar x;
  199. if source eq 'real then source := 'algebraic;
  200. if target eq 'real then target := 'algebraic;
  201. if target eq source then return exprn
  202. else if idp exprn and (x := atsoc(exprn,vars))
  203. and not(cdr x memq '(integer scalar real))
  204. and not(cdr x eq source)
  205. then return convertmode(exprn,vars,target,cdr x)
  206. else if not (x := get(source,target))
  207. then typerr(source,target)
  208. else return apply2(x,exprn,vars)
  209. end;
  210. put('algebraic,'symbolic,'!*!*a2s);
  211. put('symbolic,'algebraic,'!*!*s2a);
  212. symbolic procedure !*!*a2s(u,vars);
  213. % It would be nice if we could include the ATSOC(U,VARS) line,
  214. % since in many cases that would save recomputation. However,
  215. % in any sequential process, assignments or substitution rules
  216. % can change the value of a variable, so we have to check its
  217. % value again. More comprehensive analysis could certainly
  218. % optimize this. We could also avoid wrapping an integer, thus
  219. % making a mode change only occur within an expression.
  220. if null u then rederr "tell Hearn!!"
  221. % else if constantp u and null fixp u
  222. % or intexprnp(u,vars) and null !*composites
  223. % and null current!-modulus
  224. else if flagpcar(u,'nochange) and not(car u eq 'getel)
  225. then u
  226. % Expressions involving "random" cannot be cached.
  227. else if smember('random,u) then
  228. list(list('lambda,'(!*uncached),list(!*!*a2sfn,u)),t)
  229. else list(!*!*a2sfn,u);
  230. symbolic procedure !*!*s2a(u,vars); u;
  231. symbolic procedure formc(u,vars,mode);
  232. %this needs to be generalized;
  233. if !*rlisp88 and flagpcar(u,'modefn) and null(car u eq 'symbolic)
  234. then typerr("algebraic expression","Rlisp88 form")
  235. else if mode eq 'algebraic and intexprnp(u,vars) then u
  236. else convertmode(u,vars,'symbolic,mode);
  237. symbolic procedure intargfn(u,vars,mode);
  238. % transforms array element U into expression with integer arguments.
  239. % Array name is treated as an algebraic variable;
  240. begin scalar x,y;
  241. y := cdr u;
  242. a: if y then progn(x := convertmode(car y,vars,'integer,mode) . x,
  243. y := cdr y,
  244. go to a);
  245. return 'list . form1(car u,vars,'algebraic) . reversip!* x
  246. end;
  247. put('algebraic,'integer,'!*!*a2i);
  248. symbolic procedure !*!*a2i(u,vars);
  249. if intexprnp(u,vars) then u else list('ieval,u);
  250. symbolic procedure ieval u; !*s2i reval u;
  251. flag('(ieval),'opfn); % To make it a symbolic operator.
  252. flag('(ieval),'nochange);
  253. put('symbolic,'integer,'!*!*s2i);
  254. symbolic procedure !*!*s2i(u,vars);
  255. if fixp u then u else list('!*s2i,u);
  256. symbolic procedure !*s2i u;
  257. if fixp u then u else typerr(u,"integer");
  258. put('integer,'symbolic,'identity);
  259. symbolic procedure identity(u,vars); u;
  260. symbolic procedure formbool(u,vars,mode);
  261. if mode eq 'symbolic then formc(u,vars,mode)
  262. else if atom u then if u eq 't then u
  263. else if not idp u or atsoc(u,vars)
  264. then list('boolvalue!*,u)
  265. else list('boolvalue!*,formc!*(u,vars,mode))
  266. else if intexprlisp(cdr u,vars) and get(car u,'boolfn) then u
  267. else if idp car u and get(car u,'boolfn)
  268. then get(car u,'boolfn) . formclis(cdr u,vars,mode)
  269. else if idp car u and flagp(car u,'boolean)
  270. then car u . formboollis(cdr u,vars,mode,flagp(car u,'boolargs))
  271. else if car u eq 'boolvalue!* then rederr("Too many formbools")
  272. else if car u eq 'where
  273. then list('boolvalue!*,
  274. formc!*(list('where,
  275. mkquote list('bool!-eval,formbool(cadr u,vars,mode)),
  276. caddr u),
  277. vars,mode))
  278. else list('boolvalue!*,formc!*(u,vars,mode));
  279. symbolic procedure formboollis(u,vars,mode,bool);
  280. begin scalar x;
  281. a: if null u then return reversip!* x
  282. else if bool then x := formbool(car u,vars,mode) . x
  283. else x := formc!*(car u,vars,mode) . x;
  284. u := cdr u;
  285. go to a
  286. end;
  287. symbolic procedure bool!-eval u; lispeval u;
  288. flag('(bool!-eval),'noform);
  289. flag('(bool!-eval),'opfn); % symbolic operator bool!-eval.
  290. flag('(bool!-eval),'noval);
  291. symbolic procedure boolvalue!* u; u and null(u = 0);
  292. symbolic procedure formc!*(u,vars,mode);
  293. begin scalar !*!*a2sfn;
  294. !*!*a2sfn := 'revalx;
  295. return formc(u,vars,mode)
  296. end;
  297. symbolic procedure revalx u;
  298. % Defined this way to handle standard form kernels in pattern
  299. % matching.
  300. reval if not atom u and not atom car u then prepf u else u;
  301. % Functions with side effects must be handled carefully in this model,
  302. % otherwise they are not always evaluated within blocks.
  303. symbolic procedure formrerror(u,vars,mode);
  304. begin scalar x;
  305. argnochk u;
  306. if not fixp caddr u then typerr(caddr u,"RERROR argument");
  307. x := formc!*(cadddr u,vars,mode);
  308. if idp cadr u then return list('rerror,mkquote cadr u,caddr u,x)
  309. else if eqcar(cadr u,'quote) and idp cadadr u
  310. then return list('rerror,cadr u,caddr u,x)
  311. else typerr(cadr u,"RERROR argument")
  312. end;
  313. deflist('((rerror formrerror)),'formfn); % For bootstrapping.
  314. symbolic procedure formrederr(u,vars,mode);
  315. list('rederr,formc!*(cadr u,vars,mode));
  316. put('rederr,'formfn,'formrederr);
  317. symbolic procedure formreturn(u,vars,mode);
  318. % begin scalar x;
  319. % x := form1(cadr u,vars,mode); % FORMC here would add REVAL
  320. % if not(mode memq '(symbolic integer real))
  321. % and eqcar(x,'setq) % Should this be more general?
  322. % then x := list(!*!*a2sfn,x);
  323. % return list('return,x)
  324. % end;
  325. list('return,formc(cadr u,vars,mode));
  326. put('return,'formfn,'formreturn);
  327. symbolic procedure rsverr x;
  328. rerror('rlisp,13,list (x,"is a reserved identifier"));
  329. symbolic procedure mksetshare(u,v);
  330. mksetq(u,list('progn,'(setq alglist!* (cons nil nil)),v));
  331. symbolic procedure formsetq(u,vars,mode);
  332. begin scalar x,y,z;
  333. if idp(z := car(u := cdr u)) then y := atsoc(z,vars);
  334. if eqcar(cadr u,'quote) then mode := 'symbolic;
  335. % Make target always SYMBOLIC so that algebraic expressions
  336. % are evaluated before being stored.
  337. x := convertmode(cadr u,vars,'symbolic,mode);
  338. return if not atom z
  339. then if not idp car z then typerr(z,"assignment")
  340. else if null atom(z := macrochk(z,mode)) and arrayp car z
  341. then list('setel,intargfn(z,vars,mode),x)
  342. else if null atom z
  343. and cdr z and (get(car z,'rtype) eq 'vector
  344. or vectorp cadr z
  345. or flagpcar(cadr z,'vecfn))
  346. then putvect(u,vars,mode)
  347. else if eqcar(z,'part)
  348. then aconc('list .
  349. mkquote 'setpart!* . formlis(cdr z,vars,mode),x)
  350. else if null atom z and (y := get(car z,'setqfn))
  351. then form1(applsmacro(y,append(cdr z,cdr u),nil),vars,mode)
  352. else if mode eq 'symbolic
  353. and (!*rlisp88 or eqcar(z,'structfetch))
  354. % Allow for Rlisp '88 records in general Rlisp.
  355. then list('rsetf,form1(z,vars,mode),x)
  356. else list('setk,form1(z,vars,'algebraic),x)
  357. % algebraic needed above, since SETK expects it.
  358. else if not idp z then typerr(z,"assignment")
  359. else if flagp(z,'reserved) and null atsoc(z,vars) then rsverr z
  360. else if flagp(z,'share) then mksetshare(symbid(z,vars),x)
  361. else if mode eq 'symbolic or y or eqcar(x,'quote)
  362. then mksetq(symbid(z,vars),x)
  363. else if vectorp cadr u or flagpcar(cadr u,'vecfn)
  364. then list('setv,mkquote z,cadr u)
  365. else list('setk,mkquote z,x)
  366. end;
  367. put('setq,'formfn,'formsetq);
  368. % Table of SETQFNs.
  369. symbolic procedure setcar(a,b); progn(rplaca(a,b),b);
  370. symbolic procedure setcdr(a,b); progn(rplacd(a,b),b);
  371. put('car,'setqfn,'(lambda (u v) (setcar u v)));
  372. put('cdr,'setqfn,'(lambda (u v) (setcdr u v)));
  373. put('caar,'setqfn,'(lambda (u v) (setcar (car u) v)));
  374. put('cadr,'setqfn,'(lambda (u v) (setcar (cdr u) v)));
  375. put('cdar,'setqfn,'(lambda (u v) (setcdr (car u) v)));
  376. put('cddr,'setqfn,'(lambda (u v) (setcdr (cdr u) v)));
  377. put('caaar,'setqfn,'(lambda (u v) (setcar (caar u) v)));
  378. put('caadr,'setqfn,'(lambda (u v) (setcar (cadr u) v)));
  379. put('cadar,'setqfn,'(lambda (u v) (setcar (cdar u) v)));
  380. put('caddr,'setqfn,'(lambda (u v) (setcar (cddr u) v)));
  381. put('cdaar,'setqfn,'(lambda (u v) (setcdr (caar u) v)));
  382. put('cdadr,'setqfn,'(lambda (u v) (setcdr (cadr u) v)));
  383. put('cddar,'setqfn,'(lambda (u v) (setcdr (cdar u) v)));
  384. put('cdddr,'setqfn,'(lambda (u v) (setcdr (cddr u) v)));
  385. put('caaaar,'setqfn,'(lambda (u v) (setcar (caaar u) v)));
  386. put('caaadr,'setqfn,'(lambda (u v) (setcar (caadr u) v)));
  387. put('caadar,'setqfn,'(lambda (u v) (setcar (cadar u) v)));
  388. put('caaddr,'setqfn,'(lambda (u v) (setcar (caddr u) v)));
  389. put('cadaar,'setqfn,'(lambda (u v) (setcar (cdaar u) v)));
  390. put('cadadr,'setqfn,'(lambda (u v) (setcar (cdadr u) v)));
  391. put('caddar,'setqfn,'(lambda (u v) (setcar (cddar u) v)));
  392. put('cadddr,'setqfn,'(lambda (u v) (setcar (cdddr u) v)));
  393. put('cdaaar,'setqfn,'(lambda (u v) (setcdr (caaar u) v)));
  394. put('cdaadr,'setqfn,'(lambda (u v) (setcdr (caadr u) v)));
  395. put('cdadar,'setqfn,'(lambda (u v) (setcdr (cadar u) v)));
  396. put('cdaddr,'setqfn,'(lambda (u v) (setcdr (caddr u) v)));
  397. put('cddaar,'setqfn,'(lambda (u v) (setcdr (cdaar u) v)));
  398. put('cddadr,'setqfn,'(lambda (u v) (setcdr (cdadr u) v)));
  399. put('cdddar,'setqfn,'(lambda (u v) (setcdr (cddar u) v)));
  400. put('cddddr,'setqfn,'(lambda (u v) (setcdr (cdddr u) v)));
  401. put('nth,'setqfn,'(lambda (l i x) (setcar (pnth l i) x)));
  402. put('getv,'setqfn,'(lambda (v i x) (putv v i x)));
  403. put('igetv,'setqfn,'(lambda (v i x) (iputv v i x)));
  404. symbolic procedure formfunc(u,vars,mode);
  405. if idp cadr u then if getrmacro cadr u
  406. then rerror('rlisp,14,list("Macro",cadr u,"Used as Function"))
  407. else list('function,cadr u)
  408. else list('function,form1(cadr u,vars,mode));
  409. put('function,'formfn,'formfunc);
  410. % RLIS is a parser function that reads a list of arguments and returns
  411. % this list as one argument. It needs to be defined in this module for
  412. % bootstrapping purposes since this definition only works with its form
  413. % function.
  414. symbolic procedure rlis;
  415. begin scalar x;
  416. x := cursym!*;
  417. return if flagp(scan(),'delim) then list(x,nil)
  418. else if !*reduce4
  419. then list(x,'list . remcomma xread1 'lambda)
  420. else x . remcomma xread1 'lambda
  421. end;
  422. symbolic procedure flagop u; begin flag(u,'flagop); rlistat u end;
  423. symbolic procedure rlistat u;
  424. begin
  425. a: if null u then return nil;
  426. put(car u,'stat,'rlis);
  427. u := cdr u;
  428. go to a
  429. end;
  430. rlistat '(flagop);
  431. symbolic procedure formrlis(u,vars,mode);
  432. if not flagp(car u,'flagop)
  433. then list(car u,'list .
  434. if car u eq 'share
  435. then (begin scalar x,y;
  436. y := cdr u;
  437. a: if null y then return reversip!* x;
  438. x := mkquote car y . x;
  439. y := cdr y;
  440. go to a
  441. end)
  442. else formlis(cdr u,vars,'algebraic))
  443. else if not idlistp cdr u
  444. then typerr('!*comma!* . cdr u,"identifier list")
  445. else list('flag,
  446. 'list . formlis(cdr u,vars,'algebraic),mkquote car u);
  447. symbolic procedure mkarg(u,vars);
  448. % Returns the "unevaled" form of U.
  449. if null u or constantp u then u
  450. else if atom u then if atsoc(u,vars) then u else mkquote u
  451. else if car u memq '(quote !:dn!: !:int!:) then mkquote u
  452. else begin scalar x;
  453. a: if null u then return 'list . reversip!* x;
  454. x := mkarg(car u,vars) . x;
  455. u := cdr u;
  456. go to a
  457. end;
  458. % Form functions needed for number input.
  459. put('!:dn!:,'formfn,'dnform);
  460. % symbolic procedure dnform(u,vars,mode);
  461. % if mode eq 'symbolic
  462. % then compress nconc!*(explode cadr u,'!. . 'e . explode cddr u)
  463. % else progn(if !*adjprec then precmsg length explode abs cadr u,
  464. % mkquote(quote !:rd!: . cdr u));
  465. symbolic procedure dnform(u,vars,mode);
  466. if mode eq 'symbolic
  467. then compress nconc!*(explode cadr u,'!. . 'e . explode cddr u)
  468. else progn(if !*adjprec then precmsg length explode abs cadr u,
  469. mkquote if cddr u >= 0
  470. then decimal2internal(cadr u,cddr u)
  471. else u);
  472. put('!:int!:,'formfn,'intform);
  473. symbolic procedure intform(u,vars,mode);
  474. if mode eq 'symbolic then mkquote cadr u
  475. else progn(precmsg length explode abs cadr u, mkquote cadr u);
  476. endmodule;
  477. end;