compiler.red 90 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707
  1. % MLG: 15 Dec
  2. % added additional arguments to
  3. % Compiler BUG message in &LOCATE to get more info
  4. % <PSL.COMP>COMPILER.RED.19, 3-Dec-82 18:21:21, Edit by PERDUE
  5. % Removed REFORMNE, which was over-optimizing sometimes
  6. % <PSL.COMP>COMPILER.RED.18, 1-Dec-82 15:59:45, Edit by BENSON
  7. % Fixed car of atom bug in &PaApply
  8. % New extended compiler for PSL
  9. % John Peterson 4-5-81
  10. % <PSL.COMP>COMPILER.RED.4, 20-Sep-82 11:40:31, Edit by BENSON
  11. % Slight improvement to "FOO not compiled" messages
  12. % <PSL.COMP>COMPILER.RED.2, 20-Sep-82 10:32:51, Edit by BENSON
  13. % (DE FOO (LIST) (LIST LIST)) does the right thing
  14. % <PSL.COMP>COMPILER.RED.10, 10-Sep-82 12:43:27, Edit by BENSON
  15. % NONLOCALSYS calls NONLOCALLISP if not WVAR or WARRAY
  16. % <PSL.COMP>COMPILER.RED.9, 10-Sep-82 09:53:08, Edit by BENSON
  17. % Changed error and warning messages
  18. CompileTime flag(
  19. '(!&COMPERROR !&COMPWARN !&IREG
  20. !&ADDRVALS !&ALLARGS1 !&ALLCONST !&ANYREG !&ANYREGL !&ANYREGP
  21. !&ARGLOC !&ASSOCOP1 !&ASSOCOP2 !&ATTACH !&ATTJMP !&ATTLBL !&CALL
  22. !&CALL1 !&CALLOPEN !&CFNTYPE !&CLASSMEMBER !&CLRSTR !&COMLIS !&COMLIS1
  23. !&COMOPENTST !&COMPLY !&COMTST !&COMVAL !&COMVAL1 !&CONSTTAG
  24. !&DEFEQLBL !&DEFEQLBL1 !&DELARG !&DELCLASS !&DELETEMAC !&DELMAC
  25. !&EMITMAC !&EQP !&EQPL !&EQVP !&EXTERNALVARP !&FIXCHAINS !&FIXFRM
  26. !&FIXLABS !&FIXLINKS !&FIXREGTEST1
  27. !&FRAME !&FREERSTR !&GENLBL !&GENSYM !&GETFRAMES
  28. !&GETFRAMES1 !&GETFRAMES2 !&GETFRM !&GETFVAR !&GETGROUPARGS !&GETGROUPARGS1
  29. !&GETGROUPARGS2 !&GETLBL !&GETNUM !&HIGHEST !&HIGHEST1 !&HIGHEST2
  30. !&INALL !&INSERTMAC !&INSOP !&INSOP1 !&INSTALLDESTROY !&INSTBL !&JUMPNIL
  31. !&JUMPT !&LABCLASS !&LBLEQ !&LOADARGS !&LOADOPENEXP !&LOADTEMP1 !&LOADTEMP2
  32. !&LOADTEMPREG !&LOCATE !&LOCATEL !&LREG !&LREG1 !&MACROSUBST !&MACROSUBST1
  33. !&MACROSUBST2 !&MAKEADDRESS !&MAKEXP !&MATCHES !&MEMADDRESS !&MKFRAME
  34. !&MKFUNC !&MKNAM !&MKPROGN !&MKREG !&MOVEJUMP &NOANYREG1
  35. !&NOSIDEEFFECTP !&NOSIDEEFFECTPL !&OPENFNP !&OPENP !&OPENPL
  36. !&PA1V !&PALISV
  37. !&PA1X !&PAASSOC1 !&PAEQUAL1 !&PALIS !&PAMAPCOLLECT !&PAMAPCONC !&PAMAPDO
  38. !&PAMEMBER1 !&PANONLOCAL !&PAPROGBOD !&PASS1 !&PASS2 !&PASS3 !&PEEPHOLEOPT
  39. !&PROTECT !&RASSOC !&REFERENCES !&REFERENCESL !&REFEXTERNAL !&REFEXTERNALL
  40. !&REFMEMORY !&REFMEMORYL !&REFORMMACROS !&REGP !&REGVAL !&REMCODE
  41. !&REMMREFS !&REMMREFS1 !&REMOPEN !&REMREFS !&REMREFS1 !&REMREGS !&REMREGSL
  42. !&REMTAGS !&REMTAGS1 !&REMTAGS2 !&REMTAGS3 !&REMTAGS4 !&REMUNUSEDMAC
  43. !&REMVARL !&REMVREFS !&REMVREFS1 !&REPASC !&RMERGE !&RSTVAR !&RSTVARL !&RVAL
  44. !&SAVER1 !&STORELOCAL !&STOREVAR !&SUBARG !&SUBARGS !&TEMPREG !&TRANSFERP
  45. !&UNPROTECT !&UNUSEDLBLS !&USESDESTL !&VARBIND !&VARP !&WCONSTP
  46. !&CONSTP ISAWCONST MKNONLOCAL MKWCONST NONLOCAL NONLOCALLISP
  47. NONLOCALSYS PA1ERR WARRAYP WCONSTP WVARP),
  48. 'InternalFunction);
  49. GLOBAL '(ERFG!*
  50. !*NOLINKE !*ORD !*R2I !*UNSAFEBINDER
  51. MAXNARGS!&
  52. !*NOFRAMEFLUID !*USEREGFLUID
  53. !*INSTALLDESTROY
  54. !*USINGDESTROY
  55. !*SHOWDEST
  56. GLOBALGENSYM!&); % list of symbols to be re-used by the compiler
  57. FLUID '(ALSTS!& FLAGG!& NAME!& GOLIST!& CODELIST!& CONDTAIL!&
  58. LLNGTH!& NARG!& REGS!& EXITT!& LBLIST!& JMPLIST!& SLST!& STOMAP!&
  59. LASTACTUALREG!& DFPRINT!* !*PLAP
  60. !*SYSLISP
  61. SWITCH!&
  62. TOPLAB!&
  63. FREEBOUND!&
  64. STATUS!&
  65. REGS1!&
  66. PREGS!& DESTREG!&
  67. EXITREGS!&
  68. DEST!& ENVIRONMENT!&
  69. HOLEMAP!&
  70. LOCALGENSYM!&); % traveling pointer into GLOBALGENSYM!&
  71. %COMMENT **************************************************************
  72. %**********************************************************************
  73. % THE STANDARD LISP COMPILER
  74. %**********************************************************************
  75. % Augmented for SYSLISP
  76. %*********************************************************************;
  77. %
  78. %COMMENT machine dependent parts are in a separate file;
  79. %
  80. %COMMENT these include the macros described below and, in addition,
  81. % an auxiliary function !&MKFUNC which is required to pass
  82. % functional arguments (input as FUNCTION <func>) to the
  83. % loader. In most cases, !&MKFUNC may be defined as MKQUOTE;
  84. %
  85. %COMMENT Registers used:
  86. %1-MAXNARGS!& used for args of link. result returned in reg 1;
  87. %
  88. %COMMENT Macros used in this compiler;
  89. %
  90. %COMMENT The following macros must NOT change REGS!& 1-MAXNARGS!&:
  91. %!*ALLOC nw allocate new stack frame of nw words
  92. %!*DEALLOC nw deallocate above frame
  93. %!*ENTRY name type noargs entry point to function name of type type
  94. % with noargs args
  95. %!*EXIT EXIT to previously saved return address
  96. %!*JUMP adr unconditional jump
  97. %!*LBL adr define label
  98. %!*LAMBIND regs alst bind free lambda vars in alst currently in regs
  99. %!*PROGBIND alst bind free prog vars in alst
  100. %!*FREERSTR alst unbind free variables in alst
  101. %!*STORE reg floc store contents of reg (or NIL) in floc
  102. %
  103. %COMMENT the following macro must only change specific register being
  104. % loaded:
  105. %
  106. %!*LOAD reg exp load exp into reg;
  107. %
  108. %COMMENT the following macros do not protect regs 1-MAXNARGS!&:
  109. %
  110. %!*LINK fn type nargs link to fn of type type with nargs args
  111. %!*LINKE fn type nargs nw link to fn of type type with nargs args
  112. % and EXITT!& removing frame of nw words;
  113. %
  114. %
  115. %COMMENT variable types are:
  116. %
  117. % LOCAL allocated on stack and known only locally
  118. % GLOBAL accessed via cell (GLOBAL name) known to
  119. % loader at load time
  120. % WGLOBAL accessed via cell (WGLOBAL name) known to
  121. % loader at load time, SYSLISP
  122. % FLUID accessed via cell (FLUID name)
  123. % known to loader. This cell is rebound by LAMBIND/
  124. % PROGBIND if variable used in lambda/prog list
  125. % and restored by FREERSTR;
  126. %
  127. %COMMENT global flags used in this compiler:
  128. %!*UNSAFEBINDER for Don's BAKER problem...GC may be called in
  129. % Binder, so regs cant be preserved
  130. %!*MODULE indicates block compilation (a future extension of
  131. % this compiler)
  132. %!*NOLINKE if ON inhibits use of !*LINKE macro
  133. %!*ORD if ON forces left-to-right argument evaluation
  134. %!*PLAP if ON causes LAP output to be printed
  135. %!*R2I if ON causes recursion removal where possible;
  136. %
  137. %
  138. %COMMENT global variables used:
  139. %
  140. %DFPRINT!* name of special definition process (or NIL)
  141. %ERFG!* used by REDUCE to control error recovery
  142. %MAXNARGS!& maximum number of arguments permitted in implementation;
  143. %
  144. %
  145. %
  146. %%Standard LISP limit;
  147. %
  148. %COMMENT fluid variables used:
  149. %
  150. %ALSTS alist of fluid parameters
  151. %FLAGG used in COMTST, and in FIXREST
  152. %FREEBOUND indicates that some variables were FLUID
  153. %GOLIST storage map for jump labels
  154. %PREGS A list of protected registers
  155. %CODELIST code being built
  156. %CONDTAIL simulated stack of position in the tail of a COND
  157. %LLNGTH cell whose CAR is length of frame
  158. %NAME NAME!& of function being currently compiled
  159. %FNAME!& name of function being currently compiled, set by COMPILE
  160. %NARG number of arguments in function
  161. %REGS known current contents of registers as an alist with elements
  162. % of form (<reg> . <contents>)
  163. %EXITT label for *EXIT jump
  164. %EXITREGS List or register statuses at return point
  165. %LBLIST list of label words
  166. %JMPLIST list of locations in CODELIST!& of transfers
  167. %SLST association list for stores which have not yet been used
  168. %STOMAP storage map for variables
  169. %SWITCH boolean expression value flag - keeps track of NULLs;
  170. %
  171. SYMBOLIC PROCEDURE !&MKFUNC FN; MKQUOTE FN;
  172. SYMBOLIC PROCEDURE WARRAYP X;
  173. GET(X,'WARRAY) OR GET(X, 'WSTRING);
  174. SYMBOLIC PROCEDURE WVARP X;
  175. GET(X,'WVAR);
  176. SYMBOLIC PROCEDURE WCONSTP X;
  177. NUMBERP X OR (IDP X AND GET(X,'WCONST));
  178. SYMBOLIC PROCEDURE !&ANYREGP X;
  179. FLAGP(X, 'ANYREG);
  180. macro procedure LocalF U; % declare functions internal, ala Franz
  181. list('flag, Mkquote cdr U, ''InternalFunction);
  182. %************************************************************
  183. % The compiler
  184. %************************************************************
  185. % Top level compile entry - X is list of functions to compile
  186. SYMBOLIC PROCEDURE COMPILE X;
  187. BEGIN SCALAR EXP;
  188. FOR EACH FNAME!& IN X DO
  189. <<EXP := GETD FNAME!&;
  190. IF NULL EXP THEN !&COMPWARN LIST("No definition for", FNAME!&)
  191. ELSE IF CODEP CDR EXP THEN
  192. !&COMPWARN LIST(FNAME!&, "already compiled")
  193. ELSE COMPD(FNAME!&,CAR EXP,CDR EXP)>>
  194. END;
  195. % COMPD - Single function compiler
  196. % Makes sure function type is compilable; sends original definition to
  197. % DFPRINT!*, then compiles the function. Shows LAP code when PLAP is on.
  198. % Runs LAP and adds COMPFN property if LAP indeed redefines the function.
  199. SYMBOLIC PROCEDURE COMPD(NAME!&,TY,EXP);
  200. BEGIN
  201. IF NOT FLAGP(TY,'COMPILE)
  202. THEN <<!&COMPERROR LIST("Uncompilable function type", TY);
  203. RETURN NIL>>;
  204. IF NOT EQCAR(EXP, 'LAMBDA)
  205. THEN
  206. << !&COMPERROR LIST("Attempt to compile non-lambda expression", EXP);
  207. RETURN NIL >>
  208. %/ ELSE IF !*MODULE THEN MODCMP(NAME!&,TY,EXP)
  209. % ELSE IF DFPRINT!*
  210. % THEN APPLY(DFPRINT!*,LIST IF TY EQ 'EXPR
  211. % THEN 'DE . (NAME!& . CDR EXP)
  212. % ELSE IF TY EQ 'FEXPR
  213. % THEN 'DF . (NAME!& . CDR EXP)
  214. % ELSE IF TY EQ 'MACRO
  215. %% THEN 'DM . (NAME!& . CDR EXP)
  216. % ELSE IF TY EQ 'NEXPR
  217. % THEN 'DN . (NAME!& . CDR EXP)
  218. % ELSE LIST('PUTD,MKQUOTE NAME!&,
  219. % MKQUOTE TY,
  220. % MKQUOTE EXP))
  221. ELSE BEGIN SCALAR X;
  222. IF TY MEMQ '(EXPR FEXPR)
  223. THEN PUT(NAME!&,'CFNTYPE,LIST TY);
  224. X :=
  225. LIST('!*ENTRY,NAME!&,TY,LENGTH CADR EXP)
  226. . !&COMPROC(EXP,
  227. IF TY MEMQ '(EXPR FEXPR)
  228. THEN NAME!&);
  229. IF !*PLAP THEN FOR EACH Y IN X DO PRINT Y;
  230. % ***Code**Pointer** is a magic token that tells
  231. % COMPD to return a code pointer instead of an ID
  232. IF NAME!& = '!*!*!*Code!*!*Pointer!*!*!* then
  233. NAME!& := LAP X
  234. ELSE
  235. << LAP X;
  236. %this is the hook to the assembler. LAP must
  237. %remove old function definition if it exists;
  238. IF (X := GET(NAME!&,'CFNTYPE))
  239. AND EQCAR(GETD NAME!&,CAR X)
  240. THEN REMPROP(NAME!&,'CFNTYPE) >>
  241. END;
  242. RETURN NAME!&
  243. END;
  244. %************************************************************
  245. % Pass 1 routines
  246. %************************************************************
  247. SYMBOLIC PROCEDURE !&PASS1 EXP; %. Pass1- reform body of expression for
  248. !&PA1(EXP,NIL); % Compilation
  249. SYMBOLIC PROCEDURE PA1ERR(X); %. Error messages from PASS1
  250. STDERROR LIST("-- PA1 --", X);
  251. lisp procedure !&Pa1(U, Vbls);
  252. !&Pa1V(U, Vbls, NIL);
  253. % Do the real pass1 and an extra reform
  254. SYMBOLIC PROCEDURE !&PA1V(U,VBLS, VAR);
  255. BEGIN
  256. SCALAR Z,FN; % Z is the pass1 result. Reform if necessary
  257. Z:=!&PA1X(U,VBLS, VAR);
  258. IF IDP CAR Z AND (FN:=GET(CAR Z,'PA1REFORMFN)) THEN
  259. Z := APPLY(FN,LIST Z);
  260. RETURN Z;
  261. END;
  262. SYMBOLIC PROCEDURE !&PA1X(U,VBLS,VAR); %. VBLS are current local vars
  263. BEGIN SCALAR X;
  264. RETURN IF ATOM U % tag variables and constants
  265. THEN IF ISAWCONST U THEN MKWCONST U
  266. ELSE IF CONSTANTP U OR U MEMQ '(NIL T) THEN MKQUOTE U
  267. ELSE IF NONLOCAL U THEN !&PANONLOCAL(U, VBLS)
  268. ELSE IF U MEMQ VBLS THEN LIST('!$LOCAL,U)
  269. ELSE <<MKNONLOCAL U; !&PANONLOCAL(U, VBLS) >>
  270. ELSE IF NOT IDP CAR U
  271. THEN IF EQCAR(CAR U,'LAMBDA) THEN
  272. !&PA1V(CAR U,VBLS,VAR) . !&PALISV(CDR U,VBLS,VAR)
  273. ELSE % Change to APPLY
  274. << !&COMPERROR
  275. list("Ill-formed function expression", U);
  276. '(QUOTE NIL) >>
  277. % Changed semantics of EVAL to conform to Common Lisp.
  278. % CAR of a form is NEVER evaluated.
  279. % ELSE IF CAR U MEMQ VBLS OR FLUIDP CAR U
  280. % OR (GLOBALP CAR U
  281. % AND NOT GETD CAR U) THEN % Change to APPLY
  282. % << !&COMPWARN list("Functional form converted to APPLY", U);
  283. % !&PA1(LIST('APPLY, CAR U, 'LIST . CDR U), VBLS) >>
  284. ELSE IF X := GET(CAR U,'PA1ALGFN) % Do const folding, etc.
  285. THEN APPLY(X,LIST(U,VBLS,VAR))
  286. ELSE IF X := GET(CAR U,'PA1FN) % Do PA1FN's
  287. THEN APPLY(X,LIST(U,VBLS))
  288. ELSE IF X := GET(CAR U,'CMACRO) % CMACRO substitution
  289. THEN !&PA1V(SUBLIS(PAIR(CADR X,CDR U),CADDR X),VBLS,VAR)
  290. ELSE IF (X := GETD CAR U) % Expand macros
  291. AND CAR X EQ 'MACRO
  292. AND NOT (GET(CAR U,'COMPFN) OR GET(CAR U,'OPENFN))
  293. THEN !&PA1V(APPLY(CDR X,LIST U),VBLS,VAR)
  294. ELSE IF !&CFNTYPE CAR U EQ 'FEXPR % Transform FEXPR calls to
  295. AND NOT (GET(CAR U,'COMPFN) OR GET(CAR U,'OPENFN))
  296. THEN LIST(CAR U,MKQUOTE CDR U) % EXPR calls
  297. ELSE IF !&CFNTYPE CAR U EQ 'NEXPR % Transform NEXPR calls to
  298. AND NOT (GET(CAR U,'COMPFN) OR GET(CAR U,'OPENFN))
  299. THEN LIST(CAR U,!&PA1V('LIST . CDR U,VBLS,VAR)) % EXPR calls
  300. ELSE CAR U . !&PALISV(CDR U,VBLS,VAR);
  301. END;
  302. SYMBOLIC PROCEDURE !&PALIS(U,VBLS);
  303. !&PALISV(U,VBLS,NIL);
  304. SYMBOLIC PROCEDURE !&PALISV(U,VBLS, VAR);
  305. FOR EACH X IN U COLLECT !&PA1V(X,VBLS,VAR);
  306. SYMBOLIC PROCEDURE ISAWCONST X; %. Check to see if WCONST,
  307. %. in SYSLISP only
  308. !*SYSLISP AND WCONSTP X;
  309. SYMBOLIC PROCEDURE !&CONSTTAG();
  310. IF !*SYSLISP THEN 'WCONST ELSE 'QUOTE;
  311. SYMBOLIC PROCEDURE MKWCONST X; %. Made into WCONST
  312. BEGIN SCALAR Y;
  313. RETURN LIST('WCONST, IF (Y := GET(X, 'WCONST)) AND NOT GET(X, 'WARRAY)
  314. AND NOT GET(X, 'WSTRING) THEN
  315. Y
  316. ELSE X);
  317. END;
  318. SYMBOLIC PROCEDURE !&PAWCONST(U, VBLS);
  319. MKWCONST CADR U;
  320. SYMBOLIC PROCEDURE NONLOCAL X; %. Default NON-LOCAL types
  321. IF !*SYSLISP THEN NONLOCALSYS X
  322. ELSE NONLOCALLISP X;
  323. SYMBOLIC PROCEDURE NONLOCALLISP X;
  324. IF FLUIDP X THEN '!$FLUID
  325. ELSE IF GLOBALP X THEN '!$GLOBAL
  326. ELSE IF WVARP X OR WARRAYP X THEN
  327. <<!&COMPWARN LIST(X,"already SYSLISP non-local");NIL>>
  328. ELSE NIL;
  329. SYMBOLIC PROCEDURE NONLOCALSYS X;
  330. IF WARRAYP X THEN 'WARRAY
  331. ELSE IF WVARP X THEN 'WVAR
  332. ELSE NONLOCALLISP X;
  333. SYMBOLIC PROCEDURE !&PANONLOCAL(X, VBLS); %. Reform Non-locals
  334. % X will be a declared NONLOCAL
  335. BEGIN SCALAR Z;
  336. RETURN
  337. IF NOT IDP X OR NOT NONLOCAL X THEN PA1ERR LIST("non-local error",X)
  338. ELSE IF FLUIDP X THEN LIST('!$FLUID,X)
  339. ELSE IF GLOBALP X THEN LIST('!$GLOBAL,X)
  340. ELSE IF GET(X,'WVAR) THEN
  341. IF X MEMBER VBLS THEN <<!&COMPWARN(LIST('WVAR,X,"used as local"));
  342. LIST('!$LOCAL,X)>>
  343. ELSE LIST('WVAR,X)
  344. ELSE IF WARRAYP X THEN
  345. LIST('WCONST, X)
  346. ELSE PA1ERR LIST("Unknown in PANONLOCAL",X);
  347. END;
  348. % Make unknown symbols into FLUID for LISP, WVAR for SYSLISP, with warning
  349. % Changed to just declare it fluid, EB, 9:36am Friday, 10 September 1982
  350. SYMBOLIC PROCEDURE MKNONLOCAL U;
  351. % IF !*SYSLISP THEN
  352. % << !&COMPERROR LIST("Undefined symbol", U,
  353. % "in Syslisp, treated as WVAR");
  354. % WDECLARE1(U, 'INTERNAL, 'WVAR, NIL, 0);
  355. % LIST('WVAR, U) >>
  356. % ELSE
  357. <<!&COMPWARN LIST(U,"declared fluid"); FLUID LIST U; LIST('!$FLUID,U)>>;
  358. % Utility stuff for the PA1 functions
  359. SYMBOLIC PROCEDURE !&MKNAM U;
  360. %generates unique name for auxiliary function in U;
  361. IMPLODE NCONC(EXPLODE U,EXPLODE !&GENSYM());
  362. % For making implied PROGN's into explicit ones (as in COND)
  363. SYMBOLIC PROCEDURE !&MKPROGN U;
  364. IF NULL U OR CDR U THEN 'PROGN . U ELSE CAR U;
  365. SYMBOLIC PROCEDURE !&EQP U;
  366. %!&EQP is true if U is an object for which EQ can replace EQUAL;
  367. INUMP U OR IDP U;
  368. SYMBOLIC PROCEDURE !&EQVP U;
  369. %!&EQVP is true if EVAL U is an object for which EQ can
  370. %replace EQUAL;
  371. INUMP U OR NULL U OR U EQ 'T OR EQCAR(U,'QUOTE) AND !&EQP CADR U;
  372. % !&EQPL U is true if !&EQP of all elements of U
  373. SYMBOLIC PROCEDURE !&EQPL U;
  374. NULL U OR !&EQP(CAR U) AND !&EQPL(CDR U);
  375. SYMBOLIC PROCEDURE !&MAKEADDRESS U;
  376. % convert an expression into an addressing expression, (MEMORY var const),
  377. % where var is the variable part & const is the constant part (tagged, of
  378. % course). It is assumed that U has been through pass 1, which does constant
  379. % folding & puts any constant term at the top level.
  380. IF EQCAR(U,'LOC) THEN CADR U ELSE % GETMEM LOC x == x
  381. 'MEMORY .
  382. (IF EQCAR(U,'WPLUS2) AND !&CONSTP CADDR U THEN CDR U
  383. ELSE IF EQCAR(U,'WDIFFERENCE) AND !&CONSTP CADR U THEN
  384. LIST(LIST('WMINUS,CADDR U),CADR U)
  385. ELSE LIST(U,'(WCONST 0)));
  386. SYMBOLIC PROCEDURE !&DOOP U;
  387. % simplification for random operators - op is doable only when all operands
  388. % are constant
  389. IF !&ALLCONST CDR U THEN
  390. LIST(CAR CADR U,
  391. APPLY(GET(CAR U,'DOFN) or car U, FOR EACH X IN CDR U COLLECT CADR X))
  392. ELSE U;
  393. SYMBOLIC PROCEDURE !&ALLCONST L;
  394. NULL L OR (car L = 'QUOTE or !&WCONSTP CAR L AND NUMBERP CADR CAR L)
  395. AND !&ALLCONST CDR L;
  396. lisp procedure !&PaReformWTimes2 U;
  397. begin scalar X;
  398. U := !&Doop U;
  399. return if first U = 'WTimes2 then
  400. if !&WConstP second U and (X := PowerOf2P second second U) then
  401. list('WShift, third U, list(!&ConstTag(), X))
  402. else if !&WConstP third U and (X := PowerOf2P second third U) then
  403. list('WShift, second U, list(!&ConstTag(), X))
  404. else U
  405. else U;
  406. end;
  407. SYMBOLIC PROCEDURE !&ASSOCOP(U,VBLS); % For abelian semi-groups & monoids
  408. % given an associative, communitive operation (TIMES2, AND, ...) collect all
  409. % arguments, seperate constant args, evaluate true constants, check for zero's
  410. % and ones (0*X = 0, 1*X = X)
  411. !&ASSOCOPV(U,VBLS,NIL);
  412. SYMBOLIC PROCEDURE !&ASSOCOPV(U,VBLS,VAR);
  413. BEGIN SCALAR ARGS,NUM,CONSTS,VARS;
  414. ARGS := !&ASSOCOP1(CAR U,!&PALIS(CDR U,VBLS));
  415. CONSTS := VARS := NUM := NIL;
  416. FOR EACH ARG IN ARGS DO
  417. IF !&WCONSTP ARG THEN
  418. IF NUMBERP CADR ARG THEN
  419. IF NUM THEN NUM := APPLY(GET(CAR U,'DOFN),LIST(NUM,CADR ARG))
  420. ELSE NUM := CADR ARG
  421. ELSE CONSTS := NCONC(CONSTS,LIST ARG)
  422. ELSE VARS := NCONC(VARS,LIST ARG);
  423. IF NUM THEN
  424. <<IF NUM = GET(CAR U,'ZERO) THEN RETURN LIST(!&CONSTTAG(),NUM);
  425. IF NUM NEQ GET(CAR U,'ONE) THEN CONSTS := NUM . CONSTS
  426. ELSE IF NULL VARS AND NULL CONSTS THEN RETURN
  427. LIST(!&CONSTTAG(), NUM) >>;
  428. IF CONSTS THEN
  429. VARS := NCONC(VARS,LIST LIST('WCONST,!&INSOP(CAR U,CONSTS)));
  430. IF VAR MEMBER VARS THEN
  431. <<VARS := DELETIP(VAR,VARS);
  432. RETURN !&INSOP(CAR U,REVERSIP(VAR . REVERSIP VARS))>>;
  433. RETURN !&INSOP(CAR U,VARS);
  434. END;
  435. SYMBOLIC PROCEDURE !&ASSOCOP1(OP,ARGS);
  436. IF NULL ARGS THEN NIL
  437. ELSE NCONC(!&ASSOCOP2(OP,CAR ARGS),!&ASSOCOP1(OP,CDR ARGS));
  438. SYMBOLIC PROCEDURE !&ASSOCOP2(OP,ARG);
  439. IF EQCAR(ARG,OP) THEN !&ASSOCOP1(OP,CDR ARG)
  440. ELSE LIST ARG;
  441. SYMBOLIC PROCEDURE !&INSOP(OP,L);
  442. % Insert OP into a list of operands as follows: INSOP(~,'(A B C D)) =
  443. % (~ (~ (~ A B) C) D)
  444. IF NULL L THEN NIL ELSE if null cdr L then car L else
  445. !&INSOP1(list(OP, first L, second L), rest rest L, OP);
  446. SYMBOLIC PROCEDURE !&INSOP1(NEW, RL, OP);
  447. if null RL then NEW else !&INSOP1(list(OP, NEW, first RL), rest RL, OP);
  448. SYMBOLIC PROCEDURE !&GROUP(U,VBLS);
  449. % Like ASSOP, except inverses exist. All operands are partitioned into two
  450. % lists, non-inverted and inverted. Cancellation is done between these two
  451. % lists. The group is defined by three operations, the group operation (+),
  452. % inversion (unary -), and subtraction (dyadic -). The GROUPOPS property on
  453. % all three of there operators must contain the names of these operators in
  454. % the order (add subtract minus)
  455. !&GROUPV(U,VBLS,NIL);
  456. SYMBOLIC PROCEDURE !&GROUPV(U,VBLS,VAR);
  457. BEGIN SCALAR X,ARGS,INVARGS,FNS,CONSTS,INVCONSTS,CON,RES,VFLG,INVFLG,ONE;
  458. FNS := GET(CAR U,'GROUPOPS);
  459. ONE := LIST(!&CONSTTAG(),GET(CAR FNS,'ONE));
  460. X := !&GETGROUPARGS(FNS,CAR U . !&PALIS(CDR U, VBLS),NIL,'(NIL NIL));
  461. ARGS := CAR X;
  462. INVARGS := CADR X;
  463. FOR EACH ARG IN ARGS DO
  464. IF ARG MEMBER INVARGS THEN
  465. <<ARGS := !&DELARG(ARG,ARGS);
  466. INVARGS := !&DELARG(ARG,INVARGS)>>;
  467. CONSTS := INVCONSTS := CON := NIL;
  468. FOR EACH ARG IN ARGS DO
  469. IF !&WCONSTP ARG THEN
  470. <<ARGS := !&DELARG(ARG,ARGS);
  471. IF NUMBERP CADR ARG THEN
  472. IF CON THEN CON := APPLY(GET(CAR FNS,'DOFN),LIST(CON,CADR ARG))
  473. ELSE CON := CADR ARG
  474. ELSE CONSTS := NCONC(CONSTS,LIST ARG)>>;
  475. FOR EACH ARG IN INVARGS DO
  476. IF !&WCONSTP ARG THEN
  477. <<INVARGS := !&DELARG(ARG,INVARGS);
  478. IF NUMBERP CADR ARG THEN
  479. IF CON THEN CON := APPLY(GET(CADR FNS,'DOFN),LIST(CON,CADR ARG))
  480. ELSE CON := APPLY(GET(CADDR FNS,'DOFN),LIST CADR ARG)
  481. ELSE INVCONSTS := NCONC(INVCONSTS,LIST ARG)>>;
  482. IF CON AND CON = GET(CAR FNS,'ZERO) THEN RETURN LIST(!&CONSTTAG(),CON);
  483. IF CON AND CON = CADR ONE THEN CON := NIL;
  484. IF CON THEN CONSTS := CON . CONSTS;
  485. CONSTS := !&MAKEXP(CONSTS,INVCONSTS,FNS);
  486. IF CONSTS AND NOT !&WCONSTP CONSTS THEN CONSTS := LIST('WCONST,CONSTS);
  487. IF VAR MEMBER ARGS THEN
  488. <<ARGS := DELETE(VAR,ARGS);
  489. VFLG := T;
  490. INVFLG := NIL>>;
  491. IF VAR MEMBER INVARGS THEN
  492. <<INVARGS := DELETE(VAR,INVARGS);
  493. VFLG := T;
  494. INVFLG := T>>;
  495. ARGS := !&MAKEXP(ARGS,INVARGS,FNS);
  496. RES := IF NULL ARGS THEN
  497. IF NULL CONSTS THEN
  498. ONE
  499. ELSE CONSTS
  500. ELSE
  501. IF NULL CONSTS THEN ARGS
  502. ELSE IF EQCAR(ARGS,CADDR FNS) THEN
  503. LIST(CADR FNS,CONSTS,CADR ARGS)
  504. ELSE
  505. LIST(CAR FNS,ARGS,CONSTS);
  506. IF VFLG THEN
  507. IF RES = ONE THEN
  508. IF INVFLG THEN RES := LIST(CADDR FNS,VAR)
  509. ELSE RES := VAR
  510. ELSE
  511. RES := LIST(IF INVFLG THEN CADR FNS ELSE CAR FNS,RES,VAR);
  512. RETURN RES;
  513. END;
  514. SYMBOLIC PROCEDURE !&MAKEXP(ARGS,INVARGS,FNS);
  515. IF NULL ARGS THEN
  516. IF NULL INVARGS THEN NIL
  517. ELSE LIST(CADDR FNS,!&INSOP(CAR FNS,INVARGS))
  518. ELSE
  519. IF NULL INVARGS THEN !&INSOP(CAR FNS,ARGS)
  520. ELSE !&INSOP(CADR FNS,!&INSOP(CAR FNS,ARGS) . INVARGS);
  521. SYMBOLIC PROCEDURE !&GETGROUPARGS(FNS,EXP,INVFLG,RES);
  522. IF ATOM EXP OR NOT(CAR EXP MEMBER FNS) THEN
  523. !&GETGROUPARGS1(EXP,INVFLG,RES)
  524. ELSE IF CAR EXP EQ CAR FNS THEN !&GETGROUPARGS2(FNS,CDR EXP,INVFLG,RES)
  525. ELSE IF CAR EXP EQ CADR FNS THEN
  526. !&GETGROUPARGS(FNS,CADR EXP,INVFLG,
  527. !&GETGROUPARGS(FNS,CADDR EXP,NOT INVFLG,RES))
  528. ELSE IF CAR EXP EQ CADDR FNS THEN
  529. !&GETGROUPARGS(FNS,CADR EXP,NOT INVFLG,RES)
  530. ELSE !&COMPERROR(LIST("Compiler bug in constant folding",FNS,EXP));
  531. SYMBOLIC PROCEDURE !&GETGROUPARGS1(THING,INVFLG,RES);
  532. IF INVFLG THEN LIST(CAR RES,THING . CADR RES)
  533. ELSE (THING . CAR RES) . CDR RES;
  534. SYMBOLIC PROCEDURE !&GETGROUPARGS2(FNS,ARGS,INVFLG,RES);
  535. IF NULL ARGS THEN RES
  536. ELSE !&GETGROUPARGS2(FNS,CDR ARGS,INVFLG,
  537. !&GETGROUPARGS(FNS,CAR ARGS,INVFLG,RES));
  538. SYMBOLIC PROCEDURE !&DELARG(ARG,ARGS);
  539. IF ARG = CAR ARGS THEN CDR ARGS ELSE CAR ARGS . !&DELARG(ARG,CDR ARGS);
  540. %************************************************************
  541. % Pass 1 functions
  542. %************************************************************
  543. lisp procedure !&PaApply(U, Vars);
  544. if EqCar(third U, 'LIST) then % set up for !&COMAPPLY
  545. if EqCar(second U, 'function)
  546. and !&CfnType second second U = 'EXPR then
  547. !&Pa1(second second U . rest third U, Vars)
  548. else list('APPLY,
  549. !&Pa1(second U, Vars),
  550. 'LIST . !&PaLis(rest third U, Vars))
  551. else 'APPLY . !&PaLis(rest U, Vars);
  552. % Try to turn ASSOC into ATSOC
  553. SYMBOLIC PROCEDURE !&PAASSOC(U,VARS);
  554. !&PAASSOC1(CADR U,CADDR U) . !&PALIS(CDR U,VARS);
  555. SYMBOLIC PROCEDURE !&PAASSOC1(ASSOCVAR,ASSOCLIST);
  556. IF !&EQVP ASSOCVAR
  557. OR EQCAR(ASSOCLIST,'QUOTE) AND
  558. !&EQPL(FOR EACH U IN CADR ASSOCLIST COLLECT CAR U)
  559. THEN 'ATSOC ELSE 'ASSOC;
  560. SYMBOLIC PROCEDURE !&PACOND(U,VBLS);
  561. begin scalar RevU, Result, Temp;
  562. if null cdr U then return '(QUOTE NIL); % (COND) == NIL
  563. RevU := reverse cdr U;
  564. if first first RevU neq T then RevU := '(T NIL) . RevU;
  565. for each CondForm in RevU do
  566. if null rest CondForm then
  567. << if not Temp then
  568. << Temp := !&Gensym();
  569. VBLS := Temp . VBLS >>;
  570. Result := list(!&PA1(list('SETQ, Temp, first CondForm), VBLS),
  571. !&PA1(Temp, VBLS)) . Result >>
  572. else
  573. Result := list(!&PA1(first CondForm, VBLS),
  574. !&PA1(!&MkProgN rest CondForm, VBLS)) . Result;
  575. return if Temp then list(list('LAMBDA,
  576. list !&PA1(Temp, VBLS),
  577. 'COND . Result),
  578. '(QUOTE NIL))
  579. else 'COND . Result;
  580. end;
  581. lisp procedure !&PaCatch(U, Vbls);
  582. (lambda(Tag, Forms);
  583. << if null cdr Forms and
  584. (atom car Forms
  585. or car car Forms = 'QUOTE
  586. or car car Forms = 'LIST) then
  587. !&CompWarn list("Probable obsolete use of CATCH:", U);
  588. !&Pa1(list(list('lambda, '(!&!&HiddenVar!&!&),
  589. list('cond, list('(null ThrowSignal!*),
  590. list('(lambda (xxx)
  591. (!%UnCatch !&!&HiddenVar!&!&)
  592. xxx),
  593. 'progn . Forms)),
  594. '(t !&!&HiddenVar!&!&))),
  595. list('CatchSetup, Tag)),
  596. Vbls)>>)(cadr U, cddr U);
  597. % X-1 -> SUB1 X
  598. SYMBOLIC PROCEDURE !&PADIFF(U,VARS);
  599. IF CADDR U=1 THEN LIST('SUB1,!&PA1(CADR U,VARS))
  600. ELSE 'DIFFERENCE . !&PALIS(CDR U,VARS);
  601. SYMBOLIC PROCEDURE !&PAEQUAL(U,VARS);
  602. !&PAEQUAL1(CADR U,CADDR U) . !&PALIS(CDR U,VARS);
  603. SYMBOLIC PROCEDURE !&PAEQUAL1(LEFT,RIGHT);
  604. IF !&EQVP LEFT OR !&EQVP RIGHT THEN 'EQ
  605. ELSE IF NUMBERP LEFT OR NUMBERP RIGHT THEN 'EQN
  606. ELSE 'EQUAL;
  607. % FUNCTION will compile a non-atomic arg into a GENSYMed name.
  608. % Currently, MKFUNC = MKQUOTE
  609. SYMBOLIC PROCEDURE !&PAFUNCTION(U,VBLS);
  610. IF ATOM CADR U THEN !&MKFUNC CADR U % COMPD returns a code pointer here
  611. ELSE !&MKFUNC COMPD('!*!*!*Code!*!*Pointer!*!*!*,
  612. 'EXPR,CADR U);
  613. SYMBOLIC PROCEDURE !&PAGETMEM(U,VBLS);
  614. !&MAKEADDRESS !&PA1(CADR U,VBLS);
  615. SYMBOLIC PROCEDURE !&PAIDENT(U,VBLS); %. return form
  616. U;
  617. % LAMBDA - pick up new vars, check implicit PROGN
  618. SYMBOLIC PROCEDURE !&PACASE(U,VBLS);
  619. 'CASE . !&PA1(CADR U,VBLS) . FOR EACH EXP IN CDDR U COLLECT
  620. LIST(!&PALIS(CAR EXP,VBLS),!&PA1(CADR EXP,VBLS));
  621. SYMBOLIC PROCEDURE !&PALAMBDA(U,VBLS);
  622. <<VBLS := APPEND(CADR U,VBLS);
  623. 'LAMBDA . LIST(!&PALIS(CADR U,VBLS),!&PA1(!&MKPROGN CDDR U,VBLS)) >>;
  624. % X<0 -> MINUSP(X)
  625. SYMBOLIC PROCEDURE !&PALESSP(U,VARS);
  626. IF CADDR U=0 THEN LIST('MINUSP,!&PA1(CADR U,VARS))
  627. ELSE 'LESSP . !&PALIS(CDR U,VARS);
  628. SYMBOLIC PROCEDURE !&PALIST(U, VBLS);
  629. BEGIN SCALAR L,FN;
  630. L := LENGTH CDR U;
  631. RETURN
  632. IF L = 0 THEN '(QUOTE NIL)
  633. ELSE IF FN := ASSOC(L,'((1 . NCONS)
  634. (2 . LIST2)
  635. (3 . LIST3)
  636. (4 . LIST4)
  637. (5 . LIST5)))
  638. THEN !&PA1(CDR FN . CDR U, VBLS)
  639. ELSE !&PA1(LIST('CONS,CADR U, 'LIST . CDDR U), VBLS);
  640. END;
  641. lisp procedure !&PaNth(U, Vbls);
  642. !&PaNths(U, Vbls, '((1 . CAR) (2 . CADR) (3 . CADDR) (4 . CADDDR)));
  643. lisp procedure !&PaPNth(U, Vbls);
  644. !&PaNths(U, Vbls, '((1 . CR)
  645. (2 . CDR)
  646. (3 . CDDR)
  647. (4 . CDDDR)
  648. (5 . CDDDDR)));
  649. lisp procedure !&PaNths(U, Vbls, FnTable);
  650. begin scalar N, X, Fn;
  651. N := !&Pa1(third U, Vbls);
  652. X := second U;
  653. return if first N memq '(QUOTE WCONST) and FixP second N
  654. and (Fn := Assoc(second N, FnTable)) then
  655. if cdr Fn = 'CR then
  656. !&Pa1(X, Vbls)
  657. else !&Pa1(list(cdr Fn, X), Vbls)
  658. else list(car U, !&Pa1(X, Vbls), N);
  659. end;
  660. SYMBOLIC PROCEDURE !&PAMAP(U, VBLS);
  661. !&PAMAPDO(U, VBLS, NIL);
  662. SYMBOLIC PROCEDURE !&PAMAPC(U, VBLS);
  663. !&PAMAPDO(U, VBLS, T);
  664. SYMBOLIC PROCEDURE !&PAMAPDO(U, VBLS, CARFLAG);
  665. IF NOT EQCAR(CADDR U,'FUNCTION) THEN CAR U . !&PALIS(CDR U,VBLS)
  666. ELSE BEGIN SCALAR TMP;
  667. TMP := !&GENSYM();
  668. RETURN !&PA1(SUBLA(LIST('TMP . TMP,
  669. 'STARTINGLIST . CADR U,
  670. 'FNCALL . LIST(CADR CADDR U,
  671. IF CARFLAG THEN
  672. LIST('CAR, TMP)
  673. ELSE TMP)),
  674. '(PROG (TMP)
  675. (SETQ TMP STARTINGLIST)
  676. LOOPLABEL
  677. (COND ((ATOM TMP) (RETURN NIL)))
  678. FNCALL
  679. (SETQ TMP (CDR TMP))
  680. (GO LOOPLABEL))), VBLS);
  681. END;
  682. SYMBOLIC PROCEDURE !&PAMAPLIST(U, VBLS);
  683. !&PAMAPCOLLECT(U, VBLS, NIL);
  684. SYMBOLIC PROCEDURE !&PAMAPCAR(U, VBLS);
  685. !&PAMAPCOLLECT(U, VBLS, T);
  686. SYMBOLIC PROCEDURE !&PAMAPCOLLECT(U, VBLS, CARFLAG);
  687. IF NOT EQCAR(CADDR U,'FUNCTION) THEN CAR U . !&PALIS(CDR U,VBLS)
  688. ELSE BEGIN SCALAR TMP, RESULT, ENDPTR;
  689. TMP := !&GENSYM();
  690. RESULT := !&GENSYM();
  691. ENDPTR := !&GENSYM();
  692. RETURN !&PA1(SUBLA(LIST('TMP . TMP,
  693. 'RESULT . RESULT,
  694. 'ENDPTR . ENDPTR,
  695. 'STARTINGLIST . CADR U,
  696. 'FNCALL . LIST(CADR CADDR U,
  697. IF CARFLAG THEN
  698. LIST('CAR, TMP)
  699. ELSE TMP)),
  700. '(PROG (TMP RESULT ENDPTR)
  701. (SETQ TMP STARTINGLIST)
  702. (COND ((ATOM TMP) (RETURN NIL)))
  703. (SETQ RESULT (SETQ ENDPTR (NCONS FNCALL)))
  704. LOOPLABEL
  705. (SETQ TMP (CDR TMP))
  706. (COND ((ATOM TMP) (RETURN RESULT)))
  707. (RPLACD ENDPTR (NCONS FNCALL))
  708. (SETQ ENDPTR (CDR ENDPTR))
  709. (GO LOOPLABEL))), VBLS);
  710. END;
  711. SYMBOLIC PROCEDURE !&PAMAPCON(U, VBLS);
  712. !&PAMAPCONC(U, VBLS, NIL);
  713. SYMBOLIC PROCEDURE !&PAMAPCAN(U, VBLS);
  714. !&PAMAPCONC(U, VBLS, T);
  715. SYMBOLIC PROCEDURE !&PAMAPCONC(U, VBLS, CARFLAG);
  716. IF NOT EQCAR(CADDR U,'FUNCTION) THEN CAR U . !&PALIS(CDR U,VBLS)
  717. ELSE BEGIN SCALAR TMP, RESULT, ENDPTR;
  718. TMP := !&GENSYM();
  719. RESULT := !&GENSYM();
  720. ENDPTR := !&GENSYM();
  721. RETURN !&PA1(SUBLA(LIST('TMP . TMP,
  722. 'RESULT . RESULT,
  723. 'ENDPTR . ENDPTR,
  724. 'STARTINGLIST . CADR U,
  725. 'FNCALL . LIST(CADR CADDR U,
  726. IF CARFLAG THEN
  727. LIST('CAR, TMP)
  728. ELSE TMP)),
  729. '(PROG (TMP RESULT ENDPTR)
  730. (SETQ TMP STARTINGLIST)
  731. STARTOVER
  732. (COND ((ATOM TMP) (RETURN NIL)))
  733. (SETQ RESULT FNCALL)
  734. (SETQ ENDPTR (LASTPAIR RESULT))
  735. (SETQ TMP (CDR TMP))
  736. (COND ((ATOM ENDPTR) (GO STARTOVER)))
  737. LOOPLABEL
  738. (COND ((ATOM TMP) (RETURN RESULT)))
  739. (RPLACD ENDPTR FNCALL)
  740. (SETQ ENDPTR (LASTPAIR ENDPTR))
  741. (SETQ TMP (CDR TMP))
  742. (GO LOOPLABEL))), VBLS);
  743. END;
  744. % Attempt to change MEMBER to MEMQ
  745. SYMBOLIC PROCEDURE !&PAMEMBER(U,VARS);
  746. !&PAMEMBER1(CADR U,CADDR U) . !&PALIS(CDR U,VARS);
  747. SYMBOLIC PROCEDURE !&PAMEMBER1(THING,LST);
  748. IF !&EQVP THING OR EQCAR(LST,'QUOTE) AND !&EQPL CADR LST
  749. THEN 'MEMQ ELSE 'MEMBER;
  750. % (Intern (Compress X)) == (Implode X)
  751. % (Intern (Gensym)) == (InternGensym)
  752. SYMBOLIC PROCEDURE !&PAINTERN(U, VBLS);
  753. << U := !&PA1(CADR U, VBLS);
  754. IF EQCAR(U, 'COMPRESS) THEN 'IMPLODE . CDR U
  755. ELSE IF EQCAR(U, 'GENSYM) THEN 'INTERNGENSYM . CDR U
  756. ELSE LIST('INTERN, U) >>;
  757. % Do MINUS on constants.
  758. SYMBOLIC PROCEDURE !&PAMINUS(U,VBLS);
  759. IF EQCAR(U := !&PA1(CADR U,VBLS),'QUOTE) AND NUMBERP CADR U
  760. THEN MKQUOTE ( - CADR U)
  761. ELSE IF EQCAR(U ,'WCONST) AND NUMBERP CADR U
  762. THEN MKWCONST ( - CADR U)
  763. ELSE LIST('MINUS,U);
  764. SYMBOLIC PROCEDURE !&REFORMLOC U;
  765. IF EQCAR(CADR U, 'MEMORY) THEN
  766. LIST('WPLUS2, CADDR CADR U, CADR CADR U)
  767. ELSE U;
  768. SYMBOLIC PROCEDURE !&REFORMNULL U;
  769. BEGIN SCALAR FLIP;
  770. RETURN
  771. IF PAIRP CADR U AND (FLIP := GET(CAADR U,'FLIPTST)) THEN
  772. FLIP . CDADR U
  773. ELSE LIST('EQ, CADR U, '(QUOTE NIL));
  774. END;
  775. % Perdue 12/3/82
  776. % This optimization causes compiled code to behave differently
  777. % from interpreted code. The FLIPTST property on NE and PASS2
  778. % handling of negation in tests (&COMTST) are enough to cause good code
  779. % to be generated when NE is used as a test.
  780. % SYMBOLIC PROCEDURE !&REFORMNE U;
  781. % IF CADR U = '(QUOTE NIL) THEN CADDR U
  782. % ELSE IF CADDR U = '(QUOTE NIL) THEN CADR U
  783. % ELSE U;
  784. % PLUS2(X,1) -> ADD1(X)
  785. SYMBOLIC PROCEDURE !&PAPLUS2(U,VARS);
  786. IF CADDR U=1 THEN !&PA1(LIST('ADD1, CADR U),VARS)
  787. ELSE IF CADR U=1 THEN !&PA1('ADD1 . CDDR U,VARS)
  788. ELSE 'PLUS2 . !&PALIS(CDR U,VARS);
  789. % Pick up PROG vars, ignore labels.
  790. SYMBOLIC PROCEDURE !&PAPROG(U,VBLS);
  791. <<VBLS := APPEND(CADR U,VBLS);
  792. 'PROG . (!&PALIS(CADR U,VBLS) . !&PAPROGBOD(CDDR U,VBLS)) >>;
  793. SYMBOLIC PROCEDURE !&PAPROGBOD(U,VBLS);
  794. FOR EACH X IN U COLLECT IF ATOM X THEN X ELSE !&PA1(X,VBLS);
  795. SYMBOLIC PROCEDURE !&PAPUTMEM(U,VBLS);
  796. !&PA1('SETQ . LIST('GETMEM, CADR U) . CDDR U, VBLS);
  797. SYMBOLIC PROCEDURE !&PAPUTLISPVAR(U, VBLS);
  798. !&PA1('SETQ . LIST('LISPVAR, CADR U) . CDDR U, VBLS);
  799. SYMBOLIC PROCEDURE !&PALISPVAR(U, VBLS);
  800. LIST('!$FLUID, CADR U);
  801. SYMBOLIC PROCEDURE !&PASETQ(U,VBLS);
  802. BEGIN SCALAR VAR,FN,EXP, LN;
  803. LN := LENGTH CDR U;
  804. IF LN NEQ 2 THEN RETURN
  805. << LN := DIVIDE(LN, 2);
  806. IF CDR LN NEQ 0 THEN
  807. << !&COMPERROR LIST("Odd number of arguments to SETQ", U);
  808. U := APPEND(U, LIST NIL);
  809. LN := CAR LN + 1 >>
  810. ELSE LN := CAR LN;
  811. U := CDR U;
  812. FOR I := 1 STEP 1 UNTIL LN DO
  813. << EXP := LIST('SETQ, CAR U, CADR U) . EXP;
  814. U := CDDR U >>;
  815. !&PA1('PROGN . REVERSIP EXP, VBLS) >>;
  816. VAR := !&PA1(CADR U,VBLS);
  817. EXP := !&PA1V(CADDR U, VBLS, VAR);
  818. U := IF FLAGP(CAR VAR,'VAR) THEN LIST('!$NAME,VAR) ELSE VAR;
  819. IF (NOT (FN := GET(CAR EXP,'MEMMODFN))) OR not (LastCar EXP = VAR) THEN
  820. RETURN LIST('SETQ,U,EXP)
  821. ELSE RETURN FN . U . REVERSIP CDR REVERSIP CDR EXP;
  822. END;
  823. SYMBOLIC PROCEDURE !&INSTALLDESTROY(NAME!&);
  824. % determine which (if any) registers are unaltered by the function.
  825. % Print this information out if !*SHOWDEST, install it on the
  826. % property list of the function if !*INSTALLDESTOY
  827. BEGIN SCALAR DESTL,R,HRU;
  828. HRU := !&HIGHEST(CODELIST!&,NIL,NARG!&,T);
  829. % Find the highest register used in the code. Registers above this are
  830. % unchanged. Incoming registers have a distinguished value, IREG n, placed
  831. % in register n. If this value remains, it has not been destroyed.
  832. IF HRU = 'ALL THEN RETURN NIL;
  833. DESTL := NIL;
  834. FOR I := 1:NARG!& DO
  835. <<R := !&MKREG I;
  836. IF NOT (!&IREG I MEMBER !&REGVAL R) THEN DESTL := R . DESTL>>;
  837. FOR I := NARG!&+1 : HRU DO
  838. DESTL := !&MKREG I . DESTL;
  839. IF NULL DESTL THEN DESTL := '((REG 1));
  840. IF !*INSTALLDESTROY THEN PUT(NAME!&,'DESTROYS,DESTL);
  841. IF !*SHOWDEST THEN <<PRIN2 NAME!&;PRIN2 " DESTROYS ";PRIN2T DESTL>>;
  842. END;
  843. % COMPROC does the dirty work - initializes variables and gets the
  844. % three passes going.
  845. SYMBOLIC PROCEDURE !&COMPROC(EXP,NAME!&);
  846. %compiles a function body, returning the generated LAP;
  847. BEGIN SCALAR CODELIST!&,FLAGG!&,JMPLIST!&,LBLIST!&,
  848. LOCALGENSYM!&,
  849. LLNGTH!&,REGS!&,REGS1!&,ALSTS!&,
  850. EXITT!&,TOPLAB!&,SLST!&,STOMAP!&,
  851. CONDTAIL!&,FREEBOUND!&,HOLEMAP!&,PREGS!&,
  852. SWITCH!&,EXITREGS!&,RN; INTEGER NARG!&;
  853. LOCALGENSYM!& := GLOBALGENSYM!&;
  854. PREGS!& := NIL;
  855. REGS!& := NIL;
  856. LLNGTH!& := 0;
  857. IF NOT EQCAR(EXP, 'LAMBDA) THEN
  858. << !&COMPERROR LIST("Attempt to compile a non-lambda expression", EXP);
  859. RETURN NIL >>;
  860. NARG!& := LENGTH CADR EXP;
  861. EXITREGS!& := NIL;
  862. EXITT!& := !&GENLBL();
  863. TOPLAB!& := !&GENLBL();
  864. STOMAP!& := NIL;
  865. CODELIST!& := LIST '(!*ALLOC (!*FRAMESIZE));
  866. !&ATTLBL TOPLAB!&;
  867. EXP := !&PASS1 EXP;
  868. IF NARG!& > MAXNARGS!&
  869. THEN !&COMPERROR LIST("Too many arguments",NARG!&);
  870. ALSTS!& := !&VARBIND(CADR EXP,T); % Generate LAMBIND
  871. RN := 1;
  872. FOR I := 1:LENGTH CADR EXP DO
  873. REGS!& := !&ADDRVALS(!&MKREG I,REGS!&,LIST( !&IREG I));
  874. !&PASS2 CADDR EXP;
  875. !&FREERSTR(ALSTS!&,0); %Restores old fluid bindings
  876. !&PASS3();
  877. IF !*INSTALLDESTROY OR !*SHOWDEST THEN !&INSTALLDESTROY(NAME!&);
  878. !&REFORMMACROS(); % Plugs compile time constants into macros. FIXFRM?
  879. !&REMTAGS(); % Kludge
  880. RETURN CODELIST!&
  881. END;
  882. lisp procedure !&IReg N;
  883. if N > 0 and N <= 15 then
  884. GetV('[() (IREG 1) (IREG 2) (IREG 3) (IREG 4) (IREG 5)
  885. (IREG 6) (IREG 7) (IREG 8) (IREG 9) (IREG 10)
  886. (IREG 11) (IREG 12) (IREG 13) (IREG 14) (IREG 15)], n)
  887. else list('IREG, N);
  888. SYMBOLIC PROCEDURE !&WCONSTP X;
  889. PairP X and (first X = 'WConst or first X = 'Quote and FixP second X);
  890. %************************************************************
  891. % Pass 2 *
  892. %************************************************************
  893. % Initialize STATUS!&=0 (Top level)
  894. SYMBOLIC PROCEDURE !&PASS2 EXP; !&COMVAL(EXP,0);
  895. SYMBOLIC PROCEDURE !&COMVAL(EXP,STATUS!&);
  896. % Compile EXP. Special cases: if STATUS!&>1 (compiling for side effects),
  897. % anyreg functions are ignored since they have no side effects.
  898. % Otherwise, top level ANYREG stuff is factored out and done via a LOAD
  899. % instead of a LINK.
  900. IF !&ANYREG(EXP)
  901. THEN IF STATUS!&>1 THEN
  902. <<IF NOT (CAR EXP MEMBER '(QUOTE !$LOCAL !$FLUID)) THEN
  903. !&COMPWARN(LIST("Value of",
  904. EXP,
  905. "not used, therefore not compiled"));
  906. NIL >>
  907. ELSE !&LREG1(EXP) % Just a LOAD
  908. ELSE % When not all ANYREG
  909. IF !&ANYREGFNP EXP % Is the top level an ANYREG fn?
  910. THEN IF STATUS!&>1 THEN
  911. <<!&COMVAL(CADR EXP,STATUS!&);
  912. !&COMPWARN LIST("Top level", CAR EXP,
  913. "in", EXP, "not used, therefore not compiled");
  914. NIL>>
  915. ELSE
  916. !&LREG1(CAR EXP . !&COMLIS CDR EXP) % Preserve the anyreg fn
  917. ELSE !&COMVAL1(EXP,STOMAP!&,STATUS!&); % no anyregs in sight
  918. % Generate code which loads the value of EXP into register 1
  919. % Patch to COMVAL1 for better register allocation
  920. SYMBOLIC PROCEDURE !&COMVAL1(EXP,STOMAP!&,STATUS!&);
  921. BEGIN SCALAR X;
  922. IF !&ANYREG EXP OR !&OPENFNP EXP OR !&ANYREGFNP EXP THEN
  923. IF STATUS!&<2 AND !&NOSIDEEFFECTP EXP
  924. THEN !&COMPWARN(LIST(EXP," not compiled"))
  925. ELSE <<!&LOADOPENEXP(IF STATUS!& > 1 THEN !&AllocTemp(Exp)
  926. ELSE '(REG 1),
  927. CAR EXP . !&COMLIS CDR EXP,STATUS!&,PREGS!&)>>
  928. ELSE IF NOT ATOM CAR EXP % Non atomic function?
  929. THEN IF CAAR EXP EQ 'LAMBDA
  930. THEN !&COMPLY(CAR EXP,CDR EXP,STATUS!&) % LAMBDA compilation
  931. ELSE !&COMPERROR LIST(CAR EXP, "Invalid as function")
  932. % Should be noticed in pass 1
  933. ELSE IF X := GET(CAR EXP,'COMPFN) THEN APPLY(X,LIST(EXP,STATUS!&))
  934. % Dispatch built in compiler functions
  935. ELSE IF CAR EXP EQ 'LAMBDA
  936. THEN !&COMPERROR LIST("Invalid use of LAMBDA in COMVAL1",EXP)
  937. ELSE !&CALL(CAR EXP,CDR EXP,STATUS!&); % Call a function
  938. RETURN NIL
  939. END;
  940. % Procedure to allocate temps for OPEN exprs. Used only when STATUS!&<1 to
  941. % set up destination. Only special case is SETQ. SETQ tries to put the
  942. % value of X:=... into a register containing X (keeps variables in the same
  943. % register if possible.
  944. Symbolic Procedure !&Alloctemp(Exp);
  945. if car Exp = 'Setq then
  946. if car caddr exp = 'Setq then % Nested setq - move to actual RHS
  947. !&Alloctemp(caddr Exp)
  948. else
  949. begin
  950. Scalar Reg;
  951. If (Reg := !&RAssoc(Cadr Cadr Exp,Regs!&)) % LHS variable already in reg?
  952. and not (Car Reg member PRegs!&) then % and reg must be available
  953. Return Car Reg % Return the reg previously used for the var
  954. else
  955. Return !&Tempreg() % Just get a temp
  956. end
  957. else !&TempReg(); % not SETQ - any old temp will do
  958. SYMBOLIC PROCEDURE !&CALL(FN,ARGS,STATUS!&);
  959. !&CALL1(FN,!&COMLIS1 ARGS,STATUS!&);
  960. %Args have been compiled
  961. SYMBOLIC PROCEDURE !&CALL1(FN,ARGS,STATUS!&);
  962. %ARGS is reversed list of compiled arguments of FN;
  963. BEGIN INTEGER ARGNO;
  964. SCALAR DEST!&;
  965. ARGNO := LENGTH ARGS;
  966. IF !&ANYREGP FN THEN !&LREG1(FN . ARGS)
  967. ELSE <<!&LOADARGS(ARGS,1,PREGS!&); %Emits loads to registers
  968. !&ATTACH LIST('!*LINK,FN,!&CFNTYPE FN,ARGNO);
  969. !&REMMREFS();
  970. !&REMVREFS();
  971. % Default - all registers destroyed
  972. IF !*USINGDESTROY THEN DEST!& := GET(FN,'DESTROYS);
  973. IF NULL DEST!& THEN REGS!& := NIL
  974. ELSE
  975. BEGIN SCALAR TEMP;
  976. TEMP := NIL;
  977. FOR EACH R IN REGS!& DO
  978. IF NOT(CAR R MEMBER DEST!&) THEN TEMP := R . TEMP;
  979. REGS!& := TEMP
  980. END >>
  981. END;
  982. % Comlis altered to return unreversed list
  983. SYMBOLIC PROCEDURE !&COMLIS EXP; REVERSIP !&COMLIS1 EXP;
  984. % COMLIS1 returns reversed list of compiled arguments;
  985. SYMBOLIC PROCEDURE !&COMLIS1 EXP;
  986. BEGIN SCALAR ACUSED,Y; % Y gathers a set of ANYREG expressions denoting
  987. % the params. Code for non ANYREG stuff is emitted by ATTACH. ACUSED is
  988. % name of psuedo variable holding results of non anyreg stuff.
  989. Y := NIL;
  990. WHILE EXP DO
  991. <<IF !&CONSTP CAR EXP OR
  992. !&OPENP CAR EXP
  993. AND (NOT !*ORD OR !&NOSIDEEFFECTPL CDR EXP)
  994. THEN Y := CAR EXP . Y
  995. % Anyreg stuff is handled later. Anyreg args are not loaded until after
  996. % all others.
  997. % If !*ORD is true, order is still switched unless no side effects
  998. ELSE <<
  999. %/ Special coding for top level ANYREG
  1000. IF ACUSED THEN !&SAVER1();
  1001. IF (!&ANYREGFNP CAR EXP OR !&OPENFNP CAR EXP)
  1002. AND (NOT !*ORD OR !&NOSIDEEFFECTPL CDR EXP) THEN
  1003. <<Y := (CAAR EXP . !&COMLIS CDAR EXP) . Y;
  1004. ACUSED := T>>
  1005. % Emit code to place arg in R1, generate a name for the result to put in R1
  1006. ELSE <<!&COMVAL1(CAR EXP,STOMAP!&,1);
  1007. ACUSED := LIST('!$LOCAL,!&GENSYM());
  1008. REGS!& := !&ADDRVALS('(REG 1),REGS!&,LIST ACUSED);
  1009. % REGS!& the new variable name goes on the code list (rest already emitted)
  1010. Y := ACUSED . Y>>>>;
  1011. % place arg in memory while doing others
  1012. EXP := CDR EXP>>;
  1013. RETURN Y
  1014. END;
  1015. % SAVE R1 IF NECESSARY
  1016. SYMBOLIC PROCEDURE !&SAVER1; %MARKS CONTENTS OF REGISTER 1 FOR STORAGE;
  1017. BEGIN SCALAR X;
  1018. X := !&REGVAL '(REG 1); % Contents of R1
  1019. IF NULL X OR NOT !&VARP CAR X
  1020. THEN RETURN NIL % Dont save constants
  1021. ELSE IF NOT ASSOC(CAR X,STOMAP!&) THEN !&FRAME CAR X; % For temporaries
  1022. % as generated in COMLIS
  1023. !&STORELOCAL(CAR X,'(REG 1)) % Emit a store
  1024. END;
  1025. % Compiler for LAMBDA
  1026. SYMBOLIC PROCEDURE !&COMPLY(FN,ARGS,STATUS!&);
  1027. BEGIN SCALAR ALSTS!&,VARS, N, I;
  1028. %SCALAR OLDSTOMAP,OLDCODE;
  1029. % OLDSTOMAP := STOMAP!&;
  1030. % OLDCODE := CODELIST!&;
  1031. VARS := CADR FN;
  1032. % Compile args to the lambda
  1033. ARGS := !&COMLIS1 ARGS;
  1034. N := LENGTH ARGS;
  1035. IF N>MAXNARGS!& THEN
  1036. !&COMPERROR LIST("Too many arguments in LAMBDA form",FN);
  1037. % Put the args into registers
  1038. !&LOADARGS(ARGS,1,PREGS!&);
  1039. % Enter new ENVIRONMENT!&
  1040. ARGS := !&REMVARL VARS; % The stores that were protected;
  1041. I := 1;
  1042. % Put this junk on the frame
  1043. ALSTS!& := !&VARBIND(VARS,T); %Old fluid values saved;
  1044. % compile the body
  1045. !&COMVAL(CADDR FN,STATUS!&);
  1046. % Restore old fluids
  1047. !&FREERSTR(ALSTS!&,STATUS!&);
  1048. % Go back to the old ENVIRONMENT!&
  1049. !&RSTVARL(VARS,ARGS);
  1050. %/ !&FIXFRM(OLDSTOMAP,OLDCODE,0)
  1051. END;
  1052. % Load a sequence of expressions into the registers
  1053. SYMBOLIC PROCEDURE !&LOADARGS(ARGS,STATUS!&,PREGS!&);
  1054. BEGIN INTEGER N; SCALAR FN,DESTREG!&;
  1055. N := LENGTH ARGS;
  1056. IF N>MAXNARGS!& THEN
  1057. !&COMPERROR LIST("Too many arguments",ARGS);
  1058. WHILE ARGS DO
  1059. % Generate a load for each arg
  1060. <<DESTREG!& := !&MKREG N;
  1061. !&LOADOPENEXP(DESTREG!&,CAR ARGS,STATUS!&,PREGS!&);
  1062. PREGS!& := DESTREG!& . PREGS!&;
  1063. N := N - 1;
  1064. ARGS := CDR ARGS>>
  1065. END;
  1066. SYMBOLIC PROCEDURE !&LOADOPENEXP(DESTREG!&,ARG,STATUS!&,PREGS!&);
  1067. BEGIN SCALAR R;
  1068. IF !&ANYREG ARG OR !&RASSOC(ARG,REGS!&) THEN !&LREG(DESTREG!&,!&LOCATE ARG)
  1069. ELSE IF !&ANYREGFNP ARG THEN
  1070. <<!&LOADOPENEXP(DESTREG!&,CADR ARG,1,PREGS!&);
  1071. !&LREG(DESTREG!&,!&LOCATE (CAR ARG . DESTREG!& . CDDR ARG)) >>
  1072. ELSE % Must be an open function
  1073. IF FLAGP(CAR ARG,'MEMMOD) AND STATUS!& < 2 THEN
  1074. <<!&LOADOPENEXP(DESTREG!&,ARG,2,PREGS!&);
  1075. !&LREG(DESTREG!&,IF EQCAR(CADR ARG,'!$NAME) THEN
  1076. !&LOCATE CADR CADR ARG
  1077. ELSE !&LOCATE CADR ARG)>>
  1078. ELSE
  1079. BEGIN
  1080. SCALAR OPFN,ADJFN,ANYREGARGS;
  1081. ANYREGARGS := !&REMOPEN(DESTREG!&,CDR ARG);
  1082. OPFN := GET(CAR ARG,'OPENFN);
  1083. IF IDP OPFN THEN
  1084. APPLY(OPFN,LIST(DESTREG!&,ANYREGARGS,ARG))
  1085. ELSE
  1086. !&CALLOPEN(OPFN,DESTREG!&,ANYREGARGS,CAR ARG)
  1087. END;
  1088. END;
  1089. SYMBOLIC PROCEDURE !&REMOPEN(DESTREG!&,ARGS);
  1090. FOR EACH ARG IN ARGS COLLECT !&ARGLOC ARG;
  1091. SYMBOLIC PROCEDURE !&ARGLOC ARG;
  1092. BEGIN SCALAR LOC;
  1093. IF EQCAR(ARG,'!$NAME) THEN RETURN ARG;
  1094. IF !&CONSTP ARG THEN RETURN ARG;
  1095. IF EQCAR(ARG,'MEMORY) THEN RETURN !&MEMADDRESS ARG;
  1096. IF LOC := !&RASSOC(ARG,REGS!&) THEN
  1097. <<PREGS!& := CAR LOC . PREGS!&; RETURN CAR LOC>>;
  1098. IF !&ANYREG ARG THEN RETURN ARG;
  1099. IF !&ANYREGFNP ARG THEN RETURN (CAR ARG . !&ARGLOC CADR ARG . CDDR ARG);
  1100. IF NULL DESTREG!& OR DESTREG!& MEMBER PREGS!& THEN DESTREG!& := !&TEMPREG();
  1101. IF FLAGP(CAR ARG,'MEMMOD) THEN
  1102. <<!&LOADOPENEXP(DESTREG!&,ARG,2,PREGS!&);
  1103. RETURN CADR CADR ARG>>
  1104. ELSE !&LOADOPENEXP(DESTREG!&,ARG,1,PREGS!&);
  1105. PREGS!& := DESTREG!& . PREGS!&;
  1106. RETURN DESTREG!&
  1107. END;
  1108. SYMBOLIC PROCEDURE !&MEMADDRESS ARG;
  1109. BEGIN SCALAR TEMPDEST;
  1110. PREGS!& := DESTREG!& . PREGS!&;
  1111. TEMPDEST := !&TEMPREG();
  1112. PREGS!& := CDR PREGS!&;
  1113. ARG := CAR ARG . !&REMOPEN(TEMPDEST,CDR ARG);
  1114. IF NOT(CADDR ARG = '(WCONST 0) AND NOT !&ANYREGFNP CADR ARG
  1115. OR !&REGFP CADR ARG) THEN
  1116. <<!&LREG(TEMPDEST,!&LOCATE CADR ARG);
  1117. ARG := CAR ARG . TEMPDEST . CDDR ARG>>;
  1118. IF CADR ARG = TEMPDEST THEN PREGS!& := TEMPDEST . PREGS!&;
  1119. RETURN ARG;
  1120. END;
  1121. SYMBOLIC PROCEDURE !&CALLOPEN(OPFN,DEST!&,ARGS,OP);
  1122. BEGIN
  1123. SCALAR PATS,PARAMS,ADJFN,REGFN,ENVIRONMENT!&;
  1124. PATS := CAR OPFN;
  1125. IF IDP PATS THEN PATS := GET(PATS,'PATTERN);
  1126. PARAMS := OP . CDR OPFN;
  1127. ADJFN := CAR PATS;
  1128. REGFN := CADR PATS;
  1129. IF ADJFN THEN ARGS := APPLY(ADJFN,LIST ARGS);
  1130. PATS := CDDR PATS;
  1131. WHILE NOT NULL PATS AND NOT !&MATCHES(CAAR PATS,ARGS) DO
  1132. PATS := CDR PATS;
  1133. IF NULL PATS THEN
  1134. <<!&COMPERROR(LIST("Compiler bug - no pattern for",OP . ARGS));
  1135. RETURN NIL>>;
  1136. FOR EACH MAC IN CDAR PATS DO
  1137. !&EMITMAC(!&SUBARGS(MAC,ARGS,PARAMS));
  1138. IF REGFN THEN IF IDP REGFN THEN APPLY(REGFN,LIST(OP, ARGS))
  1139. ELSE !&EMITMAC(!&SUBARGS(REGFN,ARGS,PARAMS));
  1140. RETURN NIL;
  1141. END;
  1142. SYMBOLIC PROCEDURE !&MATCHES(PAT,SUBJ);
  1143. IF EQCAR(PAT,'QUOTE) THEN CADR PAT = SUBJ
  1144. ELSE IF NULL PAT THEN NULL SUBJ
  1145. ELSE IF EQCAR(PAT,'NOVAL) THEN STATUS!& > 1 AND !&MATCHES(CDR PAT,SUBJ)
  1146. ELSE IF ATOM PAT THEN APPLY(GET(PAT,'MATCHFN),LIST SUBJ)
  1147. ELSE PAIRP SUBJ AND !&MATCHES(CAR PAT,CAR SUBJ)
  1148. AND !&MATCHES(CDR PAT,CDR SUBJ);
  1149. SYMBOLIC PROCEDURE !&ANY U;T;
  1150. SYMBOLIC PROCEDURE !&DEST U;U = DEST!&;
  1151. % An anyreg which uses DEST!& at any level
  1152. SYMBOLIC PROCEDURE !&USESDEST U;
  1153. !&DEST U OR PAIRP U AND !&USESDESTL CDR U;
  1154. SYMBOLIC PROCEDURE !&USESDESTL U;
  1155. PAIRP U AND (!&DEST CAR U OR !&USESDEST CAR U OR !&USESDESTL CDR U);
  1156. SYMBOLIC PROCEDURE !&REGFP U;!&REGP U OR EQCAR(U,'!$LOCAL);
  1157. SYMBOLIC PROCEDURE !&REGN U; !&REGP U OR EQCAR(U,'!$LOCAL) OR U = '(QUOTE NIL);
  1158. SYMBOLIC PROCEDURE !&MEM U;
  1159. NOT(U = '(QUOTE NIL) OR EQCAR(U,'!$LOCAL))
  1160. AND (!&CONSTP U OR !&VARP U OR CAR U = 'MEMORY);
  1161. SYMBOLIC PROCEDURE !&NOTANYREG U;!&MEM U OR !&REGFP U;
  1162. SYMBOLIC PROCEDURE !&SUBARGS(MAC,ARGS,PARAMS);
  1163. FOR EACH ARG IN MAC COLLECT !&SUBARG(ARG,ARGS,PARAMS);
  1164. SYMBOLIC PROCEDURE !&SUBARG(ARG,ARGS,PARAMS);
  1165. BEGIN SCALAR ARGFN;
  1166. RETURN
  1167. IF EQCAR(ARG,'QUOTE) THEN CADR ARG
  1168. ELSE IF PAIRP ARG THEN !&SUBARGS(ARG,ARGS,PARAMS)
  1169. ELSE IF ARG = 'DEST THEN DEST!&
  1170. ELSE IF ARGFN := GET(ARG,'SUBSTFN) THEN
  1171. APPLY(ARGFN,LIST(ARG,ARGS,PARAMS))
  1172. ELSE !&COMPERROR(LIST("Compiler bug", ARG,"invalid in macro"))
  1173. END;
  1174. SYMBOLIC PROCEDURE !&ARG1(ARG,ARGS,PARAMS);
  1175. !&LOCATE CAR ARGS;
  1176. SYMBOLIC PROCEDURE !&ARG2(ARG,ARGS,PARAMS);
  1177. !&LOCATE CADR ARGS;
  1178. SYMBOLIC PROCEDURE !&ARG3(ARG,ARGS,PARAMS);
  1179. !&LOCATE CADDR ARGS;
  1180. SYMBOLIC PROCEDURE !&ARG4(ARG,ARGS,PARAMS);
  1181. !&LOCATE CADDDR ARGS;
  1182. SYMBOLIC PROCEDURE !&PARAM1(ARG,ARGS,PARAMS);
  1183. CAR PARAMS;
  1184. SYMBOLIC PROCEDURE !&PARAM2(ARG,ARGS,PARAMS);
  1185. CADR PARAMS;
  1186. SYMBOLIC PROCEDURE !&PARAM3(ARG,ARGS,PARAMS);
  1187. CADDR PARAMS;
  1188. SYMBOLIC PROCEDURE !&PARAM4(ARG,ARGS,PARAMS);
  1189. CADDDR PARAMS;
  1190. SYMBOLIC PROCEDURE !&GETTEMP(TNAME,ARGS,PARAMS);
  1191. BEGIN SCALAR TN;
  1192. RETURN IF TN := ASSOC(TNAME,ENVIRONMENT!&) THEN CDR TN
  1193. ELSE <<TN := !&TEMPREG();
  1194. ENVIRONMENT!& := (TNAME . TN) . ENVIRONMENT!&;
  1195. PREGS!& := TN . PREGS!&;
  1196. TN>>;
  1197. END;
  1198. SYMBOLIC PROCEDURE !&GETTEMPLBL(LNAME,ARGS,PARAMS);
  1199. BEGIN SCALAR LAB;
  1200. RETURN IF LAB := ASSOC(LNAME,ENVIRONMENT!&) THEN CDR LAB
  1201. ELSE <<LAB := !&GENLBL();
  1202. ENVIRONMENT!& := (LNAME . LAB) . ENVIRONMENT!&;
  1203. LAB>>
  1204. END;
  1205. SYMBOLIC PROCEDURE !&GENSYM(); % gensym local to compiler, reuses symbols
  1206. BEGIN SCALAR SYMB;
  1207. IF NULL CDR LOCALGENSYM!& THEN
  1208. RPLACD(LOCALGENSYM!&, LIST GENSYM());
  1209. SYMB := CAR LOCALGENSYM!&;
  1210. LOCALGENSYM!& := CDR LOCALGENSYM!&;
  1211. RETURN SYMB;
  1212. END;
  1213. SYMBOLIC PROCEDURE !&COMPERROR U;
  1214. << ERRORPRINTF("***** in %P: %L", NAME!&, U);
  1215. ERFG!* := T >>;
  1216. SYMBOLIC PROCEDURE !&COMPWARN U;
  1217. !*MSG AND ERRORPRINTF("*** in %P: %L", NAME!&, U);
  1218. SYMBOLIC PROCEDURE !&EMITMAC MAC;
  1219. BEGIN SCALAR EMITFN;
  1220. IF CAR MAC = '!*DO THEN APPLY(CADR MAC,CDDR MAC)
  1221. ELSE IF CAR MAC = '!*DESTROY THEN
  1222. FOR EACH REG IN CDR MAC DO REGS!& := DELASC(REG,REGS!&)
  1223. ELSE IF CAR MAC = '!*SET THEN
  1224. REGS!& := !&REPASC(CADR MAC,!&REMREGSL CADDR MAC,REGS!&)
  1225. ELSE
  1226. IF EMITFN := GET(CAR MAC,'EMITFN) THEN
  1227. APPLY(EMITFN,LIST MAC)
  1228. ELSE !&ATTACH MAC
  1229. END;
  1230. SYMBOLIC PROCEDURE !&EMITLOAD M;
  1231. !&LREG(CADR M,CADDR M);
  1232. SYMBOLIC PROCEDURE !&EMITSTORE M;
  1233. !&STOREVAR(CADDR M,CADR M);
  1234. SYMBOLIC PROCEDURE !&EMITJUMP M;
  1235. !&ATTJMP CADR M;
  1236. SYMBOLIC PROCEDURE !&EMITLBL M;
  1237. !&ATTLBL CADR M;
  1238. SYMBOLIC PROCEDURE !&EMITMEMMOD M;
  1239. BEGIN SCALAR Y, X;
  1240. X := CADR M;
  1241. !&REMREFS X;
  1242. IF EQCAR(X,'!$LOCAL) THEN
  1243. WHILE Y := ASSOC(X,SLST!&) DO SLST!& := DELETIP(Y,SLST!&);
  1244. IF EQCAR(X,'!$LOCAL) THEN M := CAR M . !&GETFRM X . CDDR M;
  1245. !&ATTACH(GET(CAR M, 'UNMEMMOD) . CDR M);
  1246. END;
  1247. % Support to patterns - register adjustment functions
  1248. SYMBOLIC PROCEDURE !&NOANYREG ARGS;
  1249. % remove all ANYREG stuff except top level MEMORY
  1250. IF NULL ARGS THEN NIL
  1251. ELSE
  1252. !&NOANYREG1 CAR ARGS . !&NOANYREG CDR ARGS;
  1253. SYMBOLIC PROCEDURE !&NOANYREG1 ARG;
  1254. IF !&ANYREGFNP ARG AND NOT EQCAR(ARG,'MEMORY) THEN
  1255. !&LOADTEMPREG ARG ELSE ARG;
  1256. SYMBOLIC PROCEDURE !&INREG ARGS;
  1257. IF NOT !&REGFP CAR ARGS THEN LIST !&LOADTEMPREG CAR ARGS ELSE ARGS;
  1258. SYMBOLIC PROCEDURE !&REGMEM ARGS;
  1259. <<ARGS := !&NOANYREG ARGS;
  1260. IF !&MEM CAR ARGS AND !&MEM CADR ARGS THEN
  1261. !&LOADTEMPREG CAR ARGS . CDR ARGS
  1262. ELSE ARGS>>;
  1263. SYMBOLIC PROCEDURE !&DESTMEM ARGS;
  1264. % A1 in DEST!&, A2 in MEM, rest (if any) not anyreg
  1265. <<ARGS := CAR ARGS . !&NOANYREG CDR ARGS;
  1266. IF STATUS!& > 1 THEN
  1267. IF !&REGFP CAR ARGS THEN ARGS
  1268. ELSE !&LOADTEMPREG CAR ARGS . CDR ARGS
  1269. ELSE IF !&DEST CADR ARGS OR !&USESDEST CADR ARGS THEN
  1270. !&DESTMEM(CAR ARGS . !&LOADTEMPREG CADR ARGS . CDDR ARGS)
  1271. ELSE IF CAR ARGS NEQ DEST!& THEN
  1272. <<!&LREG(DEST!&,!&LOCATE CAR ARGS);
  1273. DEST!& . CDR ARGS>>
  1274. ELSE ARGS>>;
  1275. SYMBOLIC PROCEDURE !&DESTMEMA ARGS;
  1276. % put either a1or A2 into DEST!&, the other to MEM.
  1277. IF CAR ARGS = DEST!& THEN % A1 = DEST!&, make A1 mem or reg
  1278. IF !&NOTANYREG CADR ARGS AND NOT !&USESDEST CADR ARGS THEN ARGS
  1279. ELSE !&LOADTEMP2 ARGS
  1280. ELSE IF CADR ARGS = DEST!& THEN % A2 = DEST!&, make A2 mem or reg
  1281. IF !&NOTANYREG CAR ARGS AND NOT !&USESDEST CAR ARGS THEN ARGS
  1282. ELSE !&LOADTEMP1 ARGS
  1283. ELSE IF !&NOTANYREG CADR ARGS OR NOT !&NOTANYREG CAR ARGS
  1284. THEN % A2 is MEM or A1 is anyreg: make A1 the destination
  1285. <<IF NOT !&NOTANYREG CADR ARGS OR !&USESDEST CADR ARGS THEN
  1286. ARGS := !&LOADTEMP2 ARGS;
  1287. !&LREG(DEST!&,!&LOCATE CAR ARGS);
  1288. DEST!& . CDR ARGS>>
  1289. ELSE % Make A2 the DEST!& - only when A2 is anyreg and a1 is mem
  1290. <<IF NOT !&NOTANYREG CAR ARGS OR !&USESDEST CAR ARGS THEN
  1291. ARGS := !&LOADTEMP1 ARGS;
  1292. !&LREG(DEST!&,!&LOCATE CADR ARGS);
  1293. LIST(CAR ARGS,DEST!&)>>;
  1294. SYMBOLIC PROCEDURE !&LOADTEMP1 U;
  1295. % Bring first arg into a temp
  1296. !&LOADTEMPREG CAR U . CDR U;
  1297. SYMBOLIC PROCEDURE !&LOADTEMP2 U;
  1298. % put second arg in a temp
  1299. CAR U . !&LOADTEMPREG CADR U . CDDR U;
  1300. SYMBOLIC PROCEDURE !&CONSARGS ARGS;
  1301. IF
  1302. NOT !&ANYREGFNP CADR ARGS AND CADR ARGS NEQ DEST!&
  1303. OR
  1304. NOT !&ANYREGFNP CAR ARGS AND CAR ARGS NEQ DEST!&
  1305. THEN ARGS
  1306. ELSE LIST(CAR ARGS,!&LOADTEMPREG CADR ARGS);
  1307. SYMBOLIC PROCEDURE !&LOADTEMPREG ARG;
  1308. % Load ARG into a temporary register. Return the register.
  1309. BEGIN
  1310. SCALAR TEMP;
  1311. TEMP := !&TEMPREG();
  1312. PREGS!& := TEMP . PREGS!&;
  1313. !&LREG(TEMP,!&LOCATE ARG);
  1314. RETURN TEMP
  1315. END;
  1316. SYMBOLIC PROCEDURE !&FIXREGTEST(OP,ARGS);
  1317. !&FIXREGTEST1(OP, first ARGS, second ARGS);
  1318. SYMBOLIC PROCEDURE !&FIXREGTEST1(OP, A1, A2);
  1319. % Fixes up the registers after a conditional jump has been emitted.
  1320. % For JUMPEQ and JUMPNE, equalities can be assumed in REGS!& or REGS1!&
  1321. % For other jumps, REGS!& copied onto REGS1!&.
  1322. <<REGS1!& := REGS!&;
  1323. IF OP = 'EQ OR OP = 'NE THEN
  1324. IF NOT !&REGP A1 THEN
  1325. << IF !&REGP A2 THEN !&FIXREGTEST1(OP,A2,A1) >>
  1326. ELSE
  1327. <<IF OP = 'EQ THEN REGS1!& := !&ADDRVALS(A1,REGS1!&,!&REMREGS A2)
  1328. ELSE REGS!& := !&ADDRVALS(A1,REGS!& ,!&REMREGS A2)>>>>;
  1329. SYMBOLIC PROCEDURE !&SETREGS1(OP, ARGS); REGS1!& := REGS!&;
  1330. % Find the location of a variable
  1331. SYMBOLIC PROCEDURE !&LOCATE X;
  1332. BEGIN SCALAR Y,VTYPE;
  1333. % Constants are their own location
  1334. IF ATOM X OR EQCAR(X,'LABEL) OR !&CONSTP X THEN RETURN X;
  1335. IF EQCAR(X,'!$NAME) THEN RETURN CADR X;
  1336. IF CAR X = 'MEMORY THEN
  1337. RETURN(CAR X . !&LOCATE CADR X . CDDR X);
  1338. IF Y := !&RASSOC(X,REGS!&) THEN RETURN CAR Y;
  1339. % If in a register, return the register number
  1340. % Registers are their own location
  1341. % For ANYREG stuff, locate each constant
  1342. IF !&ANYREGFNP X THEN
  1343. RETURN CAR X . !&LOCATEL CDR X;
  1344. IF NOT EQCAR(X,'!$LOCAL) THEN RETURN X;
  1345. % Since the value of the variable has been referenced, a previous store was
  1346. % justified, so it can be removed from SLST!&
  1347. % Must be in the frame, otherwise make nonlocal (really ought to be an error)
  1348. % Frame location (<=0) is returned
  1349. WHILE Y := ASSOC(X,SLST!&) DO SLST!& := DELETIP(Y,SLST!&);
  1350. IF Y := ASSOC(X,STOMAP!&) THEN RETURN CADR Y;
  1351. % Nasty compiler bug. Until we fix it, tell the user to simplify expressions
  1352. !&COMPERROR LIST
  1353. ("Compiler bug: expression too complicated, please simplify",X);
  1354. RETURN '(QUOTE 0); % just so it doesn't blow up
  1355. END;
  1356. SYMBOLIC PROCEDURE !&LOCATEL U;
  1357. FOR EACH X IN U COLLECT !&LOCATE X;
  1358. % Load register REG with value U. V (always NIL except when called from
  1359. % LOADARGS) is a list of other loads to be done
  1360. SYMBOLIC PROCEDURE !&LREG(REG,VAL);
  1361. BEGIN SCALAR ACTUALVAL;
  1362. ACTUALVAL := !&REMREGS VAL;
  1363. IF REG = VAL OR ACTUALVAL MEMBER !&REGVAL REG THEN RETURN NIL;
  1364. !&ATTACH LIST('!*MOVE,VAL,REG);
  1365. REGS!& := !&REPASC(REG,ACTUALVAL,REGS!&);
  1366. END;
  1367. % Load register 1 with X
  1368. SYMBOLIC PROCEDURE !&LREG1(X); !&LOADOPENEXP('(REG 1),X,1,PREGS!&);
  1369. SYMBOLIC PROCEDURE !&JUMPT LAB;
  1370. !&ATTACH LIST('!*JUMPNOTEQ,LAB,'(REG 1),'(QUOTE NIL));
  1371. SYMBOLIC PROCEDURE !&JUMPNIL LAB;
  1372. !&ATTACH LIST('!*JUMPEQ,LAB,'(REG 1),'(QUOTE NIL));
  1373. COMMENT Functions for Handling Non-local Variables;
  1374. SYMBOLIC PROCEDURE !&VARBIND(VARS,LAMBP);
  1375. %bind FLUID variables in lambda or prog lists;
  1376. %LAMBP is true for LAMBDA, false for PROG;
  1377. BEGIN SCALAR VLOCS,VNAMES,FREGS,Y,REG,TAIL; INTEGER I;
  1378. I := 1;
  1379. FOR EACH X IN VARS DO
  1380. <<
  1381. REG := !&MKREG I;
  1382. IF EQCAR(X,'!$GLOBAL) THEN % whoops
  1383. << !&COMPWARN LIST("Illegal to bind global",
  1384. CADR X, "but binding anyway");
  1385. RPLACA(X,'!$FLUID) >>; % cheat a little
  1386. IF EQCAR(X,'!$FLUID)
  1387. THEN <<FREEBOUND!& := T;
  1388. VNAMES := X . VNAMES;
  1389. IF NOT !*NOFRAMEFLUID THEN VLOCS := !&FRAME X . VLOCS;
  1390. FREGS := REG . FREGS>>
  1391. ELSE IF EQCAR(X,'!$LOCAL)
  1392. THEN <<!&FRAME X;
  1393. !&STORELOCAL(X,IF LAMBP THEN REG ELSE NIL)>>
  1394. ELSE !&COMPERROR LIST("Cannot bind non-local variable",X);
  1395. IF LAMBP THEN
  1396. IF EQCAR(X,'!$LOCAL) THEN
  1397. REGS!& := !&REPASC(REG,LIST X,REGS!&)
  1398. ELSE REGS!& := !&REPASC(REG,NIL,REGS!&);
  1399. I := I + 1>>;
  1400. IF NULL VNAMES THEN RETURN NIL;
  1401. VNAMES := 'NONLOCALVARS . VNAMES;
  1402. FREGS := 'REGISTERS . FREGS;
  1403. VLOCS := 'FRAMES . VLOCS;
  1404. TAIL := IF !*NOFRAMEFLUID THEN LIST VNAMES
  1405. ELSE LIST(VNAMES,VLOCS);
  1406. IF LAMBP THEN !&ATTACH('!*LAMBIND . FREGS . TAIL)
  1407. ELSE !&ATTACH('!*PROGBIND . TAIL);
  1408. IF !*UNSAFEBINDER THEN REGS!& := NIL;
  1409. RETURN TAIL;
  1410. END;
  1411. SYMBOLIC PROCEDURE !&FREERSTR(ALSTS!&,STATUS!&); %restores FLUID variables;
  1412. IF ALSTS!& THEN
  1413. << !&ATTACH('!*FREERSTR . ALSTS!&);
  1414. IF !*UNSAFEBINDER THEN REGS!& := NIL >>;
  1415. % ATTACH is used to emit code
  1416. SYMBOLIC PROCEDURE !&ATTACH U; CODELIST!& := U . CODELIST!&;
  1417. SYMBOLIC PROCEDURE !&STORELOCAL(U,REG);
  1418. %marks expression U in register REG for storage;
  1419. BEGIN SCALAR X;
  1420. IF NULL REG THEN REG := '(QUOTE NIL);
  1421. X := LIST('!*MOVE,REG,!&GETFRM U);
  1422. % Update list of stores done so far
  1423. !&ATTACH X;
  1424. % Zap out earlier stores if there were never picked up
  1425. % ie, if you store to X, then a ref to X will remove this store from
  1426. % SLST!&. Otherwise, the previous store will be removed by CLRSTR
  1427. % SLST!& is for variables only (anything else?)
  1428. !&CLRSTR U;
  1429. SLST!& := (U . CODELIST!&) . SLST!&;
  1430. END;
  1431. SYMBOLIC PROCEDURE !&CLRSTR VAR; %removes unneeded stores;
  1432. BEGIN SCALAR X;
  1433. % Inside conditionals, you cant tell if store was on the same path
  1434. IF CONDTAIL!& THEN RETURN NIL;
  1435. X := ASSOC(VAR,SLST!&);
  1436. IF NULL X THEN RETURN NIL;
  1437. SLST!& := DelQIP(X,SLST!&);
  1438. !&DELMAC CDR X;
  1439. END;
  1440. COMMENT Functions for general tests;
  1441. SYMBOLIC PROCEDURE !&COMTST(EXP,LABL);
  1442. %compiles boolean expression EXP.
  1443. %If EXP has the same value as SWITCH!& then branch to LABL,
  1444. %otherwise fall through;
  1445. %REGS are active registers for fall through,
  1446. %REGS1 for branch;
  1447. BEGIN SCALAR X,FN,REG;
  1448. % First factor out NOT's to set up the SWITCH!&
  1449. WHILE EQCAR(EXP,'EQ) AND CADDR EXP = '(QUOTE NIL) DO
  1450. <<SWITCH!& := NOT SWITCH!&; EXP := CADR EXP>>;
  1451. % Dispatch a built in compiling function
  1452. IF NOT SWITCH!& AND (FN := GET(CAR EXP,'FLIPTST)) THEN
  1453. EXP := FN . CDR EXP; % SWITCH!& is assumed to be true by fn's with
  1454. % a flip test
  1455. IF FN := GET(CAR EXP,'OPENTST)
  1456. THEN <<IF ATOM FN THEN APPLY(FN,LIST(EXP,LABL))
  1457. ELSE !&COMOPENTST(FN,EXP,LABL,PREGS!&)>>
  1458. % Trivial case of condition is T. FLAGG!& indicates jump cannot take place
  1459. ELSE <<IF EQCAR(EXP,'QUOTE) THEN
  1460. IF SWITCH!& AND CADR EXP
  1461. OR (NOT SWITCH!&) AND (NOT CADR EXP) THEN
  1462. <<REGS1!& := REGS!&;
  1463. !&ATTJMP LABL>>
  1464. ELSE FLAGG!& := T
  1465. ELSE <<!&COMTST(LIST('NE,EXP,'(QUOTE NIL)),LABL)>>>>
  1466. END;
  1467. SYMBOLIC PROCEDURE !&COMOPENTST(PAT,EXP,DESTLAB,PREGS!&);
  1468. BEGIN
  1469. SCALAR ANYREGARGS,ADJFN;
  1470. ANYREGARGS := !&REMOPEN(!&TEMPREG(),!&COMLIS CDR EXP);
  1471. !&CALLOPEN(PAT,DESTLAB,ANYREGARGS,CAR EXP)
  1472. END;
  1473. % Remove variables to avoid name conflicts: Hide variable names which match
  1474. % new names when entering an inner function. Other names will be available
  1475. % as global info. VARS is the list of new variable names, the result is a
  1476. % list of protected stores.
  1477. SYMBOLIC PROCEDURE !&REMVARL VARS;
  1478. FOR EACH X IN VARS COLLECT !&PROTECT X;
  1479. % Delete all references to U from SLST!&
  1480. % return the protected store
  1481. SYMBOLIC PROCEDURE !&PROTECT U;
  1482. BEGIN SCALAR X;
  1483. IF X := ASSOC(U,SLST!&) THEN SLST!& := DelQIP(X,SLST!&);
  1484. RETURN X
  1485. END;
  1486. % Restore a previous ENVIRONMENT!&. VARS is the list of variables taken out
  1487. % of the ENVIRONMENT!&; LST is the list of protected stores. One or zero
  1488. % stores for each variable.
  1489. SYMBOLIC PROCEDURE !&RSTVARL(VARS,LST);
  1490. WHILE VARS DO
  1491. <<!&RSTVAR(CAR VARS,CAR LST); VARS := CDR VARS; LST := CDR LST>>;
  1492. % Restore a particular variable and STORE
  1493. SYMBOLIC PROCEDURE !&RSTVAR(VAR,VAL);
  1494. BEGIN
  1495. !&REMREFS VAR;
  1496. !&CLRSTR VAR;
  1497. % Put back on store list if not NIL
  1498. !&UNPROTECT VAL
  1499. END;
  1500. SYMBOLIC PROCEDURE !&UNPROTECT VAL; %restores VAL to SLST!&;
  1501. IF VAL THEN SLST!& := VAL . SLST!&;
  1502. SYMBOLIC PROCEDURE !&STOREVAR(U,V);
  1503. % The store generated by a SETQ
  1504. BEGIN SCALAR VTYPE,X;
  1505. !&REMREFS U;
  1506. IF CAR U = '!$LOCAL THEN
  1507. !&STORELOCAL(U,V)
  1508. ELSE
  1509. !&ATTACH LIST('!*MOVE,V,U);
  1510. IF !&REGP V THEN
  1511. REGS!& := !&ADDRVALS(V,REGS!&,LIST U)
  1512. END;
  1513. COMMENT Support Functions;
  1514. SYMBOLIC PROCEDURE !&REFERENCES(EXP,VAR);
  1515. % True if expression EXP (probably ANYREG) references VAR.
  1516. EXP = VAR OR
  1517. IF ATOM EXP OR FLAGP(CAR EXP,'TERMINAL) THEN NIL
  1518. ELSE !&REFERENCESL(CDR EXP,VAR);
  1519. SYMBOLIC PROCEDURE !&REFERENCESL(EXP,VAR);
  1520. IF NULL EXP THEN NIL ELSE !&REFERENCES(CAR EXP,VAR)
  1521. OR !&REFERENCESL(CDR EXP,VAR);
  1522. SYMBOLIC PROCEDURE !&CFNTYPE FN;
  1523. BEGIN SCALAR X;
  1524. RETURN IF X := GET(FN,'CFNTYPE) THEN CAR X
  1525. ELSE IF X := GETD FN THEN CAR X
  1526. ELSE 'EXPR
  1527. END;
  1528. SYMBOLIC PROCEDURE !&GENLBL;
  1529. BEGIN SCALAR L;
  1530. L := LIST('LABEL,!&GENSYM());
  1531. LBLIST!& := LIST L . LBLIST!&;
  1532. RETURN L
  1533. END;
  1534. SYMBOLIC PROCEDURE !&GETLBL LABL;
  1535. BEGIN SCALAR X;
  1536. X := ASSOC(LABL,GOLIST!&);
  1537. IF NULL X THEN !&COMPERROR LIST("Compiler bug: missing label", LABL);
  1538. RETURN CDR X
  1539. END;
  1540. SYMBOLIC PROCEDURE !&ATTLBL LBL;
  1541. IF CAAR CODELIST!& EQ '!*LBL THEN !&DEFEQLBL(LBL,CADR CAR CODELIST!&)
  1542. ELSE !&ATTACH LIST('!*LBL,LBL);
  1543. SYMBOLIC PROCEDURE !&ATTJMP LBL;
  1544. BEGIN
  1545. IF CAAR CODELIST!& EQ '!*LBL
  1546. THEN <<!&DEFEQLBL(LBL,CADR CAR CODELIST!&);
  1547. !&DELMAC CODELIST!&>>;
  1548. IF !&TRANSFERP CODELIST!& THEN RETURN NIL;
  1549. !&ATTACH LIST('!*JUMP,LBL);
  1550. END;
  1551. SYMBOLIC PROCEDURE !&TRANSFERP X;
  1552. IF CAAR X = '!*NOOP THEN !&TRANSFERP CDR X ELSE
  1553. FLAGP(IF CAAR X EQ '!*LINK THEN CADAR X ELSE CAAR X,'TRANSFER);
  1554. SYMBOLIC PROCEDURE !&DEFEQLBL(LAB1,LAB2);
  1555. LBLIST!& := !&DEFEQLBL1(LBLIST!&,LAB1,LAB2);
  1556. SYMBOLIC PROCEDURE !&DEFEQLBL1(LABS,LAB1,LAB2);
  1557. IF LAB1 MEMBER CAR LABS THEN
  1558. IF LAB2 MEMBER CAR LABS THEN LABS
  1559. ELSE APPEND(!&LABCLASS LAB2,CAR LABS) . !&DELCLASS(LAB2,CDR LABS)
  1560. ELSE IF LAB2 MEMBER CAR LABS THEN
  1561. APPEND(!&LABCLASS LAB1,CAR LABS) . !&DELCLASS(LAB1,CDR LABS)
  1562. ELSE CAR LABS . !&DEFEQLBL1(CDR LABS,LAB1,LAB2);
  1563. SYMBOLIC PROCEDURE !&LABCLASS(LAB);
  1564. BEGIN SCALAR TEMP;
  1565. TEMP := LBLIST!&;
  1566. WHILE TEMP AND NOT (LAB MEMBER CAR TEMP) DO TEMP := CDR TEMP;
  1567. RETURN IF TEMP THEN CAR TEMP ELSE NIL;
  1568. END;
  1569. SYMBOLIC PROCEDURE !&DELCLASS(LAB,LABS);
  1570. IF LAB MEMBER CAR LABS THEN CDR LABS ELSE CAR LABS . !&DELCLASS(LAB,CDR LABS);
  1571. SYMBOLIC PROCEDURE !&LBLEQ(LAB1,LAB2);
  1572. LAB1 MEMBER !&LABCLASS LAB2;
  1573. SYMBOLIC PROCEDURE !&FRAME U; %allocates space for U in frame;
  1574. BEGIN SCALAR Z,RES;
  1575. Z := IF NULL STOMAP!& THEN 1 ELSE 1 + CADR CADAR STOMAP!&;
  1576. RES := !&MKFRAME Z;
  1577. STOMAP!& := LIST(U,RES) . STOMAP!&;
  1578. LLNGTH!& := MAX(Z,LLNGTH!&);
  1579. RETURN RES
  1580. END;
  1581. % GETFRM returns the frame location on a variable
  1582. SYMBOLIC PROCEDURE !&GETFRM U;
  1583. BEGIN SCALAR X;
  1584. IF X:=ASSOC(U,STOMAP!&) THEN RETURN CADR X;
  1585. !&COMPERROR LIST("Compiler bug: lost variable",U)
  1586. END;
  1587. %*************************************************************************
  1588. % The following functions determine classes or properties of expressions *
  1589. %*************************************************************************
  1590. SYMBOLIC PROCEDURE !&ANYREG U;
  1591. % !&ANYREG determines if U is an ANYREG expression
  1592. %
  1593. % ANYREG expressions are those expressions which may be loaded into any
  1594. % register without the use of (visable) temporary registers. It is assumed
  1595. % that ANYREG expressions have no side effects.
  1596. %
  1597. % ANYREG expressions are defined as constants, variables, and ANYREG functions
  1598. % whose arguments are ANYREG expressions. Note that ANYREG functions are
  1599. % not necessarily a part of ANYREG expressions; their arguments may not be
  1600. % ANYREG expressions.
  1601. !&CONSTP U OR !&VARP U OR !&ANYREGFNP U AND !&ANYREGL CDR U;
  1602. SYMBOLIC PROCEDURE !&ANYREGL U;
  1603. NULL U OR !&ANYREG(CAR U) AND !&ANYREGL CDR U;
  1604. SYMBOLIC PROCEDURE !&ANYREGFNP U;
  1605. % !&ANYREGFNP is true when U is an ANYREG function. The arguments are not
  1606. % checked
  1607. !&ANYREGP CAR U;
  1608. SYMBOLIC PROCEDURE !&OPENP U;
  1609. !&CONSTP U OR !&VARP U OR (!&ANYREGFNP U OR !&OPENFNP U) AND !&OPENPL CDR U;
  1610. SYMBOLIC PROCEDURE !&OPENPL U;
  1611. NULL U OR !&OPENP CAR U AND !&OPENPL CDR U;
  1612. SYMBOLIC PROCEDURE !&OPENFNP U;
  1613. GET(CAR U,'OPENFN);
  1614. SYMBOLIC PROCEDURE !&CONSTP U;
  1615. % True if U is a constant expression
  1616. IDP CAR U AND FLAGP(CAR U,'CONST);
  1617. SYMBOLIC PROCEDURE !&VARP U;
  1618. % True if U is a variable: (LOCAL x),(FLUID x), ...
  1619. PAIRP U AND FLAGP(CAR U,'VAR);
  1620. SYMBOLIC PROCEDURE !&REGP U;
  1621. PAIRP U AND FLAGP(CAR U,'REG);
  1622. SYMBOLIC PROCEDURE !&NOSIDEEFFECTP U;
  1623. % True if the expression U has no side effects. ANYREG expressions and
  1624. % functions are assumed to have no side effects; other functions must be
  1625. % flagged NOSIDEEFFECT. All arguments to a function must also be NOSIDEEFFECT.
  1626. !&ANYREG U OR
  1627. (!&ANYREGFNP U OR FLAGP(CAR U,'NOSIDEEFFECT)) AND !&NOSIDEEFFECTPL CDR U;
  1628. SYMBOLIC PROCEDURE !&NOSIDEEFFECTPL U;
  1629. NULL U OR !&NOSIDEEFFECTP CAR U AND !&NOSIDEEFFECTPL CDR U;
  1630. %**********************************************************************
  1631. % Basic register manipulation utilities
  1632. %**********************************************************************
  1633. SYMBOLIC PROCEDURE !&RVAL(R,RGS);
  1634. % Return the set of values in register R as determined by register list RGS
  1635. IF NULL RGS THEN NIL
  1636. ELSE IF CAAR RGS = R THEN CDAR RGS
  1637. ELSE !&RVAL(R,CDR RGS);
  1638. SYMBOLIC PROCEDURE !&REGVAL R;
  1639. % Normally, register contents are found in register list REGS!&.
  1640. !&RVAL(R,REGS!&);
  1641. SYMBOLIC PROCEDURE !&ADDRVALS(REG,RGS,VALS);
  1642. % Add the values VALS to the contents of REG in register list RGS
  1643. IF NULL RGS THEN LIST (REG . VALS)
  1644. ELSE IF CAAR RGS = REG THEN (CAAR RGS . APPEND(VALS,CDAR RGS)) . CDR RGS
  1645. ELSE CAR RGS . !&ADDRVALS(REG,CDR RGS,VALS);
  1646. SYMBOLIC PROCEDURE !&MKREG NUM;
  1647. % Used to generate a tagged register from a register number
  1648. BEGIN SCALAR AENTRY;
  1649. RETURN
  1650. IF AENTRY := ASSOC(NUM, '((1 . (REG 1)) (2 . (REG 2)) (3 . (REG 3))
  1651. (4 . (REG 4)) (5 . (REG 5)) (6 . (REG 6))
  1652. (7 . (REG 7)) (8 . (REG 8)) (9 . (REG 9)))) THEN
  1653. CDR AENTRY
  1654. ELSE LIST('REG,NUM);
  1655. END;
  1656. SYMBOLIC PROCEDURE !&MKFRAME NUM;
  1657. % Used to generate a tagged register from a register number
  1658. BEGIN SCALAR AENTRY;
  1659. RETURN
  1660. IF AENTRY := ASSOC(NUM, '((1 . (FRAME 1)) (2 . (FRAME 2)) (3 . (FRAME 3))
  1661. (4 . (FRAME 4)) (5 . (FRAME 5)) (6 . (FRAME 6))
  1662. (7 . (FRAME 7)) (8 . (FRAME 8)) (9 . (FRAME 9))))
  1663. THEN CDR AENTRY
  1664. ELSE LIST('FRAME,NUM);
  1665. END;
  1666. SYMBOLIC PROCEDURE !&RASSOC(VAL,RGS);
  1667. % Find a register in register list RGS which contains VAL. NIL is returned if
  1668. % VAL is not present in RGS
  1669. IF NULL RGS THEN NIL
  1670. ELSE IF VAL MEMBER CDAR RGS THEN CAR RGS
  1671. ELSE !&RASSOC(VAL,CDR RGS);
  1672. SYMBOLIC PROCEDURE !&REPASC(REG,VAL,REGL);
  1673. % Replace the contants of REG in list REGL by the value VAL
  1674. IF NULL REGL THEN LIST (REG . VAL)
  1675. ELSE IF REG=CAAR REGL THEN (REG . VAL) . CDR REGL
  1676. ELSE CAR REGL . !&REPASC(REG,VAL,CDR REGL);
  1677. SYMBOLIC PROCEDURE !&RMERGE U;
  1678. % RMERGE takes a list of register contents representing the information
  1679. % present in the registers from a number of different ways to reach the same
  1680. % place. RMERGE returns whatever information is known to be in the registers
  1681. % regardless of which path was taken.
  1682. IF NULL U THEN NIL ELSE
  1683. BEGIN
  1684. SCALAR RES,CONTENTS;
  1685. RES := NIL;
  1686. FOR EACH RG IN CAR U DO
  1687. <<CONTENTS := NIL;
  1688. FOR EACH THING IN CDR RG DO
  1689. IF !&INALL(THING,CAR RG,CDR U) THEN
  1690. CONTENTS := THING . CONTENTS;
  1691. IF CONTENTS THEN RES := (CAR RG . CONTENTS) . RES>>;
  1692. RETURN RES;
  1693. END;
  1694. SYMBOLIC PROCEDURE !&INALL(THING,RG,LST);
  1695. NULL LST OR (THING MEMBER !&RVAL(RG,CAR LST)) AND !&INALL(THING,RG,CDR LST);
  1696. SYMBOLIC PROCEDURE !&TEMPREG();
  1697. BEGIN SCALAR I,R,EMPTY,UNPROT;
  1698. EMPTY := UNPROT := NIL;
  1699. I := 1;
  1700. WHILE I <= MAXNARGS!& AND NOT EMPTY DO
  1701. <<R := !&MKREG I;
  1702. IF NOT(R MEMBER PREGS!&) THEN
  1703. IF I <= LASTACTUALREG!& AND NULL !&REGVAL R THEN EMPTY := R
  1704. ELSE IF NOT UNPROT THEN UNPROT := R;
  1705. I := I + 1
  1706. >>;
  1707. IF EMPTY THEN RETURN EMPTY;
  1708. IF UNPROT THEN RETURN UNPROT;
  1709. !&COMPERROR("Compiler bug: Not enough registers");
  1710. RETURN '(REG ERROR);
  1711. END;
  1712. SYMBOLIC PROCEDURE !&REMREGS U;
  1713. IF !&REGP U THEN !&REGVAL U
  1714. ELSE IF EQCAR(U,'FRAME) THEN LIST !&GETFVAR (U,STOMAP!&)
  1715. ELSE IF !&CONSTP U OR !&VARP U THEN LIST U
  1716. ELSE !&REMREGSL U;
  1717. SYMBOLIC PROCEDURE !&GETFVAR (V,SMAP);
  1718. IF NULL SMAP THEN !&COMPERROR(LIST("Compiler bug:", V,"evaporated?"))
  1719. ELSE IF CADAR SMAP = V THEN CAAR SMAP
  1720. ELSE !&GETFVAR (V,CDR SMAP);
  1721. SYMBOLIC PROCEDURE !&REMREGSL U;
  1722. FOR EACH ARG IN !&ALLARGS CDR U COLLECT (CAR U . ARG);
  1723. SYMBOLIC PROCEDURE !&ALLARGS ARGLST;
  1724. if null Arglst then NIL
  1725. else IF NULL CDR ARGLST THEN
  1726. FOR EACH VAL IN !&REMREGS CAR ARGLST COLLECT LIST VAL
  1727. ELSE !&ALLARGS1(!&REMREGS CAR ARGLST,!&ALLARGS CDR ARGLST);
  1728. SYMBOLIC PROCEDURE !&ALLARGS1(FIRSTARGS,RESTARGS);
  1729. BEGIN SCALAR RES;
  1730. RES := NIL;
  1731. FOR EACH A1 IN FIRSTARGS DO
  1732. FOR EACH A2 IN RESTARGS DO
  1733. RES := (A1 . A2) . RES;
  1734. RETURN RES;
  1735. END;
  1736. SYMBOLIC PROCEDURE !&REMMREFS();
  1737. REGS!& := FOR EACH R IN REGS!& COLLECT (CAR R . !&REMMREFS1 CDR R);
  1738. SYMBOLIC PROCEDURE !&REMMREFS1 L;
  1739. IF NULL L THEN L ELSE
  1740. IF !&REFMEMORY CAR L THEN !&REMMREFS1 CDR L
  1741. ELSE CAR L . !&REMMREFS1 CDR L;
  1742. SYMBOLIC PROCEDURE !&REFMEMORY EXP;
  1743. IF ATOM EXP OR FLAGP(CAR EXP,'TERMINAL) THEN NIL
  1744. ELSE CAR EXP MEMBER '(MEMORY CAR CDR) OR !&REFMEMORYL CDR EXP;
  1745. SYMBOLIC PROCEDURE !&REFMEMORYL L;
  1746. IF NULL L THEN NIL ELSE !&REFMEMORY CAR L OR !&REFMEMORYL CDR L;
  1747. SYMBOLIC PROCEDURE !&REMVREFS;
  1748. BEGIN SCALAR S;
  1749. REGS!& := FOR EACH R IN REGS!& COLLECT (CAR R . !&REMVREFS1 CDR R);
  1750. % Slow version:
  1751. % SLST!& := FOR EACH S IN SLST!& CONC
  1752. % IF !&EXTERNALVARP CAR S THEN NIL ELSE LIST S;
  1753. % Faster version:
  1754. while not null Slst!& and !&ExternalVarP car car Slst!& do
  1755. Slst!& := cdr Slst!&;
  1756. S := Slst!&;
  1757. while not null S and not null cdr S do
  1758. << if !&ExternalVarP car car cdr S then Rplacd(S, cddr S);
  1759. S := cdr S >>;
  1760. END;
  1761. SYMBOLIC PROCEDURE !&REMVREFS1 L;
  1762. FOR EACH THING IN L CONC
  1763. IF !&REFEXTERNAL THING THEN NIL ELSE LIST THING;
  1764. SYMBOLIC PROCEDURE !&REFEXTERNAL EXP;
  1765. IF ATOM EXP THEN NIL
  1766. ELSE IF !&EXTERNALVARP EXP THEN T
  1767. ELSE IF FLAGP(CAR EXP,'TERMINAL) THEN NIL
  1768. ELSE !&REFEXTERNALL CDR EXP;
  1769. SYMBOLIC PROCEDURE !&REFEXTERNALL EXPS;
  1770. IF NULL EXPS THEN NIL
  1771. ELSE !&EXTERNALVARP CAR EXPS OR !&REFEXTERNALL CDR EXPS;
  1772. SYMBOLIC PROCEDURE !&EXTERNALVARP U;
  1773. PAIRP U AND FLAGP(CAR U,'EXTVAR);
  1774. SYMBOLIC PROCEDURE !&REMREFS V;
  1775. % Remove all references to V from REGS!&
  1776. IF CAR V MEMBER '(MEMORY CAR CDR) THEN
  1777. !&REMMREFS()
  1778. ELSE
  1779. REGS!& := FOR EACH R IN REGS!& COLLECT
  1780. CAR R . !&REMREFS1(V,CDR R);
  1781. SYMBOLIC PROCEDURE !&REMREFS1(X,LST);
  1782. % Remove all expressions from LST which reference X
  1783. IF NULL LST THEN NIL
  1784. ELSE IF !&REFERENCES(CAR LST,X) THEN !&REMREFS1(X,CDR LST)
  1785. ELSE CAR LST . !&REMREFS1(X,CDR LST);
  1786. %************************************************************
  1787. % Test functions
  1788. %************************************************************
  1789. SYMBOLIC PROCEDURE !&TSTANDOR(EXP,LABL);
  1790. BEGIN SCALAR FLG,FLG1,FN,LAB2,REGSL,REGS1L,
  1791. TAILP;
  1792. %FLG is initial SWITCH!& condition;
  1793. %FN is appropriate AND/OR case;
  1794. %FLG1 determines appropriate switching state;
  1795. FLG := SWITCH!&;
  1796. SWITCH!& := NIL;
  1797. FN := CAR EXP EQ 'AND;
  1798. FLG1 := FLG EQ FN;
  1799. EXP := CDR EXP;
  1800. LAB2 := !&GENLBL();
  1801. WHILE EXP DO
  1802. <<SWITCH!& := NIL;
  1803. IF NULL CDR EXP AND FLG1
  1804. THEN <<IF FN THEN SWITCH!& := T;
  1805. !&COMTST(CAR EXP,LABL);
  1806. REGSL := REGS!& . REGSL;
  1807. REGS1L := REGS1!& . REGS1L>>
  1808. ELSE <<IF NOT FN THEN SWITCH!& := T;
  1809. IF FLG1
  1810. THEN <<!&COMTST(CAR EXP,LAB2);
  1811. REGSL := REGS1!& . REGSL;
  1812. REGS1L := REGS!& . REGS1L>>
  1813. ELSE <<!&COMTST(CAR EXP,LABL);
  1814. REGSL := REGS!& . REGSL;
  1815. REGS1L := REGS1!& . REGS1L>>>>;
  1816. IF NULL TAILP
  1817. THEN <<CONDTAIL!& := NIL . CONDTAIL!&; TAILP := T>>;
  1818. EXP := CDR EXP>>;
  1819. !&ATTLBL LAB2;
  1820. REGS!& := IF NOT FLG1 THEN CAR REGSL ELSE !&RMERGE REGSL;
  1821. REGS1!& := IF FLG1 THEN CAR REGS1L ELSE !&RMERGE REGS1L;
  1822. IF TAILP THEN CONDTAIL!& := CDR CONDTAIL!&;
  1823. SWITCH!& := FLG
  1824. END;
  1825. %************************************************************
  1826. % Pass2 compile functions
  1827. %************************************************************
  1828. SYMBOLIC PROCEDURE !&COMANDOR(EXP,STATUS!&);
  1829. BEGIN SCALAR FN,LABL,REGSL;
  1830. FN := CAR EXP EQ 'AND;
  1831. LABL := !&GENLBL();
  1832. EXP := CDR EXP;
  1833. WHILE EXP DO
  1834. <<!&COMVAL(CAR EXP,IF CDR EXP THEN 1 ELSE STATUS!&);
  1835. %to allow for recursion on last entry;
  1836. REGSL := REGS!& . REGSL;
  1837. IF CDR EXP THEN IF FN THEN !&JUMPNIL LABL ELSE !&JUMPT LABL;
  1838. EXP := CDR EXP>>;
  1839. REGS!& := !&RMERGE REGSL;
  1840. !&ATTLBL LABL
  1841. END;
  1842. SYMBOLIC PROCEDURE !&COMAPPLY(EXP,STATUS); % Look for LIST;
  1843. BEGIN SCALAR FN,ARGS, N,NN;
  1844. EXP := CDR EXP;
  1845. FN := CAR EXP;
  1846. ARGS := CDR EXP;
  1847. IF NULL ARGS
  1848. OR CDR ARGS
  1849. OR NOT (PAIRP CAR ARGS
  1850. AND CAAR ARGS MEMBER
  1851. '(LIST QUOTE NCONS LIST1 LIST2 LIST3 LIST4 LIST5))
  1852. OR LENGTH CDAR ARGS>MAXNARGS!&
  1853. THEN RETURN !&CALL('APPLY,EXP,STATUS);
  1854. ARGS := IF EQCAR(CAR ARGS,'QUOTE) THEN
  1855. FOR EACH THING IN CADAR ARGS COLLECT LIST('QUOTE,THING)
  1856. ELSE CDAR ARGS;
  1857. NN := LENGTH ARGS;
  1858. ARGS := REVERSIP (FN . REVERSE ARGS);
  1859. !&LOADARGS(REVERSIP !&COMLIS ARGS,1,PREGS!&);
  1860. !&ATTACH LIST('!*MOVE, !&MKREG(NN + 1), '(REG T1));
  1861. !&ATTACH LIST('!*LINK,'FASTAPPLY,'EXPR, NN);
  1862. REGS!& := NIL;
  1863. !&REMVREFS();
  1864. END;
  1865. %Bug fix to COMCOND - tail has (QUOTE T) not T. Test for tail screwed up anyway
  1866. SYMBOLIC PROCEDURE !&COMCOND(EXP,STATUS!&);
  1867. %compiles conditional expressions;
  1868. %registers REGS!& are set for dropping through,
  1869. %REGS1 are set for a branch;
  1870. BEGIN SCALAR REGS1!&,FLAGG!&,SWITCH!&,LAB1,LAB2,REGSL,
  1871. TAILP;
  1872. EXP := CDR EXP;
  1873. LAB1 := !&GENLBL();
  1874. FOR EACH X ON EXP DO % Changed IN -> ON
  1875. <<LAB2 := !&GENLBL();
  1876. SWITCH!& := NIL;
  1877. IF CDR X THEN !&COMTST(CAAR X,LAB2) % CAR -> CAAR
  1878. %update CONDTAIL!&;
  1879. ELSE IF CAAR X = '(QUOTE T) THEN % CAR -> CAAR, T->(QUOTE T)
  1880. FLAGG!& := T
  1881. ELSE <<!&COMVAL(CAAR X,1); % CAR -> CAAR
  1882. !&JUMPNIL LAB2;
  1883. REGS1!& := !&ADDRVALS('(REG 1),
  1884. REGS!&,
  1885. list '(QUOTE NIL)) >>;
  1886. IF NULL TAILP
  1887. THEN <<CONDTAIL!& := NIL . CONDTAIL!&;
  1888. TAILP := T>>;
  1889. !&COMVAL(CADR CAR X,STATUS!&); %X -> CAR X
  1890. % Branch code;
  1891. %test if need jump to LAB1;
  1892. IF NOT FLAGG!& THEN % New line
  1893. <<IF NOT !&TRANSFERP CODELIST!&
  1894. THEN <<!&ATTJMP LAB1;
  1895. REGSL := REGS!& . REGSL>>;
  1896. REGS!& := REGS1!&;>>;
  1897. %restore register status for next iteration;
  1898. %we do not need to set REGS1!& to NIL since all COMTSTs
  1899. %are required to set it;
  1900. !&ATTLBL LAB2>>;
  1901. IF NULL FLAGG!& AND STATUS!&<2
  1902. THEN <<!&LREG1('(QUOTE NIL));
  1903. REGS!& := !&RMERGE(REGS!& . REGSL)>>
  1904. ELSE IF REGSL
  1905. THEN REGS!& := !&RMERGE(REGS!& . REGSL);
  1906. !&ATTLBL LAB1;
  1907. IF TAILP THEN CONDTAIL!& := CDR CONDTAIL!&
  1908. END;
  1909. SYMBOLIC PROCEDURE !&COMCONS(EXP,STATUS!&);
  1910. IF NULL (EXP := CDR EXP) OR NULL CDR EXP OR CDDR EXP
  1911. THEN !&COMPERROR LIST("Wrong number of arguments to CONS",EXP)
  1912. ELSE IF CADR EXP='(QUOTE NIL)
  1913. THEN !&CALL('NCONS,LIST CAR EXP,STATUS!&)
  1914. ELSE IF CADR EXP MEMBER !&REGVAL '(REG 1)
  1915. AND !&OPENP CAR EXP
  1916. THEN !&CALL1('XCONS,!&COMLIS EXP,STATUS!&)
  1917. ELSE IF !&OPENP CADR EXP THEN !&CALL('CONS,EXP,STATUS!&)
  1918. ELSE !&CALL1('XCONS,!&COMLIS EXP,STATUS!&);
  1919. SYMBOLIC PROCEDURE !&COMGO(EXP,STATUS!&);
  1920. << IF STATUS!&>1 THEN <<!&ATTJMP !&GETLBL CADR EXP; SLST!& := NIL>>
  1921. ELSE !&COMPERROR LIST(EXP,"invalid go")>>;
  1922. SYMBOLIC PROCEDURE !&COMCASE(EXP,STATUS!&);
  1923. BEGIN SCALAR BOTTOMLAB,REGS1!&,JUMPS,EXPS,ELSELAB,HIGH,LOW,SAVEREGS,
  1924. JMPS,JLIST,RANGES,TABLE,TAILP;
  1925. BOTTOMLAB := !&GENLBL();
  1926. REGS1!& := NIL;
  1927. !&COMVAL(CADR EXP,1);
  1928. JUMPS := EXPS := NIL;
  1929. CONDTAIL!& := NIL . CONDTAIL!&;
  1930. TAILP := T;
  1931. FOR EACH THING ON CDDR EXP DO
  1932. BEGIN SCALAR LAB;
  1933. LAB := !&GENLBL();
  1934. JUMPS := NCONC(JUMPS,LIST LIST(CAAR THING,LAB));
  1935. EXPS := NCONC(EXPS,LIST LIST(LAB,CADAR THING));
  1936. IF NULL CDR THING THEN
  1937. IF NOT NULL CAAR THING THEN
  1938. IF STATUS!& > 1 THEN <<REGS1!& := REGS!& . REGS1!&;
  1939. ELSELAB := BOTTOMLAB>>
  1940. ELSE EXPS := NCONC(EXPS,LIST LIST(ELSELAB := !&GENLBL(),
  1941. '(QUOTE NIL)))
  1942. ELSE ELSELAB := LAB;
  1943. END;
  1944. RANGES := NIL;
  1945. TABLE := NIL;
  1946. FOR EACH JMP IN JUMPS DO
  1947. FOR EACH NUM IN CAR JMP DO
  1948. IF EQCAR(NUM,'RANGE) THEN
  1949. BEGIN
  1950. SCALAR HIGH,LOW;
  1951. LOW := !&GETNUM CADR NUM;
  1952. HIGH := !&GETNUM CADDR NUM;
  1953. IF HIGH >= LOW THEN
  1954. IF HIGH - LOW < 6 THEN
  1955. FOR I := LOW:HIGH DO
  1956. TABLE := !&INSTBL(TABLE,I,CADR JMP)
  1957. ELSE RANGES := NCONC(RANGES,LIST LIST(LOW,HIGH,CADR JMP));
  1958. END
  1959. ELSE TABLE := !&INSTBL(TABLE,!&GETNUM NUM,CADR JMP);
  1960. FOR EACH R IN RANGES DO
  1961. !&ATTACH LIST('!*JUMPWITHIN,CADDR R,CAR R,CADR R);
  1962. WHILE TABLE DO
  1963. <<JMPS := LIST CAR TABLE;
  1964. LOW := HIGH := CAAR TABLE;
  1965. JLIST := LIST CADAR TABLE;
  1966. WHILE CDR TABLE AND CAR CADR TABLE < HIGH + 5 DO
  1967. <<TABLE := CDR TABLE;
  1968. WHILE HIGH < (CAAR TABLE) - 1 DO
  1969. <<HIGH := HIGH + 1;
  1970. JLIST := NCONC(JLIST,LIST ELSELAB)>>;
  1971. HIGH := HIGH + 1;
  1972. JLIST := NCONC(JLIST,LIST CADAR TABLE);
  1973. JMPS := NCONC(JMPS,LIST CAR TABLE)>>;
  1974. IF LENGTH JMPS < 4 THEN
  1975. FOR EACH J IN JMPS DO
  1976. !&ATTACH LIST('!*JUMPEQ,CADR J,'(REG 1),LIST('WCONST,CAR J))
  1977. ELSE
  1978. !&ATTACH('!*JUMPON . '(REG 1) . LOW . HIGH . JLIST);
  1979. TABLE := CDR TABLE>>;
  1980. !&ATTJMP ELSELAB;
  1981. SAVEREGS := REGS!&;
  1982. FOR EACH THING IN EXPS DO
  1983. <<!&ATTLBL CAR THING;
  1984. REGS!& := SAVEREGS;
  1985. IF CADR THING THEN !&COMVAL(CADR THING,STATUS!&);
  1986. IF NOT !&TRANSFERP CODELIST!& THEN
  1987. <<!&ATTJMP BOTTOMLAB;
  1988. REGS1!& := REGS!& . REGS1!&>> >>;
  1989. !&ATTLBL BOTTOMLAB;
  1990. REGS!& := !&RMERGE REGS1!&;
  1991. CONDTAIL!& := CDR CONDTAIL!&
  1992. END;
  1993. SYMBOLIC PROCEDURE !&INSTBL(TBL,I,L);
  1994. IF NULL TBL THEN LIST LIST(I,L)
  1995. ELSE IF I < CAAR TBL THEN LIST(I,L) . TBL
  1996. ELSE IF I = CAAR TBL THEN
  1997. !&COMPERROR LIST("Ambiguous case",TBL)
  1998. ELSE CAR TBL . !&INSTBL(CDR TBL,I,L);
  1999. SYMBOLIC PROCEDURE !&GETNUM X;
  2000. IF !&WCONSTP X AND NUMBERP CADR X THEN CADR X
  2001. ELSE !&COMPERROR(LIST("Number expected for CASE label",X));
  2002. SYMBOLIC PROCEDURE !&COMPROG(EXP,STATUS!&); %compiles program blocks;
  2003. BEGIN SCALAR ALSTS!&,GOLIST!&,PG,PROGLIS,EXITT!&,EXITREGS!&;
  2004. INTEGER I;
  2005. %SCALAR OLDSTOMAP,OLDCODE;
  2006. % OLDCODE := CODELIST!&;
  2007. % OLDSTOMAP := STOMAP!&;
  2008. EXITREGS!& := NIL;
  2009. PROGLIS := CADR EXP;
  2010. EXP := CDDR EXP;
  2011. EXITT!& := !&GENLBL();
  2012. PG := !&REMVARL PROGLIS; %protect prog variables;
  2013. ALSTS!& := !&VARBIND(PROGLIS,NIL);
  2014. FOR EACH X IN EXP DO IF ATOM X
  2015. THEN GOLIST!& := (X . !&GENLBL()) . GOLIST!&;
  2016. WHILE EXP DO
  2017. <<IF ATOM CAR EXP
  2018. THEN <<!&ATTLBL !&GETLBL CAR EXP;
  2019. REGS!& := NIL>>
  2020. ELSE !&COMVAL(CAR EXP,IF STATUS!&>2 THEN 4 ELSE 3);
  2021. EXP := CDR EXP>>;
  2022. IF NOT !&TRANSFERP CODELIST!& AND STATUS!& < 2 THEN
  2023. !&LREG1('(QUOTE NIL));
  2024. !&ATTLBL EXITT!&;
  2025. REGS!& := !&RMERGE (REGS!& . EXITREGS!&);
  2026. !&FREERSTR(ALSTS!&,STATUS!&);
  2027. !&RSTVARL(PROGLIS,PG);
  2028. %/ !&FIXFRM(OLDSTOMAP,OLDCODE,0);
  2029. END;
  2030. SYMBOLIC PROCEDURE !&COMPROGN(EXP,STATUS!&);
  2031. BEGIN
  2032. EXP := CDR EXP;
  2033. IF NULL EXP THEN RETURN !&COMVAL('(QUOTE NIL), STATUS!&);
  2034. WHILE CDR EXP DO
  2035. <<!&COMVAL(CAR EXP,IF STATUS!&<2 THEN 2 ELSE STATUS!&);
  2036. EXP := CDR EXP>>;
  2037. !&COMVAL(CAR EXP,STATUS!&)
  2038. END;
  2039. SYMBOLIC PROCEDURE !&COMRETURN(EXP,STATUS!&);
  2040. << EXP := CDR EXP;
  2041. IF NULL EXP OR NOT NULL CDR EXP THEN
  2042. << !&COMPERROR LIST("RETURN must have exactly one argument",EXP);
  2043. EXP := '((QUOTE NIL)) >>;
  2044. IF STATUS!&<4 OR NOT !&NOSIDEEFFECTP(CAR EXP)
  2045. THEN !&LREG1(CAR !&COMLIS1 EXP);
  2046. SLST!& := NIL;
  2047. EXITREGS!& := REGS!& . EXITREGS!&;
  2048. !&ATTJMP EXITT!& >>;
  2049. SYMBOLIC PROCEDURE !&DELMAC X;
  2050. % Delete macro CAR X from CODELIST!&
  2051. RPLACA(X,'(!*NOOP));
  2052. %*************************************************************
  2053. % Pass 3
  2054. %*************************************************************
  2055. COMMENT Post Code Generation Fixups;
  2056. SYMBOLIC PROCEDURE !&PASS3;
  2057. % Pass 3 - optimization.
  2058. % The optimizations currently performed are:
  2059. % 1. Deletion of stores not yet picked up from SLST!&.
  2060. % 2. Removal of unreachable macros.
  2061. % 3. A peep hole optimizer, currently only optmizing LBL macros.
  2062. % 4. Removal of common code chains
  2063. % 5. Changing LINK to LINKE where possible
  2064. % 6. Squeezing out unused frame locations and mapping the stack onto
  2065. % the registers.
  2066. % Other functions of PASS3 are to tack exit code on the end and reverse
  2067. % the code list.
  2068. <<
  2069. FOR EACH J IN SLST!& DO !&DELMAC CDR J;
  2070. !&ATTLBL EXITT!&;
  2071. !&ATTACH '(!*EXIT (!*FRAMESIZE));
  2072. !&REMCODE(T);
  2073. !&FIXLABS();
  2074. !&FIXCHAINS();
  2075. !&FIXLINKS();
  2076. !&REMCODE(NIL);
  2077. !&FIXFRM(NIL,NIL,NARG!&);
  2078. !&PEEPHOLEOPT();
  2079. !&REMCODE(NIL);
  2080. CODELIST!& := REVERSIP CODELIST!&;
  2081. >>;
  2082. SYMBOLIC PROCEDURE !&INSERTMAC(PLACE,MAC);
  2083. RPLACW(PLACE,MAC . (CAR PLACE . CDR PLACE));
  2084. SYMBOLIC PROCEDURE !&DELETEMAC(PLACE);
  2085. RPLACW(PLACE,CDR PLACE);
  2086. SYMBOLIC PROCEDURE !&REMCODE(KEEPTOP);
  2087. BEGIN SCALAR UNUSEDLBLS;
  2088. UNUSEDLBLS := !&UNUSEDLBLS(KEEPTOP);
  2089. !&REMUNUSEDMAC(UNUSEDLBLS);
  2090. WHILE (UNUSEDLBLS := !&UNUSEDLBLS(KEEPTOP)) DO !&REMUNUSEDMAC(UNUSEDLBLS);
  2091. END;
  2092. SYMBOLIC PROCEDURE !&UNUSEDLBLS(KEEPTOP);
  2093. BEGIN SCALAR USED,UNUSED;
  2094. USED := NIL;
  2095. UNUSED := LBLIST!&;
  2096. IF KEEPTOP THEN
  2097. <<USED := !&LABCLASS(TOPLAB!&) . USED;
  2098. UNUSED := !&DELCLASS(TOPLAB!&,UNUSED)>>;
  2099. FOR EACH MAC IN CODELIST!& DO
  2100. IF CAR MAC NEQ '!*LBL THEN
  2101. FOR EACH FLD IN CDR MAC DO
  2102. IF EQCAR(FLD,'LABEL) AND !&CLASSMEMBER(FLD,UNUSED) THEN
  2103. <<USED := !&LABCLASS(FLD) . USED;
  2104. UNUSED := !&DELCLASS(FLD,UNUSED)>>;
  2105. LBLIST!& := USED;
  2106. RETURN UNUSED;
  2107. END;
  2108. SYMBOLIC PROCEDURE !&CLASSMEMBER(LAB,CLASSES);
  2109. IF NULL CLASSES THEN NIL
  2110. ELSE LAB MEMBER CAR CLASSES OR !&CLASSMEMBER(LAB,CDR CLASSES);
  2111. SYMBOLIC PROCEDURE !&REMUNUSEDMAC(UNUSEDLABS);
  2112. BEGIN SCALAR P,Q,R;
  2113. CODELIST!& := P := REVERSIP CODELIST!&;
  2114. WHILE CDR P DO
  2115. <<Q := CDR P;
  2116. IF CAAR Q = '!*NOOP OR
  2117. !&TRANSFERP P AND CAAR Q NEQ '!*LBL
  2118. OR CAAR Q = '!*LBL AND !&CLASSMEMBER(CADAR Q,UNUSEDLABS) THEN
  2119. RPLACD(P,CDR Q)
  2120. ELSE P := CDR P >>;
  2121. CODELIST!& := REVERSIP CODELIST!&;
  2122. END;
  2123. lisp procedure !&FixLinks();
  2124. %
  2125. % replace LINK by LINKE where appropriate
  2126. %
  2127. if not !*NoLinkE and not FreeBound!& then
  2128. begin scalar Switched;
  2129. for each Inst on CodeList!& do
  2130. begin scalar SaveRest;
  2131. if ExitT!& and first first Inst = '!*JUMP
  2132. and second first Inst = ExitT!&
  2133. or first first Inst = '!*EXIT then
  2134. << if first second Inst = '!*LBL then
  2135. << if first third Inst = '!*LINK then
  2136. << Inst := cdr Inst;
  2137. SaveRest := T >> >>;
  2138. if first second Inst = '!*LINK then
  2139. << if second second Inst eq NAME!& and !*R2I then
  2140. Rplaca(rest Inst, list('!*JUMP, TopLab!&))
  2141. else
  2142. Rplaca(rest Inst, '!*LINKE . '(!*FRAMESIZE)
  2143. . rest second Inst);
  2144. if not SaveRest then !&DeleteMac Inst >> >>;
  2145. end;
  2146. end;
  2147. SYMBOLIC PROCEDURE !&PEEPHOLEOPT;
  2148. %'peep-hole' optimization for various cases;
  2149. BEGIN SCALAR X,Z;
  2150. Z := CODELIST!&;
  2151. WHILE Z DO
  2152. IF CAAR Z = '!*NOOP THEN !&DELETEMAC Z
  2153. ELSE IF NOT (X := GET(CAAR Z,'OPTFN)) OR NOT APPLY(X,LIST Z)
  2154. THEN Z := CDR Z
  2155. END;
  2156. COMMENT Peep-hole optimization tables;
  2157. SYMBOLIC PROCEDURE !&STOPT U;
  2158. IF CAADR U = '!*ALLOC AND LLNGTH!& = 1
  2159. AND CDDAR U = '((FRAME 1)) THEN
  2160. <<RPLACW(U,LIST('!*PUSH,CADAR U) . CDDR U)>>
  2161. ELSE IF CAADR U = '!*MOVE AND CAADDR U = '!*ALLOC AND LLNGTH!& = 2
  2162. AND CDDAR U = '((FRAME 2)) AND CDDADR U = '((FRAME 1)) THEN
  2163. <<RPLACW(U,LIST('!*PUSH,CADADR U) . LIST('!*PUSH,CADAR U) . CDDDR U)>>;
  2164. SYMBOLIC PROCEDURE !&LBLOPT U;
  2165. BEGIN SCALAR Z;
  2166. IF CADR U = '!*LBL THEN
  2167. <<!&DEFEQLBL(CADR U,CADR CDR U);
  2168. RPLACD(U,CDDR U);
  2169. RETURN T>>;
  2170. IF CDADR U AND EQCAR(CADADR U,'LABEL) AND !&LBLEQ(CADAR U,CADADR U)
  2171. THEN RETURN RPLACW(CDR U,CDDR U)
  2172. ELSE IF CAADR U = '!*JUMP
  2173. AND (Z := GET(CAADDR U,'NEGJMP))
  2174. AND !&LBLEQ(CADAR U,CADR CADDR U)
  2175. THEN RETURN <<Z := Z . (CADADR U . CDDR CADDR U);
  2176. RPLACD(U,(Z . CDDDR U));
  2177. T>>
  2178. ELSE RETURN NIL
  2179. END;
  2180. SYMBOLIC PROCEDURE !&JUMPOPT U;
  2181. IF CADAR U = EXITT!& AND LLNGTH!& = 0 THEN
  2182. RPLACA(U,'(!*EXIT (!*FRAMESIZE)));
  2183. SYMBOLIC PROCEDURE !&FIXCHAINS();
  2184. BEGIN SCALAR LAB;
  2185. FOR EACH LABCODE ON CODELIST!& DO
  2186. IF CAAR LABCODE = '!*LBL % OR CAAR LABCODE = '!*JUMP % croaks on this one
  2187. THEN
  2188. <<LAB := CADAR LABCODE;
  2189. FOR EACH JUMPCODE ON CDR LABCODE DO
  2190. IF CAAR JUMPCODE = '!*JUMP AND CADAR JUMPCODE = LAB THEN
  2191. !&MOVEJUMP(LABCODE,JUMPCODE)>>
  2192. END;
  2193. SYMBOLIC PROCEDURE !&MOVEJUMP(LABCODE,JUMPCODE);
  2194. IF CADR LABCODE = CADR JUMPCODE THEN
  2195. BEGIN SCALAR LAB;
  2196. REPEAT
  2197. <<IF CADR LABCODE = CADR JUMPCODE THEN
  2198. <<JUMPCODE := CDR JUMPCODE;
  2199. LABCODE := CDR LABCODE>>;
  2200. WHILE CAADR LABCODE = '!*LBL DO LABCODE := CDR LABCODE;
  2201. WHILE CAADR JUMPCODE = '!*LBL DO JUMPCODE := CDR JUMPCODE;>>
  2202. UNTIL NOT(CADR JUMPCODE = CADR LABCODE);
  2203. IF CAAR LABCODE = '!*LBL THEN
  2204. RPLACD(JUMPCODE,LIST('!*JUMP,CADR CAR LABCODE) . CDR JUMPCODE)
  2205. ELSE
  2206. <<LAB := !&GENLBL();
  2207. RPLACD(JUMPCODE,LIST('!*JUMP,LAB) . CDR JUMPCODE);
  2208. RPLACD(LABCODE,LIST('!*LBL,LAB) . CDR LABCODE)>>;
  2209. END;
  2210. SYMBOLIC PROCEDURE !&FIXFRM(OLDSTOMAP,OLDCODE,HIGHREG);
  2211. % Should change FIXFRM to do sliding squeeze, not reorder;
  2212. BEGIN SCALAR LST,GAZINTA,N,NF,TOP,FRAMESUSED,R,USED,FR,P,HMAP;
  2213. HOLEMAP!& := NIL;
  2214. % No stores were generated - frame size = 0
  2215. N := 1;
  2216. GAZINTA := 1;
  2217. % Now, loop through every allocated slot in the frame
  2218. FRAMESUSED := !&GETFRAMES(CODELIST!&,OLDCODE,NIL);
  2219. WHILE N <= LLNGTH!& DO
  2220. <<USED := NIL;
  2221. FR := !&MKFRAME N;
  2222. FOR EACH VAR IN OLDSTOMAP DO IF CADR VAR = FR THEN USED := T;
  2223. IF FR MEMBER FRAMESUSED THEN USED := T;
  2224. % Find out if a frame location was used. N and GAZINTA used for squeeze
  2225. % HOLEMAP!& is an association list between old and new frame locations.
  2226. IF USED THEN <<HOLEMAP!& := LIST(FR,!&MKFRAME GAZINTA) . HOLEMAP!&;
  2227. GAZINTA := GAZINTA + 1 >>;
  2228. N := N + 1>>;
  2229. LLNGTH!& := GAZINTA - 1;
  2230. %now see if we can map stack to registers;
  2231. TOP := !&HIGHEST(CODELIST!&,OLDCODE,HIGHREG,NIL);
  2232. IF NOT(TOP = 'ALL OR
  2233. FREEBOUND!& AND NOT !*USEREGFLUID) THEN
  2234. <<HMAP := NIL;
  2235. NF := 0;
  2236. FOR EACH HOLE IN HOLEMAP!& DO
  2237. IF TOP < LASTACTUALREG!& THEN
  2238. << TOP := TOP + 1;
  2239. LLNGTH!& := LLNGTH!& - 1;
  2240. R := !&MKREG TOP;
  2241. REGS!& := DELASC(R,REGS!&);
  2242. HMAP := LIST(CAR HOLE,R) . HMAP>>
  2243. ELSE
  2244. << NF := NF + 1;
  2245. HMAP := LIST(CAR HOLE, !&MKFRAME NF) . HMAP >>;
  2246. IF NF NEQ 0 THEN LLNGTH!& := NF;
  2247. HOLEMAP!& := HMAP;
  2248. >>
  2249. ELSE IF N = GAZINTA THEN RETURN NIL;
  2250. P := CODELIST!&;
  2251. WHILE NOT (P EQ OLDCODE) DO
  2252. <<RPLACA(P,!&MACROSUBST(CAR P,HOLEMAP!&));
  2253. P := CDR P>>;
  2254. END;
  2255. SYMBOLIC PROCEDURE !&GETFRAMES(CODE,OLDCODE,RES);
  2256. IF CODE EQ OLDCODE THEN RES
  2257. ELSE !&GETFRAMES(CDR CODE,OLDCODE,!&GETFRAMES1(CDAR CODE,RES));
  2258. SYMBOLIC PROCEDURE !&GETFRAMES1(MACARGS,RES);
  2259. IF NULL MACARGS THEN RES ELSE !&GETFRAMES1(CDR MACARGS,
  2260. !&GETFRAMES2(CAR MACARGS,RES));
  2261. SYMBOLIC PROCEDURE !&GETFRAMES2(MACARG,RES);
  2262. IF ATOM MACARG OR !&VARP MACARG OR !&CONSTP MACARG OR !&REGP MACARG THEN RES
  2263. ELSE IF EQCAR(MACARG,'FRAME) THEN
  2264. IF MACARG MEMBER RES THEN RES ELSE MACARG . RES
  2265. ELSE !&GETFRAMES1(CDR MACARG,RES);
  2266. SYMBOLIC PROCEDURE !&HIGHEST(START,STOP,HIGHREG,EXITFLAG);
  2267. % Find the highest register used. 'ALL is returned if all are used.
  2268. IF START EQ STOP THEN HIGHREG ELSE
  2269. BEGIN SCALAR FN,MAC;
  2270. MAC := CAR START;
  2271. RETURN
  2272. IF CAR MAC = '!*LINK OR CAR MAC = '!*LINKE AND EXITFLAG THEN
  2273. <<FN := CADR MAC;
  2274. IF FN = NAME!& THEN
  2275. IF EXITFLAG THEN
  2276. !&HIGHEST(CDR START,STOP,HIGHREG,EXITFLAG)
  2277. ELSE 'ALL
  2278. ELSE IF (DEST!& := GET(FN,'DESTROYS)) AND !*USINGDESTROY THEN
  2279. <<FOR EACH R IN DEST!& DO HIGHREG := MAX(HIGHREG,CADR R);
  2280. !&HIGHEST(CDR START,STOP,HIGHREG,EXITFLAG)>>
  2281. ELSE 'ALL>>
  2282. ELSE IF CAR MAC = '!*LINKF OR CAR MAC = '!*LINKEF AND EXITFLAG THEN
  2283. 'ALL
  2284. ELSE
  2285. !&HIGHEST(CDR START,STOP,!&HIGHEST1(HIGHREG,CDR MAC),EXITFLAG);
  2286. END;
  2287. SYMBOLIC PROCEDURE !&HIGHEST1(H,ARGS);
  2288. BEGIN
  2289. FOR EACH A IN ARGS DO
  2290. H := MAX(H,!&HIGHEST2(H,A));
  2291. RETURN H;
  2292. END;
  2293. SYMBOLIC PROCEDURE !&HIGHEST2(H,ARG);
  2294. IF ATOM ARG THEN H
  2295. ELSE IF NOT ATOM CAR ARG THEN !&HIGHEST1(H,ARG)
  2296. ELSE IF !&CONSTP ARG THEN H
  2297. ELSE IF CAR ARG = 'REG AND NUMBERP CADR ARG THEN MAX(H,CADR ARG)
  2298. ELSE !&HIGHEST1(H,CDR ARG);
  2299. SYMBOLIC PROCEDURE !&REFORMMACROS;
  2300. BEGIN SCALAR FINALTRANSFORM;
  2301. FINALTRANSFORM := LIST(LIST('(!*FRAMESIZE),LLNGTH!&));
  2302. FOR EACH MAC ON CODELIST!& DO
  2303. RPLACA(MAC,!&MACROSUBST(CAR MAC,FINALTRANSFORM));
  2304. END;
  2305. SYMBOLIC PROCEDURE !&FIXLABS();
  2306. BEGIN SCALAR TRANSFORM,U;
  2307. TRANSFORM := NIL;
  2308. FOR EACH LAB IN LBLIST!& DO
  2309. FOR EACH EQLAB IN CDR LAB DO
  2310. TRANSFORM := LIST(EQLAB,CAR LAB) . TRANSFORM;
  2311. FOR EACH MAC ON CODELIST!& DO
  2312. RPLACA(MAC,!&MACROSUBST(CAR MAC,TRANSFORM));
  2313. IF U := ASSOC(EXITT!&,TRANSFORM) THEN EXITT!& := CADR U;
  2314. IF U := ASSOC(TOPLAB!&,TRANSFORM) THEN TOPLAB!& := CADR U;
  2315. LBLIST!& := FOR EACH LAB IN LBLIST!& COLLECT LIST CAR LAB;
  2316. END;
  2317. SYMBOLIC PROCEDURE !&MACROSUBST(MAC,ALIST);
  2318. CAR MAC . !&MACROSUBST1(CDR MAC,ALIST);
  2319. SYMBOLIC PROCEDURE !&MACROSUBST1(ARGS,ALIST);
  2320. FOR EACH ARG IN ARGS COLLECT !&MACROSUBST2(ARG,ALIST);
  2321. SYMBOLIC PROCEDURE !&MACROSUBST2(ARG,ALIST);
  2322. BEGIN SCALAR U;
  2323. U:=ASSOC(ARG,ALIST);
  2324. RETURN IF U THEN CADR U
  2325. ELSE IF ATOM ARG OR FLAGP(CAR ARG,'TERMINAL) THEN ARG
  2326. ELSE (CAR ARG . !&MACROSUBST1(CDR ARG,ALIST));
  2327. END;
  2328. SYMBOLIC PROCEDURE !&REMTAGS();
  2329. FOR EACH MAC IN CODELIST!& DO !&REMTAGS1 MAC;
  2330. SYMBOLIC PROCEDURE !&REMTAGS1 MAC;
  2331. << IF CAR MAC = '!*JUMPON THEN RPLACD(CDDDR MAC, LIST CDDDDR MAC);
  2332. FOR EACH MACFIELD IN CDR MAC DO !&REMTAGS2 MACFIELD >>;
  2333. SYMBOLIC PROCEDURE !&REMTAGS2 U;
  2334. IF EQCAR(U, 'WCONST) THEN !&REMTAGS3 CADR U;
  2335. SYMBOLIC PROCEDURE !&REMTAGS3 U;
  2336. BEGIN SCALAR DOFN;
  2337. IF ATOM U THEN RETURN NIL;
  2338. IF DOFN := GET(CAR U, 'DOFN) THEN
  2339. RPLACA(U, DOFN);
  2340. !&REMTAGS4 CDR U;
  2341. END;
  2342. SYMBOLIC PROCEDURE !&REMTAGS4 U;
  2343. FOR EACH X IN U DO !&REMTAGS3 X;
  2344. % Entry points used in setting up the system
  2345. SYMBOLIC PROCEDURE !&ONEREG U;
  2346. FOR EACH X IN U DO PUT(X,'DESTROYS,'((REG 1)));
  2347. SYMBOLIC PROCEDURE !&TWOREG U;
  2348. FOR EACH X IN U DO PUT(X,'DESTROYS,'((REG 1) (REG 2)));
  2349. SYMBOLIC PROCEDURE !&THREEREG U;
  2350. FOR EACH X IN U DO PUT(X,'DESTROYS,'((REG 1) (REG 2) (REG 3)));
  2351. END;