1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707 |
- % MLG: 15 Dec
- % added additional arguments to
- % Compiler BUG message in &LOCATE to get more info
- % <PSL.COMP>COMPILER.RED.19, 3-Dec-82 18:21:21, Edit by PERDUE
- % Removed REFORMNE, which was over-optimizing sometimes
- % <PSL.COMP>COMPILER.RED.18, 1-Dec-82 15:59:45, Edit by BENSON
- % Fixed car of atom bug in &PaApply
- % New extended compiler for PSL
- % John Peterson 4-5-81
- % <PSL.COMP>COMPILER.RED.4, 20-Sep-82 11:40:31, Edit by BENSON
- % Slight improvement to "FOO not compiled" messages
- % <PSL.COMP>COMPILER.RED.2, 20-Sep-82 10:32:51, Edit by BENSON
- % (DE FOO (LIST) (LIST LIST)) does the right thing
- % <PSL.COMP>COMPILER.RED.10, 10-Sep-82 12:43:27, Edit by BENSON
- % NONLOCALSYS calls NONLOCALLISP if not WVAR or WARRAY
- % <PSL.COMP>COMPILER.RED.9, 10-Sep-82 09:53:08, Edit by BENSON
- % Changed error and warning messages
- CompileTime flag(
- '(!&COMPERROR !&COMPWARN !&IREG
- !&ADDRVALS !&ALLARGS1 !&ALLCONST !&ANYREG !&ANYREGL !&ANYREGP
- !&ARGLOC !&ASSOCOP1 !&ASSOCOP2 !&ATTACH !&ATTJMP !&ATTLBL !&CALL
- !&CALL1 !&CALLOPEN !&CFNTYPE !&CLASSMEMBER !&CLRSTR !&COMLIS !&COMLIS1
- !&COMOPENTST !&COMPLY !&COMTST !&COMVAL !&COMVAL1 !&CONSTTAG
- !&DEFEQLBL !&DEFEQLBL1 !&DELARG !&DELCLASS !&DELETEMAC !&DELMAC
- !&EMITMAC !&EQP !&EQPL !&EQVP !&EXTERNALVARP !&FIXCHAINS !&FIXFRM
- !&FIXLABS !&FIXLINKS !&FIXREGTEST1
- !&FRAME !&FREERSTR !&GENLBL !&GENSYM !&GETFRAMES
- !&GETFRAMES1 !&GETFRAMES2 !&GETFRM !&GETFVAR !&GETGROUPARGS !&GETGROUPARGS1
- !&GETGROUPARGS2 !&GETLBL !&GETNUM !&HIGHEST !&HIGHEST1 !&HIGHEST2
- !&INALL !&INSERTMAC !&INSOP !&INSOP1 !&INSTALLDESTROY !&INSTBL !&JUMPNIL
- !&JUMPT !&LABCLASS !&LBLEQ !&LOADARGS !&LOADOPENEXP !&LOADTEMP1 !&LOADTEMP2
- !&LOADTEMPREG !&LOCATE !&LOCATEL !&LREG !&LREG1 !&MACROSUBST !&MACROSUBST1
- !&MACROSUBST2 !&MAKEADDRESS !&MAKEXP !&MATCHES !&MEMADDRESS !&MKFRAME
- !&MKFUNC !&MKNAM !&MKPROGN !&MKREG !&MOVEJUMP &NOANYREG1
- !&NOSIDEEFFECTP !&NOSIDEEFFECTPL !&OPENFNP !&OPENP !&OPENPL
- !&PA1V !&PALISV
- !&PA1X !&PAASSOC1 !&PAEQUAL1 !&PALIS !&PAMAPCOLLECT !&PAMAPCONC !&PAMAPDO
- !&PAMEMBER1 !&PANONLOCAL !&PAPROGBOD !&PASS1 !&PASS2 !&PASS3 !&PEEPHOLEOPT
- !&PROTECT !&RASSOC !&REFERENCES !&REFERENCESL !&REFEXTERNAL !&REFEXTERNALL
- !&REFMEMORY !&REFMEMORYL !&REFORMMACROS !®P !®VAL !&REMCODE
- !&REMMREFS !&REMMREFS1 !&REMOPEN !&REMREFS !&REMREFS1 !&REMREGS !&REMREGSL
- !&REMTAGS !&REMTAGS1 !&REMTAGS2 !&REMTAGS3 !&REMTAGS4 !&REMUNUSEDMAC
- !&REMVARL !&REMVREFS !&REMVREFS1 !&REPASC !&RMERGE !&RSTVAR !&RSTVARL !&RVAL
- !&SAVER1 !&STORELOCAL !&STOREVAR !&SUBARG !&SUBARGS !&TEMPREG !&TRANSFERP
- !&UNPROTECT !&UNUSEDLBLS !&USESDESTL !&VARBIND !&VARP !&WCONSTP
- !&CONSTP ISAWCONST MKNONLOCAL MKWCONST NONLOCAL NONLOCALLISP
- NONLOCALSYS PA1ERR WARRAYP WCONSTP WVARP),
- 'InternalFunction);
- GLOBAL '(ERFG!*
- !*NOLINKE !*ORD !*R2I !*UNSAFEBINDER
- MAXNARGS!&
- !*NOFRAMEFLUID !*USEREGFLUID
- !*INSTALLDESTROY
- !*USINGDESTROY
- !*SHOWDEST
- GLOBALGENSYM!&); % list of symbols to be re-used by the compiler
- FLUID '(ALSTS!& FLAGG!& NAME!& GOLIST!& CODELIST!& CONDTAIL!&
- LLNGTH!& NARG!& REGS!& EXITT!& LBLIST!& JMPLIST!& SLST!& STOMAP!&
- LASTACTUALREG!& DFPRINT!* !*PLAP
- !*SYSLISP
- SWITCH!&
- TOPLAB!&
- FREEBOUND!&
- STATUS!&
- REGS1!&
- PREGS!& DESTREG!&
- EXITREGS!&
- DEST!& ENVIRONMENT!&
- HOLEMAP!&
- LOCALGENSYM!&); % traveling pointer into GLOBALGENSYM!&
- %COMMENT **************************************************************
- %**********************************************************************
- % THE STANDARD LISP COMPILER
- %**********************************************************************
- % Augmented for SYSLISP
- %*********************************************************************;
- %
- %COMMENT machine dependent parts are in a separate file;
- %
- %COMMENT these include the macros described below and, in addition,
- % an auxiliary function !&MKFUNC which is required to pass
- % functional arguments (input as FUNCTION <func>) to the
- % loader. In most cases, !&MKFUNC may be defined as MKQUOTE;
- %
- %COMMENT Registers used:
- %1-MAXNARGS!& used for args of link. result returned in reg 1;
- %
- %COMMENT Macros used in this compiler;
- %
- %COMMENT The following macros must NOT change REGS!& 1-MAXNARGS!&:
- %!*ALLOC nw allocate new stack frame of nw words
- %!*DEALLOC nw deallocate above frame
- %!*ENTRY name type noargs entry point to function name of type type
- % with noargs args
- %!*EXIT EXIT to previously saved return address
- %!*JUMP adr unconditional jump
- %!*LBL adr define label
- %!*LAMBIND regs alst bind free lambda vars in alst currently in regs
- %!*PROGBIND alst bind free prog vars in alst
- %!*FREERSTR alst unbind free variables in alst
- %!*STORE reg floc store contents of reg (or NIL) in floc
- %
- %COMMENT the following macro must only change specific register being
- % loaded:
- %
- %!*LOAD reg exp load exp into reg;
- %
- %COMMENT the following macros do not protect regs 1-MAXNARGS!&:
- %
- %!*LINK fn type nargs link to fn of type type with nargs args
- %!*LINKE fn type nargs nw link to fn of type type with nargs args
- % and EXITT!& removing frame of nw words;
- %
- %
- %COMMENT variable types are:
- %
- % LOCAL allocated on stack and known only locally
- % GLOBAL accessed via cell (GLOBAL name) known to
- % loader at load time
- % WGLOBAL accessed via cell (WGLOBAL name) known to
- % loader at load time, SYSLISP
- % FLUID accessed via cell (FLUID name)
- % known to loader. This cell is rebound by LAMBIND/
- % PROGBIND if variable used in lambda/prog list
- % and restored by FREERSTR;
- %
- %COMMENT global flags used in this compiler:
- %!*UNSAFEBINDER for Don's BAKER problem...GC may be called in
- % Binder, so regs cant be preserved
- %!*MODULE indicates block compilation (a future extension of
- % this compiler)
- %!*NOLINKE if ON inhibits use of !*LINKE macro
- %!*ORD if ON forces left-to-right argument evaluation
- %!*PLAP if ON causes LAP output to be printed
- %!*R2I if ON causes recursion removal where possible;
- %
- %
- %COMMENT global variables used:
- %
- %DFPRINT!* name of special definition process (or NIL)
- %ERFG!* used by REDUCE to control error recovery
- %MAXNARGS!& maximum number of arguments permitted in implementation;
- %
- %
- %
- %%Standard LISP limit;
- %
- %COMMENT fluid variables used:
- %
- %ALSTS alist of fluid parameters
- %FLAGG used in COMTST, and in FIXREST
- %FREEBOUND indicates that some variables were FLUID
- %GOLIST storage map for jump labels
- %PREGS A list of protected registers
- %CODELIST code being built
- %CONDTAIL simulated stack of position in the tail of a COND
- %LLNGTH cell whose CAR is length of frame
- %NAME NAME!& of function being currently compiled
- %FNAME!& name of function being currently compiled, set by COMPILE
- %NARG number of arguments in function
- %REGS known current contents of registers as an alist with elements
- % of form (<reg> . <contents>)
- %EXITT label for *EXIT jump
- %EXITREGS List or register statuses at return point
- %LBLIST list of label words
- %JMPLIST list of locations in CODELIST!& of transfers
- %SLST association list for stores which have not yet been used
- %STOMAP storage map for variables
- %SWITCH boolean expression value flag - keeps track of NULLs;
- %
- SYMBOLIC PROCEDURE !&MKFUNC FN; MKQUOTE FN;
- SYMBOLIC PROCEDURE WARRAYP X;
- GET(X,'WARRAY) OR GET(X, 'WSTRING);
- SYMBOLIC PROCEDURE WVARP X;
- GET(X,'WVAR);
- SYMBOLIC PROCEDURE WCONSTP X;
- NUMBERP X OR (IDP X AND GET(X,'WCONST));
- SYMBOLIC PROCEDURE !&ANYREGP X;
- FLAGP(X, 'ANYREG);
- macro procedure LocalF U; % declare functions internal, ala Franz
- list('flag, Mkquote cdr U, ''InternalFunction);
- %************************************************************
- % The compiler
- %************************************************************
- % Top level compile entry - X is list of functions to compile
- SYMBOLIC PROCEDURE COMPILE X;
- BEGIN SCALAR EXP;
- FOR EACH FNAME!& IN X DO
- <<EXP := GETD FNAME!&;
- IF NULL EXP THEN !&COMPWARN LIST("No definition for", FNAME!&)
- ELSE IF CODEP CDR EXP THEN
- !&COMPWARN LIST(FNAME!&, "already compiled")
- ELSE COMPD(FNAME!&,CAR EXP,CDR EXP)>>
- END;
- % COMPD - Single function compiler
- % Makes sure function type is compilable; sends original definition to
- % DFPRINT!*, then compiles the function. Shows LAP code when PLAP is on.
- % Runs LAP and adds COMPFN property if LAP indeed redefines the function.
- SYMBOLIC PROCEDURE COMPD(NAME!&,TY,EXP);
- BEGIN
- IF NOT FLAGP(TY,'COMPILE)
- THEN <<!&COMPERROR LIST("Uncompilable function type", TY);
- RETURN NIL>>;
- IF NOT EQCAR(EXP, 'LAMBDA)
- THEN
- << !&COMPERROR LIST("Attempt to compile non-lambda expression", EXP);
- RETURN NIL >>
- %/ ELSE IF !*MODULE THEN MODCMP(NAME!&,TY,EXP)
- % ELSE IF DFPRINT!*
- % THEN APPLY(DFPRINT!*,LIST IF TY EQ 'EXPR
- % THEN 'DE . (NAME!& . CDR EXP)
- % ELSE IF TY EQ 'FEXPR
- % THEN 'DF . (NAME!& . CDR EXP)
- % ELSE IF TY EQ 'MACRO
- %% THEN 'DM . (NAME!& . CDR EXP)
- % ELSE IF TY EQ 'NEXPR
- % THEN 'DN . (NAME!& . CDR EXP)
- % ELSE LIST('PUTD,MKQUOTE NAME!&,
- % MKQUOTE TY,
- % MKQUOTE EXP))
- ELSE BEGIN SCALAR X;
- IF TY MEMQ '(EXPR FEXPR)
- THEN PUT(NAME!&,'CFNTYPE,LIST TY);
- X :=
- LIST('!*ENTRY,NAME!&,TY,LENGTH CADR EXP)
- . !&COMPROC(EXP,
- IF TY MEMQ '(EXPR FEXPR)
- THEN NAME!&);
- IF !*PLAP THEN FOR EACH Y IN X DO PRINT Y;
- % ***Code**Pointer** is a magic token that tells
- % COMPD to return a code pointer instead of an ID
- IF NAME!& = '!*!*!*Code!*!*Pointer!*!*!* then
- NAME!& := LAP X
- ELSE
- << LAP X;
- %this is the hook to the assembler. LAP must
- %remove old function definition if it exists;
- IF (X := GET(NAME!&,'CFNTYPE))
- AND EQCAR(GETD NAME!&,CAR X)
- THEN REMPROP(NAME!&,'CFNTYPE) >>
- END;
- RETURN NAME!&
- END;
- %************************************************************
- % Pass 1 routines
- %************************************************************
- SYMBOLIC PROCEDURE !&PASS1 EXP; %. Pass1- reform body of expression for
- !&PA1(EXP,NIL); % Compilation
- SYMBOLIC PROCEDURE PA1ERR(X); %. Error messages from PASS1
- STDERROR LIST("-- PA1 --", X);
-
- lisp procedure !&Pa1(U, Vbls);
- !&Pa1V(U, Vbls, NIL);
- % Do the real pass1 and an extra reform
- SYMBOLIC PROCEDURE !&PA1V(U,VBLS, VAR);
- BEGIN
- SCALAR Z,FN; % Z is the pass1 result. Reform if necessary
- Z:=!&PA1X(U,VBLS, VAR);
- IF IDP CAR Z AND (FN:=GET(CAR Z,'PA1REFORMFN)) THEN
- Z := APPLY(FN,LIST Z);
- RETURN Z;
- END;
- SYMBOLIC PROCEDURE !&PA1X(U,VBLS,VAR); %. VBLS are current local vars
- BEGIN SCALAR X;
- RETURN IF ATOM U % tag variables and constants
- THEN IF ISAWCONST U THEN MKWCONST U
- ELSE IF CONSTANTP U OR U MEMQ '(NIL T) THEN MKQUOTE U
- ELSE IF NONLOCAL U THEN !&PANONLOCAL(U, VBLS)
- ELSE IF U MEMQ VBLS THEN LIST('!$LOCAL,U)
- ELSE <<MKNONLOCAL U; !&PANONLOCAL(U, VBLS) >>
- ELSE IF NOT IDP CAR U
- THEN IF EQCAR(CAR U,'LAMBDA) THEN
- !&PA1V(CAR U,VBLS,VAR) . !&PALISV(CDR U,VBLS,VAR)
- ELSE % Change to APPLY
- << !&COMPERROR
- list("Ill-formed function expression", U);
- '(QUOTE NIL) >>
- % Changed semantics of EVAL to conform to Common Lisp.
- % CAR of a form is NEVER evaluated.
- % ELSE IF CAR U MEMQ VBLS OR FLUIDP CAR U
- % OR (GLOBALP CAR U
- % AND NOT GETD CAR U) THEN % Change to APPLY
- % << !&COMPWARN list("Functional form converted to APPLY", U);
- % !&PA1(LIST('APPLY, CAR U, 'LIST . CDR U), VBLS) >>
- ELSE IF X := GET(CAR U,'PA1ALGFN) % Do const folding, etc.
- THEN APPLY(X,LIST(U,VBLS,VAR))
- ELSE IF X := GET(CAR U,'PA1FN) % Do PA1FN's
- THEN APPLY(X,LIST(U,VBLS))
- ELSE IF X := GET(CAR U,'CMACRO) % CMACRO substitution
- THEN !&PA1V(SUBLIS(PAIR(CADR X,CDR U),CADDR X),VBLS,VAR)
- ELSE IF (X := GETD CAR U) % Expand macros
- AND CAR X EQ 'MACRO
- AND NOT (GET(CAR U,'COMPFN) OR GET(CAR U,'OPENFN))
- THEN !&PA1V(APPLY(CDR X,LIST U),VBLS,VAR)
- ELSE IF !&CFNTYPE CAR U EQ 'FEXPR % Transform FEXPR calls to
- AND NOT (GET(CAR U,'COMPFN) OR GET(CAR U,'OPENFN))
- THEN LIST(CAR U,MKQUOTE CDR U) % EXPR calls
- ELSE IF !&CFNTYPE CAR U EQ 'NEXPR % Transform NEXPR calls to
- AND NOT (GET(CAR U,'COMPFN) OR GET(CAR U,'OPENFN))
- THEN LIST(CAR U,!&PA1V('LIST . CDR U,VBLS,VAR)) % EXPR calls
- ELSE CAR U . !&PALISV(CDR U,VBLS,VAR);
- END;
- SYMBOLIC PROCEDURE !&PALIS(U,VBLS);
- !&PALISV(U,VBLS,NIL);
- SYMBOLIC PROCEDURE !&PALISV(U,VBLS, VAR);
- FOR EACH X IN U COLLECT !&PA1V(X,VBLS,VAR);
- SYMBOLIC PROCEDURE ISAWCONST X; %. Check to see if WCONST,
- %. in SYSLISP only
- !*SYSLISP AND WCONSTP X;
- SYMBOLIC PROCEDURE !&CONSTTAG();
- IF !*SYSLISP THEN 'WCONST ELSE 'QUOTE;
- SYMBOLIC PROCEDURE MKWCONST X; %. Made into WCONST
- BEGIN SCALAR Y;
- RETURN LIST('WCONST, IF (Y := GET(X, 'WCONST)) AND NOT GET(X, 'WARRAY)
- AND NOT GET(X, 'WSTRING) THEN
- Y
- ELSE X);
- END;
- SYMBOLIC PROCEDURE !&PAWCONST(U, VBLS);
- MKWCONST CADR U;
- SYMBOLIC PROCEDURE NONLOCAL X; %. Default NON-LOCAL types
- IF !*SYSLISP THEN NONLOCALSYS X
- ELSE NONLOCALLISP X;
- SYMBOLIC PROCEDURE NONLOCALLISP X;
- IF FLUIDP X THEN '!$FLUID
- ELSE IF GLOBALP X THEN '!$GLOBAL
- ELSE IF WVARP X OR WARRAYP X THEN
- <<!&COMPWARN LIST(X,"already SYSLISP non-local");NIL>>
- ELSE NIL;
- SYMBOLIC PROCEDURE NONLOCALSYS X;
- IF WARRAYP X THEN 'WARRAY
- ELSE IF WVARP X THEN 'WVAR
- ELSE NONLOCALLISP X;
- SYMBOLIC PROCEDURE !&PANONLOCAL(X, VBLS); %. Reform Non-locals
- % X will be a declared NONLOCAL
- BEGIN SCALAR Z;
- RETURN
- IF NOT IDP X OR NOT NONLOCAL X THEN PA1ERR LIST("non-local error",X)
- ELSE IF FLUIDP X THEN LIST('!$FLUID,X)
- ELSE IF GLOBALP X THEN LIST('!$GLOBAL,X)
- ELSE IF GET(X,'WVAR) THEN
- IF X MEMBER VBLS THEN <<!&COMPWARN(LIST('WVAR,X,"used as local"));
- LIST('!$LOCAL,X)>>
- ELSE LIST('WVAR,X)
- ELSE IF WARRAYP X THEN
- LIST('WCONST, X)
- ELSE PA1ERR LIST("Unknown in PANONLOCAL",X);
- END;
- % Make unknown symbols into FLUID for LISP, WVAR for SYSLISP, with warning
- % Changed to just declare it fluid, EB, 9:36am Friday, 10 September 1982
- SYMBOLIC PROCEDURE MKNONLOCAL U;
- % IF !*SYSLISP THEN
- % << !&COMPERROR LIST("Undefined symbol", U,
- % "in Syslisp, treated as WVAR");
- % WDECLARE1(U, 'INTERNAL, 'WVAR, NIL, 0);
- % LIST('WVAR, U) >>
- % ELSE
- <<!&COMPWARN LIST(U,"declared fluid"); FLUID LIST U; LIST('!$FLUID,U)>>;
- % Utility stuff for the PA1 functions
- SYMBOLIC PROCEDURE !&MKNAM U;
- %generates unique name for auxiliary function in U;
- IMPLODE NCONC(EXPLODE U,EXPLODE !&GENSYM());
- % For making implied PROGN's into explicit ones (as in COND)
- SYMBOLIC PROCEDURE !&MKPROGN U;
- IF NULL U OR CDR U THEN 'PROGN . U ELSE CAR U;
- SYMBOLIC PROCEDURE !&EQP U;
- %!&EQP is true if U is an object for which EQ can replace EQUAL;
- INUMP U OR IDP U;
- SYMBOLIC PROCEDURE !&EQVP U;
- %!&EQVP is true if EVAL U is an object for which EQ can
- %replace EQUAL;
- INUMP U OR NULL U OR U EQ 'T OR EQCAR(U,'QUOTE) AND !&EQP CADR U;
- % !&EQPL U is true if !&EQP of all elements of U
- SYMBOLIC PROCEDURE !&EQPL U;
- NULL U OR !&EQP(CAR U) AND !&EQPL(CDR U);
- SYMBOLIC PROCEDURE !&MAKEADDRESS U;
- % convert an expression into an addressing expression, (MEMORY var const),
- % where var is the variable part & const is the constant part (tagged, of
- % course). It is assumed that U has been through pass 1, which does constant
- % folding & puts any constant term at the top level.
- IF EQCAR(U,'LOC) THEN CADR U ELSE % GETMEM LOC x == x
- 'MEMORY .
- (IF EQCAR(U,'WPLUS2) AND !&CONSTP CADDR U THEN CDR U
- ELSE IF EQCAR(U,'WDIFFERENCE) AND !&CONSTP CADR U THEN
- LIST(LIST('WMINUS,CADDR U),CADR U)
- ELSE LIST(U,'(WCONST 0)));
- SYMBOLIC PROCEDURE !&DOOP U;
- % simplification for random operators - op is doable only when all operands
- % are constant
- IF !&ALLCONST CDR U THEN
- LIST(CAR CADR U,
- APPLY(GET(CAR U,'DOFN) or car U, FOR EACH X IN CDR U COLLECT CADR X))
- ELSE U;
- SYMBOLIC PROCEDURE !&ALLCONST L;
- NULL L OR (car L = 'QUOTE or !&WCONSTP CAR L AND NUMBERP CADR CAR L)
- AND !&ALLCONST CDR L;
- lisp procedure !&PaReformWTimes2 U;
- begin scalar X;
- U := !&Doop U;
- return if first U = 'WTimes2 then
- if !&WConstP second U and (X := PowerOf2P second second U) then
- list('WShift, third U, list(!&ConstTag(), X))
- else if !&WConstP third U and (X := PowerOf2P second third U) then
- list('WShift, second U, list(!&ConstTag(), X))
- else U
- else U;
- end;
- SYMBOLIC PROCEDURE !&ASSOCOP(U,VBLS); % For abelian semi-groups & monoids
- % given an associative, communitive operation (TIMES2, AND, ...) collect all
- % arguments, seperate constant args, evaluate true constants, check for zero's
- % and ones (0*X = 0, 1*X = X)
- !&ASSOCOPV(U,VBLS,NIL);
- SYMBOLIC PROCEDURE !&ASSOCOPV(U,VBLS,VAR);
- BEGIN SCALAR ARGS,NUM,CONSTS,VARS;
- ARGS := !&ASSOCOP1(CAR U,!&PALIS(CDR U,VBLS));
- CONSTS := VARS := NUM := NIL;
- FOR EACH ARG IN ARGS DO
- IF !&WCONSTP ARG THEN
- IF NUMBERP CADR ARG THEN
- IF NUM THEN NUM := APPLY(GET(CAR U,'DOFN),LIST(NUM,CADR ARG))
- ELSE NUM := CADR ARG
- ELSE CONSTS := NCONC(CONSTS,LIST ARG)
- ELSE VARS := NCONC(VARS,LIST ARG);
- IF NUM THEN
- <<IF NUM = GET(CAR U,'ZERO) THEN RETURN LIST(!&CONSTTAG(),NUM);
- IF NUM NEQ GET(CAR U,'ONE) THEN CONSTS := NUM . CONSTS
- ELSE IF NULL VARS AND NULL CONSTS THEN RETURN
- LIST(!&CONSTTAG(), NUM) >>;
- IF CONSTS THEN
- VARS := NCONC(VARS,LIST LIST('WCONST,!&INSOP(CAR U,CONSTS)));
- IF VAR MEMBER VARS THEN
- <<VARS := DELETIP(VAR,VARS);
- RETURN !&INSOP(CAR U,REVERSIP(VAR . REVERSIP VARS))>>;
- RETURN !&INSOP(CAR U,VARS);
- END;
- SYMBOLIC PROCEDURE !&ASSOCOP1(OP,ARGS);
- IF NULL ARGS THEN NIL
- ELSE NCONC(!&ASSOCOP2(OP,CAR ARGS),!&ASSOCOP1(OP,CDR ARGS));
- SYMBOLIC PROCEDURE !&ASSOCOP2(OP,ARG);
- IF EQCAR(ARG,OP) THEN !&ASSOCOP1(OP,CDR ARG)
- ELSE LIST ARG;
- SYMBOLIC PROCEDURE !&INSOP(OP,L);
- % Insert OP into a list of operands as follows: INSOP(~,'(A B C D)) =
- % (~ (~ (~ A B) C) D)
- IF NULL L THEN NIL ELSE if null cdr L then car L else
- !&INSOP1(list(OP, first L, second L), rest rest L, OP);
- SYMBOLIC PROCEDURE !&INSOP1(NEW, RL, OP);
- if null RL then NEW else !&INSOP1(list(OP, NEW, first RL), rest RL, OP);
- SYMBOLIC PROCEDURE !&GROUP(U,VBLS);
- % Like ASSOP, except inverses exist. All operands are partitioned into two
- % lists, non-inverted and inverted. Cancellation is done between these two
- % lists. The group is defined by three operations, the group operation (+),
- % inversion (unary -), and subtraction (dyadic -). The GROUPOPS property on
- % all three of there operators must contain the names of these operators in
- % the order (add subtract minus)
- !&GROUPV(U,VBLS,NIL);
- SYMBOLIC PROCEDURE !&GROUPV(U,VBLS,VAR);
- BEGIN SCALAR X,ARGS,INVARGS,FNS,CONSTS,INVCONSTS,CON,RES,VFLG,INVFLG,ONE;
- FNS := GET(CAR U,'GROUPOPS);
- ONE := LIST(!&CONSTTAG(),GET(CAR FNS,'ONE));
- X := !&GETGROUPARGS(FNS,CAR U . !&PALIS(CDR U, VBLS),NIL,'(NIL NIL));
- ARGS := CAR X;
- INVARGS := CADR X;
- FOR EACH ARG IN ARGS DO
- IF ARG MEMBER INVARGS THEN
- <<ARGS := !&DELARG(ARG,ARGS);
- INVARGS := !&DELARG(ARG,INVARGS)>>;
- CONSTS := INVCONSTS := CON := NIL;
- FOR EACH ARG IN ARGS DO
- IF !&WCONSTP ARG THEN
- <<ARGS := !&DELARG(ARG,ARGS);
- IF NUMBERP CADR ARG THEN
- IF CON THEN CON := APPLY(GET(CAR FNS,'DOFN),LIST(CON,CADR ARG))
- ELSE CON := CADR ARG
- ELSE CONSTS := NCONC(CONSTS,LIST ARG)>>;
- FOR EACH ARG IN INVARGS DO
- IF !&WCONSTP ARG THEN
- <<INVARGS := !&DELARG(ARG,INVARGS);
- IF NUMBERP CADR ARG THEN
- IF CON THEN CON := APPLY(GET(CADR FNS,'DOFN),LIST(CON,CADR ARG))
- ELSE CON := APPLY(GET(CADDR FNS,'DOFN),LIST CADR ARG)
- ELSE INVCONSTS := NCONC(INVCONSTS,LIST ARG)>>;
- IF CON AND CON = GET(CAR FNS,'ZERO) THEN RETURN LIST(!&CONSTTAG(),CON);
- IF CON AND CON = CADR ONE THEN CON := NIL;
- IF CON THEN CONSTS := CON . CONSTS;
- CONSTS := !&MAKEXP(CONSTS,INVCONSTS,FNS);
- IF CONSTS AND NOT !&WCONSTP CONSTS THEN CONSTS := LIST('WCONST,CONSTS);
- IF VAR MEMBER ARGS THEN
- <<ARGS := DELETE(VAR,ARGS);
- VFLG := T;
- INVFLG := NIL>>;
- IF VAR MEMBER INVARGS THEN
- <<INVARGS := DELETE(VAR,INVARGS);
- VFLG := T;
- INVFLG := T>>;
- ARGS := !&MAKEXP(ARGS,INVARGS,FNS);
- RES := IF NULL ARGS THEN
- IF NULL CONSTS THEN
- ONE
- ELSE CONSTS
- ELSE
- IF NULL CONSTS THEN ARGS
- ELSE IF EQCAR(ARGS,CADDR FNS) THEN
- LIST(CADR FNS,CONSTS,CADR ARGS)
- ELSE
- LIST(CAR FNS,ARGS,CONSTS);
- IF VFLG THEN
- IF RES = ONE THEN
- IF INVFLG THEN RES := LIST(CADDR FNS,VAR)
- ELSE RES := VAR
- ELSE
- RES := LIST(IF INVFLG THEN CADR FNS ELSE CAR FNS,RES,VAR);
- RETURN RES;
- END;
- SYMBOLIC PROCEDURE !&MAKEXP(ARGS,INVARGS,FNS);
- IF NULL ARGS THEN
- IF NULL INVARGS THEN NIL
- ELSE LIST(CADDR FNS,!&INSOP(CAR FNS,INVARGS))
- ELSE
- IF NULL INVARGS THEN !&INSOP(CAR FNS,ARGS)
- ELSE !&INSOP(CADR FNS,!&INSOP(CAR FNS,ARGS) . INVARGS);
- SYMBOLIC PROCEDURE !&GETGROUPARGS(FNS,EXP,INVFLG,RES);
- IF ATOM EXP OR NOT(CAR EXP MEMBER FNS) THEN
- !&GETGROUPARGS1(EXP,INVFLG,RES)
- ELSE IF CAR EXP EQ CAR FNS THEN !&GETGROUPARGS2(FNS,CDR EXP,INVFLG,RES)
- ELSE IF CAR EXP EQ CADR FNS THEN
- !&GETGROUPARGS(FNS,CADR EXP,INVFLG,
- !&GETGROUPARGS(FNS,CADDR EXP,NOT INVFLG,RES))
- ELSE IF CAR EXP EQ CADDR FNS THEN
- !&GETGROUPARGS(FNS,CADR EXP,NOT INVFLG,RES)
- ELSE !&COMPERROR(LIST("Compiler bug in constant folding",FNS,EXP));
- SYMBOLIC PROCEDURE !&GETGROUPARGS1(THING,INVFLG,RES);
- IF INVFLG THEN LIST(CAR RES,THING . CADR RES)
- ELSE (THING . CAR RES) . CDR RES;
- SYMBOLIC PROCEDURE !&GETGROUPARGS2(FNS,ARGS,INVFLG,RES);
- IF NULL ARGS THEN RES
- ELSE !&GETGROUPARGS2(FNS,CDR ARGS,INVFLG,
- !&GETGROUPARGS(FNS,CAR ARGS,INVFLG,RES));
- SYMBOLIC PROCEDURE !&DELARG(ARG,ARGS);
- IF ARG = CAR ARGS THEN CDR ARGS ELSE CAR ARGS . !&DELARG(ARG,CDR ARGS);
- %************************************************************
- % Pass 1 functions
- %************************************************************
- lisp procedure !&PaApply(U, Vars);
- if EqCar(third U, 'LIST) then % set up for !&COMAPPLY
- if EqCar(second U, 'function)
- and !&CfnType second second U = 'EXPR then
- !&Pa1(second second U . rest third U, Vars)
- else list('APPLY,
- !&Pa1(second U, Vars),
- 'LIST . !&PaLis(rest third U, Vars))
- else 'APPLY . !&PaLis(rest U, Vars);
- % Try to turn ASSOC into ATSOC
- SYMBOLIC PROCEDURE !&PAASSOC(U,VARS);
- !&PAASSOC1(CADR U,CADDR U) . !&PALIS(CDR U,VARS);
- SYMBOLIC PROCEDURE !&PAASSOC1(ASSOCVAR,ASSOCLIST);
- IF !&EQVP ASSOCVAR
- OR EQCAR(ASSOCLIST,'QUOTE) AND
- !&EQPL(FOR EACH U IN CADR ASSOCLIST COLLECT CAR U)
- THEN 'ATSOC ELSE 'ASSOC;
- SYMBOLIC PROCEDURE !&PACOND(U,VBLS);
- begin scalar RevU, Result, Temp;
- if null cdr U then return '(QUOTE NIL); % (COND) == NIL
- RevU := reverse cdr U;
- if first first RevU neq T then RevU := '(T NIL) . RevU;
- for each CondForm in RevU do
- if null rest CondForm then
- << if not Temp then
- << Temp := !&Gensym();
- VBLS := Temp . VBLS >>;
- Result := list(!&PA1(list('SETQ, Temp, first CondForm), VBLS),
- !&PA1(Temp, VBLS)) . Result >>
- else
- Result := list(!&PA1(first CondForm, VBLS),
- !&PA1(!&MkProgN rest CondForm, VBLS)) . Result;
- return if Temp then list(list('LAMBDA,
- list !&PA1(Temp, VBLS),
- 'COND . Result),
- '(QUOTE NIL))
- else 'COND . Result;
- end;
- lisp procedure !&PaCatch(U, Vbls);
- (lambda(Tag, Forms);
- << if null cdr Forms and
- (atom car Forms
- or car car Forms = 'QUOTE
- or car car Forms = 'LIST) then
- !&CompWarn list("Probable obsolete use of CATCH:", U);
- !&Pa1(list(list('lambda, '(!&!&HiddenVar!&!&),
- list('cond, list('(null ThrowSignal!*),
- list('(lambda (xxx)
- (!%UnCatch !&!&HiddenVar!&!&)
- xxx),
- 'progn . Forms)),
- '(t !&!&HiddenVar!&!&))),
- list('CatchSetup, Tag)),
- Vbls)>>)(cadr U, cddr U);
- % X-1 -> SUB1 X
- SYMBOLIC PROCEDURE !&PADIFF(U,VARS);
- IF CADDR U=1 THEN LIST('SUB1,!&PA1(CADR U,VARS))
- ELSE 'DIFFERENCE . !&PALIS(CDR U,VARS);
- SYMBOLIC PROCEDURE !&PAEQUAL(U,VARS);
- !&PAEQUAL1(CADR U,CADDR U) . !&PALIS(CDR U,VARS);
- SYMBOLIC PROCEDURE !&PAEQUAL1(LEFT,RIGHT);
- IF !&EQVP LEFT OR !&EQVP RIGHT THEN 'EQ
- ELSE IF NUMBERP LEFT OR NUMBERP RIGHT THEN 'EQN
- ELSE 'EQUAL;
- % FUNCTION will compile a non-atomic arg into a GENSYMed name.
- % Currently, MKFUNC = MKQUOTE
- SYMBOLIC PROCEDURE !&PAFUNCTION(U,VBLS);
- IF ATOM CADR U THEN !&MKFUNC CADR U % COMPD returns a code pointer here
- ELSE !&MKFUNC COMPD('!*!*!*Code!*!*Pointer!*!*!*,
- 'EXPR,CADR U);
- SYMBOLIC PROCEDURE !&PAGETMEM(U,VBLS);
- !&MAKEADDRESS !&PA1(CADR U,VBLS);
- SYMBOLIC PROCEDURE !&PAIDENT(U,VBLS); %. return form
- U;
- % LAMBDA - pick up new vars, check implicit PROGN
- SYMBOLIC PROCEDURE !&PACASE(U,VBLS);
- 'CASE . !&PA1(CADR U,VBLS) . FOR EACH EXP IN CDDR U COLLECT
- LIST(!&PALIS(CAR EXP,VBLS),!&PA1(CADR EXP,VBLS));
- SYMBOLIC PROCEDURE !&PALAMBDA(U,VBLS);
- <<VBLS := APPEND(CADR U,VBLS);
- 'LAMBDA . LIST(!&PALIS(CADR U,VBLS),!&PA1(!&MKPROGN CDDR U,VBLS)) >>;
- % X<0 -> MINUSP(X)
- SYMBOLIC PROCEDURE !&PALESSP(U,VARS);
- IF CADDR U=0 THEN LIST('MINUSP,!&PA1(CADR U,VARS))
- ELSE 'LESSP . !&PALIS(CDR U,VARS);
- SYMBOLIC PROCEDURE !&PALIST(U, VBLS);
- BEGIN SCALAR L,FN;
- L := LENGTH CDR U;
- RETURN
- IF L = 0 THEN '(QUOTE NIL)
- ELSE IF FN := ASSOC(L,'((1 . NCONS)
- (2 . LIST2)
- (3 . LIST3)
- (4 . LIST4)
- (5 . LIST5)))
- THEN !&PA1(CDR FN . CDR U, VBLS)
- ELSE !&PA1(LIST('CONS,CADR U, 'LIST . CDDR U), VBLS);
- END;
- lisp procedure !&PaNth(U, Vbls);
- !&PaNths(U, Vbls, '((1 . CAR) (2 . CADR) (3 . CADDR) (4 . CADDDR)));
- lisp procedure !&PaPNth(U, Vbls);
- !&PaNths(U, Vbls, '((1 . CR)
- (2 . CDR)
- (3 . CDDR)
- (4 . CDDDR)
- (5 . CDDDDR)));
- lisp procedure !&PaNths(U, Vbls, FnTable);
- begin scalar N, X, Fn;
- N := !&Pa1(third U, Vbls);
- X := second U;
- return if first N memq '(QUOTE WCONST) and FixP second N
- and (Fn := Assoc(second N, FnTable)) then
- if cdr Fn = 'CR then
- !&Pa1(X, Vbls)
- else !&Pa1(list(cdr Fn, X), Vbls)
- else list(car U, !&Pa1(X, Vbls), N);
- end;
- SYMBOLIC PROCEDURE !&PAMAP(U, VBLS);
- !&PAMAPDO(U, VBLS, NIL);
- SYMBOLIC PROCEDURE !&PAMAPC(U, VBLS);
- !&PAMAPDO(U, VBLS, T);
- SYMBOLIC PROCEDURE !&PAMAPDO(U, VBLS, CARFLAG);
- IF NOT EQCAR(CADDR U,'FUNCTION) THEN CAR U . !&PALIS(CDR U,VBLS)
- ELSE BEGIN SCALAR TMP;
- TMP := !&GENSYM();
- RETURN !&PA1(SUBLA(LIST('TMP . TMP,
- 'STARTINGLIST . CADR U,
- 'FNCALL . LIST(CADR CADDR U,
- IF CARFLAG THEN
- LIST('CAR, TMP)
- ELSE TMP)),
- '(PROG (TMP)
- (SETQ TMP STARTINGLIST)
- LOOPLABEL
- (COND ((ATOM TMP) (RETURN NIL)))
- FNCALL
- (SETQ TMP (CDR TMP))
- (GO LOOPLABEL))), VBLS);
- END;
- SYMBOLIC PROCEDURE !&PAMAPLIST(U, VBLS);
- !&PAMAPCOLLECT(U, VBLS, NIL);
- SYMBOLIC PROCEDURE !&PAMAPCAR(U, VBLS);
- !&PAMAPCOLLECT(U, VBLS, T);
- SYMBOLIC PROCEDURE !&PAMAPCOLLECT(U, VBLS, CARFLAG);
- IF NOT EQCAR(CADDR U,'FUNCTION) THEN CAR U . !&PALIS(CDR U,VBLS)
- ELSE BEGIN SCALAR TMP, RESULT, ENDPTR;
- TMP := !&GENSYM();
- RESULT := !&GENSYM();
- ENDPTR := !&GENSYM();
- RETURN !&PA1(SUBLA(LIST('TMP . TMP,
- 'RESULT . RESULT,
- 'ENDPTR . ENDPTR,
- 'STARTINGLIST . CADR U,
- 'FNCALL . LIST(CADR CADDR U,
- IF CARFLAG THEN
- LIST('CAR, TMP)
- ELSE TMP)),
- '(PROG (TMP RESULT ENDPTR)
- (SETQ TMP STARTINGLIST)
- (COND ((ATOM TMP) (RETURN NIL)))
- (SETQ RESULT (SETQ ENDPTR (NCONS FNCALL)))
- LOOPLABEL
- (SETQ TMP (CDR TMP))
- (COND ((ATOM TMP) (RETURN RESULT)))
- (RPLACD ENDPTR (NCONS FNCALL))
- (SETQ ENDPTR (CDR ENDPTR))
- (GO LOOPLABEL))), VBLS);
- END;
- SYMBOLIC PROCEDURE !&PAMAPCON(U, VBLS);
- !&PAMAPCONC(U, VBLS, NIL);
- SYMBOLIC PROCEDURE !&PAMAPCAN(U, VBLS);
- !&PAMAPCONC(U, VBLS, T);
- SYMBOLIC PROCEDURE !&PAMAPCONC(U, VBLS, CARFLAG);
- IF NOT EQCAR(CADDR U,'FUNCTION) THEN CAR U . !&PALIS(CDR U,VBLS)
- ELSE BEGIN SCALAR TMP, RESULT, ENDPTR;
- TMP := !&GENSYM();
- RESULT := !&GENSYM();
- ENDPTR := !&GENSYM();
- RETURN !&PA1(SUBLA(LIST('TMP . TMP,
- 'RESULT . RESULT,
- 'ENDPTR . ENDPTR,
- 'STARTINGLIST . CADR U,
- 'FNCALL . LIST(CADR CADDR U,
- IF CARFLAG THEN
- LIST('CAR, TMP)
- ELSE TMP)),
- '(PROG (TMP RESULT ENDPTR)
- (SETQ TMP STARTINGLIST)
- STARTOVER
- (COND ((ATOM TMP) (RETURN NIL)))
- (SETQ RESULT FNCALL)
- (SETQ ENDPTR (LASTPAIR RESULT))
- (SETQ TMP (CDR TMP))
- (COND ((ATOM ENDPTR) (GO STARTOVER)))
- LOOPLABEL
- (COND ((ATOM TMP) (RETURN RESULT)))
- (RPLACD ENDPTR FNCALL)
- (SETQ ENDPTR (LASTPAIR ENDPTR))
- (SETQ TMP (CDR TMP))
- (GO LOOPLABEL))), VBLS);
- END;
- % Attempt to change MEMBER to MEMQ
- SYMBOLIC PROCEDURE !&PAMEMBER(U,VARS);
- !&PAMEMBER1(CADR U,CADDR U) . !&PALIS(CDR U,VARS);
- SYMBOLIC PROCEDURE !&PAMEMBER1(THING,LST);
- IF !&EQVP THING OR EQCAR(LST,'QUOTE) AND !&EQPL CADR LST
- THEN 'MEMQ ELSE 'MEMBER;
- % (Intern (Compress X)) == (Implode X)
- % (Intern (Gensym)) == (InternGensym)
- SYMBOLIC PROCEDURE !&PAINTERN(U, VBLS);
- << U := !&PA1(CADR U, VBLS);
- IF EQCAR(U, 'COMPRESS) THEN 'IMPLODE . CDR U
- ELSE IF EQCAR(U, 'GENSYM) THEN 'INTERNGENSYM . CDR U
- ELSE LIST('INTERN, U) >>;
- % Do MINUS on constants.
- SYMBOLIC PROCEDURE !&PAMINUS(U,VBLS);
- IF EQCAR(U := !&PA1(CADR U,VBLS),'QUOTE) AND NUMBERP CADR U
- THEN MKQUOTE ( - CADR U)
- ELSE IF EQCAR(U ,'WCONST) AND NUMBERP CADR U
- THEN MKWCONST ( - CADR U)
- ELSE LIST('MINUS,U);
- SYMBOLIC PROCEDURE !&REFORMLOC U;
- IF EQCAR(CADR U, 'MEMORY) THEN
- LIST('WPLUS2, CADDR CADR U, CADR CADR U)
- ELSE U;
- SYMBOLIC PROCEDURE !&REFORMNULL U;
- BEGIN SCALAR FLIP;
- RETURN
- IF PAIRP CADR U AND (FLIP := GET(CAADR U,'FLIPTST)) THEN
- FLIP . CDADR U
- ELSE LIST('EQ, CADR U, '(QUOTE NIL));
- END;
- % Perdue 12/3/82
- % This optimization causes compiled code to behave differently
- % from interpreted code. The FLIPTST property on NE and PASS2
- % handling of negation in tests (&COMTST) are enough to cause good code
- % to be generated when NE is used as a test.
- % SYMBOLIC PROCEDURE !&REFORMNE U;
- % IF CADR U = '(QUOTE NIL) THEN CADDR U
- % ELSE IF CADDR U = '(QUOTE NIL) THEN CADR U
- % ELSE U;
- % PLUS2(X,1) -> ADD1(X)
- SYMBOLIC PROCEDURE !&PAPLUS2(U,VARS);
- IF CADDR U=1 THEN !&PA1(LIST('ADD1, CADR U),VARS)
- ELSE IF CADR U=1 THEN !&PA1('ADD1 . CDDR U,VARS)
- ELSE 'PLUS2 . !&PALIS(CDR U,VARS);
- % Pick up PROG vars, ignore labels.
- SYMBOLIC PROCEDURE !&PAPROG(U,VBLS);
- <<VBLS := APPEND(CADR U,VBLS);
- 'PROG . (!&PALIS(CADR U,VBLS) . !&PAPROGBOD(CDDR U,VBLS)) >>;
- SYMBOLIC PROCEDURE !&PAPROGBOD(U,VBLS);
- FOR EACH X IN U COLLECT IF ATOM X THEN X ELSE !&PA1(X,VBLS);
- SYMBOLIC PROCEDURE !&PAPUTMEM(U,VBLS);
- !&PA1('SETQ . LIST('GETMEM, CADR U) . CDDR U, VBLS);
- SYMBOLIC PROCEDURE !&PAPUTLISPVAR(U, VBLS);
- !&PA1('SETQ . LIST('LISPVAR, CADR U) . CDDR U, VBLS);
- SYMBOLIC PROCEDURE !&PALISPVAR(U, VBLS);
- LIST('!$FLUID, CADR U);
- SYMBOLIC PROCEDURE !&PASETQ(U,VBLS);
- BEGIN SCALAR VAR,FN,EXP, LN;
- LN := LENGTH CDR U;
- IF LN NEQ 2 THEN RETURN
- << LN := DIVIDE(LN, 2);
- IF CDR LN NEQ 0 THEN
- << !&COMPERROR LIST("Odd number of arguments to SETQ", U);
- U := APPEND(U, LIST NIL);
- LN := CAR LN + 1 >>
- ELSE LN := CAR LN;
- U := CDR U;
- FOR I := 1 STEP 1 UNTIL LN DO
- << EXP := LIST('SETQ, CAR U, CADR U) . EXP;
- U := CDDR U >>;
- !&PA1('PROGN . REVERSIP EXP, VBLS) >>;
- VAR := !&PA1(CADR U,VBLS);
- EXP := !&PA1V(CADDR U, VBLS, VAR);
- U := IF FLAGP(CAR VAR,'VAR) THEN LIST('!$NAME,VAR) ELSE VAR;
- IF (NOT (FN := GET(CAR EXP,'MEMMODFN))) OR not (LastCar EXP = VAR) THEN
- RETURN LIST('SETQ,U,EXP)
- ELSE RETURN FN . U . REVERSIP CDR REVERSIP CDR EXP;
- END;
- SYMBOLIC PROCEDURE !&INSTALLDESTROY(NAME!&);
- % determine which (if any) registers are unaltered by the function.
- % Print this information out if !*SHOWDEST, install it on the
- % property list of the function if !*INSTALLDESTOY
- BEGIN SCALAR DESTL,R,HRU;
- HRU := !&HIGHEST(CODELIST!&,NIL,NARG!&,T);
- % Find the highest register used in the code. Registers above this are
- % unchanged. Incoming registers have a distinguished value, IREG n, placed
- % in register n. If this value remains, it has not been destroyed.
- IF HRU = 'ALL THEN RETURN NIL;
- DESTL := NIL;
- FOR I := 1:NARG!& DO
- <<R := !&MKREG I;
- IF NOT (!&IREG I MEMBER !®VAL R) THEN DESTL := R . DESTL>>;
- FOR I := NARG!&+1 : HRU DO
- DESTL := !&MKREG I . DESTL;
- IF NULL DESTL THEN DESTL := '((REG 1));
- IF !*INSTALLDESTROY THEN PUT(NAME!&,'DESTROYS,DESTL);
- IF !*SHOWDEST THEN <<PRIN2 NAME!&;PRIN2 " DESTROYS ";PRIN2T DESTL>>;
- END;
- % COMPROC does the dirty work - initializes variables and gets the
- % three passes going.
- SYMBOLIC PROCEDURE !&COMPROC(EXP,NAME!&);
- %compiles a function body, returning the generated LAP;
- BEGIN SCALAR CODELIST!&,FLAGG!&,JMPLIST!&,LBLIST!&,
- LOCALGENSYM!&,
- LLNGTH!&,REGS!&,REGS1!&,ALSTS!&,
- EXITT!&,TOPLAB!&,SLST!&,STOMAP!&,
- CONDTAIL!&,FREEBOUND!&,HOLEMAP!&,PREGS!&,
- SWITCH!&,EXITREGS!&,RN; INTEGER NARG!&;
- LOCALGENSYM!& := GLOBALGENSYM!&;
- PREGS!& := NIL;
- REGS!& := NIL;
- LLNGTH!& := 0;
- IF NOT EQCAR(EXP, 'LAMBDA) THEN
- << !&COMPERROR LIST("Attempt to compile a non-lambda expression", EXP);
- RETURN NIL >>;
- NARG!& := LENGTH CADR EXP;
- EXITREGS!& := NIL;
- EXITT!& := !&GENLBL();
- TOPLAB!& := !&GENLBL();
- STOMAP!& := NIL;
- CODELIST!& := LIST '(!*ALLOC (!*FRAMESIZE));
- !&ATTLBL TOPLAB!&;
- EXP := !&PASS1 EXP;
- IF NARG!& > MAXNARGS!&
- THEN !&COMPERROR LIST("Too many arguments",NARG!&);
- ALSTS!& := !&VARBIND(CADR EXP,T); % Generate LAMBIND
- RN := 1;
- FOR I := 1:LENGTH CADR EXP DO
- REGS!& := !&ADDRVALS(!&MKREG I,REGS!&,LIST( !&IREG I));
- !&PASS2 CADDR EXP;
- !&FREERSTR(ALSTS!&,0); %Restores old fluid bindings
- !&PASS3();
- IF !*INSTALLDESTROY OR !*SHOWDEST THEN !&INSTALLDESTROY(NAME!&);
- !&REFORMMACROS(); % Plugs compile time constants into macros. FIXFRM?
- !&REMTAGS(); % Kludge
- RETURN CODELIST!&
- END;
- lisp procedure !&IReg N;
- if N > 0 and N <= 15 then
- GetV('[() (IREG 1) (IREG 2) (IREG 3) (IREG 4) (IREG 5)
- (IREG 6) (IREG 7) (IREG 8) (IREG 9) (IREG 10)
- (IREG 11) (IREG 12) (IREG 13) (IREG 14) (IREG 15)], n)
- else list('IREG, N);
- SYMBOLIC PROCEDURE !&WCONSTP X;
- PairP X and (first X = 'WConst or first X = 'Quote and FixP second X);
- %************************************************************
- % Pass 2 *
- %************************************************************
- % Initialize STATUS!&=0 (Top level)
- SYMBOLIC PROCEDURE !&PASS2 EXP; !&COMVAL(EXP,0);
- SYMBOLIC PROCEDURE !&COMVAL(EXP,STATUS!&);
- % Compile EXP. Special cases: if STATUS!&>1 (compiling for side effects),
- % anyreg functions are ignored since they have no side effects.
- % Otherwise, top level ANYREG stuff is factored out and done via a LOAD
- % instead of a LINK.
- IF !&ANYREG(EXP)
- THEN IF STATUS!&>1 THEN
- <<IF NOT (CAR EXP MEMBER '(QUOTE !$LOCAL !$FLUID)) THEN
- !&COMPWARN(LIST("Value of",
- EXP,
- "not used, therefore not compiled"));
- NIL >>
- ELSE !&LREG1(EXP) % Just a LOAD
- ELSE % When not all ANYREG
- IF !&ANYREGFNP EXP % Is the top level an ANYREG fn?
- THEN IF STATUS!&>1 THEN
- <<!&COMVAL(CADR EXP,STATUS!&);
- !&COMPWARN LIST("Top level", CAR EXP,
- "in", EXP, "not used, therefore not compiled");
- NIL>>
- ELSE
- !&LREG1(CAR EXP . !&COMLIS CDR EXP) % Preserve the anyreg fn
- ELSE !&COMVAL1(EXP,STOMAP!&,STATUS!&); % no anyregs in sight
- % Generate code which loads the value of EXP into register 1
- % Patch to COMVAL1 for better register allocation
- SYMBOLIC PROCEDURE !&COMVAL1(EXP,STOMAP!&,STATUS!&);
- BEGIN SCALAR X;
- IF !&ANYREG EXP OR !&OPENFNP EXP OR !&ANYREGFNP EXP THEN
- IF STATUS!&<2 AND !&NOSIDEEFFECTP EXP
- THEN !&COMPWARN(LIST(EXP," not compiled"))
- ELSE <<!&LOADOPENEXP(IF STATUS!& > 1 THEN !&AllocTemp(Exp)
- ELSE '(REG 1),
- CAR EXP . !&COMLIS CDR EXP,STATUS!&,PREGS!&)>>
- ELSE IF NOT ATOM CAR EXP % Non atomic function?
- THEN IF CAAR EXP EQ 'LAMBDA
- THEN !&COMPLY(CAR EXP,CDR EXP,STATUS!&) % LAMBDA compilation
- ELSE !&COMPERROR LIST(CAR EXP, "Invalid as function")
- % Should be noticed in pass 1
- ELSE IF X := GET(CAR EXP,'COMPFN) THEN APPLY(X,LIST(EXP,STATUS!&))
- % Dispatch built in compiler functions
- ELSE IF CAR EXP EQ 'LAMBDA
- THEN !&COMPERROR LIST("Invalid use of LAMBDA in COMVAL1",EXP)
- ELSE !&CALL(CAR EXP,CDR EXP,STATUS!&); % Call a function
- RETURN NIL
- END;
- % Procedure to allocate temps for OPEN exprs. Used only when STATUS!&<1 to
- % set up destination. Only special case is SETQ. SETQ tries to put the
- % value of X:=... into a register containing X (keeps variables in the same
- % register if possible.
- Symbolic Procedure !&Alloctemp(Exp);
- if car Exp = 'Setq then
- if car caddr exp = 'Setq then % Nested setq - move to actual RHS
- !&Alloctemp(caddr Exp)
- else
- begin
- Scalar Reg;
- If (Reg := !&RAssoc(Cadr Cadr Exp,Regs!&)) % LHS variable already in reg?
- and not (Car Reg member PRegs!&) then % and reg must be available
- Return Car Reg % Return the reg previously used for the var
- else
- Return !&Tempreg() % Just get a temp
- end
- else !&TempReg(); % not SETQ - any old temp will do
- SYMBOLIC PROCEDURE !&CALL(FN,ARGS,STATUS!&);
- !&CALL1(FN,!&COMLIS1 ARGS,STATUS!&);
- %Args have been compiled
- SYMBOLIC PROCEDURE !&CALL1(FN,ARGS,STATUS!&);
- %ARGS is reversed list of compiled arguments of FN;
- BEGIN INTEGER ARGNO;
- SCALAR DEST!&;
- ARGNO := LENGTH ARGS;
- IF !&ANYREGP FN THEN !&LREG1(FN . ARGS)
- ELSE <<!&LOADARGS(ARGS,1,PREGS!&); %Emits loads to registers
- !&ATTACH LIST('!*LINK,FN,!&CFNTYPE FN,ARGNO);
- !&REMMREFS();
- !&REMVREFS();
- % Default - all registers destroyed
- IF !*USINGDESTROY THEN DEST!& := GET(FN,'DESTROYS);
- IF NULL DEST!& THEN REGS!& := NIL
- ELSE
- BEGIN SCALAR TEMP;
- TEMP := NIL;
- FOR EACH R IN REGS!& DO
- IF NOT(CAR R MEMBER DEST!&) THEN TEMP := R . TEMP;
- REGS!& := TEMP
- END >>
- END;
- % Comlis altered to return unreversed list
- SYMBOLIC PROCEDURE !&COMLIS EXP; REVERSIP !&COMLIS1 EXP;
-
- % COMLIS1 returns reversed list of compiled arguments;
- SYMBOLIC PROCEDURE !&COMLIS1 EXP;
- BEGIN SCALAR ACUSED,Y; % Y gathers a set of ANYREG expressions denoting
- % the params. Code for non ANYREG stuff is emitted by ATTACH. ACUSED is
- % name of psuedo variable holding results of non anyreg stuff.
- Y := NIL;
- WHILE EXP DO
- <<IF !&CONSTP CAR EXP OR
- !&OPENP CAR EXP
- AND (NOT !*ORD OR !&NOSIDEEFFECTPL CDR EXP)
- THEN Y := CAR EXP . Y
- % Anyreg stuff is handled later. Anyreg args are not loaded until after
- % all others.
- % If !*ORD is true, order is still switched unless no side effects
- ELSE <<
- %/ Special coding for top level ANYREG
- IF ACUSED THEN !&SAVER1();
- IF (!&ANYREGFNP CAR EXP OR !&OPENFNP CAR EXP)
- AND (NOT !*ORD OR !&NOSIDEEFFECTPL CDR EXP) THEN
- <<Y := (CAAR EXP . !&COMLIS CDAR EXP) . Y;
- ACUSED := T>>
- % Emit code to place arg in R1, generate a name for the result to put in R1
- ELSE <<!&COMVAL1(CAR EXP,STOMAP!&,1);
- ACUSED := LIST('!$LOCAL,!&GENSYM());
- REGS!& := !&ADDRVALS('(REG 1),REGS!&,LIST ACUSED);
- % REGS!& the new variable name goes on the code list (rest already emitted)
- Y := ACUSED . Y>>>>;
- % place arg in memory while doing others
- EXP := CDR EXP>>;
- RETURN Y
- END;
- % SAVE R1 IF NECESSARY
- SYMBOLIC PROCEDURE !&SAVER1; %MARKS CONTENTS OF REGISTER 1 FOR STORAGE;
- BEGIN SCALAR X;
- X := !®VAL '(REG 1); % Contents of R1
- IF NULL X OR NOT !&VARP CAR X
- THEN RETURN NIL % Dont save constants
- ELSE IF NOT ASSOC(CAR X,STOMAP!&) THEN !&FRAME CAR X; % For temporaries
- % as generated in COMLIS
- !&STORELOCAL(CAR X,'(REG 1)) % Emit a store
- END;
- % Compiler for LAMBDA
- SYMBOLIC PROCEDURE !&COMPLY(FN,ARGS,STATUS!&);
- BEGIN SCALAR ALSTS!&,VARS, N, I;
- %SCALAR OLDSTOMAP,OLDCODE;
- % OLDSTOMAP := STOMAP!&;
- % OLDCODE := CODELIST!&;
- VARS := CADR FN;
- % Compile args to the lambda
- ARGS := !&COMLIS1 ARGS;
- N := LENGTH ARGS;
- IF N>MAXNARGS!& THEN
- !&COMPERROR LIST("Too many arguments in LAMBDA form",FN);
- % Put the args into registers
- !&LOADARGS(ARGS,1,PREGS!&);
- % Enter new ENVIRONMENT!&
- ARGS := !&REMVARL VARS; % The stores that were protected;
- I := 1;
- % Put this junk on the frame
- ALSTS!& := !&VARBIND(VARS,T); %Old fluid values saved;
- % compile the body
- !&COMVAL(CADDR FN,STATUS!&);
- % Restore old fluids
- !&FREERSTR(ALSTS!&,STATUS!&);
- % Go back to the old ENVIRONMENT!&
- !&RSTVARL(VARS,ARGS);
- %/ !&FIXFRM(OLDSTOMAP,OLDCODE,0)
- END;
- % Load a sequence of expressions into the registers
- SYMBOLIC PROCEDURE !&LOADARGS(ARGS,STATUS!&,PREGS!&);
- BEGIN INTEGER N; SCALAR FN,DESTREG!&;
- N := LENGTH ARGS;
- IF N>MAXNARGS!& THEN
- !&COMPERROR LIST("Too many arguments",ARGS);
- WHILE ARGS DO
- % Generate a load for each arg
- <<DESTREG!& := !&MKREG N;
- !&LOADOPENEXP(DESTREG!&,CAR ARGS,STATUS!&,PREGS!&);
- PREGS!& := DESTREG!& . PREGS!&;
- N := N - 1;
- ARGS := CDR ARGS>>
- END;
-
- SYMBOLIC PROCEDURE !&LOADOPENEXP(DESTREG!&,ARG,STATUS!&,PREGS!&);
- BEGIN SCALAR R;
- IF !&ANYREG ARG OR !&RASSOC(ARG,REGS!&) THEN !&LREG(DESTREG!&,!&LOCATE ARG)
- ELSE IF !&ANYREGFNP ARG THEN
- <<!&LOADOPENEXP(DESTREG!&,CADR ARG,1,PREGS!&);
- !&LREG(DESTREG!&,!&LOCATE (CAR ARG . DESTREG!& . CDDR ARG)) >>
- ELSE % Must be an open function
- IF FLAGP(CAR ARG,'MEMMOD) AND STATUS!& < 2 THEN
- <<!&LOADOPENEXP(DESTREG!&,ARG,2,PREGS!&);
- !&LREG(DESTREG!&,IF EQCAR(CADR ARG,'!$NAME) THEN
- !&LOCATE CADR CADR ARG
- ELSE !&LOCATE CADR ARG)>>
- ELSE
- BEGIN
- SCALAR OPFN,ADJFN,ANYREGARGS;
- ANYREGARGS := !&REMOPEN(DESTREG!&,CDR ARG);
- OPFN := GET(CAR ARG,'OPENFN);
- IF IDP OPFN THEN
- APPLY(OPFN,LIST(DESTREG!&,ANYREGARGS,ARG))
- ELSE
- !&CALLOPEN(OPFN,DESTREG!&,ANYREGARGS,CAR ARG)
- END;
- END;
- SYMBOLIC PROCEDURE !&REMOPEN(DESTREG!&,ARGS);
- FOR EACH ARG IN ARGS COLLECT !&ARGLOC ARG;
- SYMBOLIC PROCEDURE !&ARGLOC ARG;
- BEGIN SCALAR LOC;
- IF EQCAR(ARG,'!$NAME) THEN RETURN ARG;
- IF !&CONSTP ARG THEN RETURN ARG;
- IF EQCAR(ARG,'MEMORY) THEN RETURN !&MEMADDRESS ARG;
- IF LOC := !&RASSOC(ARG,REGS!&) THEN
- <<PREGS!& := CAR LOC . PREGS!&; RETURN CAR LOC>>;
- IF !&ANYREG ARG THEN RETURN ARG;
- IF !&ANYREGFNP ARG THEN RETURN (CAR ARG . !&ARGLOC CADR ARG . CDDR ARG);
- IF NULL DESTREG!& OR DESTREG!& MEMBER PREGS!& THEN DESTREG!& := !&TEMPREG();
- IF FLAGP(CAR ARG,'MEMMOD) THEN
- <<!&LOADOPENEXP(DESTREG!&,ARG,2,PREGS!&);
- RETURN CADR CADR ARG>>
- ELSE !&LOADOPENEXP(DESTREG!&,ARG,1,PREGS!&);
- PREGS!& := DESTREG!& . PREGS!&;
- RETURN DESTREG!&
- END;
- SYMBOLIC PROCEDURE !&MEMADDRESS ARG;
- BEGIN SCALAR TEMPDEST;
- PREGS!& := DESTREG!& . PREGS!&;
- TEMPDEST := !&TEMPREG();
- PREGS!& := CDR PREGS!&;
- ARG := CAR ARG . !&REMOPEN(TEMPDEST,CDR ARG);
- IF NOT(CADDR ARG = '(WCONST 0) AND NOT !&ANYREGFNP CADR ARG
- OR !®FP CADR ARG) THEN
- <<!&LREG(TEMPDEST,!&LOCATE CADR ARG);
- ARG := CAR ARG . TEMPDEST . CDDR ARG>>;
- IF CADR ARG = TEMPDEST THEN PREGS!& := TEMPDEST . PREGS!&;
- RETURN ARG;
- END;
- SYMBOLIC PROCEDURE !&CALLOPEN(OPFN,DEST!&,ARGS,OP);
- BEGIN
- SCALAR PATS,PARAMS,ADJFN,REGFN,ENVIRONMENT!&;
- PATS := CAR OPFN;
- IF IDP PATS THEN PATS := GET(PATS,'PATTERN);
- PARAMS := OP . CDR OPFN;
- ADJFN := CAR PATS;
- REGFN := CADR PATS;
- IF ADJFN THEN ARGS := APPLY(ADJFN,LIST ARGS);
- PATS := CDDR PATS;
- WHILE NOT NULL PATS AND NOT !&MATCHES(CAAR PATS,ARGS) DO
- PATS := CDR PATS;
- IF NULL PATS THEN
- <<!&COMPERROR(LIST("Compiler bug - no pattern for",OP . ARGS));
- RETURN NIL>>;
- FOR EACH MAC IN CDAR PATS DO
- !&EMITMAC(!&SUBARGS(MAC,ARGS,PARAMS));
- IF REGFN THEN IF IDP REGFN THEN APPLY(REGFN,LIST(OP, ARGS))
- ELSE !&EMITMAC(!&SUBARGS(REGFN,ARGS,PARAMS));
- RETURN NIL;
- END;
- SYMBOLIC PROCEDURE !&MATCHES(PAT,SUBJ);
- IF EQCAR(PAT,'QUOTE) THEN CADR PAT = SUBJ
- ELSE IF NULL PAT THEN NULL SUBJ
- ELSE IF EQCAR(PAT,'NOVAL) THEN STATUS!& > 1 AND !&MATCHES(CDR PAT,SUBJ)
- ELSE IF ATOM PAT THEN APPLY(GET(PAT,'MATCHFN),LIST SUBJ)
- ELSE PAIRP SUBJ AND !&MATCHES(CAR PAT,CAR SUBJ)
- AND !&MATCHES(CDR PAT,CDR SUBJ);
- SYMBOLIC PROCEDURE !&ANY U;T;
- SYMBOLIC PROCEDURE !&DEST U;U = DEST!&;
- % An anyreg which uses DEST!& at any level
- SYMBOLIC PROCEDURE !&USESDEST U;
- !&DEST U OR PAIRP U AND !&USESDESTL CDR U;
- SYMBOLIC PROCEDURE !&USESDESTL U;
- PAIRP U AND (!&DEST CAR U OR !&USESDEST CAR U OR !&USESDESTL CDR U);
- SYMBOLIC PROCEDURE !®FP U;!®P U OR EQCAR(U,'!$LOCAL);
- SYMBOLIC PROCEDURE !®N U; !®P U OR EQCAR(U,'!$LOCAL) OR U = '(QUOTE NIL);
- SYMBOLIC PROCEDURE !&MEM U;
- NOT(U = '(QUOTE NIL) OR EQCAR(U,'!$LOCAL))
- AND (!&CONSTP U OR !&VARP U OR CAR U = 'MEMORY);
- SYMBOLIC PROCEDURE !&NOTANYREG U;!&MEM U OR !®FP U;
- SYMBOLIC PROCEDURE !&SUBARGS(MAC,ARGS,PARAMS);
- FOR EACH ARG IN MAC COLLECT !&SUBARG(ARG,ARGS,PARAMS);
- SYMBOLIC PROCEDURE !&SUBARG(ARG,ARGS,PARAMS);
- BEGIN SCALAR ARGFN;
- RETURN
- IF EQCAR(ARG,'QUOTE) THEN CADR ARG
- ELSE IF PAIRP ARG THEN !&SUBARGS(ARG,ARGS,PARAMS)
- ELSE IF ARG = 'DEST THEN DEST!&
- ELSE IF ARGFN := GET(ARG,'SUBSTFN) THEN
- APPLY(ARGFN,LIST(ARG,ARGS,PARAMS))
- ELSE !&COMPERROR(LIST("Compiler bug", ARG,"invalid in macro"))
- END;
- SYMBOLIC PROCEDURE !&ARG1(ARG,ARGS,PARAMS);
- !&LOCATE CAR ARGS;
- SYMBOLIC PROCEDURE !&ARG2(ARG,ARGS,PARAMS);
- !&LOCATE CADR ARGS;
- SYMBOLIC PROCEDURE !&ARG3(ARG,ARGS,PARAMS);
- !&LOCATE CADDR ARGS;
- SYMBOLIC PROCEDURE !&ARG4(ARG,ARGS,PARAMS);
- !&LOCATE CADDDR ARGS;
- SYMBOLIC PROCEDURE !&PARAM1(ARG,ARGS,PARAMS);
- CAR PARAMS;
- SYMBOLIC PROCEDURE !&PARAM2(ARG,ARGS,PARAMS);
- CADR PARAMS;
- SYMBOLIC PROCEDURE !&PARAM3(ARG,ARGS,PARAMS);
- CADDR PARAMS;
- SYMBOLIC PROCEDURE !&PARAM4(ARG,ARGS,PARAMS);
- CADDDR PARAMS;
- SYMBOLIC PROCEDURE !&GETTEMP(TNAME,ARGS,PARAMS);
- BEGIN SCALAR TN;
- RETURN IF TN := ASSOC(TNAME,ENVIRONMENT!&) THEN CDR TN
- ELSE <<TN := !&TEMPREG();
- ENVIRONMENT!& := (TNAME . TN) . ENVIRONMENT!&;
- PREGS!& := TN . PREGS!&;
- TN>>;
- END;
- SYMBOLIC PROCEDURE !&GETTEMPLBL(LNAME,ARGS,PARAMS);
- BEGIN SCALAR LAB;
- RETURN IF LAB := ASSOC(LNAME,ENVIRONMENT!&) THEN CDR LAB
- ELSE <<LAB := !&GENLBL();
- ENVIRONMENT!& := (LNAME . LAB) . ENVIRONMENT!&;
- LAB>>
- END;
- SYMBOLIC PROCEDURE !&GENSYM(); % gensym local to compiler, reuses symbols
- BEGIN SCALAR SYMB;
- IF NULL CDR LOCALGENSYM!& THEN
- RPLACD(LOCALGENSYM!&, LIST GENSYM());
- SYMB := CAR LOCALGENSYM!&;
- LOCALGENSYM!& := CDR LOCALGENSYM!&;
- RETURN SYMB;
- END;
- SYMBOLIC PROCEDURE !&COMPERROR U;
- << ERRORPRINTF("***** in %P: %L", NAME!&, U);
- ERFG!* := T >>;
- SYMBOLIC PROCEDURE !&COMPWARN U;
- !*MSG AND ERRORPRINTF("*** in %P: %L", NAME!&, U);
- SYMBOLIC PROCEDURE !&EMITMAC MAC;
- BEGIN SCALAR EMITFN;
- IF CAR MAC = '!*DO THEN APPLY(CADR MAC,CDDR MAC)
- ELSE IF CAR MAC = '!*DESTROY THEN
- FOR EACH REG IN CDR MAC DO REGS!& := DELASC(REG,REGS!&)
- ELSE IF CAR MAC = '!*SET THEN
- REGS!& := !&REPASC(CADR MAC,!&REMREGSL CADDR MAC,REGS!&)
- ELSE
- IF EMITFN := GET(CAR MAC,'EMITFN) THEN
- APPLY(EMITFN,LIST MAC)
- ELSE !&ATTACH MAC
- END;
- SYMBOLIC PROCEDURE !&EMITLOAD M;
- !&LREG(CADR M,CADDR M);
- SYMBOLIC PROCEDURE !&EMITSTORE M;
- !&STOREVAR(CADDR M,CADR M);
- SYMBOLIC PROCEDURE !&EMITJUMP M;
- !&ATTJMP CADR M;
- SYMBOLIC PROCEDURE !&EMITLBL M;
- !&ATTLBL CADR M;
- SYMBOLIC PROCEDURE !&EMITMEMMOD M;
- BEGIN SCALAR Y, X;
- X := CADR M;
- !&REMREFS X;
- IF EQCAR(X,'!$LOCAL) THEN
- WHILE Y := ASSOC(X,SLST!&) DO SLST!& := DELETIP(Y,SLST!&);
- IF EQCAR(X,'!$LOCAL) THEN M := CAR M . !&GETFRM X . CDDR M;
- !&ATTACH(GET(CAR M, 'UNMEMMOD) . CDR M);
- END;
-
- % Support to patterns - register adjustment functions
- SYMBOLIC PROCEDURE !&NOANYREG ARGS;
- % remove all ANYREG stuff except top level MEMORY
- IF NULL ARGS THEN NIL
- ELSE
- !&NOANYREG1 CAR ARGS . !&NOANYREG CDR ARGS;
- SYMBOLIC PROCEDURE !&NOANYREG1 ARG;
- IF !&ANYREGFNP ARG AND NOT EQCAR(ARG,'MEMORY) THEN
- !&LOADTEMPREG ARG ELSE ARG;
- SYMBOLIC PROCEDURE !&INREG ARGS;
- IF NOT !®FP CAR ARGS THEN LIST !&LOADTEMPREG CAR ARGS ELSE ARGS;
- SYMBOLIC PROCEDURE !®MEM ARGS;
- <<ARGS := !&NOANYREG ARGS;
- IF !&MEM CAR ARGS AND !&MEM CADR ARGS THEN
- !&LOADTEMPREG CAR ARGS . CDR ARGS
- ELSE ARGS>>;
- SYMBOLIC PROCEDURE !&DESTMEM ARGS;
- % A1 in DEST!&, A2 in MEM, rest (if any) not anyreg
- <<ARGS := CAR ARGS . !&NOANYREG CDR ARGS;
- IF STATUS!& > 1 THEN
- IF !®FP CAR ARGS THEN ARGS
- ELSE !&LOADTEMPREG CAR ARGS . CDR ARGS
- ELSE IF !&DEST CADR ARGS OR !&USESDEST CADR ARGS THEN
- !&DESTMEM(CAR ARGS . !&LOADTEMPREG CADR ARGS . CDDR ARGS)
- ELSE IF CAR ARGS NEQ DEST!& THEN
- <<!&LREG(DEST!&,!&LOCATE CAR ARGS);
- DEST!& . CDR ARGS>>
- ELSE ARGS>>;
- SYMBOLIC PROCEDURE !&DESTMEMA ARGS;
- % put either a1or A2 into DEST!&, the other to MEM.
- IF CAR ARGS = DEST!& THEN % A1 = DEST!&, make A1 mem or reg
- IF !&NOTANYREG CADR ARGS AND NOT !&USESDEST CADR ARGS THEN ARGS
- ELSE !&LOADTEMP2 ARGS
- ELSE IF CADR ARGS = DEST!& THEN % A2 = DEST!&, make A2 mem or reg
- IF !&NOTANYREG CAR ARGS AND NOT !&USESDEST CAR ARGS THEN ARGS
- ELSE !&LOADTEMP1 ARGS
- ELSE IF !&NOTANYREG CADR ARGS OR NOT !&NOTANYREG CAR ARGS
- THEN % A2 is MEM or A1 is anyreg: make A1 the destination
- <<IF NOT !&NOTANYREG CADR ARGS OR !&USESDEST CADR ARGS THEN
- ARGS := !&LOADTEMP2 ARGS;
- !&LREG(DEST!&,!&LOCATE CAR ARGS);
- DEST!& . CDR ARGS>>
- ELSE % Make A2 the DEST!& - only when A2 is anyreg and a1 is mem
- <<IF NOT !&NOTANYREG CAR ARGS OR !&USESDEST CAR ARGS THEN
- ARGS := !&LOADTEMP1 ARGS;
- !&LREG(DEST!&,!&LOCATE CADR ARGS);
- LIST(CAR ARGS,DEST!&)>>;
- SYMBOLIC PROCEDURE !&LOADTEMP1 U;
- % Bring first arg into a temp
- !&LOADTEMPREG CAR U . CDR U;
- SYMBOLIC PROCEDURE !&LOADTEMP2 U;
- % put second arg in a temp
- CAR U . !&LOADTEMPREG CADR U . CDDR U;
- SYMBOLIC PROCEDURE !&CONSARGS ARGS;
- IF
- NOT !&ANYREGFNP CADR ARGS AND CADR ARGS NEQ DEST!&
- OR
- NOT !&ANYREGFNP CAR ARGS AND CAR ARGS NEQ DEST!&
- THEN ARGS
- ELSE LIST(CAR ARGS,!&LOADTEMPREG CADR ARGS);
- SYMBOLIC PROCEDURE !&LOADTEMPREG ARG;
- % Load ARG into a temporary register. Return the register.
- BEGIN
- SCALAR TEMP;
- TEMP := !&TEMPREG();
- PREGS!& := TEMP . PREGS!&;
- !&LREG(TEMP,!&LOCATE ARG);
- RETURN TEMP
- END;
- SYMBOLIC PROCEDURE !&FIXREGTEST(OP,ARGS);
- !&FIXREGTEST1(OP, first ARGS, second ARGS);
- SYMBOLIC PROCEDURE !&FIXREGTEST1(OP, A1, A2);
- % Fixes up the registers after a conditional jump has been emitted.
- % For JUMPEQ and JUMPNE, equalities can be assumed in REGS!& or REGS1!&
- % For other jumps, REGS!& copied onto REGS1!&.
- <<REGS1!& := REGS!&;
- IF OP = 'EQ OR OP = 'NE THEN
- IF NOT !®P A1 THEN
- << IF !®P A2 THEN !&FIXREGTEST1(OP,A2,A1) >>
- ELSE
- <<IF OP = 'EQ THEN REGS1!& := !&ADDRVALS(A1,REGS1!&,!&REMREGS A2)
- ELSE REGS!& := !&ADDRVALS(A1,REGS!& ,!&REMREGS A2)>>>>;
- SYMBOLIC PROCEDURE !&SETREGS1(OP, ARGS); REGS1!& := REGS!&;
- % Find the location of a variable
- SYMBOLIC PROCEDURE !&LOCATE X;
- BEGIN SCALAR Y,VTYPE;
- % Constants are their own location
- IF ATOM X OR EQCAR(X,'LABEL) OR !&CONSTP X THEN RETURN X;
- IF EQCAR(X,'!$NAME) THEN RETURN CADR X;
- IF CAR X = 'MEMORY THEN
- RETURN(CAR X . !&LOCATE CADR X . CDDR X);
- IF Y := !&RASSOC(X,REGS!&) THEN RETURN CAR Y;
- % If in a register, return the register number
- % Registers are their own location
- % For ANYREG stuff, locate each constant
- IF !&ANYREGFNP X THEN
- RETURN CAR X . !&LOCATEL CDR X;
- IF NOT EQCAR(X,'!$LOCAL) THEN RETURN X;
- % Since the value of the variable has been referenced, a previous store was
- % justified, so it can be removed from SLST!&
- % Must be in the frame, otherwise make nonlocal (really ought to be an error)
- % Frame location (<=0) is returned
- WHILE Y := ASSOC(X,SLST!&) DO SLST!& := DELETIP(Y,SLST!&);
- IF Y := ASSOC(X,STOMAP!&) THEN RETURN CADR Y;
- % Nasty compiler bug. Until we fix it, tell the user to simplify expressions
- !&COMPERROR LIST
- ("Compiler bug: expression too complicated, please simplify",X);
- RETURN '(QUOTE 0); % just so it doesn't blow up
- END;
- SYMBOLIC PROCEDURE !&LOCATEL U;
- FOR EACH X IN U COLLECT !&LOCATE X;
- % Load register REG with value U. V (always NIL except when called from
- % LOADARGS) is a list of other loads to be done
- SYMBOLIC PROCEDURE !&LREG(REG,VAL);
- BEGIN SCALAR ACTUALVAL;
- ACTUALVAL := !&REMREGS VAL;
- IF REG = VAL OR ACTUALVAL MEMBER !®VAL REG THEN RETURN NIL;
- !&ATTACH LIST('!*MOVE,VAL,REG);
- REGS!& := !&REPASC(REG,ACTUALVAL,REGS!&);
- END;
- % Load register 1 with X
- SYMBOLIC PROCEDURE !&LREG1(X); !&LOADOPENEXP('(REG 1),X,1,PREGS!&);
- SYMBOLIC PROCEDURE !&JUMPT LAB;
- !&ATTACH LIST('!*JUMPNOTEQ,LAB,'(REG 1),'(QUOTE NIL));
- SYMBOLIC PROCEDURE !&JUMPNIL LAB;
- !&ATTACH LIST('!*JUMPEQ,LAB,'(REG 1),'(QUOTE NIL));
- COMMENT Functions for Handling Non-local Variables;
- SYMBOLIC PROCEDURE !&VARBIND(VARS,LAMBP);
- %bind FLUID variables in lambda or prog lists;
- %LAMBP is true for LAMBDA, false for PROG;
- BEGIN SCALAR VLOCS,VNAMES,FREGS,Y,REG,TAIL; INTEGER I;
- I := 1;
- FOR EACH X IN VARS DO
- <<
- REG := !&MKREG I;
- IF EQCAR(X,'!$GLOBAL) THEN % whoops
- << !&COMPWARN LIST("Illegal to bind global",
- CADR X, "but binding anyway");
- RPLACA(X,'!$FLUID) >>; % cheat a little
- IF EQCAR(X,'!$FLUID)
- THEN <<FREEBOUND!& := T;
- VNAMES := X . VNAMES;
- IF NOT !*NOFRAMEFLUID THEN VLOCS := !&FRAME X . VLOCS;
- FREGS := REG . FREGS>>
- ELSE IF EQCAR(X,'!$LOCAL)
- THEN <<!&FRAME X;
- !&STORELOCAL(X,IF LAMBP THEN REG ELSE NIL)>>
- ELSE !&COMPERROR LIST("Cannot bind non-local variable",X);
- IF LAMBP THEN
- IF EQCAR(X,'!$LOCAL) THEN
- REGS!& := !&REPASC(REG,LIST X,REGS!&)
- ELSE REGS!& := !&REPASC(REG,NIL,REGS!&);
- I := I + 1>>;
- IF NULL VNAMES THEN RETURN NIL;
- VNAMES := 'NONLOCALVARS . VNAMES;
- FREGS := 'REGISTERS . FREGS;
- VLOCS := 'FRAMES . VLOCS;
- TAIL := IF !*NOFRAMEFLUID THEN LIST VNAMES
- ELSE LIST(VNAMES,VLOCS);
- IF LAMBP THEN !&ATTACH('!*LAMBIND . FREGS . TAIL)
- ELSE !&ATTACH('!*PROGBIND . TAIL);
- IF !*UNSAFEBINDER THEN REGS!& := NIL;
- RETURN TAIL;
- END;
- SYMBOLIC PROCEDURE !&FREERSTR(ALSTS!&,STATUS!&); %restores FLUID variables;
- IF ALSTS!& THEN
- << !&ATTACH('!*FREERSTR . ALSTS!&);
- IF !*UNSAFEBINDER THEN REGS!& := NIL >>;
- % ATTACH is used to emit code
- SYMBOLIC PROCEDURE !&ATTACH U; CODELIST!& := U . CODELIST!&;
- SYMBOLIC PROCEDURE !&STORELOCAL(U,REG);
- %marks expression U in register REG for storage;
- BEGIN SCALAR X;
- IF NULL REG THEN REG := '(QUOTE NIL);
- X := LIST('!*MOVE,REG,!&GETFRM U);
- % Update list of stores done so far
- !&ATTACH X;
- % Zap out earlier stores if there were never picked up
- % ie, if you store to X, then a ref to X will remove this store from
- % SLST!&. Otherwise, the previous store will be removed by CLRSTR
- % SLST!& is for variables only (anything else?)
- !&CLRSTR U;
- SLST!& := (U . CODELIST!&) . SLST!&;
- END;
- SYMBOLIC PROCEDURE !&CLRSTR VAR; %removes unneeded stores;
- BEGIN SCALAR X;
- % Inside conditionals, you cant tell if store was on the same path
- IF CONDTAIL!& THEN RETURN NIL;
- X := ASSOC(VAR,SLST!&);
- IF NULL X THEN RETURN NIL;
- SLST!& := DelQIP(X,SLST!&);
- !&DELMAC CDR X;
- END;
- COMMENT Functions for general tests;
- SYMBOLIC PROCEDURE !&COMTST(EXP,LABL);
- %compiles boolean expression EXP.
- %If EXP has the same value as SWITCH!& then branch to LABL,
- %otherwise fall through;
- %REGS are active registers for fall through,
- %REGS1 for branch;
- BEGIN SCALAR X,FN,REG;
- % First factor out NOT's to set up the SWITCH!&
- WHILE EQCAR(EXP,'EQ) AND CADDR EXP = '(QUOTE NIL) DO
- <<SWITCH!& := NOT SWITCH!&; EXP := CADR EXP>>;
- % Dispatch a built in compiling function
- IF NOT SWITCH!& AND (FN := GET(CAR EXP,'FLIPTST)) THEN
- EXP := FN . CDR EXP; % SWITCH!& is assumed to be true by fn's with
- % a flip test
- IF FN := GET(CAR EXP,'OPENTST)
- THEN <<IF ATOM FN THEN APPLY(FN,LIST(EXP,LABL))
- ELSE !&COMOPENTST(FN,EXP,LABL,PREGS!&)>>
- % Trivial case of condition is T. FLAGG!& indicates jump cannot take place
- ELSE <<IF EQCAR(EXP,'QUOTE) THEN
- IF SWITCH!& AND CADR EXP
- OR (NOT SWITCH!&) AND (NOT CADR EXP) THEN
- <<REGS1!& := REGS!&;
- !&ATTJMP LABL>>
- ELSE FLAGG!& := T
- ELSE <<!&COMTST(LIST('NE,EXP,'(QUOTE NIL)),LABL)>>>>
- END;
- SYMBOLIC PROCEDURE !&COMOPENTST(PAT,EXP,DESTLAB,PREGS!&);
- BEGIN
- SCALAR ANYREGARGS,ADJFN;
- ANYREGARGS := !&REMOPEN(!&TEMPREG(),!&COMLIS CDR EXP);
- !&CALLOPEN(PAT,DESTLAB,ANYREGARGS,CAR EXP)
- END;
- % Remove variables to avoid name conflicts: Hide variable names which match
- % new names when entering an inner function. Other names will be available
- % as global info. VARS is the list of new variable names, the result is a
- % list of protected stores.
- SYMBOLIC PROCEDURE !&REMVARL VARS;
- FOR EACH X IN VARS COLLECT !&PROTECT X;
- % Delete all references to U from SLST!&
- % return the protected store
- SYMBOLIC PROCEDURE !&PROTECT U;
- BEGIN SCALAR X;
- IF X := ASSOC(U,SLST!&) THEN SLST!& := DelQIP(X,SLST!&);
- RETURN X
- END;
- % Restore a previous ENVIRONMENT!&. VARS is the list of variables taken out
- % of the ENVIRONMENT!&; LST is the list of protected stores. One or zero
- % stores for each variable.
- SYMBOLIC PROCEDURE !&RSTVARL(VARS,LST);
- WHILE VARS DO
- <<!&RSTVAR(CAR VARS,CAR LST); VARS := CDR VARS; LST := CDR LST>>;
- % Restore a particular variable and STORE
- SYMBOLIC PROCEDURE !&RSTVAR(VAR,VAL);
- BEGIN
- !&REMREFS VAR;
- !&CLRSTR VAR;
- % Put back on store list if not NIL
- !&UNPROTECT VAL
- END;
- SYMBOLIC PROCEDURE !&UNPROTECT VAL; %restores VAL to SLST!&;
- IF VAL THEN SLST!& := VAL . SLST!&;
- SYMBOLIC PROCEDURE !&STOREVAR(U,V);
- % The store generated by a SETQ
- BEGIN SCALAR VTYPE,X;
- !&REMREFS U;
- IF CAR U = '!$LOCAL THEN
- !&STORELOCAL(U,V)
- ELSE
- !&ATTACH LIST('!*MOVE,V,U);
- IF !®P V THEN
- REGS!& := !&ADDRVALS(V,REGS!&,LIST U)
- END;
- COMMENT Support Functions;
- SYMBOLIC PROCEDURE !&REFERENCES(EXP,VAR);
- % True if expression EXP (probably ANYREG) references VAR.
- EXP = VAR OR
- IF ATOM EXP OR FLAGP(CAR EXP,'TERMINAL) THEN NIL
- ELSE !&REFERENCESL(CDR EXP,VAR);
- SYMBOLIC PROCEDURE !&REFERENCESL(EXP,VAR);
- IF NULL EXP THEN NIL ELSE !&REFERENCES(CAR EXP,VAR)
- OR !&REFERENCESL(CDR EXP,VAR);
- SYMBOLIC PROCEDURE !&CFNTYPE FN;
- BEGIN SCALAR X;
- RETURN IF X := GET(FN,'CFNTYPE) THEN CAR X
- ELSE IF X := GETD FN THEN CAR X
- ELSE 'EXPR
- END;
- SYMBOLIC PROCEDURE !&GENLBL;
- BEGIN SCALAR L;
- L := LIST('LABEL,!&GENSYM());
- LBLIST!& := LIST L . LBLIST!&;
- RETURN L
- END;
- SYMBOLIC PROCEDURE !&GETLBL LABL;
- BEGIN SCALAR X;
- X := ASSOC(LABL,GOLIST!&);
- IF NULL X THEN !&COMPERROR LIST("Compiler bug: missing label", LABL);
- RETURN CDR X
- END;
- SYMBOLIC PROCEDURE !&ATTLBL LBL;
- IF CAAR CODELIST!& EQ '!*LBL THEN !&DEFEQLBL(LBL,CADR CAR CODELIST!&)
- ELSE !&ATTACH LIST('!*LBL,LBL);
- SYMBOLIC PROCEDURE !&ATTJMP LBL;
- BEGIN
- IF CAAR CODELIST!& EQ '!*LBL
- THEN <<!&DEFEQLBL(LBL,CADR CAR CODELIST!&);
- !&DELMAC CODELIST!&>>;
- IF !&TRANSFERP CODELIST!& THEN RETURN NIL;
- !&ATTACH LIST('!*JUMP,LBL);
- END;
- SYMBOLIC PROCEDURE !&TRANSFERP X;
- IF CAAR X = '!*NOOP THEN !&TRANSFERP CDR X ELSE
- FLAGP(IF CAAR X EQ '!*LINK THEN CADAR X ELSE CAAR X,'TRANSFER);
- SYMBOLIC PROCEDURE !&DEFEQLBL(LAB1,LAB2);
- LBLIST!& := !&DEFEQLBL1(LBLIST!&,LAB1,LAB2);
- SYMBOLIC PROCEDURE !&DEFEQLBL1(LABS,LAB1,LAB2);
- IF LAB1 MEMBER CAR LABS THEN
- IF LAB2 MEMBER CAR LABS THEN LABS
- ELSE APPEND(!&LABCLASS LAB2,CAR LABS) . !&DELCLASS(LAB2,CDR LABS)
- ELSE IF LAB2 MEMBER CAR LABS THEN
- APPEND(!&LABCLASS LAB1,CAR LABS) . !&DELCLASS(LAB1,CDR LABS)
- ELSE CAR LABS . !&DEFEQLBL1(CDR LABS,LAB1,LAB2);
- SYMBOLIC PROCEDURE !&LABCLASS(LAB);
- BEGIN SCALAR TEMP;
- TEMP := LBLIST!&;
- WHILE TEMP AND NOT (LAB MEMBER CAR TEMP) DO TEMP := CDR TEMP;
- RETURN IF TEMP THEN CAR TEMP ELSE NIL;
- END;
- SYMBOLIC PROCEDURE !&DELCLASS(LAB,LABS);
- IF LAB MEMBER CAR LABS THEN CDR LABS ELSE CAR LABS . !&DELCLASS(LAB,CDR LABS);
- SYMBOLIC PROCEDURE !&LBLEQ(LAB1,LAB2);
- LAB1 MEMBER !&LABCLASS LAB2;
- SYMBOLIC PROCEDURE !&FRAME U; %allocates space for U in frame;
- BEGIN SCALAR Z,RES;
- Z := IF NULL STOMAP!& THEN 1 ELSE 1 + CADR CADAR STOMAP!&;
- RES := !&MKFRAME Z;
- STOMAP!& := LIST(U,RES) . STOMAP!&;
- LLNGTH!& := MAX(Z,LLNGTH!&);
- RETURN RES
- END;
- % GETFRM returns the frame location on a variable
- SYMBOLIC PROCEDURE !&GETFRM U;
- BEGIN SCALAR X;
- IF X:=ASSOC(U,STOMAP!&) THEN RETURN CADR X;
- !&COMPERROR LIST("Compiler bug: lost variable",U)
- END;
- %*************************************************************************
- % The following functions determine classes or properties of expressions *
- %*************************************************************************
- SYMBOLIC PROCEDURE !&ANYREG U;
- % !&ANYREG determines if U is an ANYREG expression
- %
- % ANYREG expressions are those expressions which may be loaded into any
- % register without the use of (visable) temporary registers. It is assumed
- % that ANYREG expressions have no side effects.
- %
- % ANYREG expressions are defined as constants, variables, and ANYREG functions
- % whose arguments are ANYREG expressions. Note that ANYREG functions are
- % not necessarily a part of ANYREG expressions; their arguments may not be
- % ANYREG expressions.
- !&CONSTP U OR !&VARP U OR !&ANYREGFNP U AND !&ANYREGL CDR U;
- SYMBOLIC PROCEDURE !&ANYREGL U;
- NULL U OR !&ANYREG(CAR U) AND !&ANYREGL CDR U;
- SYMBOLIC PROCEDURE !&ANYREGFNP U;
- % !&ANYREGFNP is true when U is an ANYREG function. The arguments are not
- % checked
- !&ANYREGP CAR U;
- SYMBOLIC PROCEDURE !&OPENP U;
- !&CONSTP U OR !&VARP U OR (!&ANYREGFNP U OR !&OPENFNP U) AND !&OPENPL CDR U;
- SYMBOLIC PROCEDURE !&OPENPL U;
- NULL U OR !&OPENP CAR U AND !&OPENPL CDR U;
- SYMBOLIC PROCEDURE !&OPENFNP U;
- GET(CAR U,'OPENFN);
- SYMBOLIC PROCEDURE !&CONSTP U;
- % True if U is a constant expression
- IDP CAR U AND FLAGP(CAR U,'CONST);
- SYMBOLIC PROCEDURE !&VARP U;
- % True if U is a variable: (LOCAL x),(FLUID x), ...
- PAIRP U AND FLAGP(CAR U,'VAR);
- SYMBOLIC PROCEDURE !®P U;
- PAIRP U AND FLAGP(CAR U,'REG);
- SYMBOLIC PROCEDURE !&NOSIDEEFFECTP U;
- % True if the expression U has no side effects. ANYREG expressions and
- % functions are assumed to have no side effects; other functions must be
- % flagged NOSIDEEFFECT. All arguments to a function must also be NOSIDEEFFECT.
- !&ANYREG U OR
- (!&ANYREGFNP U OR FLAGP(CAR U,'NOSIDEEFFECT)) AND !&NOSIDEEFFECTPL CDR U;
- SYMBOLIC PROCEDURE !&NOSIDEEFFECTPL U;
- NULL U OR !&NOSIDEEFFECTP CAR U AND !&NOSIDEEFFECTPL CDR U;
- %**********************************************************************
- % Basic register manipulation utilities
- %**********************************************************************
- SYMBOLIC PROCEDURE !&RVAL(R,RGS);
- % Return the set of values in register R as determined by register list RGS
- IF NULL RGS THEN NIL
- ELSE IF CAAR RGS = R THEN CDAR RGS
- ELSE !&RVAL(R,CDR RGS);
- SYMBOLIC PROCEDURE !®VAL R;
- % Normally, register contents are found in register list REGS!&.
- !&RVAL(R,REGS!&);
- SYMBOLIC PROCEDURE !&ADDRVALS(REG,RGS,VALS);
- % Add the values VALS to the contents of REG in register list RGS
- IF NULL RGS THEN LIST (REG . VALS)
- ELSE IF CAAR RGS = REG THEN (CAAR RGS . APPEND(VALS,CDAR RGS)) . CDR RGS
- ELSE CAR RGS . !&ADDRVALS(REG,CDR RGS,VALS);
- SYMBOLIC PROCEDURE !&MKREG NUM;
- % Used to generate a tagged register from a register number
- BEGIN SCALAR AENTRY;
- RETURN
- IF AENTRY := ASSOC(NUM, '((1 . (REG 1)) (2 . (REG 2)) (3 . (REG 3))
- (4 . (REG 4)) (5 . (REG 5)) (6 . (REG 6))
- (7 . (REG 7)) (8 . (REG 8)) (9 . (REG 9)))) THEN
- CDR AENTRY
- ELSE LIST('REG,NUM);
- END;
- SYMBOLIC PROCEDURE !&MKFRAME NUM;
- % Used to generate a tagged register from a register number
- BEGIN SCALAR AENTRY;
- RETURN
- IF AENTRY := ASSOC(NUM, '((1 . (FRAME 1)) (2 . (FRAME 2)) (3 . (FRAME 3))
- (4 . (FRAME 4)) (5 . (FRAME 5)) (6 . (FRAME 6))
- (7 . (FRAME 7)) (8 . (FRAME 8)) (9 . (FRAME 9))))
- THEN CDR AENTRY
- ELSE LIST('FRAME,NUM);
- END;
- SYMBOLIC PROCEDURE !&RASSOC(VAL,RGS);
- % Find a register in register list RGS which contains VAL. NIL is returned if
- % VAL is not present in RGS
- IF NULL RGS THEN NIL
- ELSE IF VAL MEMBER CDAR RGS THEN CAR RGS
- ELSE !&RASSOC(VAL,CDR RGS);
- SYMBOLIC PROCEDURE !&REPASC(REG,VAL,REGL);
- % Replace the contants of REG in list REGL by the value VAL
- IF NULL REGL THEN LIST (REG . VAL)
- ELSE IF REG=CAAR REGL THEN (REG . VAL) . CDR REGL
- ELSE CAR REGL . !&REPASC(REG,VAL,CDR REGL);
- SYMBOLIC PROCEDURE !&RMERGE U;
- % RMERGE takes a list of register contents representing the information
- % present in the registers from a number of different ways to reach the same
- % place. RMERGE returns whatever information is known to be in the registers
- % regardless of which path was taken.
- IF NULL U THEN NIL ELSE
- BEGIN
- SCALAR RES,CONTENTS;
- RES := NIL;
- FOR EACH RG IN CAR U DO
- <<CONTENTS := NIL;
- FOR EACH THING IN CDR RG DO
- IF !&INALL(THING,CAR RG,CDR U) THEN
- CONTENTS := THING . CONTENTS;
- IF CONTENTS THEN RES := (CAR RG . CONTENTS) . RES>>;
- RETURN RES;
- END;
- SYMBOLIC PROCEDURE !&INALL(THING,RG,LST);
- NULL LST OR (THING MEMBER !&RVAL(RG,CAR LST)) AND !&INALL(THING,RG,CDR LST);
- SYMBOLIC PROCEDURE !&TEMPREG();
- BEGIN SCALAR I,R,EMPTY,UNPROT;
- EMPTY := UNPROT := NIL;
- I := 1;
- WHILE I <= MAXNARGS!& AND NOT EMPTY DO
- <<R := !&MKREG I;
- IF NOT(R MEMBER PREGS!&) THEN
- IF I <= LASTACTUALREG!& AND NULL !®VAL R THEN EMPTY := R
- ELSE IF NOT UNPROT THEN UNPROT := R;
- I := I + 1
- >>;
- IF EMPTY THEN RETURN EMPTY;
- IF UNPROT THEN RETURN UNPROT;
- !&COMPERROR("Compiler bug: Not enough registers");
- RETURN '(REG ERROR);
- END;
- SYMBOLIC PROCEDURE !&REMREGS U;
- IF !®P U THEN !®VAL U
- ELSE IF EQCAR(U,'FRAME) THEN LIST !&GETFVAR (U,STOMAP!&)
- ELSE IF !&CONSTP U OR !&VARP U THEN LIST U
- ELSE !&REMREGSL U;
- SYMBOLIC PROCEDURE !&GETFVAR (V,SMAP);
- IF NULL SMAP THEN !&COMPERROR(LIST("Compiler bug:", V,"evaporated?"))
- ELSE IF CADAR SMAP = V THEN CAAR SMAP
- ELSE !&GETFVAR (V,CDR SMAP);
- SYMBOLIC PROCEDURE !&REMREGSL U;
- FOR EACH ARG IN !&ALLARGS CDR U COLLECT (CAR U . ARG);
- SYMBOLIC PROCEDURE !&ALLARGS ARGLST;
- if null Arglst then NIL
- else IF NULL CDR ARGLST THEN
- FOR EACH VAL IN !&REMREGS CAR ARGLST COLLECT LIST VAL
- ELSE !&ALLARGS1(!&REMREGS CAR ARGLST,!&ALLARGS CDR ARGLST);
- SYMBOLIC PROCEDURE !&ALLARGS1(FIRSTARGS,RESTARGS);
- BEGIN SCALAR RES;
- RES := NIL;
- FOR EACH A1 IN FIRSTARGS DO
- FOR EACH A2 IN RESTARGS DO
- RES := (A1 . A2) . RES;
- RETURN RES;
- END;
- SYMBOLIC PROCEDURE !&REMMREFS();
- REGS!& := FOR EACH R IN REGS!& COLLECT (CAR R . !&REMMREFS1 CDR R);
- SYMBOLIC PROCEDURE !&REMMREFS1 L;
- IF NULL L THEN L ELSE
- IF !&REFMEMORY CAR L THEN !&REMMREFS1 CDR L
- ELSE CAR L . !&REMMREFS1 CDR L;
- SYMBOLIC PROCEDURE !&REFMEMORY EXP;
- IF ATOM EXP OR FLAGP(CAR EXP,'TERMINAL) THEN NIL
- ELSE CAR EXP MEMBER '(MEMORY CAR CDR) OR !&REFMEMORYL CDR EXP;
- SYMBOLIC PROCEDURE !&REFMEMORYL L;
- IF NULL L THEN NIL ELSE !&REFMEMORY CAR L OR !&REFMEMORYL CDR L;
- SYMBOLIC PROCEDURE !&REMVREFS;
- BEGIN SCALAR S;
- REGS!& := FOR EACH R IN REGS!& COLLECT (CAR R . !&REMVREFS1 CDR R);
- % Slow version:
- % SLST!& := FOR EACH S IN SLST!& CONC
- % IF !&EXTERNALVARP CAR S THEN NIL ELSE LIST S;
- % Faster version:
- while not null Slst!& and !&ExternalVarP car car Slst!& do
- Slst!& := cdr Slst!&;
- S := Slst!&;
- while not null S and not null cdr S do
- << if !&ExternalVarP car car cdr S then Rplacd(S, cddr S);
- S := cdr S >>;
- END;
- SYMBOLIC PROCEDURE !&REMVREFS1 L;
- FOR EACH THING IN L CONC
- IF !&REFEXTERNAL THING THEN NIL ELSE LIST THING;
- SYMBOLIC PROCEDURE !&REFEXTERNAL EXP;
- IF ATOM EXP THEN NIL
- ELSE IF !&EXTERNALVARP EXP THEN T
- ELSE IF FLAGP(CAR EXP,'TERMINAL) THEN NIL
- ELSE !&REFEXTERNALL CDR EXP;
- SYMBOLIC PROCEDURE !&REFEXTERNALL EXPS;
- IF NULL EXPS THEN NIL
- ELSE !&EXTERNALVARP CAR EXPS OR !&REFEXTERNALL CDR EXPS;
- SYMBOLIC PROCEDURE !&EXTERNALVARP U;
- PAIRP U AND FLAGP(CAR U,'EXTVAR);
- SYMBOLIC PROCEDURE !&REMREFS V;
- % Remove all references to V from REGS!&
- IF CAR V MEMBER '(MEMORY CAR CDR) THEN
- !&REMMREFS()
- ELSE
- REGS!& := FOR EACH R IN REGS!& COLLECT
- CAR R . !&REMREFS1(V,CDR R);
- SYMBOLIC PROCEDURE !&REMREFS1(X,LST);
- % Remove all expressions from LST which reference X
- IF NULL LST THEN NIL
- ELSE IF !&REFERENCES(CAR LST,X) THEN !&REMREFS1(X,CDR LST)
- ELSE CAR LST . !&REMREFS1(X,CDR LST);
- %************************************************************
- % Test functions
- %************************************************************
- SYMBOLIC PROCEDURE !&TSTANDOR(EXP,LABL);
- BEGIN SCALAR FLG,FLG1,FN,LAB2,REGSL,REGS1L,
- TAILP;
- %FLG is initial SWITCH!& condition;
- %FN is appropriate AND/OR case;
- %FLG1 determines appropriate switching state;
- FLG := SWITCH!&;
- SWITCH!& := NIL;
- FN := CAR EXP EQ 'AND;
- FLG1 := FLG EQ FN;
- EXP := CDR EXP;
- LAB2 := !&GENLBL();
- WHILE EXP DO
- <<SWITCH!& := NIL;
- IF NULL CDR EXP AND FLG1
- THEN <<IF FN THEN SWITCH!& := T;
- !&COMTST(CAR EXP,LABL);
- REGSL := REGS!& . REGSL;
- REGS1L := REGS1!& . REGS1L>>
- ELSE <<IF NOT FN THEN SWITCH!& := T;
- IF FLG1
- THEN <<!&COMTST(CAR EXP,LAB2);
- REGSL := REGS1!& . REGSL;
- REGS1L := REGS!& . REGS1L>>
- ELSE <<!&COMTST(CAR EXP,LABL);
- REGSL := REGS!& . REGSL;
- REGS1L := REGS1!& . REGS1L>>>>;
- IF NULL TAILP
- THEN <<CONDTAIL!& := NIL . CONDTAIL!&; TAILP := T>>;
- EXP := CDR EXP>>;
- !&ATTLBL LAB2;
- REGS!& := IF NOT FLG1 THEN CAR REGSL ELSE !&RMERGE REGSL;
- REGS1!& := IF FLG1 THEN CAR REGS1L ELSE !&RMERGE REGS1L;
- IF TAILP THEN CONDTAIL!& := CDR CONDTAIL!&;
- SWITCH!& := FLG
- END;
- %************************************************************
- % Pass2 compile functions
- %************************************************************
- SYMBOLIC PROCEDURE !&COMANDOR(EXP,STATUS!&);
- BEGIN SCALAR FN,LABL,REGSL;
- FN := CAR EXP EQ 'AND;
- LABL := !&GENLBL();
- EXP := CDR EXP;
- WHILE EXP DO
- <<!&COMVAL(CAR EXP,IF CDR EXP THEN 1 ELSE STATUS!&);
- %to allow for recursion on last entry;
- REGSL := REGS!& . REGSL;
- IF CDR EXP THEN IF FN THEN !&JUMPNIL LABL ELSE !&JUMPT LABL;
- EXP := CDR EXP>>;
- REGS!& := !&RMERGE REGSL;
- !&ATTLBL LABL
- END;
- SYMBOLIC PROCEDURE !&COMAPPLY(EXP,STATUS); % Look for LIST;
- BEGIN SCALAR FN,ARGS, N,NN;
- EXP := CDR EXP;
- FN := CAR EXP;
- ARGS := CDR EXP;
- IF NULL ARGS
- OR CDR ARGS
- OR NOT (PAIRP CAR ARGS
- AND CAAR ARGS MEMBER
- '(LIST QUOTE NCONS LIST1 LIST2 LIST3 LIST4 LIST5))
- OR LENGTH CDAR ARGS>MAXNARGS!&
- THEN RETURN !&CALL('APPLY,EXP,STATUS);
- ARGS := IF EQCAR(CAR ARGS,'QUOTE) THEN
- FOR EACH THING IN CADAR ARGS COLLECT LIST('QUOTE,THING)
- ELSE CDAR ARGS;
- NN := LENGTH ARGS;
- ARGS := REVERSIP (FN . REVERSE ARGS);
- !&LOADARGS(REVERSIP !&COMLIS ARGS,1,PREGS!&);
- !&ATTACH LIST('!*MOVE, !&MKREG(NN + 1), '(REG T1));
- !&ATTACH LIST('!*LINK,'FASTAPPLY,'EXPR, NN);
- REGS!& := NIL;
- !&REMVREFS();
- END;
- %Bug fix to COMCOND - tail has (QUOTE T) not T. Test for tail screwed up anyway
- SYMBOLIC PROCEDURE !&COMCOND(EXP,STATUS!&);
- %compiles conditional expressions;
- %registers REGS!& are set for dropping through,
- %REGS1 are set for a branch;
- BEGIN SCALAR REGS1!&,FLAGG!&,SWITCH!&,LAB1,LAB2,REGSL,
- TAILP;
- EXP := CDR EXP;
- LAB1 := !&GENLBL();
- FOR EACH X ON EXP DO % Changed IN -> ON
- <<LAB2 := !&GENLBL();
- SWITCH!& := NIL;
- IF CDR X THEN !&COMTST(CAAR X,LAB2) % CAR -> CAAR
- %update CONDTAIL!&;
- ELSE IF CAAR X = '(QUOTE T) THEN % CAR -> CAAR, T->(QUOTE T)
- FLAGG!& := T
- ELSE <<!&COMVAL(CAAR X,1); % CAR -> CAAR
- !&JUMPNIL LAB2;
- REGS1!& := !&ADDRVALS('(REG 1),
- REGS!&,
- list '(QUOTE NIL)) >>;
- IF NULL TAILP
- THEN <<CONDTAIL!& := NIL . CONDTAIL!&;
- TAILP := T>>;
- !&COMVAL(CADR CAR X,STATUS!&); %X -> CAR X
- % Branch code;
- %test if need jump to LAB1;
- IF NOT FLAGG!& THEN % New line
- <<IF NOT !&TRANSFERP CODELIST!&
- THEN <<!&ATTJMP LAB1;
- REGSL := REGS!& . REGSL>>;
- REGS!& := REGS1!&;>>;
- %restore register status for next iteration;
- %we do not need to set REGS1!& to NIL since all COMTSTs
- %are required to set it;
- !&ATTLBL LAB2>>;
- IF NULL FLAGG!& AND STATUS!&<2
- THEN <<!&LREG1('(QUOTE NIL));
- REGS!& := !&RMERGE(REGS!& . REGSL)>>
- ELSE IF REGSL
- THEN REGS!& := !&RMERGE(REGS!& . REGSL);
- !&ATTLBL LAB1;
- IF TAILP THEN CONDTAIL!& := CDR CONDTAIL!&
- END;
- SYMBOLIC PROCEDURE !&COMCONS(EXP,STATUS!&);
- IF NULL (EXP := CDR EXP) OR NULL CDR EXP OR CDDR EXP
- THEN !&COMPERROR LIST("Wrong number of arguments to CONS",EXP)
- ELSE IF CADR EXP='(QUOTE NIL)
- THEN !&CALL('NCONS,LIST CAR EXP,STATUS!&)
- ELSE IF CADR EXP MEMBER !®VAL '(REG 1)
- AND !&OPENP CAR EXP
- THEN !&CALL1('XCONS,!&COMLIS EXP,STATUS!&)
- ELSE IF !&OPENP CADR EXP THEN !&CALL('CONS,EXP,STATUS!&)
- ELSE !&CALL1('XCONS,!&COMLIS EXP,STATUS!&);
- SYMBOLIC PROCEDURE !&COMGO(EXP,STATUS!&);
- << IF STATUS!&>1 THEN <<!&ATTJMP !&GETLBL CADR EXP; SLST!& := NIL>>
- ELSE !&COMPERROR LIST(EXP,"invalid go")>>;
- SYMBOLIC PROCEDURE !&COMCASE(EXP,STATUS!&);
- BEGIN SCALAR BOTTOMLAB,REGS1!&,JUMPS,EXPS,ELSELAB,HIGH,LOW,SAVEREGS,
- JMPS,JLIST,RANGES,TABLE,TAILP;
- BOTTOMLAB := !&GENLBL();
- REGS1!& := NIL;
- !&COMVAL(CADR EXP,1);
- JUMPS := EXPS := NIL;
- CONDTAIL!& := NIL . CONDTAIL!&;
- TAILP := T;
- FOR EACH THING ON CDDR EXP DO
- BEGIN SCALAR LAB;
- LAB := !&GENLBL();
- JUMPS := NCONC(JUMPS,LIST LIST(CAAR THING,LAB));
- EXPS := NCONC(EXPS,LIST LIST(LAB,CADAR THING));
- IF NULL CDR THING THEN
- IF NOT NULL CAAR THING THEN
- IF STATUS!& > 1 THEN <<REGS1!& := REGS!& . REGS1!&;
- ELSELAB := BOTTOMLAB>>
- ELSE EXPS := NCONC(EXPS,LIST LIST(ELSELAB := !&GENLBL(),
- '(QUOTE NIL)))
- ELSE ELSELAB := LAB;
- END;
- RANGES := NIL;
- TABLE := NIL;
- FOR EACH JMP IN JUMPS DO
- FOR EACH NUM IN CAR JMP DO
- IF EQCAR(NUM,'RANGE) THEN
- BEGIN
- SCALAR HIGH,LOW;
- LOW := !&GETNUM CADR NUM;
- HIGH := !&GETNUM CADDR NUM;
- IF HIGH >= LOW THEN
- IF HIGH - LOW < 6 THEN
- FOR I := LOW:HIGH DO
- TABLE := !&INSTBL(TABLE,I,CADR JMP)
- ELSE RANGES := NCONC(RANGES,LIST LIST(LOW,HIGH,CADR JMP));
- END
- ELSE TABLE := !&INSTBL(TABLE,!&GETNUM NUM,CADR JMP);
- FOR EACH R IN RANGES DO
- !&ATTACH LIST('!*JUMPWITHIN,CADDR R,CAR R,CADR R);
- WHILE TABLE DO
- <<JMPS := LIST CAR TABLE;
- LOW := HIGH := CAAR TABLE;
- JLIST := LIST CADAR TABLE;
- WHILE CDR TABLE AND CAR CADR TABLE < HIGH + 5 DO
- <<TABLE := CDR TABLE;
- WHILE HIGH < (CAAR TABLE) - 1 DO
- <<HIGH := HIGH + 1;
- JLIST := NCONC(JLIST,LIST ELSELAB)>>;
- HIGH := HIGH + 1;
- JLIST := NCONC(JLIST,LIST CADAR TABLE);
- JMPS := NCONC(JMPS,LIST CAR TABLE)>>;
- IF LENGTH JMPS < 4 THEN
- FOR EACH J IN JMPS DO
- !&ATTACH LIST('!*JUMPEQ,CADR J,'(REG 1),LIST('WCONST,CAR J))
- ELSE
- !&ATTACH('!*JUMPON . '(REG 1) . LOW . HIGH . JLIST);
- TABLE := CDR TABLE>>;
- !&ATTJMP ELSELAB;
- SAVEREGS := REGS!&;
- FOR EACH THING IN EXPS DO
- <<!&ATTLBL CAR THING;
- REGS!& := SAVEREGS;
- IF CADR THING THEN !&COMVAL(CADR THING,STATUS!&);
- IF NOT !&TRANSFERP CODELIST!& THEN
- <<!&ATTJMP BOTTOMLAB;
- REGS1!& := REGS!& . REGS1!&>> >>;
- !&ATTLBL BOTTOMLAB;
- REGS!& := !&RMERGE REGS1!&;
- CONDTAIL!& := CDR CONDTAIL!&
- END;
- SYMBOLIC PROCEDURE !&INSTBL(TBL,I,L);
- IF NULL TBL THEN LIST LIST(I,L)
- ELSE IF I < CAAR TBL THEN LIST(I,L) . TBL
- ELSE IF I = CAAR TBL THEN
- !&COMPERROR LIST("Ambiguous case",TBL)
- ELSE CAR TBL . !&INSTBL(CDR TBL,I,L);
- SYMBOLIC PROCEDURE !&GETNUM X;
- IF !&WCONSTP X AND NUMBERP CADR X THEN CADR X
- ELSE !&COMPERROR(LIST("Number expected for CASE label",X));
- SYMBOLIC PROCEDURE !&COMPROG(EXP,STATUS!&); %compiles program blocks;
- BEGIN SCALAR ALSTS!&,GOLIST!&,PG,PROGLIS,EXITT!&,EXITREGS!&;
- INTEGER I;
- %SCALAR OLDSTOMAP,OLDCODE;
- % OLDCODE := CODELIST!&;
- % OLDSTOMAP := STOMAP!&;
- EXITREGS!& := NIL;
- PROGLIS := CADR EXP;
- EXP := CDDR EXP;
- EXITT!& := !&GENLBL();
- PG := !&REMVARL PROGLIS; %protect prog variables;
- ALSTS!& := !&VARBIND(PROGLIS,NIL);
- FOR EACH X IN EXP DO IF ATOM X
- THEN GOLIST!& := (X . !&GENLBL()) . GOLIST!&;
- WHILE EXP DO
- <<IF ATOM CAR EXP
- THEN <<!&ATTLBL !&GETLBL CAR EXP;
- REGS!& := NIL>>
- ELSE !&COMVAL(CAR EXP,IF STATUS!&>2 THEN 4 ELSE 3);
- EXP := CDR EXP>>;
- IF NOT !&TRANSFERP CODELIST!& AND STATUS!& < 2 THEN
- !&LREG1('(QUOTE NIL));
- !&ATTLBL EXITT!&;
- REGS!& := !&RMERGE (REGS!& . EXITREGS!&);
- !&FREERSTR(ALSTS!&,STATUS!&);
- !&RSTVARL(PROGLIS,PG);
- %/ !&FIXFRM(OLDSTOMAP,OLDCODE,0);
- END;
- SYMBOLIC PROCEDURE !&COMPROGN(EXP,STATUS!&);
- BEGIN
- EXP := CDR EXP;
- IF NULL EXP THEN RETURN !&COMVAL('(QUOTE NIL), STATUS!&);
- WHILE CDR EXP DO
- <<!&COMVAL(CAR EXP,IF STATUS!&<2 THEN 2 ELSE STATUS!&);
- EXP := CDR EXP>>;
- !&COMVAL(CAR EXP,STATUS!&)
- END;
- SYMBOLIC PROCEDURE !&COMRETURN(EXP,STATUS!&);
- << EXP := CDR EXP;
- IF NULL EXP OR NOT NULL CDR EXP THEN
- << !&COMPERROR LIST("RETURN must have exactly one argument",EXP);
- EXP := '((QUOTE NIL)) >>;
- IF STATUS!&<4 OR NOT !&NOSIDEEFFECTP(CAR EXP)
- THEN !&LREG1(CAR !&COMLIS1 EXP);
- SLST!& := NIL;
- EXITREGS!& := REGS!& . EXITREGS!&;
- !&ATTJMP EXITT!& >>;
- SYMBOLIC PROCEDURE !&DELMAC X;
- % Delete macro CAR X from CODELIST!&
- RPLACA(X,'(!*NOOP));
- %*************************************************************
- % Pass 3
- %*************************************************************
- COMMENT Post Code Generation Fixups;
- SYMBOLIC PROCEDURE !&PASS3;
- % Pass 3 - optimization.
- % The optimizations currently performed are:
- % 1. Deletion of stores not yet picked up from SLST!&.
- % 2. Removal of unreachable macros.
- % 3. A peep hole optimizer, currently only optmizing LBL macros.
- % 4. Removal of common code chains
- % 5. Changing LINK to LINKE where possible
- % 6. Squeezing out unused frame locations and mapping the stack onto
- % the registers.
- % Other functions of PASS3 are to tack exit code on the end and reverse
- % the code list.
- <<
- FOR EACH J IN SLST!& DO !&DELMAC CDR J;
- !&ATTLBL EXITT!&;
- !&ATTACH '(!*EXIT (!*FRAMESIZE));
- !&REMCODE(T);
- !&FIXLABS();
- !&FIXCHAINS();
- !&FIXLINKS();
- !&REMCODE(NIL);
- !&FIXFRM(NIL,NIL,NARG!&);
- !&PEEPHOLEOPT();
- !&REMCODE(NIL);
- CODELIST!& := REVERSIP CODELIST!&;
- >>;
- SYMBOLIC PROCEDURE !&INSERTMAC(PLACE,MAC);
- RPLACW(PLACE,MAC . (CAR PLACE . CDR PLACE));
- SYMBOLIC PROCEDURE !&DELETEMAC(PLACE);
- RPLACW(PLACE,CDR PLACE);
- SYMBOLIC PROCEDURE !&REMCODE(KEEPTOP);
- BEGIN SCALAR UNUSEDLBLS;
- UNUSEDLBLS := !&UNUSEDLBLS(KEEPTOP);
- !&REMUNUSEDMAC(UNUSEDLBLS);
- WHILE (UNUSEDLBLS := !&UNUSEDLBLS(KEEPTOP)) DO !&REMUNUSEDMAC(UNUSEDLBLS);
- END;
- SYMBOLIC PROCEDURE !&UNUSEDLBLS(KEEPTOP);
- BEGIN SCALAR USED,UNUSED;
- USED := NIL;
- UNUSED := LBLIST!&;
- IF KEEPTOP THEN
- <<USED := !&LABCLASS(TOPLAB!&) . USED;
- UNUSED := !&DELCLASS(TOPLAB!&,UNUSED)>>;
- FOR EACH MAC IN CODELIST!& DO
- IF CAR MAC NEQ '!*LBL THEN
- FOR EACH FLD IN CDR MAC DO
- IF EQCAR(FLD,'LABEL) AND !&CLASSMEMBER(FLD,UNUSED) THEN
- <<USED := !&LABCLASS(FLD) . USED;
- UNUSED := !&DELCLASS(FLD,UNUSED)>>;
- LBLIST!& := USED;
- RETURN UNUSED;
- END;
- SYMBOLIC PROCEDURE !&CLASSMEMBER(LAB,CLASSES);
- IF NULL CLASSES THEN NIL
- ELSE LAB MEMBER CAR CLASSES OR !&CLASSMEMBER(LAB,CDR CLASSES);
- SYMBOLIC PROCEDURE !&REMUNUSEDMAC(UNUSEDLABS);
- BEGIN SCALAR P,Q,R;
- CODELIST!& := P := REVERSIP CODELIST!&;
- WHILE CDR P DO
- <<Q := CDR P;
- IF CAAR Q = '!*NOOP OR
- !&TRANSFERP P AND CAAR Q NEQ '!*LBL
- OR CAAR Q = '!*LBL AND !&CLASSMEMBER(CADAR Q,UNUSEDLABS) THEN
- RPLACD(P,CDR Q)
- ELSE P := CDR P >>;
- CODELIST!& := REVERSIP CODELIST!&;
- END;
- lisp procedure !&FixLinks();
- %
- % replace LINK by LINKE where appropriate
- %
- if not !*NoLinkE and not FreeBound!& then
- begin scalar Switched;
- for each Inst on CodeList!& do
- begin scalar SaveRest;
- if ExitT!& and first first Inst = '!*JUMP
- and second first Inst = ExitT!&
- or first first Inst = '!*EXIT then
- << if first second Inst = '!*LBL then
- << if first third Inst = '!*LINK then
- << Inst := cdr Inst;
- SaveRest := T >> >>;
- if first second Inst = '!*LINK then
- << if second second Inst eq NAME!& and !*R2I then
- Rplaca(rest Inst, list('!*JUMP, TopLab!&))
- else
- Rplaca(rest Inst, '!*LINKE . '(!*FRAMESIZE)
- . rest second Inst);
- if not SaveRest then !&DeleteMac Inst >> >>;
- end;
- end;
- SYMBOLIC PROCEDURE !&PEEPHOLEOPT;
- %'peep-hole' optimization for various cases;
- BEGIN SCALAR X,Z;
- Z := CODELIST!&;
- WHILE Z DO
- IF CAAR Z = '!*NOOP THEN !&DELETEMAC Z
- ELSE IF NOT (X := GET(CAAR Z,'OPTFN)) OR NOT APPLY(X,LIST Z)
- THEN Z := CDR Z
- END;
- COMMENT Peep-hole optimization tables;
- SYMBOLIC PROCEDURE !&STOPT U;
- IF CAADR U = '!*ALLOC AND LLNGTH!& = 1
- AND CDDAR U = '((FRAME 1)) THEN
- <<RPLACW(U,LIST('!*PUSH,CADAR U) . CDDR U)>>
- ELSE IF CAADR U = '!*MOVE AND CAADDR U = '!*ALLOC AND LLNGTH!& = 2
- AND CDDAR U = '((FRAME 2)) AND CDDADR U = '((FRAME 1)) THEN
- <<RPLACW(U,LIST('!*PUSH,CADADR U) . LIST('!*PUSH,CADAR U) . CDDDR U)>>;
- SYMBOLIC PROCEDURE !&LBLOPT U;
- BEGIN SCALAR Z;
- IF CADR U = '!*LBL THEN
- <<!&DEFEQLBL(CADR U,CADR CDR U);
- RPLACD(U,CDDR U);
- RETURN T>>;
- IF CDADR U AND EQCAR(CADADR U,'LABEL) AND !&LBLEQ(CADAR U,CADADR U)
- THEN RETURN RPLACW(CDR U,CDDR U)
- ELSE IF CAADR U = '!*JUMP
- AND (Z := GET(CAADDR U,'NEGJMP))
- AND !&LBLEQ(CADAR U,CADR CADDR U)
- THEN RETURN <<Z := Z . (CADADR U . CDDR CADDR U);
- RPLACD(U,(Z . CDDDR U));
- T>>
- ELSE RETURN NIL
- END;
- SYMBOLIC PROCEDURE !&JUMPOPT U;
- IF CADAR U = EXITT!& AND LLNGTH!& = 0 THEN
- RPLACA(U,'(!*EXIT (!*FRAMESIZE)));
- SYMBOLIC PROCEDURE !&FIXCHAINS();
- BEGIN SCALAR LAB;
- FOR EACH LABCODE ON CODELIST!& DO
- IF CAAR LABCODE = '!*LBL % OR CAAR LABCODE = '!*JUMP % croaks on this one
- THEN
- <<LAB := CADAR LABCODE;
- FOR EACH JUMPCODE ON CDR LABCODE DO
- IF CAAR JUMPCODE = '!*JUMP AND CADAR JUMPCODE = LAB THEN
- !&MOVEJUMP(LABCODE,JUMPCODE)>>
- END;
- SYMBOLIC PROCEDURE !&MOVEJUMP(LABCODE,JUMPCODE);
- IF CADR LABCODE = CADR JUMPCODE THEN
- BEGIN SCALAR LAB;
- REPEAT
- <<IF CADR LABCODE = CADR JUMPCODE THEN
- <<JUMPCODE := CDR JUMPCODE;
- LABCODE := CDR LABCODE>>;
- WHILE CAADR LABCODE = '!*LBL DO LABCODE := CDR LABCODE;
- WHILE CAADR JUMPCODE = '!*LBL DO JUMPCODE := CDR JUMPCODE;>>
- UNTIL NOT(CADR JUMPCODE = CADR LABCODE);
- IF CAAR LABCODE = '!*LBL THEN
- RPLACD(JUMPCODE,LIST('!*JUMP,CADR CAR LABCODE) . CDR JUMPCODE)
- ELSE
- <<LAB := !&GENLBL();
- RPLACD(JUMPCODE,LIST('!*JUMP,LAB) . CDR JUMPCODE);
- RPLACD(LABCODE,LIST('!*LBL,LAB) . CDR LABCODE)>>;
- END;
- SYMBOLIC PROCEDURE !&FIXFRM(OLDSTOMAP,OLDCODE,HIGHREG);
- % Should change FIXFRM to do sliding squeeze, not reorder;
- BEGIN SCALAR LST,GAZINTA,N,NF,TOP,FRAMESUSED,R,USED,FR,P,HMAP;
- HOLEMAP!& := NIL;
- % No stores were generated - frame size = 0
- N := 1;
- GAZINTA := 1;
- % Now, loop through every allocated slot in the frame
- FRAMESUSED := !&GETFRAMES(CODELIST!&,OLDCODE,NIL);
- WHILE N <= LLNGTH!& DO
- <<USED := NIL;
- FR := !&MKFRAME N;
- FOR EACH VAR IN OLDSTOMAP DO IF CADR VAR = FR THEN USED := T;
- IF FR MEMBER FRAMESUSED THEN USED := T;
- % Find out if a frame location was used. N and GAZINTA used for squeeze
- % HOLEMAP!& is an association list between old and new frame locations.
- IF USED THEN <<HOLEMAP!& := LIST(FR,!&MKFRAME GAZINTA) . HOLEMAP!&;
- GAZINTA := GAZINTA + 1 >>;
- N := N + 1>>;
- LLNGTH!& := GAZINTA - 1;
- %now see if we can map stack to registers;
- TOP := !&HIGHEST(CODELIST!&,OLDCODE,HIGHREG,NIL);
- IF NOT(TOP = 'ALL OR
- FREEBOUND!& AND NOT !*USEREGFLUID) THEN
- <<HMAP := NIL;
- NF := 0;
- FOR EACH HOLE IN HOLEMAP!& DO
- IF TOP < LASTACTUALREG!& THEN
- << TOP := TOP + 1;
- LLNGTH!& := LLNGTH!& - 1;
- R := !&MKREG TOP;
- REGS!& := DELASC(R,REGS!&);
- HMAP := LIST(CAR HOLE,R) . HMAP>>
- ELSE
- << NF := NF + 1;
- HMAP := LIST(CAR HOLE, !&MKFRAME NF) . HMAP >>;
- IF NF NEQ 0 THEN LLNGTH!& := NF;
- HOLEMAP!& := HMAP;
- >>
- ELSE IF N = GAZINTA THEN RETURN NIL;
- P := CODELIST!&;
- WHILE NOT (P EQ OLDCODE) DO
- <<RPLACA(P,!&MACROSUBST(CAR P,HOLEMAP!&));
- P := CDR P>>;
- END;
- SYMBOLIC PROCEDURE !&GETFRAMES(CODE,OLDCODE,RES);
- IF CODE EQ OLDCODE THEN RES
- ELSE !&GETFRAMES(CDR CODE,OLDCODE,!&GETFRAMES1(CDAR CODE,RES));
- SYMBOLIC PROCEDURE !&GETFRAMES1(MACARGS,RES);
- IF NULL MACARGS THEN RES ELSE !&GETFRAMES1(CDR MACARGS,
- !&GETFRAMES2(CAR MACARGS,RES));
- SYMBOLIC PROCEDURE !&GETFRAMES2(MACARG,RES);
- IF ATOM MACARG OR !&VARP MACARG OR !&CONSTP MACARG OR !®P MACARG THEN RES
- ELSE IF EQCAR(MACARG,'FRAME) THEN
- IF MACARG MEMBER RES THEN RES ELSE MACARG . RES
- ELSE !&GETFRAMES1(CDR MACARG,RES);
- SYMBOLIC PROCEDURE !&HIGHEST(START,STOP,HIGHREG,EXITFLAG);
- % Find the highest register used. 'ALL is returned if all are used.
- IF START EQ STOP THEN HIGHREG ELSE
- BEGIN SCALAR FN,MAC;
- MAC := CAR START;
- RETURN
- IF CAR MAC = '!*LINK OR CAR MAC = '!*LINKE AND EXITFLAG THEN
- <<FN := CADR MAC;
- IF FN = NAME!& THEN
- IF EXITFLAG THEN
- !&HIGHEST(CDR START,STOP,HIGHREG,EXITFLAG)
- ELSE 'ALL
- ELSE IF (DEST!& := GET(FN,'DESTROYS)) AND !*USINGDESTROY THEN
- <<FOR EACH R IN DEST!& DO HIGHREG := MAX(HIGHREG,CADR R);
- !&HIGHEST(CDR START,STOP,HIGHREG,EXITFLAG)>>
- ELSE 'ALL>>
- ELSE IF CAR MAC = '!*LINKF OR CAR MAC = '!*LINKEF AND EXITFLAG THEN
- 'ALL
- ELSE
- !&HIGHEST(CDR START,STOP,!&HIGHEST1(HIGHREG,CDR MAC),EXITFLAG);
- END;
- SYMBOLIC PROCEDURE !&HIGHEST1(H,ARGS);
- BEGIN
- FOR EACH A IN ARGS DO
- H := MAX(H,!&HIGHEST2(H,A));
- RETURN H;
- END;
- SYMBOLIC PROCEDURE !&HIGHEST2(H,ARG);
- IF ATOM ARG THEN H
- ELSE IF NOT ATOM CAR ARG THEN !&HIGHEST1(H,ARG)
- ELSE IF !&CONSTP ARG THEN H
- ELSE IF CAR ARG = 'REG AND NUMBERP CADR ARG THEN MAX(H,CADR ARG)
- ELSE !&HIGHEST1(H,CDR ARG);
- SYMBOLIC PROCEDURE !&REFORMMACROS;
- BEGIN SCALAR FINALTRANSFORM;
- FINALTRANSFORM := LIST(LIST('(!*FRAMESIZE),LLNGTH!&));
- FOR EACH MAC ON CODELIST!& DO
- RPLACA(MAC,!&MACROSUBST(CAR MAC,FINALTRANSFORM));
- END;
- SYMBOLIC PROCEDURE !&FIXLABS();
- BEGIN SCALAR TRANSFORM,U;
- TRANSFORM := NIL;
- FOR EACH LAB IN LBLIST!& DO
- FOR EACH EQLAB IN CDR LAB DO
- TRANSFORM := LIST(EQLAB,CAR LAB) . TRANSFORM;
- FOR EACH MAC ON CODELIST!& DO
- RPLACA(MAC,!&MACROSUBST(CAR MAC,TRANSFORM));
- IF U := ASSOC(EXITT!&,TRANSFORM) THEN EXITT!& := CADR U;
- IF U := ASSOC(TOPLAB!&,TRANSFORM) THEN TOPLAB!& := CADR U;
- LBLIST!& := FOR EACH LAB IN LBLIST!& COLLECT LIST CAR LAB;
- END;
- SYMBOLIC PROCEDURE !&MACROSUBST(MAC,ALIST);
- CAR MAC . !&MACROSUBST1(CDR MAC,ALIST);
- SYMBOLIC PROCEDURE !&MACROSUBST1(ARGS,ALIST);
- FOR EACH ARG IN ARGS COLLECT !&MACROSUBST2(ARG,ALIST);
- SYMBOLIC PROCEDURE !&MACROSUBST2(ARG,ALIST);
- BEGIN SCALAR U;
- U:=ASSOC(ARG,ALIST);
- RETURN IF U THEN CADR U
- ELSE IF ATOM ARG OR FLAGP(CAR ARG,'TERMINAL) THEN ARG
- ELSE (CAR ARG . !&MACROSUBST1(CDR ARG,ALIST));
- END;
- SYMBOLIC PROCEDURE !&REMTAGS();
- FOR EACH MAC IN CODELIST!& DO !&REMTAGS1 MAC;
- SYMBOLIC PROCEDURE !&REMTAGS1 MAC;
- << IF CAR MAC = '!*JUMPON THEN RPLACD(CDDDR MAC, LIST CDDDDR MAC);
- FOR EACH MACFIELD IN CDR MAC DO !&REMTAGS2 MACFIELD >>;
- SYMBOLIC PROCEDURE !&REMTAGS2 U;
- IF EQCAR(U, 'WCONST) THEN !&REMTAGS3 CADR U;
- SYMBOLIC PROCEDURE !&REMTAGS3 U;
- BEGIN SCALAR DOFN;
- IF ATOM U THEN RETURN NIL;
- IF DOFN := GET(CAR U, 'DOFN) THEN
- RPLACA(U, DOFN);
- !&REMTAGS4 CDR U;
- END;
- SYMBOLIC PROCEDURE !&REMTAGS4 U;
- FOR EACH X IN U DO !&REMTAGS3 X;
- % Entry points used in setting up the system
- SYMBOLIC PROCEDURE !&ONEREG U;
- FOR EACH X IN U DO PUT(X,'DESTROYS,'((REG 1)));
- SYMBOLIC PROCEDURE !&TWOREG U;
- FOR EACH X IN U DO PUT(X,'DESTROYS,'((REG 1) (REG 2)));
- SYMBOLIC PROCEDURE !&THREEREG U;
- FOR EACH X IN U DO PUT(X,'DESTROYS,'((REG 1) (REG 2) (REG 3)));
- END;
|