zbasic.lsp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445
  1. (!*
  2. "ZBASIC contains 6 packages --
  3. (1) YLSTS -- useful functions for lists.
  4. (2) YNUMS -- useful functions for numbers.
  5. (3) YSTRS -- useful functions for strings.
  6. (4) YIO -- useful functions for user io.
  7. (5) YCNTRL -- useful functions for program control.
  8. (6) YRARE -- functions we use now, but may eliminate. ")
  9. (!*
  10. " YLSTS -- BASIC LIST UTILITIES
  11. CCAR ( X:any ):any
  12. CCDR ( X:any ):any
  13. LAST ( X:list ):any
  14. NTH-CDR ( L:list N:number ):list
  15. NTH-ELT ( L:list N:number ):elt of list
  16. NTH-TAIL( L:list N:number ):list
  17. TAIL-P ( X:list Y:list ):extra-boolean
  18. NCONS ( X:any ): (CONS X NIL)
  19. KWOTE ( X:any ): '<eval of #X>
  20. MKQUOTE ( X:any ): '<eval of #X>
  21. RPLACW ( X:list Y:list ):list
  22. DREMOVE ( X:any L:list ):list
  23. REMOVE ( X:any L:list ):list
  24. DSUBST ( X:any Y:any Z:list ):list
  25. LSUBST ( NEW:list OLD:list X:any ):list
  26. COPY ( X:list ):list
  27. TCONC ( P:list X:any ): tconc-ptr
  28. LCONC ( P:list X:list ):list
  29. CVSET ( X:list ):set
  30. ENTER ( ELT:element SET:list ):set
  31. ABSTRACT( FN:function L:list ):list
  32. EACH ( L:list FN:function ):extra-boolean
  33. SOME ( L:list FN:function ):extra-boolean
  34. INTERSECTION ( SET1:list SET2:list ):extra-boolean
  35. SETDIFFERENCE ( SET1:list SET2:list ):extra-boolean
  36. SUBSET ( SET1:any SET2:list ):extra boolean
  37. UNION ( X:list Y:list ):list
  38. SEQUAL ( X:list Y:list ):extra boolean
  39. MAP2C ( X:list Y:list FN:function ):NIL
  40. MAP2 ( X:list Y:list FN:function ):NIL
  41. ATSOC ( ALST:list, KEY:atom ):any
  42. ")
  43. (FLUID '(!#SET2))
  44. (!*
  45. "CCAR( X:any ):any
  46. ----
  47. Careful Car. Returns car of x if x is a list, else NIL.")
  48. (CDE CCAR (!#X) (COND ((PAIRP !#X) (CAR !#X))))
  49. (!*
  50. "CCDR( X:any ):any
  51. ----
  52. Careful Cdr. Returns cdr of x if x is a list, else NIL.")
  53. (CDE CCDR (!#X) (COND ((PAIRP !#X) (CDR !#X))))
  54. (!*
  55. "LAST( X:list ):any
  56. ----
  57. Returns the last cell in X.
  58. E.g. (LAST '(A B C)) = (C), (LAST '(A B . C)) = C.")
  59. (!*
  60. (CDE LAST (!#X)
  61. (COND ((ATOM !#X) !#X) ((NULL (CDR !#X)) !#X) (T (LAST (CDR !#X)))))
  62. )
  63. (CDM LAST (!#X) (CONS 'LASTPAIR (CDR !#X)))
  64. (!*
  65. "NTH-CDR( L:list N:number ):list
  66. -------
  67. Returns the nth cdr of list--0 is the list, 1 the cdr ...")
  68. (CDE NTH!-CDR (!#L !#N)
  69. (COND ((LESSP !#N 1) !#L)
  70. ((ATOM !#L) NIL)
  71. (T (NTH!-CDR (CDR !#L) (SUB1 !#N)))))
  72. (!*
  73. "NTH-TAIL( L:list N:number ):list
  74. -------
  75. Returns the nth tail of list--1 is the list, 2 the cdr ...")
  76. (CDE NTH!-TAIL (!#L !#N)
  77. (COND ((LESSP !#N 2) !#L)
  78. ((ATOM !#L) NIL)
  79. (T (NTH!-TAIL (CDR !#L) (SUB1 !#N)))))
  80. (!*
  81. "NTH-ELT( L:list N:number ):list
  82. -------
  83. Returns the nth elt of list--1 is the car, 2 the cadr ...")
  84. (CDE NTH!-ELT (!#L !#N) (CAR (NTH!-TAIL !#L !#N)))
  85. (!*
  86. "TAIL-P( X:list Y:list ):extra-boolean
  87. ------
  88. If X is a non-nil tail of Y (X eq cdr Y or cddr Y or...), return X.
  89. Renamed to avoid a conflict with TAILP in compiler")
  90. (CDE TAIL!-P (!#X !#Y)
  91. (COND (!#X (PROG NIL
  92. LP (COND ((ATOM !#Y) (RETURN NIL)) ((EQ !#X !#Y) (RETURN !#X)))
  93. (SETQ !#Y (CDR !#Y))
  94. (GO LP)))))
  95. (!* " NCONS( X:any ): (CONS X NIL)
  96. -----
  97. Returns (CONS X NIL) ")
  98. (!*
  99. (CDE NCONS (!#X) (CONS !#X NIL))
  100. )
  101. (!*
  102. " KWOTE( X:any ): '<eval of #X>
  103. MKQUOTE( X:any ): '<eval of #X>
  104. -------
  105. Returns the quoted value of its argument. ")
  106. (CDM KWOTE (!#X) (CONS 'MKQUOTE (CDR !#X)))
  107. (!*
  108. (CDE MKQUOTE (!#X) (LIST 'QUOTE !#X))
  109. )
  110. (!*
  111. "RPLACW( X:list Y:list ):list
  112. ------
  113. Destructively replace the Whole list X by Y.")
  114. (!*
  115. (CDE RPLACW (!#X !#Y) (RPLACA (RPLACD !#X (CDR !#Y)) (CAR !#Y)))
  116. )
  117. (!*
  118. "DREMOVE( X:any L:list ):list
  119. -------
  120. Remove destructively all equal occurrances of X from L.")
  121. (CDE DREMOVE (!#X !#L)
  122. (COND ((ATOM !#L) NIL)
  123. ((EQUAL !#X (CAR !#L))
  124. (COND ((CDR !#L)
  125. (PROGN (RPLACA !#L (CADR !#L))
  126. (RPLACD !#L (CDDR !#L))
  127. (DREMOVE !#X !#L)))))
  128. (T (PROG (!#Z)
  129. (SETQ !#Z !#L)
  130. LP (COND ((ATOM (CDR !#L)) (RETURN !#Z))
  131. ((EQUAL !#X (CADR !#L)) (RPLACD !#L (CDDR !#L)))
  132. (T (SETQ !#L (CDR !#L))))
  133. (GO LP)))))
  134. (!*
  135. "REMOVE( X:any L:list ):list
  136. ------
  137. Return copy of L with all equal occurrences of X removed.")
  138. (CDE REMOVE (!#X !#L)
  139. (COND ((ATOM !#L) !#L)
  140. ((EQUAL (CAR !#L) !#X) (REMOVE !#X (CDR !#L)))
  141. (T (CONS (CAR !#L) (REMOVE !#X (CDR !#L))))))
  142. (!*
  143. "COPY( X:list ):list
  144. ----
  145. Make a copy of X--EQUAL but not EQ (except for atoms).")
  146. (!*
  147. (CDE COPY (!#X) (SUBST 0 0 !#X))
  148. )
  149. (!*
  150. "DSUBST( X:any Y:any Z:list ):list
  151. ------
  152. Destructively substitute copies(??) of X for Y in Z.")
  153. (!*
  154. (CDE DSUBST (!#X !#Y !#Z)
  155. (PROG (!#B)
  156. (COND ((EQUAL !#Y (SETQ !#B !#Z)) (RETURN (COPY !#X))))
  157. LP (COND ((VECTORP !#Z)
  158. (RETURN
  159. (PROG (!#I)
  160. (SETQ !#I (UPBV !#Z))
  161. LOOP (COND ((LESSP !#I 1) (RETURN NIL)))
  162. (PUTV !#Z !#I (DSUBST !#X !#Y (GETV !#Z !#I)))
  163. (SETQ !#I (SUB1 !#I))
  164. (GO LOOP))))
  165. ((ATOM !#Z) (RETURN !#B))
  166. ((EQUAL !#Y (CAR !#Z)) (RPLACA !#Z (COPY !#X)))
  167. (T (DSUBST !#X !#Y (CAR !#Z))))
  168. (COND ((AND !#Y (EQUAL !#Y (CDR !#Z)))
  169. (PROGN (RPLACD !#Z (COPY !#X)) (RETURN !#B))))
  170. (SETQ !#Z (CDR !#Z))
  171. (GO LP)))
  172. )
  173. (!* "DSUBST is the same as SubstIP.")
  174. (CDM DSUBST (!#X) (CONS 'SUBSTIP (CDR !#X)))
  175. (!*
  176. "LSUBST( NEW:list OLD:list X:any ):list
  177. ------
  178. Substitute elts of NEW (splicing) for the element old in X")
  179. (CDE LSUBST (!#NEW !#OLD !#X)
  180. (COND ((NULL !#X) NIL)
  181. ((VECTORP !#X)
  182. (PROG (!#V !#I)
  183. (SETQ !#I (UPBV !#X))
  184. (SETQ !#V (MKVECT !#I))
  185. LOOP (COND ((LESSP !#I 1) (RETURN !#V)))
  186. (PUTV !#V !#I (LSUBST !#NEW !#OLD (GETV !#V !#I)))
  187. (SETQ !#I (SUB1 !#I))
  188. (GO LOOP)))
  189. ((ATOM !#X) (COND ((EQUAL !#OLD !#X) !#NEW) (T !#X)))
  190. ((EQUAL !#OLD (CAR !#X))
  191. (NCONC (COPY !#NEW) (LSUBST !#NEW !#OLD (CDR !#X))))
  192. (T (CONS (LSUBST !#NEW !#OLD (CAR !#X)) (LSUBST !#NEW !#OLD (CDR !#X))))
  193. ))
  194. (!*
  195. (!*
  196. "TCONC( P:list X:any ): tconc-ptr
  197. -----
  198. Pointer consists of (CONS LIST (LAST LIST)).
  199. Returns (and alters) pointer consisting of (CONS LIST1 (LAST LIST1)),
  200. where LIST1 = (NCONC1 LIST X).
  201. Avoids searching down the list as nconc1 does, by pointing at last elt
  202. of list for nconc1.
  203. To use, setq ptr to (NCONS NIL), tconc elts, return car of ptr.")
  204. (CDE TCONC (!#P !#X)
  205. (COND ((NULL !#P) (CONS (SETQ !#X (NCONS !#X)) !#X))
  206. ((ATOM !#P) (PROGN (PRINT !#P) (ERROR 24 "BAD ARGUMENT 0 TCONC")))
  207. ((CDR !#P) (RPLACD !#P (CDR (RPLACD (CDR !#P) (NCONS !#X)))))
  208. (T (RPLACA (RPLACD !#P (SETQ !#X (NCONS !#X))) !#X))))
  209. (!*
  210. "LCONC( P:list X:list ):list
  211. -----
  212. Same as TCONC, but NCONCs instead of NCONC1s.")
  213. (CDE LCONC (!#P !#X)
  214. (PROG (!#Y)
  215. (COND ((NULL !#X) (RETURN !#P))
  216. ((OR (ATOM !#X) (CDR (SETQ !#Y (LAST !#X)))) (PRINT !#X))
  217. ((NULL !#P) (RETURN (CONS !#X !#Y)))
  218. ((ATOM !#P) (PRINT !#P))
  219. ((NULL (CAR !#P)) (RETURN (RPLACA (RPLACD !#P !#Y) !#X)))
  220. (T (PROGN (RPLACD (CDR !#P) !#X) (RETURN (RPLACD !#P !#Y)))))
  221. (ERROR 25 "BAD ARGUMENT 0 LCONC")))
  222. )
  223. (!*
  224. "CVSET( X:list ):list
  225. --------------------
  226. Converts list to set, i.e., removes redundant elements.")
  227. (CDE CVSET (!#X)
  228. (PROG (!#RES)
  229. (COND ((NULL !#X) (RETURN NIL)))
  230. (SETQ !#RES (NCONS NIL))
  231. LOOP (COND ((NULL !#X) (RETURN (CAR !#RES))))
  232. (COND ((NOT (MEMBER (CAR !#X) (CDR !#X))) (TCONC !#RES (CAR !#X))))
  233. (SETQ !#X (CDR !#X))
  234. (GO LOOP)))
  235. (!*
  236. "ENTER( ELT:element SET:list ):list
  237. -----
  238. Returns (ELT . SET) if ELT is not member of SET, else SET.")
  239. (CDE ENTER (!#ELT !#SET)
  240. (COND ((MEMBER !#ELT !#SET) !#SET) (T (CONS !#ELT !#SET))))
  241. (!*
  242. "ABSTRACT( FN:function L:list ):list
  243. --------
  244. Returns list of elts of list satisfying FN.")
  245. (CDE ABSTRACT (!#FN !#L)
  246. (PROG (!#ABSTRACTED)
  247. (SETQ !#ABSTRACTED (NCONS NIL))
  248. (MAPC !#L
  249. (FUNCTION
  250. (LAMBDA (!#Z)
  251. (COND ((APPLY !#FN (LIST !#Z)) (TCONC !#ABSTRACTED !#Z))))))
  252. (RETURN (CAR !#ABSTRACTED))))
  253. (!*
  254. "EACH( L:list FN:function ):extra boolean
  255. ----
  256. Returns L if each elt satisfies FN, else NIL.")
  257. (CDE EACH (!#L !#FN)
  258. (PROG (!#LIS)
  259. (SETQ !#LIS !#L)
  260. LOOP (COND ((NULL !#LIS) (RETURN (COND (!#L !#L) (T T))))
  261. ((NOT (APPLY !#FN (NCONS (CAR !#LIS)))) (RETURN NIL)))
  262. (SETQ !#LIS (CDR !#LIS))
  263. (GO LOOP)))
  264. (!*
  265. "SOME( L:list FN:function ):extra boolean
  266. ----
  267. Returns the first tail of the list whose CAR satisfies function.")
  268. (CDE SOME (!#L !#FN)
  269. (PROG NIL
  270. LOOP (COND ((NULL !#L) (RETURN NIL))
  271. ((APPLY !#FN (LIST (CAR !#L))) (RETURN !#L)))
  272. (SETQ !#L (CDR !#L))
  273. (GO LOOP)))
  274. (!*
  275. "INTERSECTION( #SET1:list #SET2:list ):extra boolean
  276. ------------
  277. Returns list of elts in SET1 which are also members of SET2 ")
  278. (CDE INTERSECTION (!#SET1 !#SET2) (ABSTRACT (FUNCTION INTERSECTION1) !#SET1))
  279. (CDE INTERSECTION1 (!#ELT) (MEMBER !#ELT !#SET2))
  280. (!*
  281. "SETDIFFERENCE( #SET1:list #SET2:list ):extra boolean
  282. -------------
  283. Returns all elts of SET1 not members of SET2.")
  284. (CDE SETDIFFERENCE (!#SET1 !#SET2) (ABSTRACT (FUNCTION SETDIFFERENCE1) !#SET1))
  285. (CDE SETDIFFERENCE1 (!#ELT) (NOT (MEMBER !#ELT !#SET2)))
  286. (!*
  287. "SUBSET( #SET1:any #SET2:list ):extra boolean
  288. ------
  289. Returns SET1 if each element of SET1 is a member of SET2.")
  290. (CDE SUBSET (!#SET1 !#SET2) (AND !#SET1 (EACH !#SET1 (FUNCTION SUBSET1))))
  291. (CDE SUBSET1 (!#ELT) (MEMBER !#ELT !#SET2))
  292. (!*
  293. "UNION( X:list Y:list ):list
  294. -----
  295. Returns the union of lists X, Y")
  296. (CDE UNION (!#X !#Y) (APPEND !#X (SETDIFFERENCE !#Y !#X)))
  297. (!*
  298. "SEQUAL( X:list Y:list ):extra boolean
  299. ------
  300. Returns X if X and Y are set-equal: same length and X subset of Y.")
  301. (CDE SEQUAL (!#X !#Y) (AND (EQUAL (LENGTH !#X) (LENGTH !#Y)) (SUBSET !#X !#Y)))
  302. (!*
  303. "MAP2( X:list Y:list FN:function ):NIL
  304. ------
  305. Applies FN (of two arguments) to successive paired tails of X and Y.")
  306. (DE MAP2 (!#L1 !#L2 !#FN)
  307. (PROG NIL
  308. LOOP (COND ((NULL (AND !#L1 !#L2))
  309. (COND ((OR !#L1 !#L2) (ERROR 0 "MAP2: mismatched lists"))
  310. (T (RETURN NIL)))))
  311. (APPLY !#FN (LIST !#L1 !#L2))
  312. (SETQ !#L1 (CDR !#L1))
  313. (SETQ !#L2 (CDR !#L2))
  314. (GO LOOP)))
  315. (!*
  316. "MAP2C( X:list Y:list FN:function ):NIL
  317. ------
  318. Applies FN (of two arguments) to successive paired elts of X and Y.")
  319. (DE MAP2C (!#L1 !#L2 !#FN)
  320. (PROG NIL
  321. LOOP (COND ((NULL (AND !#L1 !#L2))
  322. (COND ((OR !#L1 !#L2) (ERROR 0 "MAP2C: mismatched lists"))
  323. (T (RETURN NIL)))))
  324. (APPLY !#FN (LIST (CAR !#L1) (CAR !#L2)))
  325. (SETQ !#L1 (CDR !#L1))
  326. (SETQ !#L2 (CDR !#L2))
  327. (GO LOOP)))
  328. (!*
  329. "ATSOC( ALST:list, KEY:atom ):any
  330. -----
  331. Like ASSOC, except uses an EQ check. Returns first element of
  332. ALST whose CAR is KEY.")
  333. (!*
  334. (CDE ATSOC (KEY ALST)
  335. (COND ((NULL ALST) NIL)
  336. ((EQ (CAAR ALST) KEY) (CAR ALST))
  337. (T (ATSOC KEY (CDR ALST)))))
  338. )
  339. (!*
  340. " YNUMS -- BASIC NUMBER UTILITIES
  341. ADD1 ( number ):number EXPR
  342. SUB1 ( number ):number EXPR
  343. ZEROP ( any ):boolean EXPR
  344. MINUSP ( number ):boolean EXPR
  345. PLUSP ( number ):boolean EXPR
  346. POSITIVE( X:any ):extra-boolean EXPR
  347. NEGATIVE( X:any ):extra-boolean EXPR
  348. NUMERAL ( X:number/digit/any ):boolean EXPR
  349. GREAT1 ( X:number Y:number ):extra-boolean EXPR
  350. LESS1 ( X:number Y:number ):extra-boolean EXPR
  351. GEQ ( X:number Y:number ):extra-boolean EXPR
  352. LEQ ( X:number Y:number ):extra-boolean EXPR
  353. ODD ( X:integer ):boolean EXPR
  354. SIGMA ( L:list FN:function ):integer EXPR
  355. RAND16 ( ):integer EXPR
  356. IRAND ( N:integer ):integer EXPR
  357. ")
  358. (!*
  359. "The DEC compiler may optimize calls to PLUS2, DIFFERENCE, EQUAL,
  360. LESSP, etc. by converting them to calls to ADD1, SUB1, ZEROP,
  361. MINUSP, etc. This will create circular defintions in the
  362. conditional defintions, about which the compiler will complain.
  363. Such complaints can be ignored.")
  364. (!*
  365. (COND ((AND (CODEP (CCDR (GETD 'ADD1)))
  366. (CODEP (CCDR (GETD 'SUB1)))
  367. (CODEP (CCDR (GETD 'MINUSP))))
  368. (PROGN (TERPRI)
  369. (PRIN2
  370. "Ignore any circular definition msg for ADD1, SUB1, MINUSP")
  371. (TERPRI))))
  372. (!*
  373. "ADD1( number ):number EXPR
  374. ----
  375. Note: DEC compiler optimizes (PLUS2 N 1) into (ADD1 N). ")
  376. (CDE ADD1 (!#N) (PLUS2 !#N 1))
  377. (!*
  378. "SUB1( number ):number EXPR
  379. ----
  380. Note: DEC compiler optimizes (DIFFERENCE N 1) into (SUB1 N). ")
  381. (CDE SUB1 (!#N) (DIFFERENCE !#N 1))
  382. (!*
  383. "ZEROP( X:any ):boolean EXPR
  384. -----
  385. Returns non-nil iff X equals 0.")
  386. (CDE ZEROP (!#X) (EQN !#X 0))
  387. (!*
  388. "MINUSP( N:number ):boolean EXPR
  389. ------
  390. Returns non-nil iff N is less than 0.")
  391. (CDE MINUSP (!#N) (LESSP !#N 0))
  392. )
  393. (!*
  394. "PLUSP( N:number ):boolean EXPR
  395. -----
  396. Returns non-nil iff N is greater than 0.")
  397. (CDE PLUSP (!#N) (GREATERP !#N 0))
  398. (!*
  399. "ODD( X:integer ):boolean EXPR
  400. ---
  401. Returns T if x is odd, else NIL.
  402. WARNING: EVENP is used by REDUCE to test if a list has even
  403. length. ODD and EVENP are thus highly distinct.")
  404. (CDE ODD (!#X) (EQN 1 (REMAINDER !#X 2)))
  405. (!*
  406. "POSITIVE( X:any ):boolean EXPR
  407. --------
  408. Returns non-nil iff X is a positive number.")
  409. (CDE POSITIVE (!#X) (AND (NUMBERP !#X) (GREATERP !#X 0)))
  410. (!*
  411. "NEGATIVE( X:any ):boolean EXPR
  412. --------
  413. Returns non-nil iff X is a negative number.")
  414. (CDE NEGATIVE (!#X) (AND (NUMBERP !#X) (LESSP !#X 0)))
  415. (!*
  416. "NUMERAL( X:any ): boolean EXPR
  417. -------
  418. Returns true for both numbers and digits. Some dialects
  419. had been treating the digits as numbers, and this fn is
  420. included as a replacement for NUMBERP where NUMBERP might
  421. really be checking for digits.
  422. N.B.: Digits are characters and thus ID's")
  423. (DE NUMERAL (!#X) (OR (DIGIT !#X) (NUMBERP !#X)))
  424. (!*
  425. "GREAT1( X:number Y:number ):extra-boolean EXPR
  426. ------
  427. Returns X if it is strictly greater than Y, else NIL.
  428. GREATERP is simpler if only T/NIL is needed.")
  429. (CDE GREAT1 (!#X !#Y)
  430. (COND ((AND (NUMBERP !#X) (NUMBERP !#Y) (GREATERP !#X !#Y)) !#X)))
  431. (!*
  432. "LESS1( X:number Y:number ):extra-boolean EXPR
  433. -----
  434. Returns X if it is strictly less than Y, else NIL
  435. LESSP is simpler if only T/NIL is needed.")
  436. (CDE LESS1 (!#X !#Y)
  437. (COND ((AND (NUMBERP !#X) (NUMBERP !#Y) (LESSP !#X !#Y)) !#X)))
  438. (!*
  439. (!*
  440. "GEQ( X:number Y:number ):extra-boolean EXPR
  441. ---
  442. Returns X if it is greater than or equal to Y, else NIL.")
  443. (CDE GEQ (!#X !#Y)
  444. (COND ((AND (NUMBERP !#X) (NUMBERP !#Y) (NOT (LESSP !#X !#Y))) !#X)))
  445. (!*
  446. "LEQ( X:number Y:number ):extra-boolean EXPR
  447. ---
  448. Returns X if it is less than or equal to Y, else NIL.")
  449. (CDE LEQ (!#X !#Y)
  450. (COND ((AND (NUMBERP !#X) (NUMBERP !#Y) (NOT (GREATERP !#X !#Y))) !#X)))
  451. )
  452. (!*
  453. "SIGMA( L:list, FN:function ):integer EXPR
  454. -----
  455. Returns sum of results of applying FN to each elt of LST.")
  456. (CDE SIGMA (!#L !#FN)
  457. (COND ((NULL !#L) 0)
  458. (T (PLUS2 (APPLY !#FN (LIST (CAR !#L))) (SIGMA (CDR !#L) !#FN)))))
  459. (!*
  460. "RAND16( ):integer EXPR
  461. IRAND ( N:integer ):integer EXPR
  462. ------
  463. Linear-congruential random-number generator. To avoid dependence
  464. upon the big number package, we are forced to use 16-bit numbers,
  465. which means the generator will cycle after only 2^16.
  466. The randomness obtained should be sufficient for selecting choices
  467. in VOCAL, but not for monte-carlo experiments and other sensitive
  468. stuff.")
  469. (GLOBAL '(G!:RANDOM G!:RADD G!:RMUL G!:RMOD))
  470. (!* "decimal 14933 = octal 35125, decimal 21749 = octal 52365 ")
  471. (SETQ G!:RANDOM 0)
  472. (SETQ G!:RADD 14933)
  473. (SETQ G!:RMUL 21749)
  474. (SETQ G!:RMOD (TIMES 256 256))
  475. (!*
  476. "Returns a new 16-bit unsigned random integer. Leftmost bits are
  477. most random so you shouldn't use REMAINDER to scale this to range")
  478. (DE RAND16 NIL
  479. (SETQ G!:RANDOM (REMAINDER (TIMES G!:RMUL (PLUS G!:RADD G!:RANDOM)) G!:RMOD)))
  480. (!*
  481. "Scale new random number to range 0 to N-1 with approximately equal
  482. probability. Uses times/quotient instead of remainder to make best
  483. use of high-order bits which are most random")
  484. (DE IRAND (N) (QUOTIENT (TIMES (RAND16) N) G!:RMOD))
  485. (!*
  486. " YSTRS -- BASIC STRING UTILITIES
  487. EXPLODEC ( X:any ):char-list EXPR
  488. EXPLODE2 ( X:any ):char-list EXPR
  489. FLATSIZE ( X:str ):integer EXPR
  490. FLATSIZE2( X:str ):integer EXPR
  491. NTHCHAR ( X:str N:number ):char-id EXPR
  492. ICOMPRESS( LST:lst ):<interned id> EXPR
  493. SUBSTR ( STR:str START:num LENGTH:num ):string EXPR
  494. CAT-DE ( L: list of strings ):string EXPR
  495. CAT-ID-DE( L: list of strings ):<uninterned id> EXPR
  496. SSEXPR ( S: string ):<interned id> EXPR
  497. ")
  498. (!*
  499. (!*
  500. "EXPLODE2( X:any ):char-list EXPR
  501. EXPLODEC( X:any ):char-list EXPR
  502. --------
  503. List of characters which would appear in PRIN2 of X. If either
  504. is built into the interpreter, we will use that defintion for both.
  505. Otherwise, the definition below should work, but inefficiently.
  506. Note that this definition does not support vectors and lists.
  507. (The DEC and IBM interpreters support EXPLODE and EXPLODE2 by using
  508. the same internal algorithm that is used for PRIN1 (PRIN2), but put
  509. the chars generated into a list instead of printing them.
  510. Thus, they work on arbitrary s-expressions.) ")
  511. (!* "If either EXPLODEC or EXPLODE2 is defined, the CDE does nothing.")
  512. (COND ((GETD 'EXPLODEC) (FLAG '(EXPLODE2) 'LOSE)))
  513. (CDE EXPLODE2 (!#X)
  514. (PROG (!#BIG !#TAIL)
  515. (COND ((IDP !#X) (GO IDS))
  516. ((STRINGP !#X) (GO STRS))
  517. ((NUMBERP !#X) (RETURN (EXPLODE !#X)))
  518. ((CODEP !#X) (RETURN (EXPLODE !#X)))
  519. (T (ERROR "EXPLODE2 -- bad argument")))
  520. (!*
  521. "For ids -- Note: last elt of #BIG will never be bang
  522. unless char before it was also a bang.")
  523. IDS (SETQ !#TAIL (SETQ !#BIG (EXPLODE !#X)))
  524. IDLP (COND ((EQUAL (CAR !#TAIL) '!!) (RPLACW !#TAIL (CDR !#TAIL)))
  525. ((NULL (CDR !#TAIL)) (RETURN !#BIG)))
  526. (SETQ !#TAIL (CDR !#TAIL))
  527. (GO IDLP)
  528. (!* "For strings. #BIG has at least 2 elts, the quotes")
  529. STRS (SETQ !#TAIL (SETQ !#BIG (EXPLODE !#X)))
  530. STRLP(COND ((NULL (CDDR !#TAIL))
  531. (PROGN (RPLACD !#TAIL NIL) (RETURN (CDR !#BIG))))
  532. ((EQUAL (CAR (SETQ !#TAIL (CDR !#TAIL))) '!")
  533. (RPLACD !#TAIL (CDDR !#TAIL))))
  534. (GO STRLP)))
  535. (REMFLAG '(EXPLODEC EXPLODE2) 'LOSE)
  536. (CDE EXPLODEC (!#X) (EXPLODE2 !#X))
  537. (CDE EXPLODE2 (!#X) (EXPLODEC !#X))
  538. (!*
  539. "Note: According to the STANDARD LISP REPORT, EXPLODE and EXPLODE2
  540. are only defined for atoms. If your interpreter does not support
  541. extended EXPLODE and EXPLODE2, then change the second CDE's below
  542. for FLATSIZE and FLATSIZE2 to get recursive versions of them.")
  543. (!*
  544. " FLATSIZE( X:any ):integer EXPR
  545. --------
  546. Number of chars in a PRIN1 of X.
  547. Also equals length of list created by EXPLODE of X,
  548. assuming that EXPLODE extends to arbitrary s-expressions.
  549. DEC and IBM interpreters use the same internal algorithm that
  550. is used for PRIN1, but count chars instead of printing them. ")
  551. (CDE FLATSIZE (!#X) (LENGTH (EXPLODE !#X)))
  552. (!*
  553. "If your EXPLODE only works for atoms, comment out the above
  554. CDE and turn the CDE below into DE.")
  555. (CDE FLATSIZE (E)
  556. (COND ((ATOM E) (LENGTH (EXPLODE E)))
  557. (T ((LAMBDA (L1 D)
  558. (COND ((NULL D) (PLUS L1 2))
  559. (T ((LAMBDA (L2)
  560. (COND ((ATOM D) (PLUS 5 L1 L2)) (T (PLUS 1 L1 L2))))
  561. (FLATSIZE D)))))
  562. (FLATSIZE (CAR E))
  563. (CDR E)))))
  564. (!*
  565. " FLATSIZE2( X:any ):integer EXPR
  566. ---------
  567. Number of chars in a PRIN2 of X.
  568. Also equals length of list created by EXPLODE2 of X,
  569. assuming that EXPLODE2 extends to arbitrary s-expressions.
  570. DEC and IBM interpreters use the same internal algorithm that
  571. is used for PRIN2, but count chars instead of printing them. ")
  572. (!* " FLATSIZE will often suffice for FLATSIZE2 ")
  573. (CDE FLATSIZE2 (!#X) (LENGTH (EXPLODE2 !#X)))
  574. (!*
  575. "If your EXPLODE2 only works for atoms, comment out the CDE above
  576. and turn the CDE below into DE.")
  577. (CDE FLATSIZE2 (E)
  578. (COND ((ATOM E) (LENGTH (EXPLODE2 E)))
  579. (T ((LAMBDA (L1 D)
  580. (COND ((NULL D) (PLUS L1 2))
  581. (T ((LAMBDA (L2)
  582. (COND ((ATOM D) (PLUS 5 L1 L2)) (T (PLUS 1 L1 L2))))
  583. (FLATSIZE2 D)))))
  584. (FLATSIZE2 (CAR E))
  585. (CDR E)))))
  586. )
  587. (!*
  588. " NTHCHAR( X:any, N:number ):character-id EXPR
  589. -------
  590. Returns nth character of EXPLODE2 of X.")
  591. (CDE NTHCHAR (!#X !#N)
  592. (PROG (!#Y)
  593. (COND ((SETQ !#Y (NTH!-TAIL (EXPLODE2 !#X) !#N)) (RETURN (CAR !#Y))))))
  594. (!*
  595. "ICOMPRESS( LST:list ):interned atom EXPR
  596. ---------
  597. Returns INTERN'ed atom made by COMPRESS.")
  598. (!*
  599. (CDE ICOMPRESS (!#LST) (INTERN (COMPRESS !#LST)))
  600. )
  601. (!* "Implode is the same as ICOMPRESS, but more efficient.")
  602. (CDM ICOMPRESS (!#X) (CONS 'IMPLODE (CDR !#X)))
  603. (!*
  604. "SUBSTR( STR:string START:number LENGTH:number ):string EXPR
  605. ------
  606. Returns a substring of the given LENGTH beginning with the
  607. character at location START in the string.
  608. NB: The first location of the string is 0.
  609. If START or LENGTH is negative, 0 is assumed.
  610. If the length given would exceed the end of the string, the
  611. subtring returned quietly goes to end of string, no error.")
  612. (!*
  613. (CDE SUBSTR (!#STR !#START !#LENGTH)
  614. (PROG (!#BIG !#TAIL)
  615. (COND ((NOT (STRINGP !#STR))
  616. (ERROR 0 "SUBSTR -- argument not a string."))
  617. ((OR (NOT (NUMBERP !#START)) (NOT (NUMBERP !#LENGTH)))
  618. (ERROR 0 "SUBSTR -- start or length not number"))
  619. ((LESSP !#LENGTH 1) (RETURN ""))
  620. ((EQUAL !#STR "") (RETURN ""))
  621. ((MINUSP !#START) (SETQ !#START 0)))
  622. (!* "Fall thru when CDR of #BIG is desired first character")
  623. (SETQ !#BIG (EXPLODE !#STR))
  624. LP (COND ((MINUSP (SETQ !#START (SUB1 !#START))) NIL)
  625. ((NULL (CDR (SETQ !#BIG (CDR !#BIG)))) (RETURN ""))
  626. ((EQUAL (CAR !#BIG) '!")
  627. (PROGN (!* "Next char must also be quote")
  628. (SETQ !#BIG (CDR !#BIG))
  629. (GO LP)))
  630. (T (GO LP)))
  631. (!* "CDR of #BIG is desired first character")
  632. (!* "When length drops below zero, chop off remainder")
  633. (!* "If list ends first, make string from what we have")
  634. (SETQ !#TAIL !#BIG)
  635. LP2 (COND ((MINUSP (SETQ !#LENGTH (SUB1 !#LENGTH)))
  636. (RPLACD !#TAIL (LIST '!")))
  637. ((NULL (CDR (SETQ !#TAIL (CDR !#TAIL)))) NIL)
  638. ((EQUAL (CAR !#TAIL) '!")
  639. (PROGN (SETQ !#TAIL (CDR !#TAIL)) (GO LP2)))
  640. (T (GO LP2)))
  641. (RETURN (COMPRESS (RPLACA !#BIG '!")))))
  642. )
  643. (!* "SUBSTR is handled more efficiently by PSL function SUB")
  644. (CDE SUBSTR (!#S !#ST !#LEN)
  645. (SUB !#S (COND ((MINUSP !#ST) 0) (T !#ST)) (SUB1 !#LEN)))
  646. (!*
  647. "CAT-DE( L: list of expressions ):string EXPR
  648. -------
  649. Returns a string made from the concatenation of the prin2 names
  650. of the expressions in the list. Usually called via CAT macro.")
  651. (DE CAT!-DE (!#L)
  652. (COMPRESS (CONS '!" (NCONC (MAPCAN !#L (FUNCTION EXPLODE2)) (LIST '!")))))
  653. (!*
  654. "CAT-ID-DE( L: list of any ):uninterned id EXPR
  655. -------
  656. Returns an id made from the concatenation of the prin2 names
  657. of the expressions in the list. Usually called via CAT-ID macro.")
  658. (DE CAT!-ID!-DE (!#L) (COMPRESS (MAPCAN !#L (FUNCTION EXPLODE2))))
  659. (!*
  660. "SSEXPR( S: string ): id EXPR
  661. ------
  662. Returns ID `read' from string. Not very robust.")
  663. (DE SSEXPR (!#STR)
  664. (COND ((STRINGP !#STR) (ICOMPRESS (EXPLODE2 !#STR))) (T !#STR)))
  665. (!*
  666. "YIO -- simple I/O utilities. All EXPR's.
  667. CONFIRM (#QUEST: string ):boolean
  668. EATEOL ():NIL
  669. TTY-DE (#L: list ):NIL
  670. TTY-TX-DE (#L: list ):NIL
  671. TTY-XT-DE (#L: list ):NIL
  672. TTY-TT-DE (#L: list ):NIL
  673. TTY-ELT (#X: elt ):NIL
  674. PRINA (#X: any ):NIL
  675. PRIN1SQ (#X: any ):NIL
  676. PRIN2SQ (#X: any ):NIL
  677. PRINCS (#X: single-char-id ):NIL
  678. --queue-code--
  679. SEND ():NIL
  680. SEND-1 (#EE)
  681. ENQUEUE (#FN #ARG)
  682. Q-PRIN1 (#E: any ):NIL
  683. Q-PRINT (#E: any ):NIL
  684. Q-PRIN2 (#E: any ):NIL
  685. Q-TERPRI ()
  686. ONEARG-TERPRI (#E: any ):NIL
  687. Q-TYO (#N: ascii-code ):NIL
  688. Q-PRINC (#C: single-char-id ):NIL
  689. * Q-TTY-DE (#CMDS: list ):NIL
  690. * Q-TTY-XT-DE (#CMDS: list ):NIL
  691. * Q-TTY-TX-DE (#CMDS: list ):NIL
  692. * Q-TTY-TT-DE (#CMDS: list ):NIL
  693. ")
  694. (GLOBAL '(!#SELECTQ G!:SHOW!:ERRORS G!:SHOW!:TRACE))
  695. (FLAG '(PRINT PRIN1 PRIN2 PRINC SETCUR TYO PPRINT TERPRI POSN PPOS)
  696. 'SAY!:PRINT)
  697. (DE PRINT2 (!#X) (PROGN (PRIN2 !#X) (TERPRI) !#X))
  698. (DE CONFIRM (!#QUEST)
  699. (PROG (!#ANS)
  700. LP0 (TTY!-XT !#QUEST)
  701. LP1 (SEND)
  702. (SETQ !#ANS (UPPER!-CASE (READCH)))
  703. (COND ((EQUAL !#ANS !$EOL!$) (SETQ !#ANS (UPPER!-CASE (READCH)))))
  704. (COND ((EQUAL !#ANS 'Y) (PROGN (EATEOL) (RETURN T)))
  705. ((EQUAL !#ANS 'N) (PROGN (EATEOL) (RETURN NIL)))
  706. ((EQUAL !#ANS '!?) (PROGN (EATEOL) (GO LP0)))
  707. (T (PROGN (EATEOL) (TTY!-XT "Please type Y, N or ?."))))
  708. (GO LP1)))
  709. (CDE UPPER!-CASE (CH)
  710. (PROG (TMP)
  711. (COND ((AND (LITER CH)
  712. (SETQ TMP
  713. (MEMQ CH
  714. '(A B C D E F G H I J K L M N O P Q R S T U V
  715. W X Y Z)))) (RETURN
  716. (CAR (NTH!-TAIL
  717. '(Z Y X W V U T S R Q P O N M L K J I H G F E D C B A)
  718. (LENGTH TMP)))))
  719. (T (RETURN CH)))))
  720. (!* DE CONFIRM (!#QUEST)
  721. (PROG (!#ANS)
  722. LP0 (TTY!-XT !#QUEST)
  723. LP1 (SEND)
  724. (SETQ !#ANS (CAR (EXPLODEC (READ))))
  725. (COND ((EQ !#ANS 'Y) (PROGN (EATEOL) (RETURN T)))
  726. ((EQ !#ANS 'N) (PROGN (EATEOL) (RETURN NIL)))
  727. ((EQ !#ANS '!?) (GO LP0))
  728. (T (TTY!-XT "Please type Y, N or ?.")))
  729. (GO LP1)))
  730. (!*
  731. "Eat (discard) text until $EOL$ or <ESC> seen.
  732. <ESC> meaningful only on PDP-10 systems.
  733. $EOL$ meaningful only on correctly-implemented Standard-LISP systems. ")
  734. (DE EATEOL NIL
  735. (PROG (!#CH)
  736. LP (SETQ !#CH (READCH))
  737. (COND ((MEMQ !#CH (LIST '!$EOL!$ !$EOL!$)) (RETURN NIL)))
  738. (GO LP)))
  739. (!* "An idea whose time has not yet come... ")
  740. (!* DE TTY!-DE (EOLS!#BEFORE !#L EOLS!#AFTER)
  741. (PROG (OLD!#CHAN)
  742. (SETQ OLD!#CHAN (WRS NIL))
  743. LP1 (COND ((ONEP EOLS!#BEFORE) (TTY!-ELT !$EOL!$))
  744. ((ZEROP EOLS!#BEFORE) NIL)
  745. (T (PROGN (TTY!-ELT !$EOL!$)
  746. (SETQ EOLS!#BEFORE (SUB1 EOLS!#BEFORE))
  747. (GO LP1))))
  748. (MAPC !#L (FUNCTION TTY!-ELT))
  749. LP1 (COND ((ONEP EOLS!#AFTER) (TTY!-ELT !$EOL!$))
  750. ((ZEROP EOLS!#AFTER) NIL)
  751. (T (PROGN (TTY!-ELT !$EOL!$)
  752. (SETQ EOLS!#AFTER (SUB1 EOLS!#AFTER))
  753. (GO LP2))))
  754. (WRS OLD!#CHAN)))
  755. (!* "So, for now at least, ... ")
  756. (DE TTY!-DE (!#L)
  757. (PROG (OLD!#CHAN)
  758. (SETQ OLD!#CHAN (WRS NIL))
  759. (MAPC !#L (FUNCTION TTY!-ELT))
  760. (WRS OLD!#CHAN)))
  761. (DE TTY!-TX!-DE (!#L)
  762. (PROG (OLD!#CHAN)
  763. (SETQ OLD!#CHAN (WRS NIL))
  764. (TTY!-ELT !$EOL!$)
  765. (MAPC !#L (FUNCTION TTY!-ELT))
  766. (WRS OLD!#CHAN)))
  767. (DE TTY!-XT!-DE (!#L)
  768. (PROG (OLD!#CHAN)
  769. (SETQ OLD!#CHAN (WRS NIL))
  770. (MAPC !#L (FUNCTION TTY!-ELT))
  771. (TTY!-ELT !$EOL!$)
  772. (WRS OLD!#CHAN)))
  773. (DE TTY!-TT!-DE (!#L)
  774. (PROG (OLD!#CHAN)
  775. (SETQ OLD!#CHAN (WRS NIL))
  776. (TTY!-ELT !$EOL!$)
  777. (MAPC !#L (FUNCTION TTY!-ELT))
  778. (TTY!-ELT !$EOL!$)
  779. (WRS OLD!#CHAN)))
  780. (DE TTY!-ELT (!#E) (COND ((EQ !#E !$EOL!$) (Q!-TERPRI)) (T (Q!-PRIN2 !#E))))
  781. (!*
  782. "PRINA( X:any ): any
  783. -----
  784. Prin2s expression, after TERPRIing if it is too big for line, or spacing
  785. if it is not at the beginning of a line. Returns the value of X.
  786. Except for the space, this is just PRIN2 in the IBM interpreter.")
  787. (DE PRINA (!#X)
  788. (PROGN
  789. (COND ((LEQ (CHRCT) (FLATSIZE !#X)) (TERPRI))
  790. ((GREATERP (POSN) 0) (PRIN2 " ")))
  791. (PRIN2 !#X)))
  792. (!*
  793. "CHRCT (): <number>
  794. -----
  795. CHaRacter CounT left in line.
  796. Also a CDE in YPP.LSP -- built into IMSSS DEC interpreter.")
  797. (CDE CHRCT NIL (DIFFERENCE (MIN 80 (LINELENGTH NIL)) (POSN)))
  798. (!*
  799. "BINARY (#X: boolean): old-value
  800. ------
  801. Stub for non-IMSSS interpreters.
  802. In IMSSS interpreter, will put terminal into binary mode or
  803. take it out, according to argument, and return old value.")
  804. (CDE BINARY (!#X) NIL)
  805. (!*
  806. "PRIN1SQ (#X: any)
  807. -------
  808. PRIN1, Safe, use apostrophe for Quoted expressions.
  809. This is essentially a PRIN1 which tries not to exceed the right margin.
  810. It exceeds it only in those cases where the pname of a single atom
  811. exceeds the entire linelength. In such cases, <big> is printed at the
  812. terminal as a warning.
  813. (QUOTE xxx) structures are printed in 'xxx form to save space.
  814. Again, this is a little superfluous for the IBM interpreter.
  815. ")
  816. (DE PRIN1SQ (!#X)
  817. (PROG (!#SIZE)
  818. (COND ((ATOM !#X)
  819. (PROGN (SETQ !#SIZE (FLATSIZE !#X))
  820. (COND ((LESSP (CHRCT) !#SIZE)
  821. (PROGN (TERPRI)
  822. (COND ((LESSP (CHRCT) !#SIZE)
  823. (TTY "<big>"))))))
  824. (RETURN (PRIN1 !#X))))
  825. ((AND (EQ (CAR !#X) 'QUOTE)
  826. (CDR !#X)
  827. (NULL (CDDR !#X))
  828. (NOT (NUMBERP (CADR !#X))))
  829. (PROGN (PRINCS "'") (RETURN (PRIN1SQ (CADR !#X))))))
  830. (PRINCS "(")
  831. LP (PRIN1SQ (CAR !#X))
  832. (SETQ !#X (CDR !#X))
  833. (COND ((NULL !#X) (RETURN (PRINCS ")"))))
  834. (PRINCS " ")
  835. (COND ((NULL (ATOM !#X)) (GO LP)))
  836. (PRINCS ".")
  837. (PRINCS " ")
  838. (PRIN1SQ !#X)
  839. (PRINCS ")")))
  840. (!*
  841. "PRIN2SQ (#X: any)
  842. -------
  843. PRIN2, Safe, use apostrophe for Quoted expressions.
  844. Just like PRIN1SQ, but uses PRIN2 as a basis.
  845. ")
  846. (DE PRIN2SQ (!#X)
  847. (PROG (!#SIZE)
  848. (COND ((ATOM !#X)
  849. (PROGN (SETQ !#SIZE (FLATSIZE !#X))
  850. (COND ((LESSP (CHRCT) !#SIZE)
  851. (PROGN (TERPRI)
  852. (COND ((LESSP (CHRCT) !#SIZE)
  853. (TTY "<big>"))))))
  854. (RETURN (PRIN2 !#X))))
  855. ((AND (EQ (CAR !#X) 'QUOTE)
  856. (CDR !#X)
  857. (NULL (CDDR !#X))
  858. (NOT (NUMBERP (CADR !#X))))
  859. (PROGN (PRINCS "'") (RETURN (PRIN2SQ (CADR !#X))))))
  860. (PRINCS "(")
  861. LP (PRIN2SQ (CAR !#X))
  862. (SETQ !#X (CDR !#X))
  863. (COND ((NULL !#X) (RETURN (PRINCS ")"))))
  864. (PRINCS " ")
  865. (COND ((NULL (ATOM !#X)) (GO LP)))
  866. (PRINCS ".")
  867. (PRINCS " ")
  868. (PRIN2SQ !#X)
  869. (PRINCS ")")))
  870. (!*
  871. "PRINCS (#X: single-character-atom)
  872. -------
  873. PRINC Safe. Does a PRINC, but first worries about right margin.
  874. ")
  875. (DE PRINCS (!#X) (PROGN (COND ((LESSP (CHRCT) 1) (TERPRI))) (PRINC !#X)))
  876. (!*
  877. "1980 Jul 24 -- New Queued-I/O routines.
  878. To interface other code to this new I/O method, the following changes
  879. must be made in other code:
  880. PRIN2 --> TTY
  881. TERPRI --> $EOL$ inside a TTY, which causes Q-TERPRI to be called
  882. TYO --> Q-TYO
  883. PRIN1, PRINT -- These are used only for debugging. Do a (SEND) just
  884. before starting to print things in realtime, or use Q-PRIN1 etc.
  885. TTY -- Ok, expands into TTY-DE which calls Q-PRIN2 and Q-TERPRI.
  886. SAY -- I don't know what to do with this crock. It seems to be
  887. a poor substitute for TTY. If so it can be changed to TTY
  888. with the arguments fixed to be correct. <!GRAM>LPARSE.LSP
  889. ")
  890. (GLOBAL
  891. '(!*BATCHOUT !*BATCHQUEUE !*BATCHMAX !*BATCHCNT G!:WASTED!:SENDS
  892. G!:GOOD!:SENDS G!:GOOD!:OUTPUTS))
  893. (!*
  894. "When *BATCHOUT is NIL, output is done in realtime and *BATCHQUEUE
  895. remains NIL. When *BATCHOUT is true, output is queued and SEND
  896. executes&dequeues it later.")
  897. (!* "Initialize *BATCHQUEUE for TCONC operations.")
  898. (SETQ !*BATCHQUEUE (NCONS NIL))
  899. (!* "Initialize *BATCHMAX and *BATCHCNT ")
  900. (SETQ !*BATCHMAX 100)
  901. (SETQ !*BATCHCNT !*BATCHMAX)
  902. (DE SEND NIL
  903. (PROGN
  904. (COND ((CAR !*BATCHQUEUE)
  905. (PROGN (SETQ G!:GOOD!:SENDS (ADD1 G!:GOOD!:SENDS))
  906. (SETQ G!:GOOD!:OUTPUTS
  907. (PLUS G!:GOOD!:OUTPUTS (LENGTH (CAR !*BATCHQUEUE))))
  908. (MAPC (CAR !*BATCHQUEUE) (FUNCTION SEND!-1))
  909. (SETQ !*BATCHCNT !*BATCHMAX)
  910. (!* "Set it again up for TCONC's.")
  911. (SETQ !*BATCHQUEUE (NCONS NIL))))
  912. (T (SETQ G!:WASTED!:SENDS (ADD1 G!:WASTED!:SENDS))))))
  913. (DE SEND!-1 (!#EE) (APPLY (CAR !#EE) (NCONS (CDR !#EE))))
  914. (DE ENQUEUE (!#FN !#ARG)
  915. (PROGN (COND ((ZEROP (SETQ !*BATCHCNT (SUB1 !*BATCHCNT))) (SEND)))
  916. (SETQ !*BATCHQUEUE (TCONC !*BATCHQUEUE (CONS !#FN !#ARG)))))
  917. (DE Q!-PRIN1 (!#E)
  918. (COND (!*BATCHOUT (ENQUEUE 'PRIN1 !#E)) (1 (PRIN1 !#E))))
  919. (DE Q!-PRINT (!#E)
  920. (COND (!*BATCHOUT (ENQUEUE 'PRINT !#E)) (1 (PRINT !#E))))
  921. (DE Q!-PRIN2 (!#E)
  922. (COND (!*BATCHOUT (ENQUEUE 'PRIN2 !#E)) (1 (PRIN2 !#E))))
  923. (DE Q!-TERPRI NIL
  924. (COND (!*BATCHOUT (ENQUEUE 'ONEARG!-TERPRI NIL)) (1 (TERPRI))))
  925. (DE ONEARG!-TERPRI (!#E) (TERPRI))
  926. (DE Q!-TYO (!#N) (COND (!*BATCHOUT (ENQUEUE 'TYO !#N)) (1 (TYO !#N))))
  927. (DE Q!-PRINC (!#C)
  928. (COND (!*BATCHOUT (ENQUEUE 'PRINC !#C)) (1 (PRINC !#C))))
  929. (!* " These call PRIN2, so they would cause double-enqueuing. ")
  930. (!* DE Q!-TTY!-DE (!#CMDS)
  931. (COND (!*BATCHOUT (ENQUEUE 'TTY!-DE !#CMDS)) (1 (TTY!-DE !#CMDS))))
  932. (!* DE Q!-TTY!-XT!-DE (!#CMDS)
  933. (COND (!*BATCHOUT (ENQUEUE 'TTY!-XT!-DE !#CMDS)) (1 (TTY!-XT!-DE !#CMDS))))
  934. (!* DE Q!-TTY!-TX!-DE (!#CMDS)
  935. (COND (!*BATCHOUT (ENQUEUE 'TTY!-TX!-DE !#CMDS)) (1 (TTY!-TX!-DE !#CMDS))))
  936. (!* DE Q!-TTY!-TT!-DE (!#CMDS)
  937. (COND (!*BATCHOUT (ENQUEUE 'TTY!-TT!-DE !#CMDS)) (1 (TTY!-TT!-DE !#CMDS))))
  938. (SETQ G!:WASTED!:SENDS (SETQ G!:GOOD!:SENDS (SETQ G!:GOOD!:OUTPUTS 0)))
  939. (!*
  940. " YCNTRL -- ROUTINES INVOLVED WITH PROGRAM CONTROL STRUCTURES
  941. CATCH ( EXP:s-expression LABELS:id or idlist ):any EXPR
  942. THROW ( VALU:any LABEL:id ): error label EXPR
  943. ERRSET-DE ( #EXP #LBL ):any EXPR
  944. APPLY# ( ARG1: function ARG2: argument:list ):any EXPR
  945. BOUND ( X:any ):boolean EXPR
  946. MKPROG ( VARS:id-lst BODY:exp ):prog EXPR
  947. BUG-STOP (): any EXPR
  948. ")
  949. (GLOBAL '(!$THROWN!$ G!:SHOW!:ERRORS G!:SHOW!:TRACE))
  950. (!*
  951. (!*
  952. "CATCH( EXP:s-expression LABELS:id or idlist ): any EXPR
  953. -----
  954. For use with throw. If no THROW occurs in expression, then
  955. returns value of expression. If thrown label is MEMQ or EQ to
  956. labels, then returns thrown value. OW, thrown label is passed
  957. up higher. Expression should be quoted, as in ERRORSET.")
  958. (CDE CATCH (!#EXP !#LABELS)
  959. (PROG (!#EE)
  960. (COND ((PAIRP
  961. (SETQ !#EE (ERRORSET !#EXP G!:SHOW!:ERRORS G!:SHOW!:TRACE)))
  962. (RETURN (CAR !#EE)))
  963. ((OR (EQ !#LABELS T) (EQ !#EE !#LABELS) (MEMQ !#EE !#LABELS))
  964. (RETURN !$THROWN!$))
  965. (T (ERROR !#EE NIL)))))
  966. (!*
  967. "THROW( VALU:any LABEL:id ): error label EXPR
  968. -----
  969. Throws value with label up to enclosing CATCH having label.
  970. If there is no such CATCH, causes error.")
  971. (CDE THROW (!#VALU !#LABEL)
  972. (PROGN (SETQ !$THROWN!$ !#VALU) (ERROR !#LABEL NIL)))
  973. )
  974. (!*
  975. "ERRSET-DE ( EXP LBL ):any EXPR
  976. Named errset. If error matches label, then acts like errorset.
  977. Otherwise propagates error upward.
  978. Matching: Every label stops errors NIL, $EOF$.
  979. Label 'ERRORX stops any error.
  980. Other labels stop errors whose first arg is EQ to them.
  981. Usually called via ERRSET macro.")
  982. (DE ERRSET!-DE (!#EXP !#LBL)
  983. (PROG (!#Y)
  984. (SETQ !#Y (ERRORSET !#EXP G!:SHOW!:ERRORS G!:SHOW!:TRACE))
  985. (COND ((OR (PAIRP !#Y)
  986. (NULL !#Y)
  987. (EQ !#Y '!$EOF!$)
  988. (EQ !#Y !#LBL)
  989. (EQ !#LBL 'ERRORX))
  990. (RETURN !#Y))
  991. (T (ERROR !#Y "propagated")))))
  992. (!*
  993. "APPLY#(ARG1: function ARG2: argument:list): any EXPR
  994. ------
  995. Like APPLY, but can use fexpr and macro functions.")
  996. (CDE APPLY!# (!#ARG1 !#ARG2) (EVAL (CONS !#ARG1 !#ARG2)))
  997. (!*
  998. "BOUND( X:any ): boolean EXPR
  999. -----
  1000. Returns T if X is a bound id.")
  1001. (CDE BOUND (!#X) (AND (IDP !#X) (PAIRP (ERRORSET !#X NIL NIL))))
  1002. (!*
  1003. "MKPROG( VARS:id-lst BODY:exp ) EXPR
  1004. ------
  1005. Makes a prog around the body, binding the vars.")
  1006. (CDE MKPROG (!#VARS !#BODY) (CONS 'PROG (CONS !#VARS !#BODY)))
  1007. (!*
  1008. "BUGSTOP ():NIL EXPR
  1009. -------
  1010. Enter a read/eval/print loop, exit when OK is seen.")
  1011. (DE BUG!-STOP (!#STR)
  1012. (PROG (!#EXP OLD!#ICHAN OLD!#OCHAN OLD!#LENGTH)
  1013. (SETQ OLD!#ICHAN (RDS NIL))
  1014. (SETQ OLD!#OCHAN (WRS NIL))
  1015. (SETQ OLD!#LENGTH (LINELENGTH NIL))
  1016. (LINELENGTH 78)
  1017. (COND ((PAIRP !#STR) (TTY!-DE !#STR)) (T (PRIN2 !#STR)))
  1018. LOOP (TERPRI)
  1019. (PRIN2 "--Bug Stop-- Type OK to continue.")
  1020. (TERPRI)
  1021. (SETQ !#EXP (ERRORSET '(READ) T NIL))
  1022. (COND ((ATOM !#EXP) (PROGN (PRIN2 " --Read failed-- ") (GO LOOP))))
  1023. (SETQ !#EXP (CAR !#EXP))
  1024. (COND ((EQ !#EXP 'OK)
  1025. (PROGN (EATEOL)
  1026. (PRIN2 "resuming... ")
  1027. (TERPRI)
  1028. (LINELENGTH OLD!#LENGTH)
  1029. (RDS OLD!#ICHAN)
  1030. (WRS OLD!#OCHAN)
  1031. (RETURN NIL)))
  1032. ((AND (PAIRP !#EXP) (EQ (CAR !#EXP) 'RETURN))
  1033. (PROGN (EATEOL)
  1034. (PRIN2 "returning... ")
  1035. (TERPRI)
  1036. (LINELENGTH OLD!#LENGTH)
  1037. (RDS OLD!#ICHAN)
  1038. (WRS OLD!#OCHAN)
  1039. (RETURN (EVAL (CADR !#EXP))))))
  1040. (SETQ !#EXP (ERRORSET !#EXP T NIL))
  1041. (COND ((ATOM !#EXP) (PRIN2 " --EVAL failed-- "))
  1042. (T (PRIN1 (CAR !#EXP))))
  1043. (GO LOOP)))
  1044. (!*
  1045. " YRARE -- ROUTINES WHICH ARE USED, BUT OF DUBIOUS USEFULNESS
  1046. ?? DELETE THESE ??
  1047. LOADV ( V:vector FN:function ):vector EXPR
  1048. AMONG ( ALST KEY ITEM ) EXPR
  1049. INSERT ( ITEM ALST KEY ) EXPR
  1050. DCONS ( X:any Y:list ):list EXPR
  1051. SUBLIST ( X:list P1:integer P2:integer ):list EXPR
  1052. SUBLIST1( Y ) EXPR
  1053. LDIFF ( X:list Y:list ):list EXPR used in editor/copy in ZEDIT
  1054. MAPCAR# ( L:list FN:function ):any EXPR
  1055. MAP# ( L:list FN:function ):any EXPR
  1056. INITIALP( X:list Y:list ):boolean EXPR
  1057. SUBLISTP( X:list Y:list ):list EXPR
  1058. INITQ ( X:any Y:list R:fn ):boolean EXPR
  1059. ")
  1060. (!*
  1061. "LOADV( V:vector FN:function ):vector EXPR
  1062. -----
  1063. Loads vector with values. Function should be 1-place numerical.
  1064. V[I] _ FN( I ).
  1065. If value of function is 'novalue, then doesn't change value. ??")
  1066. (CDE LOADV (!#V !#FN)
  1067. (PROG (!#CTR !#LEN)
  1068. (COND ((NOT (SETQ !#LEN (VECTORP !#V))) (RETURN !#V)))
  1069. (SETQ !#CTR 0)
  1070. LOOP (PUTV !#V !#CTR (APPLY !#FN (LIST !#CTR)))
  1071. (COND ((LESSP !#CTR !#LEN) (PROGN (MAKE !#CTR 1) (GO LOOP))))
  1072. (RETURN !#V)))
  1073. (!*
  1074. "AMONG(ALST:association-list KEY:atom ITEM:atom):boolean EXPR
  1075. -----
  1076. Tests if item is found under key in association list.
  1077. Uses EQUAL tests.")
  1078. (CDE AMONG (!#ALST !#KEY !#ITEM)
  1079. (PROG (RES)
  1080. (SETQ RES
  1081. (ERRORSET
  1082. (LIST 'AMONG1 (MKQUOTE !#ALST) (MKQUOTE !#KEY) (MKQUOTE !#ITEM))
  1083. NIL
  1084. NIL))
  1085. (COND ((EQ RES 'FOUND) (RETURN T))
  1086. ((NULL RES) (RETURN NIL))
  1087. ((ATOM RES) (ERROR RES NIL)))))
  1088. (CDE AMONG1 (!#ALST !#KEY !#ITEM)
  1089. (MAPC !#ALST
  1090. (FUNCTION
  1091. (LAMBDA (!#ENTRY)
  1092. (AND (EQUAL (CAR !#ENTRY) !#KEY)
  1093. (MEMQ !#ITEM (CDR !#ENTRY))
  1094. (ERROR 'FOUND NIL))))))
  1095. (!*
  1096. "INSERT (ITEM:item ALST:association:list KEY:any):association list
  1097. ------
  1098. EXPR (destructive operation on ALST)
  1099. Inserts item in association list under key or if key not present
  1100. adds (KEY ITEM) to the ALST.")
  1101. (CDE INSERT (!#ITEM !#ALST !#KEY)
  1102. (PROG (!#AS!:ITEM)
  1103. (COND ((SETQ !#AS!:ITEM (ASSOC !#KEY !#ALST))
  1104. (COND ((NOT (MEMBER !#ITEM (CCDR !#AS!:ITEM)))
  1105. (RPLACD !#AS!:ITEM (CONS !#ITEM (CDR !#AS!:ITEM))))))
  1106. (T (DCONS (LIST !#KEY !#ITEM) !#ALST)))
  1107. (RETURN !#ALST)))
  1108. (!*
  1109. "DCONS( X:any Y:list ):list EXPR
  1110. -----
  1111. Destructively cons x to list.")
  1112. (CDE DCONS (!#X !#Y)
  1113. (PROGN (RPLACD !#Y (CONS (CAR !#Y) (CDR !#Y))) (RPLACA !#Y !#X)))
  1114. (!*
  1115. "SUBLIST( X:list P1:integer P2:integer ):list EXPR
  1116. -------
  1117. Returns sublist from p1 to p2 positions, negatives counting from end.
  1118. I.e., (SUBLIST '(A B C D E) 2 -2) = (B C D)")
  1119. (CDE SUBLIST (!#X !#P1 !#P2)
  1120. (LDIFF (NTH!-TAIL !#X (SETQ !#P1 (SUBLIST1 !#X !#P1)))
  1121. (NTH!-TAIL !#X (ADD1 (SUBLIST1 !#X !#P2)))))
  1122. (CDE SUBLIST1 (!#X !#Y)
  1123. (COND ((LESSP !#Y 0) (MAX 1 (PLUS 1 !#Y (LENGTH !#X)))) (T !#Y)))
  1124. (!*
  1125. "LDIFF( X:list Y:list ):list EXPR
  1126. -----
  1127. If X is a tail of Y, returns the list difference of X and Y,
  1128. a list of the elements of Y preceeding X.")
  1129. (CDE LDIFF (!#X !#Y)
  1130. (COND ((OR (EQ !#X !#Y) (ATOM !#X)) NIL)
  1131. ((NULL !#Y) !#X)
  1132. (T (PROG (!#V !#Z)
  1133. (SETQ !#Z (SETQ !#V (NCONS (CAR !#X))))
  1134. LOOP (SETQ !#X (CDR !#X))
  1135. (COND ((OR (EQ !#X !#Y) (ATOM !#X)) (RETURN !#Z)))
  1136. (SETQ !#V (CDR (RPLACD !#V (NCONS (CAR !#X)))))
  1137. (GO LOOP)))))
  1138. (!*
  1139. "MAPCAR#( L:list FN:function ):any EXPR
  1140. -------
  1141. Extends mapcar to work on general s-expressions as well as lists.
  1142. The return is of same form, i.e.
  1143. (MAPCAR# 'ATOM '(A B C . D)) = (T T T . T)
  1144. Also, if for any member of list the variable SPLICE is set to
  1145. true by function, then for that member the return from the
  1146. function is spliced into the return.")
  1147. (CDE MAPCAR!# (!#L !#FN)
  1148. (PROG (!#M !#SPLICE !#TEMP)
  1149. (SETQ !#M (NCONS NIL))
  1150. LOOP (COND ((NULL !#L) (RETURN (CAR !#M)))
  1151. ((ATOM !#L)
  1152. (RETURN
  1153. (COND ((NULL (CAR !#M)) (APPLY !#FN (LIST !#L)))
  1154. (T (PROGN (RPLACD (CDR !#M) (APPLY !#FN (LIST !#L)))
  1155. (CAR !#M)))))))
  1156. (SETQ !#TEMP (APPLY !#FN (LIST (CAR !#L))))
  1157. (COND (!#SPLICE (PROGN (SETQ !#SPLICE NIL) (LCONC !#M !#TEMP)))
  1158. (T (TCONC !#M !#TEMP)))
  1159. (SETQ !#L (CDR !#L))
  1160. (GO LOOP)))
  1161. (!*
  1162. "MAP#( L:list FN:function ):any EXPR
  1163. ----
  1164. Extends map to work on general s-expressions as well as lists.")
  1165. (CDE MAP!# (!#L !#FN)
  1166. (PROG (!#MAPPED)
  1167. LOOP (COND ((NULL !#L) (RETURN !#MAPPED)))
  1168. (APPLY !#FN (LIST !#L))
  1169. (COND ((ATOM !#L) (RETURN !#MAPPED)))
  1170. (SETQ !#L (CDR !#L))
  1171. (GO LOOP)))
  1172. (!*
  1173. "INITIALP( X:list Y:list ):boolean EXPR
  1174. --------
  1175. Returns T if X is EQUAL to some ldiff of Y.")
  1176. (CDE INITIALP (!#X !#Y)
  1177. (COND ((NULL !#X) (COND (!#Y !#Y) (T T)))
  1178. ((NULL !#Y) NIL)
  1179. ((NOT (EQUAL (CAR !#X) (CAR !#Y))) NIL)
  1180. (T (INITIALP (CDR !#X) (CDR !#Y)))))
  1181. (!*
  1182. "SUBLISTP( X:list Y:list ):list EXPR
  1183. --------
  1184. Returns a tail of Y (or T) if X is a sublist of Y.")
  1185. (CDE SUBLISTP (!#X !#Y)
  1186. (COND ((NULL !#X) (COND (!#Y !#Y) (T T)))
  1187. ((NULL !#Y) NIL)
  1188. ((INITIALP !#X !#Y) T)
  1189. (T (SUBLISTP !#X (CDR !#Y)))))
  1190. (!*
  1191. "INITQ( X:any Y:list R:fn ):boolean EXPR
  1192. -----
  1193. Returns T if x is an initial portion of Y under the relation R.")
  1194. (CDE INITQ (!#X !#Y !#R)
  1195. (COND ((OR (NULL !#X) (NULL !#Y)) NIL)
  1196. ((APPLY !#R (LIST (CAR !#X) (CAR !#Y)))
  1197. (CONS (CAR !#X) (INITQ (CDR !#X) (CDR !#Y) !#R)))))