reval.red 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. module reval; % Functions for algebraic evaluation of prefix forms.
  2. % Author: Anthony C. Hearn.
  3. % Copyright (c) 1991 RAND. All rights reserved.
  4. fluid '(!*exp !*intstr !*listargs !*resimp alglist!* dmode!* subfg!*
  5. varstack!*);
  6. switch listargs;
  7. global '(!*resubs !*sqvar!* !*val);
  8. symbolic procedure reval u;
  9. reval1(u,t);
  10. symbolic procedure aeval u;
  11. reval1(u,nil);
  12. symbolic procedure aeval!* u;
  13. % This version rebinds alglist!* to avoid invalid computation in
  14. % loops.
  15. begin scalar alglist!*;
  16. return reval1(u,nil)
  17. end;
  18. symbolic procedure reval1(u,v);
  19. (begin scalar x,y;
  20. if null u then return nil % this may give trouble
  21. else if stringp u then return u
  22. else if fixp u
  23. then return if flagp(dmode!*,'convert) then reval2(u,v) else u
  24. else if atom u
  25. then if null subfg!* then return u
  26. else if idp u and (x := get(u,'avalue))
  27. then if u memq varstack!* then recursiveerror u
  28. else <<varstack!* := u . varstack!*;
  29. return if y := get(car x,'evfn)
  30. then apply2(y,u,v)
  31. else reval1(cadr x,v)>>
  32. else nil
  33. else if not idp car u % or car u eq '!*comma!*
  34. then errpri2(u,t)
  35. else if car u eq '!*sq
  36. then return if caddr u and null !*resimp
  37. then if null v then u else prepsqxx cadr u
  38. else reval2(u,v)
  39. else if flagp(car u,'remember) then return rmmbreval(u,v)
  40. else if flagp(car u,'opfn) then return reval1(opfneval u,v)
  41. else if x := get(car u,'psopfn)
  42. then <<u := apply1(x,cdr u);
  43. if x := get(x,'cleanupfn) then u := apply2(x,u,v);
  44. return u>>
  45. % Note that we assume that the results of such functions are
  46. % always returned in evaluated form.
  47. else if arrayp car u then return reval1(getelv u,v);
  48. return if x := getrtype u then
  49. if y := get(x,'evfn) then apply2(y,u,v)
  50. else rerror(alg,101,
  51. list("Missing evaluation for type",x))
  52. else if not atom u
  53. and not atom cdr u
  54. and null cddr u % Don't pass opr to list if
  55. % there is more than one arg.
  56. and (y := getrtype cadr u) eq 'list % Only lists
  57. and (x := get(y,'aggregatefn)) % for now.
  58. and not flagp(car u,'boolean)
  59. and not !*listargs and not flagp(car u,'listargp)
  60. then apply2(x,u,v)
  61. else reval2(u,v)
  62. end) where varstack!* := varstack!*;
  63. flagop listargp;
  64. symbolic procedure rmmbreval(u,v);
  65. % The leading operator of u is flagged 'remember.
  66. begin scalar fn,x,w,u1,u2;
  67. fn := car u;
  68. u1:={fn}; u2:={fn};
  69. for each y in cdr u do
  70. <<w:=reval1(y,nil); u2:=aconc(u2,w);
  71. if eqcar(w,'!*sq) then w:=!*q2a(cadr w);
  72. u1:=aconc(u1,w)>>;
  73. if (x:=assoc(u1,w:=get(fn,'kvalue))) then<<x:=cadr x; go to a>>;
  74. % Evaluate "algebraic procedure" and "algebraic operator" directly.
  75. if flagp(fn,'opfn) then x:= reval1(opfneval u2,v)
  76. else if get(fn,'simpfn) then x:=!*q2a1(simp!* u2,v)
  77. else % All others are passed to reval.
  78. << remflag({fn},'remember);
  79. x:=reval1(u2,v);
  80. flag({fn},'remember);
  81. >>;
  82. if not smember(u1,x) and not smember(u2,x)
  83. then put!-kvalue(fn,get(fn,'kvalue),(car u)
  84. . foreach uuu in cdr u collect reval uuu,x);
  85. a: return x;
  86. end;
  87. symbolic procedure remember u;
  88. % Remember declaration for operator and procedure names.
  89. for each fn in u do
  90. <<if not flagp(fn,'opfn) and null get(fn,'simpfn)
  91. then <<redmsg(fn,"operator"); mkop fn>>;
  92. if flagp(fn,'noval) or flagp(fn,'listargp)
  93. then typerr(fn,"remember operator");
  94. flag({fn},'remember);
  95. >>;
  96. put('remember,'stat,'rlis);
  97. symbolic procedure recursiveerror u;
  98. msgpri(nil,u,"improperly defined in terms of itself",nil,t);
  99. put('quote,'psopfn,'car); % Since we don't want this evaluated.
  100. symbolic procedure opfneval u;
  101. if flagp(car u ,'remember) then
  102. begin scalar interm,resul,x;
  103. interm := for each j in
  104. (if flagp(car u,'noval) then cdr u else revlis cdr u)
  105. collect if fixp j then j else mkquote j;
  106. if (x:=assoc(car u . interm ,get(car u,'kvalue)))
  107. then return cadr x;
  108. resul := lispeval(car u . interm);
  109. put!-kvalue(car u,get(car u,'kvalue), car u . interm, resul);
  110. return resul;
  111. end
  112. else
  113. lispeval(car u . for each j in
  114. (if flagp(car u,'noval) then cdr u else revlis cdr u)
  115. collect mkquote j);
  116. flag('(reval),'opfn); % to make it a symbolic operator.
  117. symbolic procedure reval2(u,v); !*q2a1(simp!* u,v);
  118. symbolic procedure getrtype u;
  119. % Returns overall algebraic type of u (or NIL is expression is a
  120. % scalar). Analysis is incomplete for efficiency reasons.
  121. % Type conflicts will later be resolved when expression is evaluated.
  122. begin scalar x,y;
  123. return
  124. if null u then nil % Suggested by P.K.H. Gragert to avoid the
  125. % loop caused if NIL has a share flag.
  126. else if atom u
  127. then if not idp u then not numberp u and getrtype1 u
  128. else if flagp(u,'share) % then getrtype lispeval u
  129. then if (x := eval u) eq u then nil else getrtype x
  130. else if (x := get(u,'avalue)) and
  131. not(car x memq '(scalar generic))
  132. or (x := get(u,'rtype)) and (x := list x)
  133. then if y := get(car x,'rtypefn) then apply1(y,nil)
  134. else car x
  135. else nil
  136. else if not idp car u then nil
  137. else if (x := get(car u,'avalue)) and (x := get(car x,'rtypefn))
  138. then apply1(x,cdr u)
  139. else getrtype2 u
  140. end;
  141. symbolic procedure getrtype1 u;
  142. % Placeholder for packages that use vectors.
  143. nil;
  144. symbolic procedure getrtype2 u;
  145. % Placeholder for packages that key expression type to the operator.
  146. begin scalar x;
  147. % Next line is maybe only needed by EXCALC.
  148. return if (x := get(car u,'rtype)) and (x := get(x,'rtypefn))
  149. then apply1(x,cdr u)
  150. else if x := get(car u,'rtypefn) then apply1(x,cdr u)
  151. else nil
  152. end;
  153. remprop('rtypecar,'stat);
  154. symbolic procedure rtypecar u;
  155. for each j in u do put(j,'rtypefn,'getrtypecar);
  156. deflist('((rtypecar rlis)),'stat);
  157. rtypecar difference,expt,minus,plus,recip;
  158. deflist('
  159. ((quotient getrtypeor)
  160. (times getrtypeor)
  161. (!*sq (lambda (x) nil))
  162. ),'rtypefn);
  163. symbolic procedure getrtypecar u; getrtype car u;
  164. symbolic procedure getrtypeor u;
  165. u and (getrtype car u or getrtypeor cdr u);
  166. symbolic procedure !*eqn2a u;
  167. % If u is an equation a=b, it is converted to an equivalent equation
  168. % a-b=0, or if a=0, b=0. Otherwise u is returned converted to true
  169. % prefix form.
  170. if not eqexpr u then prepsqyy u
  171. else if null cdr u or null cddr u or cdddr u
  172. then typerr(u,"equation")
  173. else (if rh=0 then lh else if lh=0 then rh else{'difference,lh,rh})
  174. where lh=prepsqyy cadr u,rh=prepsqyy caddr u;
  175. symbolic procedure prepsqyy u;
  176. if eqcar(u,'!*sq) then prepsqxx cadr u else u;
  177. symbolic procedure getelv u;
  178. % Returns the value of the array element U.
  179. % getel(car u . for each x in cdr u collect ieval x);
  180. getel(car u . for each x in cdr u collect reval_without_mod x);
  181. symbolic procedure setelv(u,v);
  182. % setel(car u . for each x in cdr u collect ieval x,v);
  183. setel(car u . for each x in cdr u collect reval_without_mod x,v);
  184. symbolic procedure reval_without_mod u;
  185. % Evaluate u without a modulus.
  186. if dmode!* eq '!:mod!: then (reval u where dmode!* = nil)
  187. else reval u;
  188. symbolic procedure revlis u; for each j in u collect reval j;
  189. symbolic procedure revop1 u;
  190. if !*val then car u . revlis cdr u else u;
  191. symbolic procedure mk!*sq u;
  192. % Modified by Francis J. Wright to return a list correctly.
  193. % if null numr u then 0
  194. % else if atom numr u and denr u=1 then numr u
  195. % else '!*sq . expchk u . if !*resubs then !*sqvar!* else list nil;
  196. (if null numr u then 0
  197. else if atom numr u and denr u=1 then numr u
  198. else if kernp u and eqcar(mvar numr u,'list) then mvar numr u
  199. else '!*sq . u . if !*resubs then !*sqvar!* else list nil)
  200. where u=expchk u;
  201. symbolic macro procedure !*sq u;
  202. % Provide an interface to symbolic mode.
  203. prepsq cadr u;
  204. symbolic procedure expchk u; if !*exp then u else offexpchk u;
  205. symbolic procedure lengthreval u;
  206. begin scalar v,w,x;
  207. if length u neq 1
  208. then rerror(alg,11,
  209. "LENGTH called with wrong number of arguments");
  210. u := car u;
  211. if idp u and arrayp u then return 'list . get(u,'dimension);
  212. v := aeval u;
  213. if (w := getrtype v) and (x := get(w,'lengthfn))
  214. then return apply1(x,v)
  215. else if atom v then return 1
  216. else if not idp car v or not(x := get(car v,'lengthfn))
  217. then if w
  218. then lprie list("LENGTH not defined for argument of type",w)
  219. else typerr(u,"LENGTH argument")
  220. else return apply1(x,cdr v)
  221. end;
  222. put('length,'psopfn,'lengthreval);
  223. % Code for evaluation of expressions whose type can only be
  224. % infered after partial evaluation.
  225. symbolic procedure yetunknowntypeeval(u,v);
  226. % Assumes that only psopfn's can produce yet unknown types.
  227. reval1(eval!-yetunknowntypeexpr(u,v),v);
  228. symbolic procedure eval!-yetunknowntypeexpr(u,v);
  229. if atom u
  230. then ((if w then eval!-yetunknowntypeexpr(cadr w,v)
  231. else u)
  232. where w = get(u,'avalue))
  233. else if car u eq '!*sq or get(car u,'dname) or car u eq '!:dn!:
  234. then u
  235. else ((if x and (getrtype u eq 'yetunknowntype)
  236. then apply1(x,cdr u)
  237. else car u . for each j in cdr u collect
  238. eval!-yetunknowntypeexpr(j,v))
  239. where x = get(car u,'psopfn));
  240. put('yetunknowntype,'evfn,'yetunknowntypeeval);
  241. endmodule;
  242. end;