complr.red 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412
  1. COMMENT **************************************************************
  2. **********************************************************************
  3. THE STANDARD LISP COMPILER
  4. **********************************************************************
  5. *********************************************************************;
  6. COMMENT machine dependent parts are in a separate file;
  7. COMMENT these include the macros described below and, in addition,
  8. an auxiliary function !&MKFUNC which is required to pass
  9. functional arguments (input as FUNCTION <func>) to the
  10. loader. In most cases, !&MKFUNC may be defined as MKQUOTE;
  11. COMMENT global flags used in this compiler:
  12. !*MODULE indicates block compilation (a future extension of
  13. this compiler)
  14. !*MSG indicates whether certain messages should be printed
  15. !*NOLINKE if ON inhibits use of !*LINKE c-macro
  16. !*ORD if ON forces left-to-right argument evaluation
  17. !*PLAP if ON causes LAP output to be printed
  18. !*R2I if ON causes recursion removal where possible;
  19. GLOBAL '(!*MODULE !*MSG !*NOLINKE !*ORD !*PLAP !*R2I);
  20. COMMENT global variables used:
  21. ERFG!* used by REDUCE to control error recovery
  22. MAXNARGS maximum number of arguments permitted;
  23. GLOBAL '(ERFG!* MAXNARGS);
  24. MAXNARGS := 15; %Standard LISP limit;
  25. COMMENT fluid variables used:
  26. ALSTS alist of fluid parameters
  27. CODELIST code being built
  28. CONDTAIL simulated stack of position in the tail of a COND
  29. DFPRINT!* name of special definition process (or NIL)
  30. EXIT label for !*EXIT jump
  31. FLAGG used in !&COMTST, and in !&FIXREST
  32. FREELST list of free variables with bindings
  33. GOLIST storage map for jump labels
  34. IREGS initial register contents
  35. IREGS1 temporary placeholder for IREGS for branch compilation
  36. JMPLIST list of locations in CODELIST of transfers
  37. LBLIST list of label words
  38. LLNGTH cell whose CAR is length of frame
  39. NAME name of function being currently compiled
  40. NARG number of arguments in function
  41. REGS known current contents of registers as an alist with
  42. elements of form (<reg> . <contents>)
  43. REGS1 temporary placeholder for REGS during branch compilation
  44. SLST association list for stores which have not yet been used
  45. STLST list of active stores in function
  46. STOMAP storage map for variables
  47. SWITCH boolean expression value flag - keeps track of NULLs;
  48. FLUID '(ALSTS CODELIST CONDTAIL DFPRINT!* EXIT FLAGG FREELST GOLIST
  49. IREGS IREGS1 JMPLIST LBLIST LLNGTH NAME NARG REGS REGS1 SLST
  50. STLST STOMAP SWITCH);
  51. COMMENT c-macros used in this compiler;
  52. COMMENT The following c-macros must NOT change regs 1-MAXNARGS:
  53. !*ALLOC n allocate new stack frame of n words
  54. !*DEALLOC n deallocate above frame
  55. !*ENTRY name type nargs entry point to function name of type type
  56. with nargs args
  57. !*EXIT exit to previously saved return address
  58. !*STORE reg floc store contents of reg (or NIL) in floc
  59. !*JUMP adr unconditional jump
  60. !*JUMPC adr exp type jump to adr if exp is of type type
  61. !*JUMPNC adr exp type jump to adr if exp is not of type type
  62. !*JUMPNIL adr jump on register 1 eq to NIL
  63. !*JUMPT adr jump on register 1 not eq to NIL
  64. !*JUMPE adr exp jump on register 1 eq to exp
  65. !*JUMPN adr exp jump on register 1 not eq to exp
  66. !*LBL adr define label
  67. !*LAMBIND regs alst bind free lambda vars in alst currently in regs
  68. !*PROGBIND alst bind free prog vars in alst
  69. !*FREERSTR alst unbind free variables in alst
  70. COMMENT the following c-macro must only change specific register
  71. being loaded:
  72. !*LOAD reg exp load exp into reg;
  73. COMMENT the following c-macros do not protect regs 1-MAXNARGS:
  74. !*LINK fn type nargs link to fn of type type with nargs args
  75. !*LINKE fn type nargs n link to fn of type type with nargs args
  76. and exit removing frame of n words
  77. !*CODE list this macro allows for the inclusion of a list
  78. of c-macro expressions (or even explicit
  79. assembly language) in a function definition;
  80. FLAG('(!*ALLOC !*DEALLOC !*ENTRY !*EXIT !*STORE !*JUMP !*JUMPC !*JUMPNC
  81. !*JUMPNIL !*JUMPT !*JUMPE !*JUMPN !*LBL !*LAMBIND !*PROGBIND
  82. !*FREERSTR !*LOAD !*LINK !*LINKE !*CODE),
  83. 'MC);
  84. COMMENT general functions used in this compiler;
  85. SYMBOLIC PROCEDURE ATSOC(U,V);
  86. IF NULL V THEN NIL
  87. ELSE IF U EQ CAAR V THEN CAR V
  88. ELSE ATSOC(U,CDR V);
  89. SYMBOLIC PROCEDURE EQCAR(U,V); NOT ATOM U AND CAR U EQ V;
  90. SYMBOLIC PROCEDURE LPRI U;
  91. IF ATOM U THEN LPRI LIST U
  92. ELSE FOR EACH X IN U DO <<PRIN2 X; PRIN2 " ">>;
  93. SYMBOLIC PROCEDURE LPRIE U;
  94. <<LPRI ("*****" . IF ATOM U THEN LIST U ELSE U);
  95. ERFG!* := T;
  96. TERPRI()>>;
  97. SYMBOLIC PROCEDURE LPRIM U;
  98. IF !*MSG
  99. THEN <<TERPRI();
  100. LPRI ("***" . IF ATOM U THEN LIST U ELSE U);
  101. TERPRI()>>;
  102. SYMBOLIC PROCEDURE MKQUOTE U; LIST('QUOTE,U);
  103. SYMBOLIC PROCEDURE REVERSIP U;
  104. BEGIN SCALAR X,Y;
  105. WHILE U DO <<X := CDR U; Y := RPLACD(U,Y); U := X>>;
  106. RETURN Y
  107. END;
  108. SYMBOLIC PROCEDURE RPLACW(A,B); RPLACA(RPLACD(A,CDR B),CAR B);
  109. COMMENT the following two functions are used by the CONS open
  110. coding. They should be defined in the interpreter if
  111. possible. They should only be compiled without a COMPFN
  112. for CONS;
  113. SYMBOLIC PROCEDURE NCONS U; U . NIL;
  114. SYMBOLIC PROCEDURE XCONS(U,V); V . U;
  115. COMMENT Top level compiling functions;
  116. SYMBOLIC PROCEDURE COMPILE X;
  117. BEGIN SCALAR EXP;
  118. FOR EACH Y IN X DO
  119. IF NULL (EXP := GETD Y) THEN LPRIM LIST(Y,'UNDEFINED)
  120. ELSE COMPD(Y,CAR EXP,CDR EXP);
  121. RETURN X
  122. END;
  123. SYMBOLIC PROCEDURE COMPD(NAME,TYPE,EXP);
  124. BEGIN
  125. IF NOT FLAGP(TYPE,'COMPILE)
  126. THEN <<LPRIM LIST("UNCOMPILABLE FUNCTION",NAME,"OF TYPE",
  127. TYPE);
  128. RETURN NIL>>;
  129. IF NOT ATOM EXP
  130. THEN IF !*MODULE THEN MODCMP(NAME,TYPE,EXP)
  131. ELSE IF DFPRINT!*
  132. THEN APPLY(DFPRINT!*,
  133. LIST IF TYPE EQ 'EXPR
  134. THEN 'DE . (NAME . CDR EXP)
  135. ELSE IF TYPE EQ 'FEXPR
  136. THEN 'DF . (NAME . CDR EXP)
  137. ELSE IF TYPE EQ 'MACRO
  138. THEN 'DM . (NAME . CDR EXP)
  139. ELSE LIST('PUTD,MKQUOTE NAME,
  140. MKQUOTE TYPE,
  141. MKQUOTE EXP))
  142. ELSE BEGIN SCALAR X;
  143. IF FLAGP(TYPE,'COMPILE)
  144. THEN PUT(NAME,'CFNTYPE,LIST TYPE);
  145. X :=
  146. LIST('!*ENTRY,NAME,TYPE,LENGTH CADR EXP)
  147. . !&COMPROC(EXP,
  148. IF FLAGP(TYPE,'COMPILE)
  149. THEN NAME);
  150. IF !*PLAP THEN FOR EACH Y IN X DO PRINT Y;
  151. LAP X;
  152. %this is the entry point to the assembler. LAP
  153. %must remove any preexisting function definition;
  154. IF (X := GET(NAME,'CFNTYPE))
  155. AND EQCAR(GETD NAME,CAR X)
  156. THEN REMPROP(NAME,'CFNTYPE)
  157. END;
  158. RETURN NAME
  159. END;
  160. FLAG('(EXPR FEXPR MACRO),'COMPILE);
  161. SYMBOLIC PROCEDURE !&COMPROC(EXP,NAME);
  162. %compiles a function body, returning the generated LAP;
  163. BEGIN SCALAR CODELIST,FLAGG,IREGS,IREGS1,JMPLIST,LBLIST,
  164. LLNGTH,REGS,REGS1,ALSTS,EXIT,SLST,STLST,STOMAP,
  165. CONDTAIL,FREELST,
  166. SWITCH; INTEGER NARG;
  167. LLNGTH := LIST 1;
  168. NARG := 0;
  169. EXIT := !&GENLBL();
  170. STOMAP := '((NIL 1));
  171. CODELIST := LIST ('!*ALLOC . LLNGTH);
  172. EXP := !&PASS1 EXP;
  173. IF LENGTH CADR EXP>MAXNARGS
  174. THEN LPRIE LIST("TOO MANY ARGS FOR COMPILER IN",NAME);
  175. FOR EACH Z IN CADR EXP DO <<!&FRAME Z;
  176. NARG := NARG + 1;
  177. IF NOT NONLOCAL Z
  178. THEN IREGS :=
  179. NCONC(IREGS,
  180. LIST LIST(NARG,Z));
  181. REGS :=
  182. NCONC(REGS,LIST LIST(NARG,Z))>>;
  183. IF NULL REGS THEN REGS := LIST (1 . NIL);
  184. ALSTS := !&FREEBIND(CADR EXP,T);
  185. !&PASS2 CADDR EXP;
  186. !&FREERST(ALSTS,0);
  187. !&PASS3();
  188. RPLACA(LLNGTH,1 - CAR LLNGTH);
  189. RETURN CODELIST
  190. END;
  191. SYMBOLIC PROCEDURE NONLOCAL X;
  192. IF FLUIDP X THEN 'FLUID ELSE IF GLOBALP X THEN 'GLOBAL ELSE NIL;
  193. COMMENT Pass 1 of the compiler;
  194. SYMBOLIC PROCEDURE !&PASS1 EXP; !&PA1(EXP,NIL);
  195. SYMBOLIC PROCEDURE !&PA1(U,VBLS);
  196. BEGIN SCALAR X;
  197. RETURN IF ATOM U
  198. THEN IF CONSTANTP U OR U MEMQ '(NIL T) THEN MKQUOTE U
  199. ELSE IF U MEMQ VBLS THEN U
  200. ELSE IF NONLOCAL U THEN U
  201. ELSE <<MKNONLOCAL U; U>>
  202. ELSE IF NOT ATOM CAR U
  203. THEN !&PA1(CAR U,VBLS) . !&PALIS(CDR U,VBLS)
  204. ELSE IF X := GET(CAR U,'PA1FN) THEN APPLY(X,LIST(U,VBLS))
  205. ELSE IF (X := GETD CAR U)
  206. AND CAR X EQ 'MACRO
  207. AND NOT GET(CAR U,'COMPFN)
  208. THEN !&PA1(APPLY(CDR X,LIST U),VBLS)
  209. ELSE IF X := GET(CAR U,'CMACRO)
  210. THEN !&PA1(SUBLIS(PAIR(CADR X,CDR U),CADDR X),VBLS)
  211. ELSE IF !&CFNTYPE CAR U EQ 'FEXPR
  212. AND NOT GET(CAR U,'COMPFN)
  213. THEN LIST(CAR U,MKQUOTE CDR U)
  214. ELSE IF CAR U MEMQ VBLS OR FLUIDP CAR U
  215. THEN LIST('APPLY,CAR U,!&PALIST(CDR U,VBLS))
  216. ELSE CAR U . !&PALIS(CDR U,VBLS)
  217. END;
  218. SYMBOLIC PROCEDURE !&PAIDEN(U,VBLS); U;
  219. PUT('GO,'PA1FN,'!&PAIDEN);
  220. PUT('QUOTE,'PA1FN,'!&PAIDEN);
  221. PUT('CODE,'PA1FN,'!&PAIDEN);
  222. SYMBOLIC PROCEDURE !&PACOND(U,VBLS);
  223. 'COND . FOR EACH Z IN CDR U
  224. COLLECT LIST(!&PA1(CAR Z,VBLS),
  225. !&PA1(!&MKPROGN CDR Z,VBLS));
  226. PUT('COND,'PA1FN,'!&PACOND);
  227. SYMBOLIC PROCEDURE !&PAFUNC(U,VBLS);
  228. IF ATOM CADR U THEN !&MKFUNC CADR U
  229. ELSE !&MKFUNC COMPD(!&MKNAM NAME,'EXPR,CADR U);
  230. PUT('FUNCTION,'PA1FN,'!&PAFUNC);
  231. SYMBOLIC PROCEDURE !&PALAMB(U,VBLS);
  232. 'LAMBDA . LIST(CADR U,!&PA1(!&MKPROGN CDDR U,APPEND(CADR U,VBLS)));
  233. PUT('LAMBDA,'PA1FN,'!&PALAMB);
  234. SYMBOLIC PROCEDURE !&PALIST(U,VBLS); 'LIST . !&PALIS(U,VBLS);
  235. SYMBOLIC PROCEDURE !&PAPROG(U,VBLS);
  236. 'PROG . (CADR U . !&PAPROG1(CDDR U,APPEND(CADR U,VBLS)));
  237. SYMBOLIC PROCEDURE !&PAPROG1(U,VBLS);
  238. FOR EACH X IN U COLLECT IF ATOM X THEN X ELSE !&PA1(X,VBLS);
  239. PUT('PROG,'PA1FN,'!&PAPROG);
  240. SYMBOLIC PROCEDURE !&PALIS(U,VBLS);
  241. FOR EACH X IN U COLLECT !&PA1(X,VBLS);
  242. SYMBOLIC PROCEDURE MKNONLOCAL U;
  243. <<LPRIM LIST(U,"declared fluid"); FLUID LIST U; LIST('FLUID,U)>>;
  244. SYMBOLIC PROCEDURE !&MKNAM U;
  245. %generates unique name for auxiliary function in U;
  246. INTERN COMPRESS APPEND(EXPLODE U,EXPLODE GENSYM());
  247. SYMBOLIC PROCEDURE !&MKPROGN U;
  248. IF NULL U OR CDR U THEN 'PROGN . U ELSE CAR U;
  249. COMMENT CMACRO definitions for some functions;
  250. COMMENT We do not expand CAAAAR and similar functions, since fewer
  251. instructions are generated without open coding;
  252. DEFLIST('((CAAR (LAMBDA (U) (CAR (CAR U))))
  253. (CADR (LAMBDA (U) (CAR (CDR U))))
  254. (CDAR (LAMBDA (U) (CDR (CAR U))))
  255. (CDDR (LAMBDA (U) (CDR (CDR U))))
  256. (CAAAR (LAMBDA (U) (CAR (CAR (CAR U)))))
  257. (CAADR (LAMBDA (U) (CAR (CAR (CDR U)))))
  258. (CADAR (LAMBDA (U) (CAR (CDR (CAR U)))))
  259. (CADDR (LAMBDA (U) (CAR (CDR (CDR U)))))
  260. (CDAAR (LAMBDA (U) (CDR (CAR (CAR U)))))
  261. (CDADR (LAMBDA (U) (CDR (CAR (CDR U)))))
  262. (CDDAR (LAMBDA (U) (CDR (CDR (CAR U)))))
  263. (CDDDR (LAMBDA (U) (CDR (CDR (CDR U)))))
  264. (NOT (LAMBDA (U) (NULL U)))),'CMACRO);
  265. COMMENT Pass 2 of the compiler;
  266. SYMBOLIC PROCEDURE !&PASS2 EXP; !&COMVAL(EXP,0);
  267. SYMBOLIC PROCEDURE !&COMVAL(EXP,STATUS);
  268. %computes code for value of EXP;
  269. IF !&ANYREG(EXP,NIL)
  270. THEN IF STATUS>1 THEN NIL ELSE !&LREG1(EXP,STATUS)
  271. ELSE !&COMVAL1(EXP,STOMAP,STATUS);
  272. SYMBOLIC PROCEDURE !&COMVAL1(EXP,STOMAP,STATUS);
  273. BEGIN SCALAR X;
  274. IF ATOM EXP THEN IF STATUS<2 THEN !&LREG1(EXP,STATUS) ELSE NIL
  275. ELSE IF NOT ATOM CAR EXP
  276. THEN IF CAAR EXP EQ 'LAMBDA
  277. THEN !&COMPLY(CAR EXP,CDR EXP,STATUS)
  278. ELSE LPRIE LIST("INVALID FUNCTION",CAR EXP)
  279. ELSE IF X := GET(CAR EXP,'COMPFN) THEN APPLY(X,LIST(EXP,STATUS))
  280. ELSE IF !*R2I AND CAR EXP EQ NAME AND STATUS=0 AND NULL FREELST
  281. THEN !&COMREC(EXP,STATUS)
  282. ELSE IF CAR EXP EQ 'LAMBDA
  283. THEN LPRIE LIST("INVALID USE OF LAMBDA IN FUNCTION",NAME)
  284. ELSE IF CAR EXP EQ '!*CODE THEN !&ATTACH EXP
  285. ELSE !&CALL(CAR EXP,CDR EXP,STATUS);
  286. RETURN NIL
  287. END;
  288. SYMBOLIC PROCEDURE !&ANYREG(U,V);
  289. %determines if U can be loaded in any register;
  290. %!*ORD = T means force correct order, unless safe;
  291. IF EQCAR(U,'QUOTE) THEN T
  292. ELSE (ATOM U
  293. OR IDP CAR U AND GET(CAR U,'ANYREG) AND !&ANYREG(CADR U,NIL))
  294. AND (NULL !*ORD OR !&ANYREGL V);
  295. SYMBOLIC PROCEDURE !&ANYREGL U;
  296. NULL U OR !&ANYREG(CAR U,NIL) AND !&ANYREGL CDR U;
  297. SYMBOLIC PROCEDURE !&CALL(FN,ARGS,STATUS);
  298. !&CALL1(FN,!&COMLIS ARGS,STATUS);
  299. SYMBOLIC PROCEDURE !&CALL1(FN,ARGS,STATUS);
  300. %ARGS is reversed list of compiled arguments of FN;
  301. BEGIN INTEGER ARGNO;
  302. ARGNO := LENGTH ARGS;
  303. !&LOADARGS(ARGS,STATUS);
  304. !&ATTACH LIST('!*LINK,FN,!&CFNTYPE FN,ARGNO);
  305. IF FLAGP(FN,'ONEREG) THEN REGS := (1 . NIL) . CDR REGS
  306. ELSE IF FLAGP(FN,'TWOREG)
  307. THEN REGS := (1 . NIL) . DELASC(2,CDR REGS)
  308. ELSE REGS := LIST (1 . NIL)
  309. END;
  310. SYMBOLIC PROCEDURE DELASC(U,V);
  311. IF NULL V THEN NIL
  312. ELSE IF U=CAAR V THEN CDR V
  313. ELSE CAR V . DELASC(U,CDR V);
  314. SYMBOLIC PROCEDURE !&COMLIS EXP;
  315. %returns reversed list of compiled arguments;
  316. BEGIN SCALAR ACUSED,Y;
  317. WHILE EXP DO
  318. <<IF !&ANYREG(CAR EXP,CDR EXP) THEN Y := CAR EXP . Y
  319. ELSE <<IF ACUSED THEN !&STORE1();
  320. !&COMVAL1(CAR EXP,STOMAP,1);
  321. ACUSED := GENSYM();
  322. REGS := (1 . (ACUSED . CDAR REGS)) . CDR REGS;
  323. Y := ACUSED . Y>>;
  324. EXP := CDR EXP>>;
  325. RETURN Y
  326. END;
  327. SYMBOLIC PROCEDURE !&STORE1; %Marks contents of register 1 for storage;
  328. BEGIN SCALAR X;
  329. X := CADAR REGS;
  330. IF NULL X OR EQCAR(X,'QUOTE) THEN RETURN NIL
  331. ELSE IF NOT ATSOC(X,STOMAP) THEN !&FRAME X;
  332. !&STORE0(X,1)
  333. END;
  334. SYMBOLIC PROCEDURE !&COMPLY(FN,ARGS,STATUS);
  335. BEGIN SCALAR ALSTS,VARS; INTEGER I;
  336. VARS := CADR FN;
  337. !&LOADARGS(!&COMLIS ARGS,1);
  338. ARGS := !&REMVARL VARS; % The stores that were protected;
  339. I := 1;
  340. FOR EACH V IN VARS DO <<!&FRAME V;
  341. REGS := !&REPASC(I,V,REGS);
  342. I := I + 1>>;
  343. ALSTS := !&FREEBIND(VARS,T); %Old fluid values saved;
  344. I := 1;
  345. FOR EACH V IN VARS DO <<IF NOT NONLOCAL V THEN !&STORE0(V,I);
  346. I := I + 1>>;
  347. !&COMVAL(CADDR FN,STATUS);
  348. !&FREERST(ALSTS,STATUS);
  349. !&RSTVARL(VARS,ARGS)
  350. END;
  351. SYMBOLIC PROCEDURE !&COMREC(EXP,STATUS);
  352. BEGIN SCALAR X,Z;
  353. !&LOADARGS(!&COMLIS CDR EXP,STATUS);
  354. Z := CODELIST;
  355. IF NULL CDR Z
  356. THEN LPRIE LIST("CIRCULAR DEFINITION FOR",CAR EXP);
  357. WHILE CDDR Z DO Z := CDR Z;
  358. IF CAAR Z EQ '!*LBL THEN X := CDAR Z
  359. ELSE <<X := !&GENLBL(); RPLACD(Z,LIST('!*LBL . X,CADR Z))>>;
  360. !&ATTJMP X
  361. END;
  362. SYMBOLIC PROCEDURE !&LOADARGS(ARGS,STATUS);
  363. BEGIN INTEGER N;
  364. N := LENGTH ARGS;
  365. IF N>MAXNARGS THEN LPRIE LIST("TOO MANY ARGUMENTS IN",NAME);
  366. IF STATUS>0 THEN !&CLRREGS();
  367. WHILE ARGS DO
  368. <<!&LREG(N,CAR ARGS,CDR ARGS,STATUS);
  369. N := N - 1;
  370. ARGS := CDR ARGS>>
  371. END;
  372. SYMBOLIC PROCEDURE !&LOCATE X;
  373. BEGIN SCALAR Y,VTYPE;
  374. IF EQCAR(X,'QUOTE) THEN RETURN LIST X
  375. ELSE IF Y := !&RASSOC(X,REGS) THEN RETURN LIST CAR Y
  376. ELSE IF NOT ATOM X THEN RETURN LIST (CAR X . !&LOCATE CADR X)
  377. ELSE IF VTYPE := NONLOCAL X THEN RETURN LIST LIST(VTYPE,X);
  378. WHILE Y := ATSOC(X,SLST) DO SLST := DELETE(Y,SLST);
  379. RETURN IF Y := ATSOC(X,STOMAP) THEN CDR Y ELSE LIST MKNONLOCAL X
  380. END;
  381. SYMBOLIC PROCEDURE !&LREG(REG,U,V,STATUS);
  382. BEGIN SCALAR X,Y;
  383. IF (X := ASSOC(REG,REGS)) AND U MEMBER CDR X THEN RETURN NIL
  384. ELSE IF (Y := ASSOC(REG,IREGS))
  385. AND (STATUS>0 OR !&MEMLIS(CADR Y,V))
  386. THEN <<!&STORE0(CADR Y,REG); IREGS := DELETE(Y,IREGS)>>;
  387. !&ATTACH ('!*LOAD . (REG . !&LOCATE U));
  388. REGS := !&REPASC(REG,U,REGS)
  389. END;
  390. SYMBOLIC PROCEDURE !&LREG1(X,STATUS); !&LREG(1,X,NIL,STATUS);
  391. COMMENT Functions for handling non-local variables;
  392. SYMBOLIC PROCEDURE !&FREEBIND(VARS,LAMBP);
  393. %bind FLUID variables in lambda or prog lists;
  394. %LAMBP is true for LAMBDA, false for PROG;
  395. BEGIN SCALAR FALST,FREGS,X,Y; INTEGER I;
  396. I := 1;
  397. FOR EACH X IN VARS DO <<IF FLUIDP X
  398. THEN <<FALST :=
  399. (X . !&GETFFRM X) . FALST;
  400. FREGS := I . FREGS>>
  401. ELSE IF GLOBALP X
  402. THEN LPRIE LIST("CANNOT BIND GLOBAL ",
  403. X);
  404. I := I + 1>>;
  405. IF NULL FALST THEN RETURN NIL;
  406. IF LAMBP THEN !&ATTACH LIST('!*LAMBIND,FREGS,FALST)
  407. ELSE !&ATTACH LIST('!*PROGBIND,FALST);
  408. RETURN FALST
  409. END;
  410. SYMBOLIC PROCEDURE !&FREERST(ALSTS,STATUS); %restores FLUID variables;
  411. IF ALSTS THEN !&ATTACH LIST('!*FREERSTR,ALSTS);
  412. SYMBOLIC PROCEDURE !&ATTACH U; CODELIST := U . CODELIST;
  413. SYMBOLIC PROCEDURE !&STORE0(U,REG);
  414. %marks expression U in register REG for storage;
  415. BEGIN SCALAR X;
  416. X := '!*STORE . (REG . !&GETFRM U);
  417. STLST := X . STLST;
  418. !&ATTACH X;
  419. IF ATOM U
  420. THEN <<!&CLRSTR U; SLST := (U . CODELIST) . SLST>>
  421. END;
  422. SYMBOLIC PROCEDURE !&CLRSTR VAR; %removes unneeded stores;
  423. BEGIN SCALAR X;
  424. IF CONDTAIL THEN RETURN NIL;
  425. X := ATSOC(VAR,SLST);
  426. IF NULL X THEN RETURN NIL;
  427. STLST := !&DELEQ(CADR X,STLST);
  428. SLST := !&DELEQ(X,SLST);
  429. RPLACA(CADR X,'!*NOOP)
  430. END;
  431. COMMENT Functions for general tests;
  432. SYMBOLIC PROCEDURE !&COMTST(EXP,LABL);
  433. %compiles boolean expression EXP.
  434. %If EXP has the same value as SWITCH then branch to LABL,
  435. %otherwise fall through;
  436. %REGS/IREGS are active registers for fall through,
  437. %REGS1/IREGS1 for branch;
  438. BEGIN SCALAR X;
  439. WHILE EQCAR(EXP,'NULL) DO
  440. <<SWITCH := NOT SWITCH; EXP := CADR EXP>>;
  441. IF NOT ATOM EXP AND ATOM CAR EXP AND (X := GET(CAR EXP,'COMTST))
  442. THEN APPLY(X,LIST(EXP,LABL))
  443. ELSE <<IF EXP='(QUOTE T)
  444. THEN IF SWITCH THEN !&ATTJMP LABL ELSE FLAGG := T
  445. ELSE <<!&COMVAL(EXP,1);
  446. !&ATTACH LIST(IF SWITCH THEN '!*JUMPT
  447. ELSE '!*JUMPNIL,CAR LABL);
  448. !&ADDJMP CODELIST>>;
  449. REGS1 := REGS;
  450. IREGS1 := IREGS>>;
  451. IF EQCAR(CAR CODELIST,'!*JUMPT)
  452. THEN REGS := (1 . ('(QUOTE NIL) . CDAR REGS)) . CDR REGS
  453. ELSE IF EQCAR(CAR CODELIST,'!*JUMPNIL)
  454. THEN REGS1 := (1 . ('(QUOTE NIL) . CDAR REGS1)) . CDR REGS1
  455. END;
  456. COMMENT Specific function open coding;
  457. SYMBOLIC PROCEDURE !&COMANDOR(EXP,STATUS);
  458. BEGIN SCALAR FN,LABL,IREGSL,REGSL;
  459. FN := CAR EXP EQ 'AND;
  460. LABL := !&GENLBL();
  461. IF STATUS>1
  462. THEN BEGIN SCALAR REGS1;
  463. !&TSTANDOR(EXP,LABL);
  464. REGS := !&RMERGE2(REGS,REGS1)
  465. END
  466. ELSE BEGIN
  467. IF STATUS>0 THEN !&CLRREGS();
  468. EXP := CDR EXP;
  469. WHILE EXP DO
  470. <<!&COMVAL(CAR EXP,IF CDR EXP THEN 1 ELSE STATUS);
  471. %to allow for recursion on last entry;
  472. IREGSL := IREGS . IREGSL;
  473. REGSL := REGS . REGSL;
  474. IF CDR EXP
  475. THEN <<!&ATTACH LIST(IF FN THEN '!*JUMPNIL
  476. ELSE '!*JUMPT,CAR LABL);
  477. !&ADDJMP CODELIST>>;
  478. EXP := CDR EXP>>;
  479. IREGS := !&RMERGE IREGSL;
  480. REGS := !&RMERGE REGSL
  481. END;
  482. !&ATTLBL LABL
  483. END;
  484. SYMBOLIC PROCEDURE !&TSTANDOR(EXP,LABL);
  485. BEGIN SCALAR FLG,FLG1,FN,LAB2,REGSL,REGS1L,TAILP;
  486. %FLG is initial switch condition;
  487. %FN is appropriate AND/OR case;
  488. %FLG1 determines appropriate switching state;
  489. FLG := SWITCH;
  490. SWITCH := NIL;
  491. FN := CAR EXP EQ 'AND;
  492. FLG1 := FLG EQ FN;
  493. EXP := CDR EXP;
  494. LAB2 := !&GENLBL();
  495. !&CLRREGS();
  496. WHILE EXP DO
  497. <<SWITCH := NIL;
  498. IF NULL CDR EXP AND FLG1
  499. THEN <<IF FN THEN SWITCH := T;
  500. !&COMTST(CAR EXP,LABL);
  501. REGSL := REGS . REGSL;
  502. REGS1L := REGS1 . REGS1L>>
  503. ELSE <<IF NOT FN THEN SWITCH := T;
  504. IF FLG1
  505. THEN <<!&COMTST(CAR EXP,LAB2);
  506. REGSL := REGS1 . REGSL;
  507. REGS1L := REGS . REGS1L>>
  508. ELSE <<!&COMTST(CAR EXP,LABL);
  509. REGSL := REGS . REGSL;
  510. REGS1L := REGS1 . REGS1L>>>>;
  511. IF NULL TAILP
  512. THEN <<CONDTAIL := NIL . CONDTAIL; TAILP := T>>;
  513. EXP := CDR EXP>>;
  514. !&ATTLBL LAB2;
  515. REGS := IF NOT FLG1 THEN CAR REGSL ELSE !&RMERGE REGSL;
  516. REGS1 := IF FLG1 THEN CAR REGS1L ELSE !&RMERGE REGS1L;
  517. IF TAILP THEN CONDTAIL := CDR CONDTAIL;
  518. SWITCH := FLG
  519. END;
  520. PUT('AND,'COMPFN,'!&COMANDOR);
  521. PUT('OR,'COMPFN,'!&COMANDOR);
  522. PUT('AND,'COMTST,'!&TSTANDOR);
  523. PUT('OR,'COMTST,'!&TSTANDOR);
  524. SYMBOLIC PROCEDURE !&COMCOND(EXP,STATUS);
  525. %compiles conditional expressions;
  526. %registers REGS and IREGS are set for dropping through,
  527. %REGS1 and IREGS1 are set for a branch;
  528. BEGIN SCALAR IREGS1,REGS1,FLAGG,SWITCH,LAB1,LAB2,REGSL,IREGSL,TAILP;
  529. EXP := CDR EXP;
  530. LAB1 := !&GENLBL();
  531. IF STATUS>0 THEN !&CLRREGS();
  532. FOR EACH X IN EXP DO <<LAB2 := !&GENLBL();
  533. SWITCH := NIL;
  534. IF CDR X THEN !&COMTST(CAR X,LAB2)
  535. %update CONDTAIL;
  536. ELSE <<!&COMVAL(CAR X,1);
  537. !&ATTACH LIST('!*JUMPNIL,CAR LAB2);
  538. !&ADDJMP CODELIST;
  539. IREGS1 := IREGS;
  540. REGS1 := (1 . '(QUOTE NIL) .
  541. CDAR REGS) . CDR REGS>>;
  542. IF NULL TAILP
  543. THEN <<CONDTAIL := NIL . CONDTAIL;
  544. TAILP := T>>;
  545. !&COMVAL(CADR X,STATUS);
  546. % Branch code;
  547. %test if need jump to LAB1;
  548. IF NOT !&TRANSFERP CAR CODELIST
  549. THEN <<!&ATTJMP LAB1;
  550. IREGSL := IREGS . IREGSL;
  551. REGSL := REGS . REGSL>>;
  552. REGS := REGS1;
  553. %restore register status for next iteration;
  554. IREGS := IREGS1;
  555. IREGS1 := NIL;
  556. %we do not need to set REGS1 to NIL since all !&COMTSTs
  557. %are required to set it;
  558. !&ATTLBL LAB2>>;
  559. IF NULL FLAGG AND STATUS<2
  560. THEN <<!&LREG1('(QUOTE NIL),STATUS);
  561. IREGS := !&RMERGE1(IREGS,IREGSL);
  562. REGS := !&RMERGE1(REGS,REGSL)>>
  563. ELSE IF REGSL
  564. THEN <<IREGS := !&RMERGE1(IREGS,IREGSL);
  565. REGS := !&RMERGE1(REGS,REGSL)>>;
  566. !&ATTLBL LAB1;
  567. IF TAILP THEN CONDTAIL := CDR CONDTAIL
  568. END;
  569. SYMBOLIC PROCEDURE !&RMERGE U;
  570. IF NULL U THEN NIL ELSE !&RMERGE1(CAR U,CDR U);
  571. SYMBOLIC PROCEDURE !&RMERGE1(U,V);
  572. IF NULL V THEN U ELSE !&RMERGE1(!&RMERGE2(U,CAR V),CDR V);
  573. SYMBOLIC PROCEDURE !&RMERGE2(U,V);
  574. IF NULL U OR NULL V THEN NIL
  575. ELSE (LAMBDA X;
  576. IF X
  577. THEN (CAAR U . XN(CDAR U,CDR X))
  578. . !&RMERGE2(CDR U,DELETE(X,V))
  579. ELSE !&RMERGE2(CDR U,V))
  580. ASSOC(CAAR U,V);
  581. FLAG('(!*JUMP !*LINKE ERROR),'TRANSFER);
  582. PUT('COND,'COMPFN,'!&COMCOND);
  583. SYMBOLIC PROCEDURE !&COMCONS(EXP,STATUS);
  584. IF NULL (EXP := CDR EXP) OR NULL CDR EXP OR CDDR EXP
  585. THEN LPRIE "MISMATCH OF ARGUMENTS"
  586. ELSE IF CADR EXP='(QUOTE NIL)
  587. THEN !&CALL('NCONS,LIST CAR EXP,STATUS)
  588. ELSE IF EQCAR(!&RASSOC(CADR EXP,REGS),1)
  589. AND !&ANYREG(CAR EXP,NIL)
  590. THEN !&CALL1('XCONS,!&COMLIS REVERSE EXP,STATUS)
  591. ELSE IF !&ANYREG(CADR EXP,NIL) THEN !&CALL('CONS,EXP,STATUS)
  592. ELSE !&CALL1('XCONS,REVERSIP !&COMLIS EXP,STATUS);
  593. PUT('CONS,'COMPFN,'!&COMCONS);
  594. SYMBOLIC PROCEDURE !&COMGO(EXP,STATUS);
  595. <<!&CLRREGS();
  596. IF STATUS>2 THEN <<!&ATTJMP !&GETLBL CADR EXP; SLST := NIL>>
  597. ELSE LPRIE LIST(EXP,"INVALID")>>;
  598. PUT('GO,'COMPFN,'!&COMGO);
  599. SYMBOLIC PROCEDURE !&COMLIST(EXP,STATUS);
  600. %we only support explicit functions up to 5 arguments here;
  601. BEGIN SCALAR M,N,FN;
  602. EXP := CDR EXP;
  603. M := MIN(MAXNARGS,5);
  604. N := LENGTH EXP;
  605. IF N=0 THEN !&LREG1('(QUOTE NIL),STATUS)
  606. ELSE IF N>M THEN !&COMVAL(!&COMLIST1 EXP,STATUS)
  607. ELSE !&CALL(IF N=1 THEN 'NCONS
  608. ELSE IF N=2 THEN 'LIST2
  609. ELSE IF N=3 THEN 'LIST3
  610. ELSE IF N=4 THEN 'LIST4
  611. ELSE 'LIST5,EXP,STATUS)
  612. END;
  613. SYMBOLIC PROCEDURE LIST2(U,V); U . (V . NIL);
  614. SYMBOLIC PROCEDURE LIST3(U,V,W); U . (V . (W . NIL));
  615. SYMBOLIC PROCEDURE LIST4(U,V,W,X); U . (V . (W . (X . NIL)));
  616. SYMBOLIC PROCEDURE LIST5(U,V,W,X,Y); U . (V . (W . (X . (Y . NIL))));
  617. SYMBOLIC PROCEDURE !&COMLIST1 EXP;
  618. IF NULL EXP THEN '(QUOTE NIL)
  619. ELSE LIST('CONS,CAR EXP,'LIST . CDR EXP);
  620. PUT('LIST,'COMPFN,'!&COMLIST);
  621. SYMBOLIC PROCEDURE !&PAMAP(U,VARS);
  622. IF EQCAR(CADDR U,'FUNCTION)
  623. THEN (LAMBDA X;
  624. LIST(CAR U,
  625. !&PA1(CADR U,VARS),
  626. MKQUOTE (IF ATOM X THEN X ELSE !&PA1(X,VARS))))
  627. CADR CADDR U
  628. ELSE CAR U . !&PALIS(CDR U,VARS);
  629. PUT('MAP,'PA1FN,'!&PAMAP);
  630. PUT('MAPC,'PA1FN,'!&PAMAP);
  631. PUT('MAPCAN,'PA1FN,'!&PAMAP);
  632. PUT('MAPCAR,'PA1FN,'!&PAMAP);
  633. PUT('MAPCON,'PA1FN,'!&PAMAP);
  634. PUT('MAPLIST,'PA1FN,'!&PAMAP);
  635. SYMBOLIC PROCEDURE !&COMMAP(EXP,STATUS);
  636. BEGIN SCALAR BODY,FN,LAB1,LAB2,LAB3,TMP,MTYPE,RESULT,SLST1,VAR,X;
  637. BODY := CADR EXP;
  638. FN := CADDR EXP;
  639. LAB1 := !&GENLBL();
  640. LAB2 := !&GENLBL();
  641. MTYPE :=
  642. IF CAR EXP MEMQ '(MAPCAR MAPLIST) THEN 'CONS
  643. ELSE IF CAR EXP MEMQ '(MAPCAN MAPCON)
  644. THEN <<LAB3 := !&GENLBL(); 'NCONC>>
  645. ELSE NIL;
  646. !&CLRREGS();
  647. IF MTYPE THEN <<!&FRAME (RESULT := GENSYM());
  648. IF NULL LAB3 THEN !&STORE0(RESULT,NIL)>>;
  649. !&FRAME (VAR := GENSYM());
  650. !&COMVAL(BODY,1);
  651. REGS := LIST LIST(1,VAR);
  652. IF LAB3 THEN <<!&STORE0(VAR,1); !&FRAME (TMP := GENSYM());
  653. !&COMVAL('(NCONS 'NIL),1);
  654. !&STORE0(RESULT,1); !&STORE0(TMP,1);
  655. !&LREG1(VAR,1)>>;
  656. !&ATTJMP LAB2;
  657. !&ATTLBL LAB1;
  658. !&STORE0(VAR,1);
  659. X := IF CAR EXP MEMQ '(MAP MAPCON MAPLIST) THEN VAR
  660. ELSE LIST('CAR,VAR);
  661. IF EQCAR(FN,'QUOTE) THEN FN := CADR FN;
  662. SLST1 := SLST; %to allow for store in function body;
  663. !&COMVAL(LIST(FN,X),IF MTYPE THEN 1 ELSE 3);
  664. IF MTYPE
  665. THEN <<IF LAB3 THEN <<!&ATTACH LIST('!*JUMPNIL,CAR LAB3);
  666. !&ADDJMP CODELIST;
  667. !&ATTACH '(!*LOAD 2 1);
  668. !&LREG1(TMP,1);
  669. !&STORE0(TMP,2);
  670. !&ATTACH '(!*LINK NCONC EXPR 2);
  671. !&ATTLBL LAB3>>
  672. ELSE <<!&LREG(2,RESULT,NIL,1);
  673. !&ATTACH '(!*LINK CONS EXPR 2);
  674. !&STORE0(RESULT,1)>>;
  675. REGS := LIST (1 . NIL)>>;
  676. SLST := XN(SLST,SLST1);
  677. !&COMVAL(LIST('CDR,VAR),1);
  678. !&ATTLBL LAB2;
  679. !&ATTACH LIST('!*JUMPT,CAR LAB1);
  680. !&ADDJMP CODELIST;
  681. IF MTYPE
  682. THEN !&COMVAL(LIST(IF LAB3 THEN 'CDR ELSE 'REVERSIP,RESULT),1)
  683. ELSE REGS := LIST LIST(1,MKQUOTE NIL)
  684. END;
  685. SYMBOLIC PROCEDURE XN(U,V);
  686. IF NULL U THEN NIL
  687. ELSE IF CAR U MEMBER V THEN CAR U . XN(CDR U,DELETE(CAR U,V))
  688. ELSE XN(CDR U,V);
  689. PUT('MAP,'COMPFN,'!&COMMAP);
  690. PUT('MAPC,'COMPFN,'!&COMMAP);
  691. PUT('MAPCAN,'COMPFN,'!&COMMAP);
  692. PUT('MAPCAR,'COMPFN,'!&COMMAP);
  693. PUT('MAPCON,'COMPFN,'!&COMMAP);
  694. PUT('MAPLIST,'COMPFN,'!&COMMAP);
  695. SYMBOLIC PROCEDURE !&COMPROG(EXP,STATUS); %compiles program blocks;
  696. BEGIN SCALAR ALSTS,GOLIST,PG,PROGLIS,EXIT; INTEGER I;
  697. PROGLIS := CADR EXP;
  698. EXP := CDDR EXP;
  699. EXIT := !&GENLBL();
  700. PG := !&REMVARL PROGLIS; %protect prog variables;
  701. FOR EACH X IN PROGLIS DO !&FRAME X;
  702. ALSTS := !&FREEBIND(PROGLIS,NIL);
  703. FOR EACH X IN PROGLIS DO IF NOT NONLOCAL X THEN !&STORE0(X,NIL);
  704. FOR EACH X IN EXP DO IF ATOM X
  705. THEN GOLIST := (X . !&GENLBL()) . GOLIST;
  706. WHILE EXP DO
  707. <<IF ATOM CAR EXP
  708. THEN <<!&CLRREGS();
  709. !&ATTLBL !&GETLBL CAR EXP;
  710. REGS := LIST (1 . NIL)>>
  711. ELSE !&COMVAL(CAR EXP,IF STATUS>2 THEN 4 ELSE 3);
  712. IF NULL CDR EXP
  713. AND STATUS<2
  714. AND (ATOM CAR EXP OR NOT CAAR EXP MEMQ '(GO RETURN))
  715. THEN EXP := LIST '(RETURN (QUOTE NIL))
  716. ELSE EXP := CDR EXP>>;
  717. !&ATTLBL EXIT;
  718. IF CDR !&FINDLBL EXIT THEN REGS := LIST (1 . NIL);
  719. !&FREERST(ALSTS,STATUS);
  720. !&RSTVARL(PROGLIS,PG)
  721. END;
  722. PUT('PROG,'COMPFN,'!&COMPROG);
  723. SYMBOLIC PROCEDURE !&REMVARL VARS;
  724. FOR EACH X IN VARS COLLECT !&REMVAR X;
  725. SYMBOLIC PROCEDURE !&REMVAR X;
  726. %removes references to variable X from IREGS and REGS
  727. %and protects SLST;
  728. <<!&REMSTORES X; !&PROTECT X>>;
  729. SYMBOLIC PROCEDURE !&REMSTORES X;
  730. BEGIN
  731. FOR EACH Y IN IREGS DO IF X EQ CADR Y
  732. THEN <<!&STORE0(CADR Y,CAR Y);
  733. IREGS := DELETE(Y,IREGS)>>;
  734. FOR EACH Y IN REGS DO WHILE X MEMBER CDR Y DO
  735. RPLACD(Y,!&DELEQ(X,CDR Y))
  736. END;
  737. SYMBOLIC PROCEDURE !&PROTECT U;
  738. BEGIN SCALAR X;
  739. IF X := ATSOC(U,SLST) THEN SLST := !&DELEQ(X,SLST);
  740. RETURN X
  741. END;
  742. SYMBOLIC PROCEDURE !&RSTVARL(VARS,LST);
  743. FOR EACH X IN VARS DO
  744. <<!&REMSTORES X; !&CLRSTR X; !&UNPROTECT CAR LST; LST := CDR LST>>;
  745. SYMBOLIC PROCEDURE !&UNPROTECT VAL; %restores VAL to SLST;
  746. IF VAL THEN SLST := VAL . SLST;
  747. SYMBOLIC PROCEDURE !&COMPROGN(EXP,STATUS);
  748. BEGIN
  749. EXP := CDR EXP;
  750. IF NULL EXP THEN RETURN NIL;
  751. WHILE CDR EXP DO
  752. <<!&COMVAL(CAR EXP,IF STATUS<2 THEN 2 ELSE STATUS);
  753. EXP := CDR EXP>>;
  754. !&COMVAL(CAR EXP,STATUS)
  755. END;
  756. PUT('PROG2,'COMPFN,'!&COMPROGN);
  757. PUT('PROGN,'COMPFN,'!&COMPROGN);
  758. SYMBOLIC PROCEDURE !&COMRETURN(EXP,STATUS);
  759. <<IF STATUS<4 OR NOT !&ANYREG(CADR EXP,NIL)
  760. THEN !&LREG1(CAR !&COMLIS LIST CADR EXP,STATUS);
  761. !&ATTJMP EXIT>>;
  762. PUT('RETURN,'COMPFN,'!&COMRETURN);
  763. SYMBOLIC PROCEDURE !&COMSETQ(EXP,STATUS);
  764. BEGIN SCALAR X;
  765. EXP := CDR EXP;
  766. IF STATUS>1 AND (NULL CADR EXP OR CADR EXP='(QUOTE NIL))
  767. THEN !&STORE2(CAR EXP,NIL)
  768. ELSE <<!&COMVAL(CADR EXP,1);
  769. !&STORE2(CAR EXP,1);
  770. IF X := !&RASSOC(CAR EXP,IREGS)
  771. THEN IREGS := DELETE(X,IREGS);
  772. REGS := (1 . (CAR EXP . CDAR REGS)) . CDR REGS>>
  773. END;
  774. SYMBOLIC PROCEDURE !&REMSETVAR(U,V);
  775. %removes references to SETQ variable U from regs list V;
  776. IF NULL V THEN NIL
  777. ELSE (CAAR V . !&REMS1(U,CDAR V)) . !&REMSETVAR(U,CDR V);
  778. SYMBOLIC PROCEDURE !&REMS1(U,V);
  779. %removes references to SETQ variable U from list V;
  780. IF NULL V THEN NIL
  781. ELSE IF SMEMQ(U,CAR V) THEN !&REMS1(U,CDR V)
  782. ELSE CAR V . !&REMS1(U,CDR V);
  783. SYMBOLIC PROCEDURE SMEMQ(U,V);
  784. %true if atom U is a member of V at any level (excluding
  785. %quoted expressions);
  786. IF ATOM V THEN U EQ V
  787. ELSE IF CAR V EQ 'QUOTE THEN NIL
  788. ELSE SMEMQ(U,CAR V) OR SMEMQ(U,CDR V);
  789. SYMBOLIC PROCEDURE !&STORE2(U,V);
  790. BEGIN SCALAR VTYPE;
  791. REGS := !&REMSETVAR(U,REGS);
  792. IF VTYPE := NONLOCAL U
  793. THEN !&ATTACH LIST('!*STORE,V,LIST(VTYPE,U))
  794. ELSE IF NOT ATSOC(U,STOMAP)
  795. THEN !&ATTACH LIST('!*STORE,V,MKNONLOCAL U)
  796. ELSE !&STORE0(U,V)
  797. END;
  798. PUT('SETQ,'COMPFN,'!&COMSETQ);
  799. COMMENT Specific test open coding;
  800. SYMBOLIC PROCEDURE !&COMEQ(EXP,LABL);
  801. BEGIN SCALAR U,V,W;
  802. U := CADR EXP;
  803. V := CADDR EXP;
  804. IF U MEMBER CDAR REGS THEN W := !&COMEQ1(V,U)
  805. ELSE IF V MEMBER CDAR REGS THEN W := !&COMEQ1(U,V)
  806. ELSE IF !&ANYREG(V,NIL) THEN <<!&COMVAL(U,1); W := !&LOCATE V>>
  807. ELSE IF !&ANYREG(U,LIST V)
  808. THEN <<!&COMVAL(V,1); W := !&LOCATE U>>
  809. ELSE <<U := !&COMLIS CDR EXP; W := !&LOCATE CADR U>>;
  810. !&ATTACH ((IF SWITCH THEN '!*JUMPE ELSE '!*JUMPN)
  811. . (CAR LABL . W));
  812. IREGS1 := IREGS;
  813. REGS1 := REGS;
  814. !&ADDJMP CODELIST
  815. END;
  816. SYMBOLIC PROCEDURE !&COMEQ1(U,V);
  817. IF !&ANYREG(U,LIST V) THEN !&LOCATE U
  818. ELSE <<!&COMVAL(U,1); !&LOCATE V>>;
  819. PUT('EQ,'COMTST,'!&COMEQ);
  820. SYMBOLIC PROCEDURE !&TESTFN(EXP,LABL);
  821. %generates c-macros !*JUMPC and !*JUMPNC;
  822. BEGIN SCALAR X;
  823. IF NOT (X := !&RASSOC(CADR EXP,REGS)) THEN !&COMVAL(CADR EXP,1);
  824. !&CLRREGS();
  825. !&ATTACH LIST(IF SWITCH THEN '!*JUMPC ELSE '!*JUMPNC,
  826. CAR LABL,
  827. IF X THEN CAR X ELSE 1,CAR EXP);
  828. REGS1 := REGS;
  829. !&ADDJMP CODELIST
  830. END;
  831. COMMENT Support functions;
  832. SYMBOLIC PROCEDURE !&MEMLIS(U,V);
  833. V AND (!&MEMB(U,CAR V) OR !&MEMLIS(U,CDR V));
  834. SYMBOLIC PROCEDURE !&MEMB(U,V);
  835. IF ATOM V THEN U EQ V ELSE !&MEMB(U,CADR V);
  836. SYMBOLIC PROCEDURE !&RASSOC(U,V);
  837. IF NULL V THEN NIL
  838. ELSE IF U MEMBER CDAR V THEN CAR V
  839. ELSE !&RASSOC(U,CDR V);
  840. SYMBOLIC PROCEDURE !&REPASC(REG,U,V);
  841. IF NULL V THEN LIST LIST(REG,U)
  842. ELSE IF REG=CAAR V THEN LIST(REG,U) . CDR V
  843. ELSE CAR V . !&REPASC(REG,U,CDR V);
  844. SYMBOLIC PROCEDURE !&CLRREGS; %store deferred values in IREGS;
  845. WHILE IREGS DO
  846. <<!&STORE0(CADAR IREGS,CAAR IREGS); IREGS := CDR IREGS>>;
  847. SYMBOLIC PROCEDURE !&CFNTYPE FN;
  848. BEGIN SCALAR X;
  849. RETURN IF NOT ATOM FN THEN 'EXPR
  850. ELSE IF X := GET(FN,'CFNTYPE) THEN CAR X
  851. ELSE IF X := GETD FN THEN CAR X
  852. ELSE 'EXPR
  853. END;
  854. SYMBOLIC PROCEDURE !&GENLBL;
  855. BEGIN SCALAR L;
  856. L := GENSYM();
  857. LBLIST := LIST L . LBLIST;
  858. RETURN LIST L
  859. END;
  860. SYMBOLIC PROCEDURE !&GETLBL LABL;
  861. BEGIN SCALAR X;
  862. X := ATSOC(LABL,GOLIST);
  863. IF NULL X THEN LPRIE LIST(LABL," - MISSING LABEL -");
  864. RETURN CDR X
  865. END;
  866. SYMBOLIC PROCEDURE !&FINDLBL LBLST; ASSOC(CAR LBLST,LBLIST);
  867. SYMBOLIC PROCEDURE !&RECHAIN(OLBL,NLBL);
  868. % Fix OLBL to now point at NLBL;
  869. BEGIN SCALAR X,Y,USES;
  870. X := !&FINDLBL OLBL;
  871. Y := !&FINDLBL NLBL;
  872. RPLACA(OLBL,CAR NLBL); % FIX L VAR;
  873. USES := CDR X; % OLD USES;
  874. RPLACD(X,NIL);
  875. RPLACD(Y,APPEND(USES,CDR Y));
  876. FOR EACH X IN USES DO RPLACA(CDR X,CAR NLBL)
  877. END;
  878. SYMBOLIC PROCEDURE !&MOVEUP U;
  879. IF CAADR U EQ '!*JUMP
  880. THEN <<JMPLIST := !&DELEQ(CDR U,JMPLIST);
  881. RPLACW(U,CDR U);
  882. JMPLIST := U . JMPLIST>>
  883. ELSE RPLACW(U,CDR U);
  884. SYMBOLIC PROCEDURE !&ATTLBL LBL;
  885. IF CAAR CODELIST EQ '!*LBL THEN !&RECHAIN(LBL,CDAR CODELIST)
  886. ELSE !&ATTACH ('!*LBL . LBL);
  887. SYMBOLIC PROCEDURE !&ATTJMP LBL;
  888. BEGIN
  889. IF CAAR CODELIST EQ '!*LBL
  890. THEN <<!&RECHAIN(CDAR CODELIST,LBL);
  891. CODELIST := CDR CODELIST>>;
  892. IF !&TRANSFERP CAR CODELIST THEN RETURN NIL;
  893. !&ATTACH ('!*JUMP . LBL);
  894. !&ADDJMP CODELIST
  895. END;
  896. SYMBOLIC PROCEDURE !&TRANSFERP X;
  897. FLAGP(IF CAR X EQ '!*LINK THEN CADR X ELSE CAR X,'TRANSFER);
  898. SYMBOLIC PROCEDURE !&ADDJMP CLIST;
  899. BEGIN SCALAR X;
  900. X := !&FINDLBL CDAR CLIST;
  901. RPLACD(X,CAR CLIST . CDR X);
  902. JMPLIST := CLIST . JMPLIST
  903. END;
  904. SYMBOLIC PROCEDURE !&REMJMP CLIST;
  905. BEGIN SCALAR X;
  906. X := !&FINDLBL CDAR CLIST;
  907. RPLACD(X,!&DELEQ(CAR CLIST,CDR X));
  908. JMPLIST := !&DELEQ(CLIST,JMPLIST);
  909. !&MOVEUP CLIST
  910. END;
  911. SYMBOLIC PROCEDURE !&DELEQ(U,V);
  912. IF NULL V THEN NIL
  913. ELSE IF U EQ CAR V THEN CDR V
  914. ELSE CAR V . !&DELEQ(U,CDR V);
  915. SYMBOLIC PROCEDURE !&FRAME U; %allocates space for U in frame;
  916. BEGIN SCALAR Z;
  917. STOMAP := LIST(U,Z := CADAR STOMAP - 1) . STOMAP;
  918. IF Z<CAR LLNGTH THEN RPLACA(LLNGTH,Z)
  919. END;
  920. SYMBOLIC PROCEDURE !&GETFRM U;
  921. (LAMBDA X;
  922. IF X THEN CDR X ELSE LPRIE LIST("COMPILER ERROR: LOST VAR",U))
  923. ATSOC(U,STOMAP);
  924. SYMBOLIC PROCEDURE !&GETFFRM U;
  925. BEGIN SCALAR X; X := !&GETFRM U; FREELST := X . FREELST; RETURN X
  926. END;
  927. COMMENT Pass 3 of the compiler (post code generation fixups);
  928. SYMBOLIC PROCEDURE !&PASS3;
  929. BEGIN SCALAR FLAGG; %remove spurious stores;
  930. FOR EACH J IN SLST DO <<STLST := !&DELEQ(CADR J,STLST);
  931. RPLACA(CADR J,'!*NOOP)>>;
  932. !&FIXCHAINS();
  933. !&FIXLINKS();
  934. !&FIXFRM();
  935. !&ATTLBL EXIT;
  936. IF FLAGG
  937. THEN <<IF NOT !*NOLINKE
  938. AND CAAR CODELIST EQ '!*LBL
  939. AND CAADR CODELIST EQ '!*LINKE
  940. THEN RPLACA(CDR CODELIST,
  941. LIST('!*LINK,CADADR CODELIST,
  942. CADR CDADR CODELIST,
  943. CADDR CDADR CODELIST));
  944. %removes unnecessary !*LINKE;
  945. !&ATTACH ('!*DEALLOC . LLNGTH);
  946. !&ATTACH LIST '!*EXIT>>;
  947. !&PEEPHOLEOPT();
  948. !&FIXREST()
  949. END;
  950. SYMBOLIC PROCEDURE !&FIXCHAINS;
  951. BEGIN SCALAR EJMPS,EJMPS1,P,Q; %find any common chains of code;
  952. IF NOT CAR CODELIST='!*LBL . EXIT THEN !&ATTLBL EXIT;
  953. CODELIST := CDR CODELIST;
  954. IF NOT CAR CODELIST='!*JUMP . EXIT THEN !&ATTJMP EXIT;
  955. EJMPS := REVERSE JMPLIST;
  956. WHILE EJMPS DO
  957. BEGIN
  958. P := CAR EJMPS;
  959. EJMPS := CDR EJMPS;
  960. IF CAAR P EQ '!*JUMP
  961. THEN <<EJMPS1 := EJMPS;
  962. WHILE EJMPS1 DO
  963. IF CAR P=CAAR EJMPS1 AND CADR P=CADAR EJMPS1
  964. THEN <<!&REMJMP P;
  965. !&FIXCHN(P,CDAR EJMPS1);
  966. EJMPS1 := NIL>>
  967. ELSE EJMPS1 := CDR EJMPS1>>
  968. END
  969. END;
  970. SYMBOLIC PROCEDURE !&FIXLINKS;
  971. %replace !*LINK by !*LINKE where appropriate;
  972. BEGIN SCALAR EJMPS,P,Q;
  973. EJMPS := JMPLIST;
  974. IF NOT !*NOLINKE
  975. THEN WHILE EJMPS DO
  976. BEGIN
  977. P := CAR EJMPS;
  978. Q := CDR P;
  979. EJMPS := CDR EJMPS;
  980. IF NOT CADAR P EQ CAR EXIT THEN RETURN NIL
  981. ELSE IF NOT CAAR P EQ '!*JUMP
  982. OR NOT CAAR Q EQ '!*LINK
  983. THEN RETURN FLAGG := T;
  984. RPLACW(CAR Q,
  985. '!*LINKE
  986. . (CADAR Q
  987. . (CADDAR Q
  988. . (CADR CDDAR Q . LLNGTH))));
  989. !&REMJMP P
  990. END
  991. ELSE FLAGG := T
  992. END;
  993. SYMBOLIC PROCEDURE !&FINDBLK(U,LBL);
  994. IF NULL CDR U THEN NIL
  995. ELSE IF CAADR U EQ '!*LBL AND !&TRANSFERP CADDR U THEN U
  996. ELSE IF GET(CAADR U,'NEGJMP) AND CADADR U EQ LBL THEN U
  997. ELSE !&FINDBLK(CDR U,LBL);
  998. PUT('!*NOOP,'OPTFN,'!&MOVEUP);
  999. PUT('!*LBL,'OPTFN,'!&LBLOPT);
  1000. SYMBOLIC PROCEDURE !&LBLOPT U;
  1001. BEGIN SCALAR Z;
  1002. IF CADAR U EQ CADADR U THEN RETURN !&REMJMP CDR U
  1003. ELSE IF CAADR U EQ '!*JUMP
  1004. AND (Z := GET(CAADDR U,'NEGJMP))
  1005. AND CADAR U EQ CADR CADDR U
  1006. THEN RETURN <<Z := Z . (CADADR U . CDDR CADDR U);
  1007. !&REMJMP CDR U;
  1008. !&REMJMP CDR U;
  1009. RPLACD(U,Z . (CADR U . CDDR U));
  1010. !&ADDJMP CDR U;
  1011. T>>
  1012. ELSE RETURN NIL
  1013. END;
  1014. SYMBOLIC PROCEDURE !&PEEPHOLEOPT;
  1015. %'peep-hole' optimization for various cases;
  1016. BEGIN SCALAR X,Z;
  1017. Z := CODELIST;
  1018. WHILE Z DO
  1019. IF NOT (X := GET(CAAR Z,'OPTFN)) OR NOT APPLY(X,LIST Z)
  1020. THEN Z := CDR Z
  1021. END;
  1022. SYMBOLIC PROCEDURE !&FIXREST;
  1023. %checks for various cases involving unique (and unused) labels
  1024. %and sequences like (JUMPx lab) M1 ... Mn ... (LAB lab) M1 ... Mn
  1025. %where Mi do not affect reg 1;
  1026. BEGIN SCALAR LABS,TLABS,X,Y,Z;
  1027. WHILE CODELIST DO
  1028. <<IF CAAR CODELIST EQ '!*LBL
  1029. THEN <<!&LBLOPT CODELIST;
  1030. IF CDR (Z := !&FINDLBL CDAR CODELIST)
  1031. THEN <<Y := CAR CODELIST . Y;
  1032. IF NULL CDDR Z
  1033. AND !&TRANSFERP CADR Z
  1034. AND CAADR Y EQ '!*LOAD
  1035. AND !&NOLOADP(CDADR Y,
  1036. CDR ATSOC(CADR Z,
  1037. JMPLIST))
  1038. THEN <<IF
  1039. NOT !&NOLOADP(CDADR Y,
  1040. CDR CODELIST)
  1041. THEN RPLACW(CDR CODELIST,
  1042. CADR Y
  1043. . CADR CODELIST
  1044. . CDDR CODELIST);
  1045. RPLACW(CDR Y,CDDR Y)>>
  1046. ELSE <<IF NULL CDDR Z
  1047. AND CAADR CODELIST EQ '!*JUMP
  1048. AND GET(CAADR Z,'NEGJMP)
  1049. THEN LABS :=
  1050. (CADR Z . Y) . LABS;
  1051. IF !&TRANSFERP CADR CODELIST
  1052. THEN TLABS :=
  1053. (CADAR Y . Y)
  1054. . TLABS>>>>>>
  1055. ELSE IF GET(CAAR CODELIST,'NEGJMP)
  1056. AND (Z := ATSOC(CAR CODELIST,LABS))
  1057. THEN <<X := CAR CODELIST;
  1058. CODELIST := CDR CODELIST;
  1059. Z := CDDR Z;
  1060. WHILE CAR Y=CAR Z
  1061. AND (CAAR Y EQ '!*STORE
  1062. OR CAAR Y EQ '!*LOAD
  1063. AND NOT CADAR Y=1) DO
  1064. <<CODELIST := CAR Y . CODELIST;
  1065. RPLACW(Z,CADR Z . CDDR Z);
  1066. Y := CDR Y>>;
  1067. CODELIST := X . CODELIST;
  1068. Y := X . Y>>
  1069. ELSE IF CAAR CODELIST EQ '!*JUMP
  1070. AND (Z := ATSOC(CADAR CODELIST,TLABS))
  1071. AND (X :=
  1072. !&FINDBLK(CDR CODELIST,
  1073. IF CAAR Y EQ '!*LBL THEN CADAR Y
  1074. ELSE NIL))
  1075. THEN BEGIN SCALAR W;
  1076. IF NOT CAADR X EQ '!*LBL
  1077. THEN <<IF NOT CAAR X EQ '!*LBL
  1078. THEN X :=
  1079. CDR RPLACD(X,
  1080. ('!*LBL . !&GENLBL())
  1081. . CDR X);
  1082. W :=
  1083. GET(CAADR X,'NEGJMP)
  1084. . (CADAR X . CDDADR X);
  1085. !&REMJMP CDR X;
  1086. RPLACD(X,W . (CADR X . CDDR X));
  1087. !&ADDJMP CDR X>>
  1088. ELSE X := CDR X;
  1089. W := NIL;
  1090. REPEAT <<W := CAR Y . W; Y := CDR Y>>
  1091. UNTIL Y EQ CDR Z;
  1092. RPLACD(X,NCONC(W,CDR X));
  1093. !&REMJMP CODELIST;
  1094. TLABS := NIL; %since code chains have changed;
  1095. CODELIST := NIL . (CAR Y . CODELIST);
  1096. Y := CDR Y
  1097. END
  1098. ELSE Y := CAR CODELIST . Y;
  1099. CODELIST := CDR CODELIST>>;
  1100. CODELIST := Y
  1101. END;
  1102. SYMBOLIC PROCEDURE !&NOLOADP(ARGS,INSTRS);
  1103. %determines if a LOAD is not necessary in instruction stream;
  1104. ATOM CADR ARGS
  1105. AND (CAAR INSTRS EQ '!*LOAD AND CDAR INSTRS=ARGS
  1106. OR CAAR INSTRS EQ '!*STORE
  1107. AND (CDAR INSTRS=ARGS
  1108. OR NOT CADDAR INSTRS=CADR ARGS
  1109. AND !&NOLOADP(ARGS,CDR INSTRS)));
  1110. SYMBOLIC PROCEDURE !&FIXCHN(U,V);
  1111. BEGIN SCALAR X;
  1112. WHILE CAR U=CAR V DO <<!&MOVEUP U; V := CDR V>>;
  1113. X := !&GENLBL();
  1114. IF CAAR V EQ '!*LBL THEN !&RECHAIN(X,CDAR V)
  1115. ELSE RPLACW(V,('!*LBL . X) . (CAR V . CDR V));
  1116. IF CAAR U EQ '!*LBL THEN <<!&RECHAIN(CDAR U,X); !&MOVEUP U>>;
  1117. IF CAAR U EQ '!*JUMP THEN RETURN NIL;
  1118. RPLACW(U,('!*JUMP . X) . (CAR U . CDR U));
  1119. !&ADDJMP U
  1120. END;
  1121. SYMBOLIC PROCEDURE !&FIXFRM;
  1122. BEGIN SCALAR HOLES,LST,X,Y,Z; INTEGER N;
  1123. IF NULL STLST AND NULL FREELST THEN RETURN RPLACA(LLNGTH,1);
  1124. N := 0;
  1125. WHILE NOT N<CAR LLNGTH DO
  1126. <<Y := NIL;
  1127. FOR EACH LST IN STLST DO IF N=CADDR LST
  1128. THEN Y := CDDR LST . Y;
  1129. FOR EACH LST IN FREELST DO IF N=CAR LST THEN Y := LST . Y;
  1130. IF NULL Y THEN HOLES := N . HOLES ELSE Z := (N . Y) . Z;
  1131. N := N - 1>>;
  1132. Y := Z;
  1133. IF CAAR Z>CAR LLNGTH THEN RPLACA(LLNGTH,CAAR Z);
  1134. WHILE HOLES DO
  1135. <<WHILE HOLES AND CAR HOLES<CAR LLNGTH DO HOLES := CDR HOLES;
  1136. IF HOLES
  1137. THEN <<HOLES := REVERSIP HOLES;
  1138. FOR EACH X IN CDAR Z DO RPLACA(X,CAR HOLES);
  1139. RPLACA(LLNGTH,
  1140. IF NULL CDR Z OR CAR HOLES<CAADR Z
  1141. THEN CAR HOLES
  1142. ELSE CAADR Z);
  1143. HOLES := REVERSIP CDR HOLES;
  1144. Z := CDR Z>>>>;
  1145. %now see if we can map frame to registers;
  1146. N := IF NARG<3 THEN 3 ELSE NARG + 1;
  1147. IF FREELST OR NULL !&REGP CODELIST OR CAR LLNGTH<N - MAXNARGS
  1148. THEN RETURN NIL;
  1149. FOR EACH X IN STLST DO RPLACW(X,
  1150. LIST('!*LOAD,
  1151. N - CADDR X,
  1152. IF NULL CADR X
  1153. THEN '(QUOTE NIL)
  1154. ELSE CADR X));
  1155. WHILE Y DO
  1156. <<FOR EACH X IN CDAR Y DO NOT CAR X>0
  1157. AND RPLACA(X,N - CAR X);
  1158. %first test makes sure replacement only occurs once;
  1159. Y := CDR Y>>;
  1160. RPLACA(LLNGTH,1)
  1161. END;
  1162. SYMBOLIC PROCEDURE !&REGP U;
  1163. %there is no test for !*LAMBIND/!*PROGBIND
  1164. %since FREELST tested explicitly in !&FIXFRM;
  1165. IF NULL CDR U THEN T
  1166. ELSE IF CAAR U MEMQ '(!*LOAD !*STORE)
  1167. AND NUMBERP CADAR U AND CADAR U>2
  1168. THEN NIL
  1169. ELSE IF FLAGP(CAADR U,'UNKNOWNUSE)
  1170. AND
  1171. NOT (IDP CADADR U
  1172. AND (FLAGP(CADADR U,'ONEREG)
  1173. OR FLAGP(CADADR U,'TWOREG))
  1174. OR CAR U='!*JUMP . EXIT)
  1175. THEN NIL
  1176. ELSE !&REGP CDR U;
  1177. FLAG('(!*CODE !*LINK !*LINKE),'UNKNOWNUSE);
  1178. SYMBOLIC PROCEDURE !*CODE U; EVAL U;
  1179. PUT('!*JUMPN,'NEGJMP,'!*JUMPE);
  1180. PUT('!*JUMPE,'NEGJMP,'!*JUMPN);
  1181. PUT('!*JUMPNIL,'NEGJMP,'!*JUMPT);
  1182. PUT('!*JUMPT,'NEGJMP,'!*JUMPNIL);
  1183. PUT('!*JUMPC,'NEGJMP,'!*JUMPNC);
  1184. PUT('!*JUMPNC,'NEGJMP,'!*JUMPC);
  1185. COMMENT Some arithmetic optimizations to reduce the amount of code
  1186. generated;
  1187. SYMBOLIC PROCEDURE !&PAPLUS2(U,VARS);
  1188. IF CADDR U=1 THEN LIST('ADD1,!&PA1(CADR U,VARS))
  1189. ELSE IF CADR U=1 THEN LIST('ADD1,!&PA1(CADDR U,VARS))
  1190. ELSE 'PLUS2 . !&PALIS(CDR U,VARS);
  1191. PUT('PLUS2,'PA1FN,'!&PAPLUS2);
  1192. SYMBOLIC PROCEDURE !&PADIFF(U,VARS);
  1193. IF CADDR U=1 THEN LIST('SUB1,!&PA1(CADR U,VARS))
  1194. ELSE 'DIFFERENCE . !&PALIS(CDR U,VARS);
  1195. PUT('DIFFERENCE,'PA1FN,'!&PADIFF);
  1196. SYMBOLIC PROCEDURE !&PALESSP(U,VARS);
  1197. IF CADDR U=0 THEN LIST('MINUSP,!&PA1(CADR U,VARS))
  1198. ELSE 'LESSP . !&PALIS(CDR U,VARS);
  1199. PUT('LESSP,'PA1FN,'!&PALESSP);
  1200. COMMENT removing unnecessary calls to MINUS;
  1201. SYMBOLIC PROCEDURE !&PAMINUS(U,VARS);
  1202. IF EQCAR(U := !&PA1(CADR U,VARS),'QUOTE) AND NUMBERP CADR U
  1203. THEN MKQUOTE ( - CADR U)
  1204. ELSE LIST('MINUS,U);
  1205. PUT('MINUS,'PA1FN,'!&PAMINUS);
  1206. END;