easy-non-sl.red 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. %
  2. % EASY-NON-SL.RED - Commonly used Non-Standard Lisp functions
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 18 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.KERNEL>EASY-NON-SL.RED.2, 17-Sep-82 16:10:18, Edit by BENSON
  12. % Added ChannelPrin2T, ChannelSpaces, ChannelTab, ChannelSpaces2
  13. % <PSL.INTERP>EASY-NON-SL.RED.7, 9-Jul-82 12:46:43, Edit by BENSON
  14. % Changed NTH to improve error reporting, using DoPNTH
  15. % <PSL.INTERP>EASY-NON-SL.RED.2, 19-Apr-82 23:05:35, Edit by BENSON
  16. % Changed order of tests in PNTH
  17. % <PSL.INTERP>EASY-NON-SL.RED.20, 23-Feb-82 21:36:36, Edit by BENSON
  18. % Added NE (not eq)
  19. % <PSL.INTERP>EASY-NON-SL.RED.19, 16-Feb-82 22:30:33, Edit by BENSON
  20. % made NEQ GEQ and LEQ back into EXPRs
  21. % <PSL.INTERP>EASY-NON-SL.RED.16, 15-Feb-82 18:01:14, Edit by BENSON
  22. % Made NEQ GEQ and LEQ into macros
  23. % <PSL.INTERP>EASY-NON-SL.RED.12, 18-Jan-82 12:28:13, Edit by BENSON
  24. % Added NexprP
  25. CompileTime flag('(DelqIP1 DeletIP1 SubstIP1 DelAscIP1 DelAtQIP1 DoPNTH),
  26. 'InternalFunction);
  27. % predicates
  28. expr procedure NEQ(U, V); %. not EQUAL (should be changed to not EQ)
  29. not(U = V);
  30. expr procedure NE(U, V); %. not EQ
  31. not(U eq V);
  32. expr procedure GEQ(U, V); %. greater than or equal to
  33. not(U < V);
  34. expr procedure LEQ(U, V); %. less than or equal to
  35. not(U > V);
  36. lisp procedure EqCar(U, V); %. car U eq V
  37. PairP U and car U eq V;
  38. lisp procedure ExprP U; %. Is U an EXPR?
  39. EqCar(U, 'LAMBDA) or CodeP U or EqCar(GetD U, 'EXPR);
  40. lisp procedure MacroP U; %. Is U a MACRO?
  41. EqCar(GetD U, 'MACRO);
  42. lisp procedure FexprP U; %. Is U an FEXPR?
  43. EqCar(GetD U, 'FEXPR);
  44. lisp procedure NexprP U; %. Is U an NEXPR?
  45. EqCar(GetD U, 'NEXPR);
  46. % Function definition
  47. lisp procedure CopyD(New, Old); %. FunDef New := FunDef Old;
  48. %
  49. % CopyD(New:id, Old:id):id
  50. % -----------------------
  51. % Type: EVAL, SPREAD
  52. % The function body and type for New become the same as Old. If no
  53. % definition exists for Old, the error
  54. %
  55. % ***** `Old' has no definition in CopyD
  56. %
  57. % occurs. New is returned.
  58. %
  59. begin scalar OldDef;
  60. OldDef := GetD Old;
  61. if PairP OldDef then
  62. PutD(New, car OldDef, cdr OldDef)
  63. else
  64. StdError BldMsg("%r has no definition in CopyD", Old);
  65. return New;
  66. end;
  67. % Numerical functions
  68. lisp procedure Recip N; %. Floating point reciprocal
  69. 1.0 / N;
  70. % Commonly used constructors
  71. lisp procedure MkQuote U; %. Eval MkQuote U eq U
  72. list('QUOTE, U);
  73. % Nicer names to access parts of a list
  74. macro procedure First U; %. First element of a list
  75. 'CAR . cdr U;
  76. macro procedure Second U; %. Second element of a list
  77. 'CADR . cdr U;
  78. macro procedure Third U; %. Third element of a list
  79. 'CADDR . cdr U;
  80. macro procedure Fourth U; %. Fourth element of a list
  81. 'CADDDR . cdr U;
  82. macro procedure Rest U; %. Tail of a list
  83. 'CDR . cdr U;
  84. % Destructive and EQ versions of Standard Lisp functions
  85. lisp procedure ReversIP U; %. Destructive REVERSE (REVERSe In Place)
  86. begin scalar X,Y;
  87. while PairP U do
  88. << X := cdr U;
  89. Y := RplacD(U, Y);
  90. U := X >>;
  91. return Y
  92. end;
  93. lisp procedure SubstIP1(A, X, L); % Auxiliary function for SubstIP
  94. << if X = car L then RplacA(L, A)
  95. else if PairP car L then SubstIP(A, X, car L);
  96. if PairP cdr L then SubstIP(A, X, cdr L) >>;
  97. lisp procedure SubstIP(A, X, L); %. Destructive version of Subst
  98. if null L then NIL
  99. else if X = L then A
  100. else if not PairP L then L
  101. else
  102. << SubstIP1(A, X, L);
  103. L >>;
  104. lisp procedure DeletIP1(U, V); % Auxiliary function for DeletIP
  105. if PairP cdr V then
  106. if U = cadr V then RplacD(V, cddr V)
  107. else DeletIP1(U, cdr V);
  108. lisp procedure DeletIP(U, V); %. Destructive DELETE
  109. if not PairP V then V
  110. else if U = car V then cdr V
  111. else
  112. << DeletIP1(U, V);
  113. V >>;
  114. lisp procedure DelQ(U, V); %. EQ version of DELETE
  115. if not PairP V then V
  116. else if car V eq U then cdr V
  117. else car V . DelQ(U, cdr V);
  118. lisp procedure Del(F, U, V); %. Generalized Delete, F is comparison function
  119. if not PairP V then V
  120. else if Apply(F, list(car V, U)) then cdr V
  121. else car V . Del(F, U, cdr V);
  122. lisp procedure DelqIP1(U, V); % Auxiliary function for DelqIP
  123. if PairP cdr V then
  124. if U eq cadr V then RplacD(V, cddr V)
  125. else DelqIP1(U, cdr V);
  126. lisp procedure DelqIP(U, V); %. Destructive DELQ
  127. if not PairP V then V
  128. else if U eq car V then cdr V
  129. else
  130. << DelqIP1(U, V);
  131. V >>;
  132. lisp procedure Atsoc(U, V); %. EQ version of ASSOC
  133. if not PairP V then NIL
  134. else if PairP car V and U eq caar V then car V
  135. else Atsoc(U, cdr V);
  136. lisp procedure Ass(F, U, V); %. Generalized Assoc, F is comparison function
  137. %
  138. % Not to be confused with Elbow
  139. %
  140. if not PairP V then NIL
  141. else if PairP car V and Apply(F, list(U, caar V)) then car V
  142. else Ass(F, U, cdr V);
  143. lisp procedure Mem(F, U, V); %. Generalized Member, F is comparison function
  144. if not PairP V then NIL
  145. else if Apply(F, list(U, car V)) then V
  146. else Mem(F, U, cdr V);
  147. lisp procedure RAssoc(U, V); %. Reverse Assoc, compare with cdr of entry
  148. if not PairP V then NIL
  149. else if PairP car V and U = cdar V then car V
  150. else RAssoc(U, cdr V);
  151. lisp procedure DelAsc(U, V); %. Remove first (U . xxx) from V
  152. if not PairP V then NIL
  153. else if PairP car V and U = caar V then cdr V
  154. else car V . DelAsc(U, cdr V);
  155. lisp procedure DelAscIP1(U, V); % Auxiliary function for DelAscIP
  156. if PairP cdr V then
  157. if PairP cadr V and U = caadr V then
  158. RplacD(V, cddr V)
  159. else DelAscIP1(U, cdr V);
  160. lisp procedure DelAscIP(U, V); %. Destructive DelAsc
  161. if not PairP V then NIL
  162. else if PairP car V and U = caar V then cdr V
  163. else
  164. << DelAscIP1(U, V);
  165. V >>;
  166. lisp procedure DelAtQ(U, V); %. EQ version of DELASC
  167. if not PairP V then NIL
  168. else if EqCar(car V, U) then cdr V
  169. else car V . DelAtQ(U, cdr V);
  170. lisp procedure DelAtQIP1(U, V); % Auxiliary function for DelAtQIP
  171. if PairP cdr V then
  172. if PairP cadr V and U eq caadr V then
  173. RplacD(V, cddr V)
  174. else DelAtQIP1(U, cdr V);
  175. lisp procedure DelAtQIP(U, V); %. Destructive DelAtQ
  176. if not PairP V then NIL
  177. else if PairP car V and U eq caar V then cdr V
  178. else
  179. << DelAtQIP1(U, V);
  180. V >>;
  181. lisp procedure SublA(U,V); %. EQ version of SubLis, replaces atoms only
  182. begin scalar X;
  183. return if not PairP U or null V then V
  184. else if atom V then
  185. if (X := Atsoc(V, U)) then cdr X else V
  186. else SublA(U, car V) . SublA(U, cdr V)
  187. end;
  188. lisp procedure RplacW(A, B); %. RePLACe Whole pair
  189. if PairP A then
  190. if PairP B then
  191. RplacA(RplacD(A,
  192. cdr B),
  193. car B)
  194. else
  195. NonPairError(B, 'RplacW)
  196. else
  197. NonPairError(A, 'RPlacW);
  198. lisp procedure LastCar X; %. last element of list
  199. if atom X then X else car LastPair X;
  200. lisp procedure LastPair X; %. last pair of list
  201. if atom X or atom cdr X then X else LastPair cdr X;
  202. lisp procedure Copy U; %. copy all pairs in S-Expr
  203. %
  204. % See also TotalCopy in COPIERS.RED
  205. %
  206. if PairP U then Copy car U . Copy cdr U else U; % blows up if circular
  207. lisp procedure NTH(U, N); %. N-th element of list
  208. (lambda(X);
  209. if PairP X then car X else RangeError(U, N, 'NTH))(DoPNTH(U, N));
  210. lisp procedure DoPNTH(U, N);
  211. if N = 1 or not PairP U then U
  212. else DoPNTH(cdr U, N - 1);
  213. lisp procedure PNTH(U, N); %. Pointer to N-th element of list
  214. if N = 1 then U
  215. else if not PairP U then
  216. RangeError(U, N, 'PNTH)
  217. else PNTH(cdr U, N - 1);
  218. lisp procedure AConc(U, V); %. destructively add element V to the tail of U
  219. NConc(U, list V);
  220. lisp procedure TConc(Ptr, Elem); %. AConc maintaining pointer to end
  221. %
  222. % ACONC with pointer to end of list
  223. % Ptr is (list . last CDR of list)
  224. % returns updated Ptr
  225. % Ptr should be initialized to (NIL . NIL) before calling the first time
  226. %
  227. << Elem := list Elem;
  228. if not PairP Ptr then % if PTR not initialized, return starting ptr
  229. Elem . Elem
  230. else if null cdr Ptr then % Nothing in the list yet
  231. RplacA(RplacD(Ptr, Elem), Elem)
  232. else
  233. << RplacD(cdr Ptr, Elem);
  234. RplacD(Ptr, Elem) >> >>;
  235. lisp procedure LConc(Ptr, Lst); %. NConc maintaining pointer to end
  236. %
  237. % NCONC with pointer to end of list
  238. % Ptr is (list . last CDR of list)
  239. % returns updated Ptr
  240. % Ptr should be initialized to NIL . NIL before calling the first time
  241. %
  242. if null Lst then Ptr
  243. else if atom Ptr then % if PTR not initialized, return starting ptr
  244. Lst . LastPair Lst
  245. else if null cdr Ptr then % Nothing in the list yet
  246. RplacA(RplacD(Ptr, LastPair Lst), Lst)
  247. else
  248. << RplacD(cdr Ptr, Lst);
  249. RplacD(Ptr, LastPair Lst) >>;
  250. % MAP functions of 2 arguments
  251. lisp procedure Map2(L, M, Fn); %. for each X, Y on L, M do Fn(X, Y);
  252. << while PairP L and PairP M do
  253. << Apply(Fn, list(L, M));
  254. L := cdr L;
  255. M := cdr M >>;
  256. if PairP L or PairP M then
  257. StdError "Different length lists in MAP2"
  258. else NIL >>;
  259. lisp procedure MapC2(L, M, Fn); %. for each X, Y in L, M do Fn(X, Y);
  260. << while PairP L and PairP M do
  261. << Apply(Fn, list(car L, car M));
  262. L := cdr L;
  263. M := cdr M >>;
  264. if PairP L or PairP M then
  265. StdError "Different length lists in MAPC2"
  266. else NIL >>;
  267. % Printing functions
  268. lisp procedure ChannelPrin2T(C, U); %. Prin2 and TerPri
  269. << ChannelPrin2(C, U);
  270. ChannelTerPri C;
  271. U >>;
  272. lisp procedure Prin2T U; %. Prin2 and TerPri
  273. ChannelPrin2T(OUT!*, U);
  274. lisp procedure ChannelSpaces(C, N); %. Prin2 N spaces
  275. for I := 1 step 1 until N do ChannelWriteChar(C, char BLANK);
  276. lisp procedure Spaces N; %. Prin2 N spaces
  277. ChannelSpaces(OUT!*, N);
  278. lisp procedure ChannelTAB(Chn, N); %. Spaces to column N
  279. begin scalar M;
  280. M := ChannelPosn Chn;
  281. if N < M then
  282. << ChannelTerPri Chn;
  283. M := 0 >>;
  284. ChannelSpaces(Chn, N - M);
  285. end;
  286. lisp procedure TAB N; %. Spaces to column N
  287. ChannelTAB(OUT!*, N);
  288. if_system(Dec20, <<
  289. lap '((!*entry FileP expr 1)
  290. (!*MOVE (REG 1) (REG 2))
  291. (hrli 2 8#010700) % make a byte pointer
  292. (hrlzi 1 2#001000000000000001) % gj%old + gj%sht
  293. (gtjfn)
  294. (jrst NotFile)
  295. (rljfn) % release it
  296. (jfcl)
  297. (!*MOVE (QUOTE T) (REG 1))
  298. (!*EXIT 0)
  299. NotFile
  300. (!*MOVE (QUOTE NIL) (REG 1))
  301. (!*EXIT 0)
  302. ); >>, <<
  303. lisp procedure FileP F; %. is F an existing file?
  304. %
  305. % This could be done more efficiently in a much more system-dependent way,
  306. % but efficiency probably doesn't matter too much here.
  307. %
  308. if PairP(F := ErrorSet(list('OPEN, MkQuote F, '(QUOTE INPUT)), NIL, NIL))
  309. then
  310. << Close car F;
  311. T >>
  312. else NIL; >>);
  313. % This doesn't belong anywhere and will be eliminated soon
  314. lisp procedure PutC(Name, Ind, Exp); %. Used by RLISP to define SMACROs
  315. << put(Name, Ind, Exp);
  316. Name >>;
  317. LoadTime <<
  318. PutD('Spaces2, 'EXPR, cdr GetD 'TAB); % For compatibility
  319. PutD('ChannelSpaces2, 'EXPR, cdr GetD 'ChannelTAB);
  320. >>;
  321. END;