!IMP syntax checker - based on M68000 IMP compiler ! (qv for fuller annotation) ! Hamish Dewar Computer Science Edinburgh University 1983 ! constinteger MAXNAME=127 recordformat EDFILE(integer start1,lim1, {part 1} start2,lim2, {part2} lim, {VMLIM} lbeg,fp,change,flag, line {line number of current pos}, diff {diff between LINE and ROW}, shift {right shift of window on file}, byteinteger top {top row of sub_window}, win {floating top}, bot {bottom row +1 of sub_window}, min {minimum window size}, row {last row position}, col {last col position}, string(maxname) name) ! externalroutinespec EDI(record(edfile)name main,sec, string(255) message) externalroutinespec CONNECT EDFILE(record(edfile)name f) externalroutinespec DISCONNECT EDFILE(record(edfile)name f) ! !$IF VAX conststring(13) permfile="ECCE_PERM" !$IF AMDAHL {%conststring(18) permfile="ERCLIB:VECCE.IPERM" !$FINISH !! control constinteger logbit= 16_00040000 {print log}, warnbit= 16_00020000 {print warnings}, nonsbit= 16_00010000 {print nonstandard reports}, DICTLIST= 16_00001000 {list dict entries}, EXPLIST= 16_00000800 {list EXP entries} owninteger control=warnbit+nonsbit !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! externalroutine ECCECI(record(edfile)name main) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ownstring(maxname) extraname ownrecord(edfile) extra=0,null=0 integer curstart,curlim integer nonstop owninteger change=0 !! Fault numbers constinteger FORMERR=0, ATOMERR=1, NAMERR=2, CATERR=3, SIZERR=4, ASSERR=5, TYPERR=6, DUPERR=7, NOSTART=8, NOCYCLE=9, ORDERERR=10, MATCHERR=11, RANGERR=12, NONLITERAL=13, BOUNDSERR=14, ACCESSERR=15, NOTINLOOP=16, NOTINROUT=17, NOTINFUN=18, NOTINPRED=19, PLEXERR=20, NOIF=21, NONSTAND=22, NOTIN=23, INDEXERR=24, MOPERR=27, NOTERM=28, NONSTARTER=29, NONVAR=30, NONREF=31, TOOMANY=32, TOOFEW=33, UNWANTED=34, NOPARM=35, UNENDING=37, SELFREF=38 constinteger NOEND=40, NOBEGIN=41, IDMISSING=42, NOFINISH=43, NOREPEAT=44, COUNTERR=45, NORESULT=46 constinteger ERRMAX=46 constinteger POINT=64,WARN=128 owninteger FAULTNUM=0 owninteger FAULTS=0; !fault count ! constinteger MAXINT=16_7FFFFFFF, MININT=¬MAXINT, MAX10=maxint//10, MAXDIG=maxint-max10*10 constinteger FALSE=0, TRUE=1 integer I ! !! Program statistics owninteger STATEMENTS=0; !statement count !%owninteger ATOMS=0; !atom count !%owninteger IDENTATOMS=0; !identifier count !%owninteger NUMATOMS=0; !numeric atom count !%owninteger MISSES=0; !ident mismatches !%owninteger ZAPS=0 ! !!!!!!!!!!!!!!!! Operand Representation !!!!!!!!!!!!!!!!!!! constinteger SMALLMIN=-1000, SMALLMAX=1000, LITMIN=smallmax+1, LITMAX=smallmax+1000, D0=litmax+1, D1=d0+1, D2=d0+2, D6=d0+6, D7=d0+7, A0=d0+8, A1=a0+1, A6=a0+6, A7=a0+7, INDA0=a0+8, POSTA0=inda0+8, POSTA7=posta0+7, PREA0=posta0+8, PREA7=prea0+7, DICTMIN=prea0+8, DICTMAX=prea0+1200, LABMIN=dictmax+1, LAB1=labmin+1, LABMAX=labmin+20, EXPMIN=labmax+1, EXPMAX=labmax+300, UNDEF=expmax+1, AD=16_4000 constinteger MAXDREG=d0+4, MAXAREG=a0+3 constinteger D0B=1, D1B=2, D2B=4, A0B=16_100, A1B=16_200, A2B=16_400 constinteger ALLREGS=2_0000111100011111; !a3:a0 & d4:d0 owninteger FREE=allregs constinteger NULLTYPE=dictmin, RECY=nulltype+1, ARRY=recy+1, STRINGY=arry+1, REALY=stringy+1, INTY=realy+1, CHARTYPE=inty+1, BOOLTYPE=chartype+1, FALSECONST=booltype+1, TRUECONST=booltype+2, INTTYPE=trueconst+1, SHORTTYPE=inttype+1, HALFTYPE=shorttype+1, BYTETYPE=halftype+1, MITETYPE=bytetype+1, BITTYPE=MITETYPE+1, LONGINTTYPE=bittype+1, REALTYPE=longinttype+1, LONGREALTYPE=realtype+1 constinteger PURETYPE=8191, DIRECT=8192, INDIRECT=16384 constinteger ANYINT=inty+direct, ANYINTVAR=inty+indirect, ANYSTRING=stringy+direct, ANYSTRINGVAR=stringy+indirect constinteger ANYNAME=nulltype+indirect ! owninteger dictshown=dictmin !!!!!!!!!!!!!!!!!!!!!!! Big Literals !!!!!!!!!!!!!!!!!!!!!!! owninteger LITPOS=litmin, SLITPOS=litmax integerarray LITSTORE(litmin:litmax) ! !!!!!!!!!!!!!!!!!!!!!!!!!! MODE VALUES !!!!!!!!!!!!!!!!!!!!!!!!! !Size codes: constinteger bytesize=1, wordsize=2, longsize=3 constinteger sizemask=16_C0, sizeshift=6 !Address modes: constinteger dmode=0, amode=2_001000, indmode=2_010000, postmode=2_011000, premode=2_100000, dispmode=2_101000, indexmode=2_110000, absmode=2_111000, pcmode=2_111010, litmode=2_111100 constinteger ownmode=dispmode+6; !d(A6) ! !!!!!!!!!!!!!!!!!!!!!!!! Identifiers !!!!!!!!!!!!!!!!!!!!!!!! ! recordformat OBJINFO C (integer flags,type, (integer extra, byteinteger spare,mode or integer low), integer val) recordformat IDENTINFO C ((integer flags,type, (integer extra, byteinteger spare,mode or integer low), integer val or record(objinfo) details), integer text,link) ! ! Significance of FLAGS: constinteger VAR=16_0001, LAB=16_0002, PROC=16_0004, STATIC=16_0008, SPEC=16_0010, EXT=16_0020, PARM=16_0040, MORE=16_0080, TYPEID=16_0100, OKFLAG=16_0200, ALT=16_0800, RFLAG=16_1000,WFLAG=16_2000 ! ! Significance of VAL: ! for literal : the actual value ! for variable : machine address (displacement) ! for undefined label : reference chain ! for undefined procedure : " ! for base type : (index to) range ! for record type : size of record in bytes ! ! Identifier dictionary: record(identinfo)array DICT(d0:labmax) ! indexing DICT: owninteger DLIM=trueconst+1; !dict limit (up) owninteger DLIM0 owninteger PERMLIM=dictmin owninteger DMIN=dictmax-1; !dict upper limit (down) ! Text of identifiers (indexed by _TEXT): constinteger CHARBOUND=6000 byteintegerarray CHAR(0:charbound) integer CHARBASE,CHARLIM,CHARMIN; !pointers integer NEWLEN ! Hash index to DICT: integerarray HASHINDEX(0:255) integername HEAD; !head of ident search list ! !!!!!!!!!!!!!!!!!!!!! Complex operands !!!!!!!!!!!!!!!!!!!!!!! !%recordformat EXPINFO(%integer act,x,y) !%record(expinfo)%array EXP(expmin:expmax) owninteger EXPLO=expmax+1, OLDEXPLO=expmax+1 constinteger NP0=expmin owninteger NP,CONDNP,INSTNP !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!! Keywords and operators !!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !*!!!!!!! Keyword codes -- used by KEYGEN to produce tables !! constinteger END=1 {end}, REPEAT=2 {repeat}, FINISH=3 {finish}, ELSE=4 {else}, BEGIN=5 {begin}, EXIT=6 {exit_1,continue_0}, RETURN=7 {return}, TF=8 {true_1,false_0}, RESULT=9 {result}, STOP=10 {stop}, GOTO=11 {goto}, SIGNAL=12 {signal}, MONITOR=13 {monitor}, ON=15 {on}, IU=16 {if_0,unless_1}, WHILE=17 {while}, UNTIL=18 {until_1}, FOR=19 {for}, THEN=20 {then}, START=21 {start}, CYCLE=22 {cycle}, KEYLABEL=23 {label}, PREFIX=24 {const_9,constant_9,own_8,external_40,system_40,dynamic_40}, KRANGE=25 {short_1,half_2,byte_3,mite_4,bit_5}, KEYLONG=26 {long}, KEYINTEGER=27 {integer}, KEYREAL=28 {real}, KEYSTRING=29 {string}, KEYRECORD=30 {record}, KEYFORMAT=31 {format}, FNMAP=32 {fn_0,function_0,map_1}, RPRED=33 {routine_0,predicate_1}, KEYSPEC=34 {spec}, KEYARRAY=35 {array}, KEYNAME=36 {name}, KEYSWITCH=37 {switch}, OF=38 {of}, KEYFILE=39 {file}, PROGRAM=40 {program}, KEYLIST=41 {list}, KEYCONTROL=42 {control}, COMMENT=43 {comment}, KEYEVENT=44 {event}, INCLUDE=45 {include}, ALIAS=46 {alias}, KEYNOT=47 {not}, KEYAND=64 {and}, KEYOR=65 {or} CONSTintegerARRAY SYMINIT(97:122) = C 2, 15, 27, 57, 64, 87,118,122,126, 1, 1,141,154,168,175,184, 1,199,230,270,278, 1,288, 1, 1, 1 CONSTBYTEINTEGERARRAY SYMBOL(1:292) = C 128,114,114, 97,121,163,108,105, 97,115,174,110,100,192,101,103, 105,110,133,121,116,101,153,105,116,153,111,110,116,105,110,117, 101,134,121, 99,108,101,150,109,109,101,110,116,171,115,116, 97, 110,116,152,152,114,111,108,170,121,110, 97,109,105, 99,152,110, 100,129,108,115,101,132,120,105,116,134,118,101,110,116,172,116, 101,114,110, 97,108,152,105,110,105,115,104,131, 97,108,115,101, 136,111,114,109, 97,116,159,110,160,117,110, 99,116,105,111,110, 160,147,108,101,167,111,116,111,139, 97,108,102,153,102,144,110, 116,101,103,101,114,155, 99,108,117,100,101,173, 97, 98,101,108, 151,111,110,103,154,105,115,116,169,111,110,105,116,111,114,141, 105,116,101,153, 97,112,160, 97,109,101,164,111,116,175,110,143, 119,110,152,102,166,114,193,114,101,100,105, 99, 97,116,101,161, 111,103,114, 97,109,168,101,112,101, 97,116,130,111,117,116,105, 110,101,161,116,117,114,110,135,115,117,108,116,137, 97,108,156, 99,111,114,100,158,116,111,112,138,105,103,110, 97,108,140,121, 115,116,101,109,152,104,111,114,116,153,112,101, 99,162,119,105, 116, 99,104,165, 97,114,116,149,114,105,110,103,157,114,117,101, 136,104,101,110,148,110,108,101,115,115,144,116,105,108,146,104, 105,108,101,145 CONSTBYTEINTEGERARRAY ALTDISP(1:292) = C 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0, 0, 3, 0, 0, 5, 8, 12, 17, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 3, 0, 0, 4, 0, 0, 0, 4, 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 6, 27, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 0, 14, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 4, 0, 0, 4, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 8, 2, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 6, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 5, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 30, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 40, 5, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 !*!!!!!! end of generated tables !!!!!!!!!!!!!!!!!!!!!!!!!!! ! constinteger TERMINATOR=52, CONST=53, IDENT=54, AREF=55, RECREF=56, MODSIGN=57, COLON=58, COMMA=59, RIGHT=60, RIGHTBRACKET=61, DUD=63 !Operators (in banks of 8 acc to rank) constinteger BOOLAND=64, BOOLOR=65, BOOLNOT=66, FLOAT=67, IMOD=68, FMOD=69 constinteger EQUALS=70, NOTEQ=71, LESSEQ=72, LESS=73, GREATEQ=74, GREATER=75, EQEQ=76, NOTEQEQ=77, RESOLVE=79 constinteger PLUS=80, MINUS=81, LOGOR=82, LOGXOR=83, CONCAT=84 constinteger MULT=88, FDIV=89, IDIV=90, LOGAND=91 constinteger FPOWER=96, IPOWER=97, LSHIFT=100, RSHIFT=101, LOGNOT=102 constinteger FCALL=106, MCALL=107 constinteger ATOMMAX=107 ! Instruction actions: constinteger swgoto=35, rcall=mcall+2, assign=41, jamassign=42, plusass=43, compare=44, jump=45, label=46, adecl=47 constinteger actmax=49 ! !Branch cases ( = machine condition-code) constinteger EQ=2_0111, NE=2_0110, GT=2_1110, LE=2_1111, LT=2_1101, GE=2_1100, CC=2_0100, CS=2_0101 constinteger DOUBLE=16 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! Perm procedure identifiers which are recognised explicitly and ! either implemented in-line or mapped to system entry-point constinteger DSHORT=dictmin+6, DLENGTH=dshort+1, DCHARNO=dlength+1, DADDR=dcharno+1, DTOSTR=daddr+1, DREM=dtostr+1, DNEXTSYM=drem+1, DREADSYM=dnextsym+1, DPRINTSTR=dreadsym+3, DREAD=dictmin+27, DNEWLINE=dictmin+41 !System entry-points used explicitly constinteger SIGENTRY=16_1114, SCOMPENTRY=16_1128, BOUNDENTRY=16_1134, AGETENTRY=16_1138, INDEXENTRY=16_113C, IREADENTRY=16_1118 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! owninteger STARTS=0, CYCLES=0 owninteger LOOPLAB=0 owninteger CURLAB=lab1 ! recordformat BLOCKINF(integer sp, delta, fortemps, flags, type, localdpos, parlim, localtext, localpc, localspc, pidpos, access, forward, events, eventpc, faults, return, shorts) !Flag bits (VAR=1 from D_FLAGS) constinteger WRONGCC=2, NONLOCALREF=4, DYNARRAY=8 constinteger HADON=16_10, HADINST=16_20 constinteger OUTERLEVEL=0, MAXLEVEL=16 owninteger LEVEL=outerlevel; !current block level record(blockinf) C; !info for current block record(blockinf)array HOLD(0:maxlevel-1); !info for global blocks ! Final core image constinteger PUREBOUND=0, OWNBASE=purebound+1, FINALBOUND=ownbase+8191 byteintegerarray FINAL(0:finalbound); !for switch info only owninteger FINALAD=2, OWNAD=ownbase !%owninteger FIRSTENTRY=finalbound, FIRSTDPOS=dictmax !%ownintegername CONSTAD; !== ownad or finalad !%owninteger CONSTBOUND=purebound; !for const/code ! =finalbound; !for own owninteger PC=0, SPC=finalbound; !for switch info !Recognition:- constinteger CASEMASK=95, CASEBIT=32; !for case conversion !Memo variables for current statement:- owninteger ITEM=0; !current operand record(objinfo) T; !full typeinfo for ITEM record(identinfo)name DITEM owninteger ELEMENTS; !range details owninteger HASH owninteger SPECCING=0, MCODING=0 owninteger DECLMODE, DSIZE ownrecord(identinfo) D; !declaration details !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! Source file input and listing owninteger ATOM=0; !current lexical atom owninteger MATCHED=1; !indic that atom has been matched owninteger SYM=nl; !current input symbol owninteger LINE=0; !current line number owninteger MAINLINE=0 owninteger DIAGLINE=-9999 owninteger PROLINE=0 owninteger MODESYM='&'; !space or '+' or '&' or '"' !%owninteger OUTCOL=0; !output line position ! Pointers to source file: owninteger LINESTART=0 owninteger FP=0; !(file pointer) current position owninteger CHARS=0 owninteger ATOMP=0; !start of current atom owninteger FAULTP=0; !fault position owninteger MAINFP owninteger STRINGP,EXPP owninteger listout=0 ! !! Listing, diagnostic and report routines ! ownstring(255) rep="" ! routine NEWLINE print string(rep); print symbol(nl) rep = "" end ! routine PUT SYM(integer k) rep = rep.tostring(k) if length(rep) < 132 end ! routine PRINT STRING(string(255) s) rep = rep.s if length(rep) < 132 end ! routine SPACES(integer n) while n > 0 cycle rep = rep." "; n = n-1 repeat end ! routine WRITE(integer val,p) routine PD(integer v) p = p-1 pd(v//10) and v = v-v//10*10 if v <= -10 spaces(p) and p = 0 if p > 0 put sym('0'-v) end if val < 0 start put sym('-'); pd(val) finish else pd(-val) end !%routine put ident(%integer t) ! rep = rep.string(charbase+t) !!%integer l ! t = t+charbase ! l = byteinteger(t); l = 11 %if l > 11 ! %while l > 0 %cycle ! l = l-1; t = t+1 ! put sym(byteinteger(t)) ! %repeat !%end ! !%routine mark at(%integer col) ! put sym(' ') %while outcol < col; put sym('|') !%end ! !%routine show dict(%integer from) !%integer f,i !%record(identinfo) d !%constbyteintegerarray flagsym(0:7) = ! 'V','L','P','O','S','E', 'A', 'M' !%constbyteintegerarray dsym(0:3) = ! ' ','D','I','!' !%conststring(6)%array typetext(0:7) = ! "NULL ", "RECORD", "ARRAY ", "STRING", ! "REALY ", "INTY ", "CHAR ", "BOOL " ! %return %if from >= dlim ! newline %and outcol = 0 %if outcol # 0 ! print string(" __identifier___flags___type___extra___value___") ! newline; outcol = 0 ! %cycle ! spaces(5); outcol = 5 ! pdec(from); mark at(10) ! d = dict(from) ! put sym(' ') ! put ident(d_text) ! mark at(23) ! %for i = 7,-1,0 %cycle ! %if d_flags>>i&1 = 0 %then put sym(' ') %c ! %else put sym(flagsym(i)) ! %repeat ! put sym('|') ! i = d_type-nulltype ! %if 0 <= i <= 7 %then printstring(typetext(i)) %c ! %else putsym(dsym(d_type>>13)) %and pdec(d_type&puretype) ! mark at(39) ! put sym(' '); pdec(d_extra); mark at(47) ! put sym(' '); pdec(d_val); mark at(56) ! newline; outcol = 0 ! from = from+1 ! %repeat %until from = dlim ! print string(" +----------------------------------------------+") ! newline; outcol = 0 !%end ! !%routine show exp(%integer from,to) !![out of date] !%conststring(7)%array acttext(0:63) = ! "?0", "?1", "ADD", "SUB", ! "?4", "LOGAND", "LOGOR", "LOGXOR", ! "NEGATE", "LOGNOT", "LSHIFT", "RSHIFT", ! "IABS", "FABS", "?14", "?15", ! "MULT", "IDIV", "IPOWER", "FPLUS", ! "FMINUS", "FMULT", "FDIV", "FPOWER", ! "FNEGATE", "FLOAT", "CONCAT", "BOOLNOT", ! "BOOLAND", "BOOLOR", "MEMBER", "MODULO", ! "RECREF", "AREF", "INDRECT", "SWJUMP", ! "FCALL", "MCALL", "?38", "RCALL", ! "?40", "ASSIGN", "JAMASS", "PLUSASS", ! "COMPARE", "JUMP", "LABEL", "ADECL", ! "?48", "?49", "?50", "?51", ! "?52", "?53", "?54", "?55", ! "?56", "?57", "?58", "?59", ! "?60", "?61", "?62", "?63" !%routine put operand(%integer i) ! %if dictmin <= i <= dictmax %then put ident(dict(i)_text) %else pdec(i) !%end ! %return %if from >= np ! newline %and outcol = 0 %if outcol # 0 ! print string(" __action_____first_______second____") ! newline; outcol = 0 ! %cycle ! spaces(5); outcol = 5 ! pdec(from); mark at(10) ! put sym(' '); printstring(acttext(exp(from)_act&63)) ! mark at(20); put sym(' ') ! put operand(exp(from)_x) ! mark at(32); put sym(' ') ! put operand(exp(from)_y) ! mark at(44) ! newline; outcol = 0 ! from = from+1 ! %if from = to %start ! from = explo ! %exit %if from >= oldexplo ! printstring(" |---------------------------------|") ! newline; outcol = 0 ! %finish ! %repeat %until from >= oldexplo ! oldexplo = explo ! print string(" +---------------------------------+") ! newline; outcol = 0 !%end ! !! Fault reporting ! routine REPORT(integer n,joker) integer mark,start,errline,k,editfp routine PRINT IDENT(integer x) put sym('"') print string(string(dict(x)_text+charbase)) put sym('"') end routine PRINT TEXT(integer x,stream) constinteger esc=27 integer k,p switch s(0:errmax) put sym(mark) write(line,4) put sym(modesym); put sym(' ') ->s(n&63) s(formerr): printstring("Faulty form"); -> print s(atomerr): printstring("Unknown atom"); -> print s(namerr): printstring("Unknown name"); -> print s(caterr): printstring("Unsuitable"); -> print s(sizerr): printstring("Size"); -> print s(typerr): printstring("Wrong type"); -> print s(boundserr): printstring("Inside out"); -> print s(unending): printstring("Endless loop"); -> print s(indexerr): printstring("Index"); -> print s(accesserr): printstring("Not accessible");-> print s(notinloop): printstring("Not in loop"); -> print s(notinrout): printstring("Not in routine");-> print s(notinfun): printstring("Not in fn/map"); -> print s(notinpred): printstring("Not in pred"); -> print s(plexerr): printstring("Too complex!"); -> print s(duperr): printstring("Duplicate"); -> print s(ordererr): printstring("Out of order"); -> print s(matcherr): printstring("Mismatch"); -> print s(rangerr): printstring("Out of range"); -> print s(nonliteral):printstring("Not literal"); -> print s(nonstand): printstring("Nonstandard"); -> print s(notin): printstring("Not in yet"); -> print s(moperr): printstring("Faulty operand");-> print s(nocycle): printstring("Missing %CYCLE"); -> print s(nostart): printstring("Missing %START"); -> print s(noif): printstring("Missing %IF"); -> print s(noterm): printstring("';' missing"); -> print s(nonstarter):printstring("Non-starter"); -> print s(nonvar): printstring("Not variable"); -> print s(nonref): printstring("Not reference"); -> print s(noparm): printstring("No parameters"); -> print s(toofew): printstring("Too few"); -> print s(unwanted): printstring("Unwanted"); -> print s(toomany): printstring("Too many"); -> print s(selfref): printstring("Self-reference"); -> print s(nobegin): printstring("Extra %END"); -> print print: spaces(21-length(rep)) p = start if p < faultp-50 then p = faultp-47 and printstring("...") c else put sym(' ') cycle k = byteinteger(p); p = p+1 if p = faultp start !$IF VAX put sym(esc) and put sym('F') if stream = 0 !$FINISH put sym('~') !$IF VAX put sym(esc) and put sym('G') if stream = 0 !$FINISH finish exit if k = nl if ' ' <= k <= '~' then put sym(k) c else put sym('[') and write(k,-1) and put sym(']') repeat return s(noend): printstring("%END"); ->mend s(noresult): printstring("Result"); ->mend s(nofinish): printstring("%FINISH"); ->mend0 s(norepeat): printstring("%REPEAT") mend0: printstring(" etc") if curlab > lab1+2 -> mend s(idmissing): cycle ! newline %and spaces(8) %and outcol = 8 %if outcol > 50 put sym(' ') print ident(x) print string("(?)") if dict(x)_flags&spec = 0; !switch x = dict(x)_val repeat until x = 0 mend: printstring(" missing") if c_type # 0 start print string(" at END of ") print ident(c_pidpos) finish else n = 0 return s(counterr): if elements < 0 start write(-elements,0); printstring(" extra") finish else start write(elements,0); printstring(" missing") finish printstring(" value(s) for ") print ident(x) return s(asserr): print ident(x) print string(" void") end !Warning or error mark = '?' if n&warn = 0 start mark = '*' c_faults = c_faults+1; faults = faults+1 finish faultnum = 0; c_access = -1 !Ignore uncorrected earlier error return if main_start1 <= fp < change !Track back if before current line start = linestart; errline = line if n&point = 0 then faultp = 0 else start faultp = joker if joker > 0 while faultp <= start cycle start = start-1 errline = errline-1 if byteinteger(start) = nl repeat start = start-1 while start # curstart and byteinteger(start-1) # nl finish editfp = start; editfp = faultp-1 if faultp > start editfp = mainfp if curlim = extra_lim2 start = start+1 while byteinteger(start) = ' ' print text(joker,0) newline and return if n&warn # 0 or nonstop # 0 main_fp = editfp; main_line = line if change # 0 then main_change = 16_7FFFFFFE edi(main,null,rep) rep = "" nonstop = 1 if main_flag = 'I' stop if main_flag < 0 signal 12 if main_change < 16_7FFFFFFE {change made} end; !report routine CROAK(string(255) s) print string("** ".s.". Checking abandoned at line ") write(line,0); newline nonstop = -999 signal 12 end routine FAULT(integer n) !Note fault number and position of (earliest) fault ! for subsequent reporting (warnings and weak errors) faultnum = n and faultp = atomp if faultnum = 0 end routine EXPFAULT(integer n) faultnum = n!point and faultp = expp if faultnum = 0 or expp < faultp end constinteger pred=1, uparr=1<<1, nocomma=1<<2, overload=1<<3, ranges=1<<4, nolength=1<<5, initass=1<<6, kgoto=1<<7, hyphen=1<<8, naming=1<<9, klabel=1<<10, ibmhex=1<<11, oldcycle=1<<12, loop2=1<<13 routine NONSTANDARD(integer case) owninteger hadit=0 if control&nonsbit # 0 and case&hadit = 0 start hadit = hadit+case fault(nonstand+point+warn) finish end routine ERROR(integer case) report(case,atomp) signal 14 end routine NAME ERROR !check if the culprit has occurred before !and, if not, add it to the pool of unknowns stored at the !far end of the dictionary. while item < 0 c and string(dict(-item)_text+charbase) # string(charlim) cycle item = dict(-item)_link repeat if item >= 0 start; !first time report(namerr+point,atomp) if charmin-newlen-80 >= charlim start dmin = dmin-1 charmin = charmin-newlen-1 string(charmin) = string(charlim) dict(dmin)_text = charmin-charbase head == dict(head)_link while head > 0; !find last link dict(dmin)_link = head; head = -dmin finish finish signal 14 end routine SYNTAX ERROR integer e e = formerr+point; e = atomerr+point if atom = dud report(e,atomp) signal 14 end !!!!!!!!!!!!!!!!!!!! CELL CONSTRUCTORS !!!!!!!!!!!!!!!!!!! ! !%integerfn litref(%integer v) !%integer i ! %result = v %if smallmin <= v <= smallmax ! litstore(litpos) = v ! i = litmin-1 ! i = i+1 %until litstore(i) = v ! %if i = litpos %start ! litpos = litpos+1 ! croak("Too many literals") %if litpos >= slitpos ! %finish ! %result = i !%end !%integerfn litval(%integer v) ! %result = v %if v <= smallmax ! %result = litstore(v) !%end integerfn floated(integer item) result = 0 if item = 0 result = explo; !expref(float,item,0) end !%predicate is short (%integer v) ! %true %if -32768 <= v <= 32767 ! %false !%end !%predicate is mite (%integer v) ! %true %if -128 <= v <= 127 ! %false !%end !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!! CODE GENERATION !!!!!!!!!!!!!!!!!!!!!!!! ! routine forget end routine forget all integer i,j litpos = litmin; explo = expmax+1; oldexplo = explo end ! routine set label(integer b) end; !set label routine set user label(integer dpos) end routine compile(integer from,to) ! show exp(from,to) %if control&explist # 0 np = np0 end routine compile entry end routine compile end end; !compile end !!!!!!!!!!!!!!! end of Code Generation !!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! routine PUT3(integer act,x,y) ! exp(np)_act = act; exp(np)_x = x; exp(np)_y = y ! np = np+1 end ! routine PUT2(integer act,x) end ! integerfn TEMPVAR result = dlim end routine OPEN BLOCK(integer pidpos) forget; !a bit extreme croak("Too many levels") if level = maxlevel hold(level) = c; level = level+1 c = 0 starts = 0; cycles = 0 curlab = lab1; looplab = 0 forget all c_flags = 0; c_type = d_type c_pidpos = pidpos c_localdpos = dlim; c_parlim = dlim; c_localtext = charlim c_localpc = pc; c_localspc = spc c_access = 1 end; !OPEN BLOCK routine CLOSE BLOCK integer i integer miss,dpos integername p record(identinfo)name dp !Check identifier usage miss = 0; p == miss dpos = c_localdpos while dpos # dlim cycle dp == dict(dpos) ! %if (dp_xtype = ptrxtype %and dp_type = dpos) if dp_flags&(proc+lab) # 0 and dp_flags&(ext+spec) = spec start p = dpos; p == dp_val; p = 0 finish ! %if hashindex(dp_spare) = dpos %start ! dp_link = dict(dp_link)_link %while dp_link >= c_localdpos ! hashindex(dp_spare) = dp_link ! %finish ! dpos = dp_xtype %if dp_type = 0 %and dp_xtype > dpos; !skip fields dpos = dpos+1 repeat report(idmissing,miss) if miss # 0 compile end pc = c_localpc; spc = c_localspc dlim = c_parlim; charlim = c_localtext for i = 0,1,255 cycle hashindex(i) = dict(hashindex(i))_link while hashindex(i) >= c_localdpos repeat level = level-1; c = hold(level) starts = 0; cycles = 0 end; !CLOSE BLOCK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! Source input !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! routine SWITCH INPUT ! croak("Input ended") %if fp = main_lim2 signal 12 if fp = main_lim2 if nonstop < 0 start; !perming nonstop = nonstop+3; permlim = dlim c_localdpos = dlim; c_parlim = dlim statements = 0 finish if fp # main_lim1 start nonstop = nonstop-1 fp = mainfp; line = mainline curstart = main_start1; curlim = main_lim1 finish else fp = main_start2 if main_start2 <= fp <= main_lim2 start curstart = main_start2; curlim = main_lim2 finish modesym = ' '; sym = nl end routine READ LINE ! Read (or otherwise make available) the next source line ! Skip remnant of previous line if SYM # NL *NB* ! Set LINESTART to point to start of new line report(faultnum,faultp) if faultnum # 0 while sym # nl cycle; !Skip remnant sym = byteinteger(fp); fp = fp+1 repeat while fp = curlim cycle switch input repeat line = line+1; linestart = fp sym = 0 end; !READ LINE ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! Lexical processing !!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! owninteger percent=0, subatom=0 ! !Aliases: constinteger ARROW=resolve constinteger EXCLAM=logor, EXCLAM2=logxor, DOT=concat constinteger STAR=mult, SLASH=fdiv, SLASH2=idiv, AMPERSAND=logand constinteger BACKSLASH=fpower, BACKSLASH2=ipower, UPARROW=fpower, UPARROW2=ipower, TILDE=lognot constinteger LEFT=aref, UNDERLINE=recref, LEFTBRACKET=106 constinteger SIMPLE=104, MAJOR=plus, SCOND=equals, COND=keyand ! ! Type compatibility vectors: constinteger RECOK=1<<0, ARROK=1<<1, STRINGOK=1<<2, REALOK=1<<3, INTOK=1<<4, CHAROK=1<<5, BOOLOK=1<<6, ENUMOK=1<<7, SETOK=1<<8 constinteger ZNOP=1<<9, REFONLY=1<<10, VARONLY=1<<11 constinteger ARITHOK=intok+realok, ORDOK=intok+charok+boolok+enumok, ANY=realok+ordok+stringok+arrok+recok ! constintegerarray opbits(64:atommax) = {BOOLAND} boolok, {BOOLOR} boolok, 0, 0, 0, 0, {EQUALS} any, {NOTEQ} any, {LESSEQ} setok+stringok+ordok+realok, {LESS} stringok+ordok+realok, {GREATEQ} setok+stringok+ordok+realok, {GREATER} stringok+ordok+realok, any, any, 0, {RESOLVE} stringok, {PLUS} znop+setok+arithok, {MINUS} znop+setok+arithok, {LOGOR} znop+intok, {LOGXOR} znop+intok, {CONCAT} stringok, 0, 0, 0, {MULT} arithok, {FDIV} arithok, {IDIV} intok, {LOGAND} intok, 0, 0, 0, 0, {FPOWER} arithok, {IPOWER} intok, 0, 0, {LSHIFT} znop+intok, {RSHIFT} znop+intok, {LOGNOT} intok, 0, {AREF} arrok, {RECREF} recok, {} 0, 0 ! integerfn NEXT ATOM !Encode next atom from source file ![Time-critical] switch s(0:255) constinteger tab=9 integer i,j,p,radix,digits real rval constbyteintegerarray map(0:127) = 0 ('0'), '0','1','2','3','4','5','6','7','8','9', 0, 0, 0, 0, 0, 0, 0, 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', 0, 0, 0, 0, 0, 0, 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', 0, 0, 0, 0, 0 routine assemble real j = 0 cycle cycle sym = byteinteger(fp); fp = fp+1 repeat until sym # ' ' i = sym-'0' return unless 0 <= i < radix rval = rval*radix+i; j = j+1 repeat end ! atoms = atoms+1 matched = 0 again: s(tab): read line if sym = nl cycle sym = byteinteger(fp); fp = fp+1 repeat until sym # ' ' atomp = fp; !(actually one after) -> s(sym) linebreak: s(nl): result = terminator if atom # comma -> again s('{'): cycle sym = byteinteger(fp); fp = fp+1 -> linebreak if sym = nl repeat until sym = '}' -> again s('+'): result = plus s('-'): fp = fp+1 and result = arrow if byteinteger(fp) = '>' -> again if byteinteger(fp) = nl result = minus s('*'): result = star s('/'): fp = fp+1 and result = slash2 if byteinteger(fp) = '/' result = slash s('¬'): fp = fp+1 and result = backslash2 if byteinteger(fp) = '¬' result = backslash s('^'): nonstandard(uparr) fp = fp+1 and result = uparrow2 if byteinteger(fp) = '^' result = uparrow s('!'): fp = fp+1 and result = exclam2 if byteinteger(fp) = '!' result = exclam s('&'): result = ampersand s('.'): result = dot s('='): fp = fp+1 and result = eqeq if byteinteger(fp) = '=' result = equals s('#'): fp = fp+1 and result = noteqeq if byteinteger(fp) = '#' result = noteq s('<'): fp = fp+1 and result = lesseq if byteinteger(fp) = '=' fp = fp+1 and result = noteq if byteinteger(fp) = '>' fp = fp+1 and result = lshift if byteinteger(fp) = '<' result = less s('>'): fp = fp+1 and result = greateq if byteinteger(fp) = '=' fp = fp+1 and result = rshift if byteinteger(fp) = '>' result = greater s('_'): result = underline s(':'): result = colon s(','): result = comma s(';'): result = terminator s('('): result = left s(')'): result = right s('|'): result = modsign s('E'): s('e'): fp = fp+1 and -> stringconst if byteinteger(fp) = '"' s('M'): s('m'): s('C'): s('c'): fp = fp+1 and -> charconst if byteinteger(fp) = '''' s('A'):s('B'):s('D'):s('F'):s('G'):s('H'): s('I'):s('J'):s('K'):s('L'):s('N'):s('O'):s('P'): s('Q'):s('R'):s('S'):s('T'):s('U'):s('V'):s('W'):s('X'): s('Y'):s('Z'):s('a'):s('b'):s('d'):s('f'): s('g'):s('h'):s('i'):s('j'):s('k'):s('l'):s('n'): s('o'):s('p'):s('q'):s('r'):s('s'):s('t'):s('u'):s('v'): s('w'):s('x'):s('y'):s('z'): -> keyword if percent # 0 ! identatoms = identatoms+1 newlen = charlim+1; hash = sym!casebit; !lower-case (if letter) byteinteger(newlen) = hash cycle sym = byteinteger(fp); fp = fp+1 repeat until sym # ' ' !$IF AMDAHL { %if sym = '''' %start { radix = 16 %and -> ibm %if hash = 'x' { radix = 8 %and -> ibm %if hash = 'k' { radix = 2 %and -> ibm %if hash = 'b' { %finish !$FINISH sym = map(sym) if sym # 0 start cycle newlen = newlen+1; byteinteger(newlen) = sym hash = hash<<1!!sym cycle sym = byteinteger(fp); fp = fp+1 repeat until sym # ' ' sym = map(sym) repeat until sym = 0 finish fp = fp-1 newlen = newlen-charlim; byteinteger(charlim) = newlen head == hashindex(hash&255) item = head if item > 0 start cycle result = ident if item <= 0 ditem == dict(item) exit if string(ditem_text+charbase) = string(charlim) ! misses = misses+1 item = ditem_link repeat until item <= 0 finish result = ident s('%'): sym = byteinteger(fp) -> again unless 'a' <= sym!casebit <= 'z' fp = fp+1 keyword: percent = 0 p = syminit(sym!casebit) cycle ! %cycle ! sym = byteinteger(fp)!casebit ! %exit %if symbol(p) # sym while symbol(p) = byteinteger(fp)!casebit cycle p = p+1; fp = fp+1 repeat exit if symbol(p) >= 128 atom = altdisp(p) if atom = 0 start result = dud unless sym!casebit = 'c' and byteinteger(fp) = nl read line ->again finish p = p+atom repeat percent = 1 if 'a' <= byteinteger(fp)!casebit <= 'z' subatom = altdisp(p) atom = symbol(p)-128 result = dud if atom = 0 result = atom !$IF AMDAHL {ibm: { nonstandard(ibmhex) { item = -1; t_val = 0 { -> ibm1 !$FINISH s('0'):s('1'):s('2'):s('3'):s('4'):s('5'):s('6'):s('7'):s('8'):s('9'): item = 0; t_type = inty radix = 10; t_val = sym-'0' ibm1: cycle cycle cycle sym = byteinteger(fp); fp = fp+1 repeat until sym # ' ' i = sym-'0' if radix = 10 start exit if i < 0 or i >= 10 if t_val > max10 or (t_val=max10 and i > maxdig) start t_type = realy; rval = t_val assemble real exit finish t_val = t_val*10+i finish else start i = sym!casebit-'a'+10 if i >= 10 exit if i < 0 or i >= radix j = radix cycle i = i+t_val if j&1 # 0 t_val = t_val<<1; j = j>>1 repeat until j = 0 t_val = i finish repeat exit unless sym = '_' radix = t_val result = dud if radix = 0 t_val = 0 repeat if sym = '.' start t_type = realy and rval = t_val if t_type = inty assemble real result = dud if j = 0 rval = rval/radix¬j finish ! %if t_type = realy %start; !vax->ieee ! t_val = integer(addr(rval)) ! t_val = t_val<<16+t_val>>16-16_01000000 ! %finish ! numatoms = numatoms+1 !$IF AMDAHL { %if item < 0 %start { %result = dud %if sym # '''' { item = 0 { %finish %else %start { fp = fp-1; sym = 0 { %finish !$IF VAX OR APM fp = fp-1; sym = 0 !$FINISH result = const s(''''): charconst: item = 0; t_type = inty t_val = 0 cycle sym = byteinteger(fp); fp = fp+1 result = dud if sym = nl; !?allow if sym = '''' start exit unless byteinteger(fp) = '''' fp = fp+1 finish t_val = t_val<<8+sym repeat result = const if t_val # 0 result = dud s('"'): stringconst: item = 0; t_type = stringy stringp = atomp; !for include t_val = 0 i = line; j = linestart cycle sym = byteinteger(fp); fp = fp+1 if sym = '"' start exit if byteinteger(fp) # '"' fp = fp+1 finish t_val = t_val+1 if t_val > 255 start sym = 0 fp = atomp; linestart = j result = dud finish read line if sym = nl repeat result = const s(*): result = dud end; !NEXT ATOM routine LOOKUP FIELD IDENT(integer list) item = list; return if item = 0 cycle ditem == dict(item) if ditem_flags&typeid = 0 start return if string(ditem_text+charbase) = string(charlim) exit if ditem_flags&more = 0 finish item = item+1; !misses = misses+1 repeat item = 0 end predicate A (integer k) !Basic atom-testing predicate atom = next atom if matched # 0 false if k # atom matched = 1 true end routine GET(integer k) atom = next atom if matched # 0 matched = 1 return if atom = k syntax error if atom = dud faultp = atomp; report(formerr+point,-k) signal 14 end routine ALLOW(integer k) if a(k) start finish end routine DECLARE if speccing = 0 start; !not within spec params if item >= c_localdpos start; !there already if d_flags&spec = 0 and d_flags+spec = ditem_flags c and ditem_type = d_type start ditem_flags = ditem_flags-spec return finish fault(duperr+point) finish d_link = head; head = dlim; !insert in list ! d_spare = hash&255 if item > 0 then d_text = ditem_text c else start d_text = charlim-charbase; charlim = charlim+newlen+1 croak("Identifier space exhausted") if charlim+80 >= charmin finish finish else d_text = 0 item = dlim; ditem == dict(item) ditem = d dlim = dlim+1; croak("Too many identifiers") if dlim >= dmin end; !DECLARE routine DECLARE ANON d_text = 0; d_link = 0 dict(dlim) = d dlim = dlim+1; croak("Too many identifiers") if dlim >= dmin end owninteger jammy predicate A ASSOP atom = next atom if matched # 0 if atom # equals and atom # eqeq start false unless atom = less and byteinteger(fp) = '-' jammy = 2; fp = fp+1 finish else jammy = 0 matched = 1 true end !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! Expressions !!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! owninteger literal=0 routinespec get EXPRESSION(integer rank,control) integerfn COMPAT(integer control) if t_type = inty start if control&intok = 0 and control&realok # 0 start item = floated(item) t_type = realy finish result = control&(intok+realok) finish result = control&(boolok>>(booltype-t_type)) if t_type <= booltype result = control&enumok if t_type < direct result = control&arrok end ! integerfn LISTMATCH(integer alist,blist) record(identinfo)name ap,bp result = 1 if alist = blist result = 0 if alist < dictmin or blist < dictmin cycle ap == dict(alist); bp == dict(blist) result = 0 if ap_type # bp_type; !for now alist = alist+1; blist = blist+1 repeat until ap_flags&bp_flags&more = 0 result = 0 if ap_flags&more # 0 or bp_flags&more # 0; !for now result = 1 end ! routine GET REFERENCE(integer reftype) integer type,temp get EXPRESSION(simple,refonly+any) type = ditem_type&puretype; reftype = reftype&puretype return if reftype = type if type < reftype start temp = type; type = reftype; reftype = temp finish return if reftype = nulltype; !untyped %name type = dict(type)_type return if type <= inty and type = reftype return if type >= direct and type = dict(reftype)_type; !aname expfault(typerr+point) end ! routine GET VALUE(integer valtype) record(identinfo)name dp,p get EXPRESSION(major,any) valtype = valtype&puretype dp == dict(valtype) if t_type # dp_type start; !base types differ return if item = 0 = t_val; !zero if dp_type = realy and t_type = inty start !float t_type = realy return finish else if t_type >= inty; !scalar if item = 0 start return if dp_low <= t_val <= dp_val jammy = jammy!1 if jammy >= 0 finish else start if t_low >= dp_low start return if t_val <= dp_val jammy = jammy!1 if jammy >= 0 return if t_low <= dp_val finish else start jammy = jammy!1 if jammy >= 0 return if t_val >= dp_low finish finish expfault(rangerr+point) if jammy < 2 return else if t_type = stringy if t_val > dp_val start; !VALUE = LENGTH* jammy = jammy!1 if jammy >= 0 expfault(rangerr+point) if item = 0 and jammy < 2 finish return else if t_type = recy return if t_extra = dp_extra jammy = jammy!1 and return if jammy >= 2 !partial assignment? else if t_type = realy return finish expfault(typerr+point) end; !GET VALUE ! routine GET LITERAL(integer littype) literal = literal+1 get VALUE(littype) literal = literal-1 end ! routine GET LITINT literal = literal+1 get EXPRESSION(major,intok) literal = literal-1 end ! routine GET LITSTRING integer holditem !Must be quoted string (for %alias and %include) holditem = item; !preserve get(const) error(typerr+point) if t_type # stringy item = holditem; !restore end ! routine GET PARMLIST record(identinfo)name hp,dp integer i,j,headitem,headact,dpos,case,procnp,first headitem = item; hp == ditem headact = rcall !stack procedure ident ! procnp = np; put3(headact,headitem,0) i = 0; first = 1 dpos = headitem; dp == hp cycle !Set up expression state from formal param details error(toomany+point) if dp_flags&more = 0 dpos = dpos+1 and dp == dict(dpos) until dp_flags&parm # 0 if dp_flags&proc # 0 start get(ident) name error if item <= 0 fault(typerr+point) if ditem_flags&proc = 0; !for now fault(caterr+point) if item > headitem else if dp_type < indirect; !value ! %if pp_type&numericmask # 0 %then case = i&7 %and i = i+1 %c ! %else case = i>>3+8 %and i = i+8 case = i&7; i = i+1 get VALUE(dp_type) finish else start; !name or proc case = i>>3+8; i = i+8 get REFERENCE(dp_type) finish ! case = case<<8+headact ! item = litref(t_val) %if item = 0 ! j = np-1 ! %if first = 0 %start ! j = np ! !NB Don't re-order parameters for implicits ! %if item >= expmin %and headitem > dnewline %start ! %while j > procnp %and exp(j-1)_y < expmin %cycle ! exp(j)_act = exp(j-1)_act; exp(j)_y = exp(j-1)_y ! j = j-1 ! %repeat ! %finish ! exp(np)_x = 0; np = np+1 ! %finish ! exp(j)_act = case; exp(j)_y = item ! first = 0 repeat until not a(comma) ! %if hp_type # nulltype %start ! i = explo ! %while i <= expmax %cycle ! %if exp(i)_x = headitem %start; ![enough?] ! item = i; j = procnp ! %cycle ! %exit %if exp(i)_y # exp(j)_y ! i = i+1; j = j+1 ! ->okf %if j >= np ! %repeat ! %finish ! i = i+1 ! %repeat ! %cycle ! explo = explo-1; np = np-1 ! exp(explo) = exp(np) ! %repeat %until np = procnp item = explo !okf:np = procnp ! %finish end; !get PARMLIST routine GET RESOLUTION if not a(left) start get REFERENCE(anystringvar) get(dot) get(left) finish get VALUE(anystring) get(right) if a(dot) start get REFERENCE(anystringvar) finish end ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! routine GET EXPRESSION(integer rank,control) !Main expression recognition routine !To bring together the treatment of all binary operators ! and ensure fast recognition of simple expressions, ! expressions of different levels are handled by ! precedence techniques rather than syntactically !CONTROL defines acceptability integer type,f,opok,c1,op,atomp1,item1 record(objinfo) t1 record(identinfo)name dp integerfn litval switch lit(64:atommax) -> lit(op) lit(plus): result = t1_val+t_val lit(minus): result = t1_val-t_val lit(mult): result = t1_val*t_val lit(idiv): result = t1_val//t_val if t_val # 0 fault(rangerr) result = 0 lit(logand): lit(booland): result = t1_val&t_val lit(logor): lit(boolor): result = t1_val!t_val lit(logxor): result = t1_val!!t_val lit(lshift): result = t1_val<<t_val lit(rshift): result = t1_val>>t_val lit(boolnot): result = t_val!!true lit(lognot): result = ¬t_val !lit(negate): %result = -t_val lit(equals): result = true if t1_val = t_val result = false lit(noteq): result = true if t1_val # t_val result = false lit(lesseq): result = true if t1_val <= t_val result = false lit(less): result = true if t1_val < t_val result = false lit(greateq): result = true if t1_val >= t_val result = false lit(greater): result = true if t1_val > t_val result = false lit(concat): result = t1_val+t_val lit(*): !report(notwhat,-op) result = 1 end !Get leading operand atom = next atom if matched # 0 atomp1 = atomp; !note position for reports if atom = ident start matched = 1 name error if item <= 0 fault(selfref+point) if item >= dlim0 type = ditem_type if control&(refonly+varonly) # 0 start error(nonvar+point) if control&varonly # 0 and f&var = 0 error(nonref+point) if type < direct finish f = ditem_flags if inty <= type <= booltype and f&proc = 0 start; !literal item = 0; t = ditem_details else fault(nonliteral+point) if literal > 0 if f&proc # 0 start ditem == dict(type) and type = ditem_type if f&parm # 0 error(caterr+point) if type = nulltype; !routine if a(left) start dp == ditem get PARMLIST; get(right) ditem == dp else error(toofew+point) if ditem_flags&more # 0 item = explo;!expref(f&var+fcall,item,0) finish finish cycle dp == dict(type&puretype); t = dp_details atom = next atom if matched # 0 exit if atom # underline and atom # left matched = 1 item1 = item if atom = left start cycle syntax error if t_type < direct; !element type type = t_type get VALUE(t_val); !index item = explo;!expref(aref,item1,item,t_val) ditem == dp exit if not a(comma) dp == dict(type&puretype); t = dp_details item1 = item repeat get(right) else; !rec subfield syntax error if t_type # recy get(ident) lookup field ident(t_extra) error(namerr+point) if item <= 0 type = ditem_type item = explo;!expref(recref,item,item1) finish repeat -> final if control&(varonly+refonly) # 0 finish else error(nonvar+point) if control&varonly # 0 error(nonref+point) if control&refonly # 0 if a(const) start else if atom = minus; !leave unmatched item = 0; t = 0; t_type = inty else if a(left) if rank < major start; !condition get EXPRESSION(cond,any) finish else start jammy = jammy-4 c1 = control; c1 = c1!intok if c1&realok # 0 get EXPRESSION(major,c1) jammy = jammy+4 finish get(right) else if a(keynot) syntax error if rank >= major get EXPRESSION(scond,any) if item = 0 then t_val = t_val!!true c else item = explo; !expref(boolnot,item,0) else if atom = backslash item = 0; t = 0; t_type = inty atom = tilde else if a(modsign) fault(typerr+point) if control&arithok = 0 get EXPRESSION(major,arithok) get(modsign) if item = 0 start if t_val < 0 start if t_val # minint then t_val = -t_val else expfault(rangerr) finish else if t_type = inty item = explo;!expref(imod,item,0) else if t_type = realy item = explo;!expref(fmod,item,0) else error(typerr) finish else syntax error finish finish atom = next atom if matched # 0 while atom >= rank cycle op = atom; matched = 1 opok = opbits(op); c1 = compat(opok); ![may change ITEM,T_TYPE] fault(typerr+point) if c1 = 0 item1 = item; t1 = t if op >= major start; !non-conditional if op = dot then get EXPRESSION(dot,stringok) {right-associate} c else get EXPRESSION(op&(¬7)+8,c1) if t_type = realy and t1_type = inty start item1 = floated(item1); t1_type = realy finish ! op = op+? %if t_type = realy %and opok&intok # 0 else if op = resolve start get RESOLUTION else if op >= eqeq get EXPRESSION(simple,any+refonly) else if op >= equals get EXPRESSION(major,c1) if equals <= atom < eqeq start op = atom; matched = 1 get EXPRESSION(major,c1) finish if t_type = realy and t1_type = inty start item1 = floated(item1); t1_type = realy finish else get EXPRESSION(scond,any) if atom >= cond start syntax error if atom # op finish finish t_type = booltype t_low = 0 and t_val = 1 if item # 0 finish if item1 = 0 start; !first operand literal if item = 0 start; !both literal t_val = litval continue if item = 0 ! item1 = litref(t1_val) ! %else %if inverse(op) # 0; !invertable ! op = inverse(op) ! temp = t; t = t1; t1 = temp; !standardise order ! item1 = item; item = 0 else ! item1 = litref(t1_val) finish finish if item = 0 start; !second operand literal if op = minus and t_type = inty start; !standardise t_val = -t_val if t_val # minint; op = plus finish item = item1 and continue if t_val = 0 and opok&znop # 0 finish item = explo;!expref(op,item1,item,t_val) t_low = minint; t_val = maxint; !?real repeat final: expp = atomp1; !restore to start expfault(typerr) if compat(control) = 0 end; !get EXPRESSION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! Conditions and loops !!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! routine GET CONDITION integer polarity polarity = subatom condnp = np get EXPRESSION(cond,any) ! put3(jump+polarity,item,0) end; !get CONDITION routine GET STATEMENTS(integer stopper) integer holdnp,holdlooplab switch initial(0:atommax) routine GET INSTRUCTION integer item1,hold,act record(identinfo)name ditem1 routine putact ! put3(act,t_val,hold) end ! if c_flags < hadinst start; !first in block c_flags = c_flags+hadinst fault(ordererr) if level <= outerlevel finish instnp = np cycle if a(ident) start name error if item <= 0 if ditem_flags&var # 0 start matched = 0 get EXPRESSION(simple,any) item1 = item; ditem1 == ditem if a(equals) start get VALUE(ditem1_type) ! put2(assign,item1) else if a(eqeq) syntax error if ditem1_type < indirect get REFERENCE(ditem1_type) item = item+ad if item # 0 ! put2(assign,item1+ad) else if atom = less and byteinteger(fp) = '-' fp = fp+1; matched = 1 jammy = 2 get VALUE(ditem1_type) ! put2(jamassign,item1) else syntax error if not a(arrow) get RESOLUTION ! put2(resolve,item1) finish else error(caterr+point) if ditem_flags&proc = 0 ditem == dict(ditem_type) if ditem_flags&parm # 0 error(caterr+point) if ditem_type # nulltype if a(left) start get PARMLIST; get(right) else; !parameterless routine error(toofew+point) if ditem_flags&more # 0 ! put3(rcall,item,0) finish finish finish else start act = atom; hold = subatom; t_val = 0 c_access = 0 if a(monitor) start c_access = 1 ! fault(monitor<<8) else if a(exit); !%exit, %continue if looplab = 0 then fault(notinloop+point) c else t_val = looplab and putact exit else if a(return) if c_type # nulltype then fault(notinrout+point) c else putact exit else if a(result) error(notinfun+point) if c_type <= nulltype syntax error if not a assop if c_type < direct start; !function fault(caterr+point) if atom = eqeq get VALUE(c_type) ! put2(result,0) else; !map fault(caterr+point) if atom # eqeq get REFERENCE(c_type+(indirect-direct)) ! put2(result,0) finish exit else if a(tf); !%true, %false if c_type # booltype then fault(notinpred+point) c else putact exit else if a(arrow) or a(goto) nonstandard(kgoto) if atom = goto get(ident) if byteinteger(fp) # '(' start if item < c_localdpos or ditem_flags&lab = 0 c or ditem_type # nulltype start d_flags = spec+lab; d_type = nulltype declare finish ! put3(jump,item,0) finish else start name error if item < c_localdpos syntax error if ditem_flags&lab = 0 or ditem_type = nulltype get(left) get VALUE(ditem_type); !index get(right) finish exit else if a(stop) putact exit else if a(signal) c_access = 1 allow(keyevent) get LITINT expfault(rangerr+point) unless 0 <= t_val <= 15 hold = t_val; t_val = 0 get LITINT if a(comma) hold = t_val<<4+hold item = 0; t_val = 0 get VALUE(anyint) if a(comma) ! put2(act,hold) exit else syntax error finish finish repeat until not a(keyand) end; !GET INSTRUCTION routine GET FOR CLAUSE integer loopvar,k,s,start,sval,i,inc,ival,e,n,temp integer eval record(identinfo)name dp holdnp = np; temp = 0 dict(curlab)_val = 1; !dummy condnp = np get(ident) name error if item <= 0 fault(typerr+point) if dict(ditem_type&puretype)_type # inty fault(caterr+point+warn) if ditem_type # direct+inttype loopvar = item; dp == ditem get(equals) get VALUE(ditem_type) start = item; sval = t_val get(comma) get VALUE(anyint) inc = item; ival = t_val expfault(rangerr+point) and ival = 1 if inc = 0 = ival get(comma) get VALUE(ditem_type) !Deal with INC and replace START by START-INC ! k = undef ! k = exp(start)_y %if start >= expmin %and exp(start)_act = plus if inc = 0 start; !literal increment i = 1; !litref(ival) if start = 0 start; !START and INC both literal sval = sval-ival; s = 1; !litref(sval) ! %else %if k <= litmax; !START is x+lit ! k = ival-litval(k) ! s = exp(start)_x; s = explo;!expref(plus,s,litref(k)) %if k # 0 else s = explo;!expref(plus,start,litref(-ival)) finish finish else start; !allocate temp var ! i = tempvar; put3(assign,i,inc); temp = temp-4 ! %if start = inc %start; !identical ! s = 0; sval = 0 ! %else %if k = inc; !START is x+INC ! s = exp(start)_x ! %else ! s = start; s = litref(sval) %if s = 0 s = explo;!expref(minus,s,i) ! %finish finish ! %if item = 0 %start; !literal end-value ! e = litref(t_val); eval = t_val ! %finish %else %start ! e = tempvar; put3(assign,e,item); temp = temp-4 ! %finish ! put3(assign,loopvar,s) ! put3(label,curlab,0) if start!inc!item = 0 start; !all literal k = t_val-sval; n = k//ival fault(boundserr) if n < 0 fault(unending) if n*ival # k ! %if 0 <= t_val <= 32767 %start ! temp = loopvar ! %finish finish ! %if temp <= 0 %start ! c_fortemps = c_fortemps-temp; !ie increment ! put3(compare,loopvar,e) ! put3(eq,0,curlab+1) ! %finish ! put3(plusass,loopvar,i) ! compile(holdnp,np) end; !get FORCLAUSE routine GET SWITCH INDEX integer item1 record(identinfo)name dp item1 = item; dp == ditem get(left) item = 1 if a(star) start fault(duperr+point) if dp_spare # 0 dp_spare = 1 else get LITERAL(dp_type) !beware faulty declaration or index if dp_type > inttype and faultnum = 0 start t_val = t_val-dict(dp_type)_low+dp_val expfault(duperr+point) if final(t_val) # 0 ! define jumps(final(t_val)); !in case of lit jumps final(t_val) = 1 finish finish get(right) c_access = 1 end ![unsure of efficiency implications of trapping overflow lower down] on event 1,14 start !$IF VAX report(rangerr,0) if event_event = 1 !$IF AMDAHL { report(rangerr,0) %if eventinf>>8 = 1 !$FINISH -> skip finish !!!!!!!!!!!!!!!!!!! Start of new statement !!!!!!!!!!!!!!!!!!! next: statements = statements+1 next1: report(faultnum,faultp) if faultnum # 0 d = 0; declmode = 0; dsize = 0 dlim0 = dlim; elements = 0 speccing = 0; mcoding = 0 literal = 0; jammy = 0 dict(curlab)_val = 0; dict(curlab+1)_val = 0 np = np0; instnp = np0; condnp = np0 ! constad == finalad; constbound = purebound if explo < expmin+50 or litpos > litmax-50 start !zaps = zaps+1; zaps = zaps+999 %if litpos > litmax-50 forget all finish t_val = 0 ! initial(terminator): atom = next atom; matched = 1 -> initial(atom) initial(star): initial(exclam): initial(exclam2): read line -> next1 term: get(terminator) -> next skip: c_access = -1 if atom # terminator start cycle subatom = atom; atom = next atom repeat until atom = terminator starts = starts+1 if subatom = start cycles = cycles+1 if subatom = cycle finish -> next initial(dud): syntax error; !ie atom error initial(*): error(nonstarter+point) initial(ident): if byteinteger(fp) = ':' start; !simple label fp = fp+1 d_flags = lab; d_type = nulltype declare set user label(item) ->next finish name error if item <= 0 if ditem_flags&lab # 0 start get SWITCH INDEX get(colon) ->next finish initial(return): initial(result): initial(tf): initial(stop): initial(signal): initial(monitor): initial(exit): initial(goto): initial(arrow): matched = 0 get INSTRUCTION -> next if a(terminator) c_access = 1 if a(iu) start holdnp = np get CONDITION ! compile(holdnp,np) else if a(while) holdnp = np ! put3(label,curlab,0) get CONDITION ! compile(holdnp,np) ! put3(jump,curlab,0) ! put3(label,curlab+1,0) else if a(for) get FOR CLAUSE ! put3(jump,curlab,0) ! put3(label,curlab+1,0) else syntax error if not a(until) get CONDITION finish -> term initial(iu): !%if, %unless cycle holdnp = np get CONDITION ! compile(holdnp,np) if a(then) start -> fudge if a(start) get INSTRUCTION finish else start get(start) fudge: cycle get(terminator) curlab = curlab+2 get STATEMENTS(else) curlab = curlab-2 exit if atom # else; !%finish -> get CONDITION if a(iu) repeat return if atom # finish finish exit if not a(else) -> fudge if a(start) get INSTRUCTION and exit if not a(iu) repeat -> term initial(cycle): if a(terminator) start holdlooplab = looplab; looplab = curlab curlab = curlab+2 get STATEMENTS(repeat) curlab = curlab-2; looplab = holdlooplab return if atom # repeat get CONDITION if a(until) -> term finish nonstandard(oldcycle) get FOR CLAUSE -> for1 initial(while): holdnp = np ! put3(label,curlab,0) get CONDITION ! compile(holdnp,np) get(cycle) get(terminator) holdlooplab = looplab; looplab = curlab curlab = curlab+2 get STATEMENTS(repeat) curlab = curlab-2; looplab = holdlooplab return if atom # repeat nonstandard(loop2) and get CONDITION if a(until) ! put3(jump,curlab,0) ! put3(label,curlab+1,0) ->term initial(for): get FOR CLAUSE get(cycle) for1: get(terminator) holdlooplab = looplab; looplab = curlab curlab = curlab+2 get STATEMENTS(repeat) curlab = curlab-2; looplab = holdlooplab return if atom # repeat ! put3(repeat,0,0) -> term initial(on): fault(ordererr+point) if c_flags >= hadon or level <= outerlevel c_flags = c_flags!hadon matched = 1 allow(keyevent) cycle get LITINT expfault(rangerr+point) unless 0 <= t_val <= 15 c_events = c_events!1<<t_val repeat until not a(comma) get(start) ! put3(on,0,0) curlab = curlab+2 get STATEMENTS(finish) curlab = curlab-2 return if atom # finish -> term ! initial(else): -> skip if starts # 0 return if stopper = else error(noif) if stopper = finish initial(finish): starts = starts-1 and -> skip if starts # 0 return if stopper = finish or stopper = else error(nostart) initial(repeat): cycles = cycles-1 and -> skip if cycles # 0 return if stopper = repeat error(nocycle) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!! Declarations !!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! integerfn NEWATYPE(integer eltype,xtype) integer dpos record(identinfo)name dp ownrecord(identinfo) d=0 dpos = dictmin cycle dp == dict(dpos) result = dpos+direct if dp_flags&typeid # 0 c and dp_type = eltype and dp_val = xtype dpos = dpos+1 repeat until dpos = dlim d_flags = typeid; d_type = eltype; d_val = xtype dict(dpos) = d dlim = dlim+1; croak("Too many identifers") if dlim >= dmin result = dpos+direct end ! integerfn NEWSTYPE(integer max) integer dpos record(identinfo)name dp ownrecord(identinfo) d=0 dpos = dictmin cycle dp == dict(dpos) result = dpos if dp_type = stringy and dp_val = max dpos = dpos+1 repeat until dpos = dlim d_flags = typeid; d_type = stringy d_val = max dict(dpos) = d dlim = dlim+1; croak("Too many identifers") if dlim >= dmin result = dpos end ! integerfn NEWRANGE(integer type,lower,upper) integer dpos record(identinfo)name dp ownrecord(identinfo) d=0 fault(boundserr) and upper = lower if lower > upper elements = maxint elements = upper-lower if upper!!lower >= 0 c or minint+upper-lower < 0 elements = elements+1 if elements # maxint dpos = dictmin cycle dp == dict(dpos) result = dpos if dp_flags = typeid and dp_type = type c and dp_low = lower and dp_val = upper dpos = dpos+1 repeat until dpos = dlim d_flags = typeid; d_type = type d_low = lower; d_val = upper dict(dpos) = d dlim = dlim+1; croak("Too many identifers") if dlim >= dmin result = dpos end routine GET LITBOUNDS integer lower get(left) get LITINT; lower = t_val get(colon) get LITINT; get(right) t_low = lower item = newrange(inty,t_low,t_val); !always integer at present end routine GET IDENT dlim0 = dlim get(ident) declare get LITSTRING if d_flags&ext # 0 and a(alias) end routine GET IDENTLIST dlim0 = dlim cycle get(ident) declare get LITSTRING if d_flags&ext # 0 and a(alias) repeat until not a(comma) end routine GET TYPE(integer flags) owninteger fbase ownrecord(identinfo)name formp,fieldp ! routine GET FORMATDEF; !(%integername base) integer disp,max,base routine GET FIELD IDENT get(ident) if item > 0 then d_text = ditem_text c else start d_text = charlim-charbase; charlim = charlim+newlen+1 croak("Identifier space exhausted") if charlim+80 >= charmin finish ditem == dict(dlim); fieldp == ditem ditem = d if formp_extra = 0 then formp_extra = dlim c else start ! lookup field ident(formp_extra) ! fault(duperr+point) %and item = dlim %if item # dlim finish dlim = dlim+1; croak("Too many identifiers") if dlim >= dmin end routine get UNIT cycle if a(left) start get FORMATDEF; get(right) return if not a(comma) else get TYPE(static+more) if d_flags&parm = 0 start; !not array cycle disp = disp+1 if disp&1 # 0 and dsize # 1 d_val = disp disp = disp+dsize get FIELD IDENT return if not a(comma) atom = next atom repeat until atom # ident else; !array d_flags = d_flags-parm disp = disp+1 if disp&1 # 0; d_val = disp get FIELD IDENT get LITBOUNDS fieldp_type = newatype(d_type,item) disp = disp+dsize*elements return if not a(comma) finish finish repeat end max = 0; base = 0 cycle disp = base get UNIT max = disp if max < disp repeat until not a(keyor) base = max end; !get FORMATDEF dsize = 0; d_mode = 0; d_val = 0 d_type = nulltype if a(rpred) start; !%routine,(%integerfn) flags = flags&(¬static) if flags&ext # 0 syntax error if flags&static # 0 nonstandard(pred) and d_type = booltype if subatom # 0 d_flags = flags+proc; declmode = declmode+pcmode return finish if a(krange) start; !%byte,%short,%half,%mite d_type = inttype+subatom; dsize = 1 dsize = 2 if d_type = shorttype or d_type = halftype nonstandard(ranges) if d_type >= mitetype allow(keyinteger) else if a(keyinteger); !%integer d_type = inttype; dsize = 4 atom = next atom if atom = left start get LITBOUNDS d_type = item dsize = 2 if elements <= 65536 and t_low >= -32768 dsize = 1 if elements <= 256 and t_low >= -128 finish else if a(keylong); !%long d_type = longinttype; dsize = 8 d_type = longrealtype and get(keyreal) if not a(keyinteger) else if a(keyreal); !%real d_type = realtype; dsize = 4 else if a(keystring); !%string d_type = stringy t_val = 255; dsize = 256 if a(left) start t_val = 0 if not a(star) start get LITINT expfault(rangerr+point) and t_val = 255 unless 0 < t_val <= 255 finish get(right) finish else nonstandard(nolength) if t_val # 0 start d_type = newstype(t_val) dsize = (t_val+2)&(¬1); !+1 & evened up finish else if a(keyrecord); !%record d_type = recy if a(keyformat) start syntax error if flags&(static+ext) # 0 if a(keyspec) start d_flags = typeid+spec get IDENT finish else start d_flags = typeid get IDENT formp == ditem get(left) fbase = 0 get FORMATDEF fieldp_flags = fieldp_flags-more get(right) finish d_flags = typeid return finish get(left) if not a(star) start if not a(ident) start get FORMATDEF fieldp_flags = fieldp_flags-more get(right) d_flags = typeid declare anon finish name error if item <= 0 syntax error if ditem_type # recy d_type = item; dsize = ditem_val finish get(right) else syntax error if atom # keyname; !untyped %name finish !End of basic type info: set item size in DECLMODE if dsize <= 4 start if dsize <= 2 then declmode = dsize<<sizeshift c else declmode = longsize<<sizeshift finish !Appendages if a(fnmap) start; !%fn, %map flags = flags&(¬static) if flags&ext # 0 syntax error if flags&static # 0 flags = flags+var and d_type = d_type+direct if subatom # 0; !map d_flags = flags+proc; declmode = declmode+pcmode return finish d_type = d_type+direct while a(keyarray) or a(keyname) cycle if atom = keyarray start; !%array nonstandard(naming) if d_type >= indirect if not a(keyname) start syntax error if flags&parm # 0 flags = flags+parm; !as indic exit finish d_type = newatype(d_type,inty) finish syntax error if d_type >= indirect d_type = d_type+(indirect-direct) dsize = 4 repeat d_flags = flags!!var end; !GET TYPE ! routine GET OWN ARRAY DECLARATION integer holdval,dpos record(identinfo)name dp ! constad = constad+1 %if constad&1 # 0 ! d_val = constad ! d_val = d_val-ownbase %if d_val >= ownbase get IDENT dpos = item; dp == ditem get LITBOUNDS dp_type = newatype(d_type,item) if a assop start allow(terminator) cycle get LITERAL(d_type) faultnum = rangerr+point+warn if faultnum = rangerr+point holdval = t_val t_val = 1 if a(left) start t_val = elements get LITINT if not a(star) get(right) finish ! plant const(holdval,t_val) elements = elements-t_val repeat until not a(comma) report(counterr,dpos) if elements # 0 and faultnum = 0 finish ! plant const(0,elements) %if elements > 0 end; !get OWN ADECL routine GET ARRAY DECLARATION !ie get IDENTLISTS and BOUNDS integer i,dlim1,hold,holdval,type !%routine put bound pair ! hold = litref(holdval) %if hold = 0 ! item = litref(t_val) %if item = 0 ! put3(r,hold,item); !(range),lower,upper !%end routine GET BOUNDS integer range get VALUE(anyint) hold = item; t_val = minint if hold # 0 holdval = t_val get(colon) get VALUE(anyint) t_val = maxint if item # 0 range = newrange(inty,holdval,t_val) GET BOUNDS if a(comma) type = newatype(type,range) end cycle type = d_type get IDENTLIST dlim1 = dlim get(left) GET BOUNDS get(right) ! %if hold = 0 = item {both literal} %and np = np0 {1-dim} %c ! %and elements <= 32767 {safe to multiply?} %c ! %and (elements*dsize*(dlim-dpos))<<1-c_sp-c_delta <= 32000 %start ! d_par = parref(inty,0,r,0) ! %finish %else %start ! put bound pair ! d_par = 0 ! i = np ! %while i # np0 %cycle ! i = i-1 ! d_par = parref(inty,0,exp(i)_act,d_par) ! %repeat ! exp(np0)_act = adecl ! %finish ! i = np while dlim0 # dlim1 cycle ! %if i = np0 %start ! c_delta = c_delta-elements*dsize ! c_delta = c_delta-1 %if c_delta&1 # 0 ! dict(dlim0)_flags = dict(dlim0)_flags!static ! %finish %else %start ! np = i; compile(np0,np0) ! c_flags = c_flags!dynarray ! %finish ! dict(dlim0)_val = c_sp+c_delta dict(dlim0)_type = type dlim0 = dlim0+1 repeat repeat until not a(comma) end; !get BOUNDS routine GET PARMDEF integer headitem,dpos,dlim1 record(identinfo)name headditem,dp integerfn PARMMATCH(integer apos) integer bpos record(identinfo)name ap,bp bpos = dlim1 ap == dict(apos) while bpos # dlim cycle result = 0 if ap_flags&more = 0 apos = apos+1 and ap == dict(apos) until ap_flags&parm # 0 bp == dict(bpos) result = 0 if ap_type # bp_type; !for now bpos = bpos+1 repeat result = 1 if ap_flags&more = 0 result = 0 end ! headitem = item; headditem == ditem dlim1 = dlim if a(left) start cycle get TYPE(parm!more) if atom # ident if d_flags&proc = 0 start get IDENT exit if not a(comma) and atom = right if atom # comma then nonstandard(nocomma) c else atom = next atom finish else start get IDENT speccing = speccing+2 get PARMDEF speccing = speccing-2 exit if not a(comma) finish repeat dict(dlim-1)_flags = dict(dlim-1)_flags-more get(right) finish if speccing >= 2 start dpos = dictmin cycle dp == dict(dpos) if dp_flags&proc # 0 and dp_type = headditem_type start if parmmatch(dpos) # 0 start headditem_type = dpos; dlim = dlim1 return finish finish dpos = dpos+1 repeat until dpos >= headitem fault(caterr); dlim = dlim1 return finish if speccing = 0 and headditem_flags&spec # 0 start headditem_flags = headditem_flags-spec fault(matcherr) if parmmatch(headitem) = 0 else headditem_flags = headditem_flags!more if dlim # dlim1 finish end; !get PARMDEF initial(keylabel): nonstandard(klabel) d_flags = lab+spec; d_type = nulltype get IDENTLIST -> term initial(prefix): d_flags = subatom; ! !wflag!okflag ! fault(prefix<<8) %if d_flags&extmask # 0 atom = next atom initial(krange): initial(keylong): initial(keyinteger): initial(keyreal): initial(keystring): initial(keyrecord): initial(rpred): matched = 0 get TYPE(d_flags) if a(keyspec) start if a(left) start get LITINT; get(right) declmode = declmode&sizemask+absmode d_val = t_val get IDENT speccing = 1 and get PARMDEF if d_flags&proc # 0 -> term finish d_flags = d_flags+spec get IDENTLIST and -> term if d_flags&proc = 0 finish if d_flags&proc # 0 start get(ident) if item >= c_localdpos and ditem_type = d_type c and ditem_flags&proc # 0 start if ditem_flags&spec = 0 or d_flags&spec # 0 start item = 0; d_flags = d_flags+alt declare finish finish else declare get LITSTRING if d_flags&ext # 0 and a(alias) if d_flags&spec # 0 start speccing = 1 get PARMDEF finish else start open block(item) get PARMDEF c_parlim = dlim compile entry get(terminator) get STATEMENTS(end) ! %if c_access > 0 %start ! report(noresult,0) %if c_type > nulltype; !fn/map/pred ! %finish close block finish else if d_flags = typeid {dealt with} else if d_flags&parm # 0; !array d_flags = d_flags-parm if d_flags&static # 0 start get OWN ARRAY DECLARATION finish else start if d_flags&static = 0 and c_flags >= hadon start fault(ordererr); c_flags = c_flags&(¬(hadon+hadinst)) finish get ARRAY DECLARATION finish else if d_flags = static {const} d_type = dict(d_type&puretype)_type d_type = d_type+direct if d_type = recy or d_type = stringy cycle get IDENT syntax error if not a assop get LITERAL(d_type) faultnum = rangerr+point+warn if faultnum = rangerr+point dict(dlim-1)_val = t_val repeat until not a(comma) else if d_flags&static # 0 {own} ! constad == ownad; constbound = finalbound declmode = declmode+ownmode cycle ! constad = constad+1 %if constad&1 # 0 %and dsize # 1 ! t_val = constad-ownbase get IDENT t_val = 0 if a assop start ! %if d_flags&direct = 0 get LITERAL(d_type) faultnum = rangerr+point+warn if faultnum = rangerr+point finish elements = 1 ! plant const(t_val,1) repeat until not a(comma) else; !dynamic variable ! declmode = declmode+dispmode+level if d_flags&static = 0 and c_flags >= hadon start fault(ordererr); c_flags = c_flags&(¬(hadon+hadinst)) finish cycle !problematic c_delta = c_delta-1 %if c_delta&1 # 0 %and dsize # 1 c_delta = c_delta-dsize c_delta = c_delta-1 if c_delta&1 # 0 t_val = c_sp+c_delta get IDENT if a assop start nonstandard(initass) if d_type >= indirect start fault(caterr+point) if atom # eqeq get REFERENCE(d_type) item = item+ad if item # 0 ! put3(assign,dlim-1+ad,item) finish else start fault(caterr+point) if atom = eqeq get VALUE(d_type) ! put2(assign,dlim-1) finish ! compile(np0,np0) finish repeat until not a(comma) finish -> term routine GET SWITCH DECLARATION integer i,j,dlim1 matched = 1 cycle d_flags = lab; d_type = nulltype declmode = pcmode+wordsize<<sizeshift get IDENTLIST dlim1 = dlim get LITBOUNDS cycle; !For each ident in group exit if spc-elements <= 0; !ignore if too many for i = 1,1,elements cycle spc = spc-1; final(spc) = 0 repeat dict(dlim0)_val = spc dict(dlim0)_type = item dlim0 = dlim0+1 repeat until dlim0 = dlim1 repeat until not a(comma) end initial(keyswitch): get SWITCH DECLARATION ->term !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!! Control statements !!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! initial(keycontrol): get LITINT control = 0 if t_val = 0 control = control!!t_val ->term initial(include): get LITSTRING extra_name = "" while t_val > 0 cycle extra_name = extra_name.tostring(byteinteger(atomp)) atomp = atomp+1; t_val = t_val-1 repeat get(terminator) if faultnum = 0 start connect edfile(extra) nonstop = -999 and signal 12 if extra_flag # 0 mainfp = fp; mainline = line line = 0; sym = nl fp = extra_start2; curstart = fp; curlim = extra_lim2 modesym = '&'; nonstop = nonstop+1 finish ->next initial(keylist): ->term initial(begin): c_sp = -8 get(terminator) open block(0) get STATEMENTS(0) close block -> term if stopper >= 0 return initial(end): if not a(of) start fault(nofinish) if stopper = else or stopper = finish fault(norepeat) if stopper = repeat return if stopper >= 0 fault(nobegin) ->term finish if a(keylist) start ->term finish if a(keyfile) start if curlim = extra_lim2 start switch input ->next finish finish else get(program) end; !GET STATEMENTS routine INIT(integer t,l,h) d_flags = typeid; d_type = t; d_low = l; d_val = h dict(dlim) = d; dlim = dlim+1 end on event 12 start -> printout if fp = main_lim2 -> ended if main_flag < 0 or nonstop = -999; !abandon or CROAK change = main_change finish printstring(" IMP Checker "); newline hashindex(i) = 0 for i = 0,1,255; !hash table empty charbase = addr(char(0)); byteinteger(charbase) = 0; !for anon ident charlim = charbase+1 charmin = charlim+charbound; !(1 over top) dict(i)_val = 0 for i = d0,1,labmax d_flags = typeid; d_low = minint; d_val = maxint dmin = dictmax-1; dlim = dictmin cycle d_type = dlim; dict(dlim) = d dlim = dlim+1 repeat until dlim > booltype d_flags = 0 init(booltype,0,0) init(booltype,0,1) d_flags = typeid init(inty,minint,maxint) init(inty,-32768,32767) init(inty,0,65535) init(inty,0,255) init(inty,-128,127) init(inty,0,1) init(inty,minint,maxint) init(realy,minint,maxint) init(realy,minint,maxint) c = 0; c_localdpos = dlim; c_parlim = dlim level = outerlevel spc = finalbound faults = 0; line = 0; mainline = 0 ! mainfp = main_start1 extra_name = permfile connect edfile(extra) nonstop = -999 and signal 12 if extra_flag # 0 fp = extra_start2; curstart = fp; curlim = extra_lim2 nonstop = -2; nonstop = -1 if main_flag = 'I' sym = nl get STATEMENTS(-1) ! report(noend,0) %if level < mainlevel ! report(nobegin,0) %if level > mainlevel ! compile end %while level >= mainlevel printout: ! time2 = cputime if faults = 0 start write(statements,1) print string(" statements checked ") finish else start write(faults,1) print string(" fault") put sym('s') if faults > 1 print string(" reported ") finish newline ended: newline; !*for now to ensure message not erased* ! %if control&logbit # 0 %start !! write(zaps,1); print symbol('Z') ! write(statements,1); print symbol('S') ! statements = 1 %if statements = 0 ! atoms = atoms+statements ! print(atoms/statements,1,1); print symbol('A') ! print(numatoms/statements,1,1); print symbol('N') ! print(identatoms/statements,1,1); print symbol('I') ! print(misses/identatoms,1,2); print symbol('H') ! print((time2-time1)/statements,3,3); print symbol('M') !! write(finalad,1); print symbol('B') !! write(ownad-ownbase,1); print symbol('O') ! newline ! %finish end; !of ECCECI endoffile