!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