begin 
!$IF ECSVAX
{%conststring(51) title = -
{"  EUCSD IMP Compiler for M68000.  VAX Version  2.3b"
!$IF APM
%conststring(51) title = -
"  EUCSD IMP Compiler for M68000.  APM Version  2.3b"
!$FINISH
!
! Hamish Dewar  Computer Science   Edinburgh University  1982/83/84
!
%constinteger WHICH='.imp'

!<
                              start2,lim2, {part 2}
                              lim, {VMLIM}
                              lbeg,fp,change,flag,
                              line  {line number of current pos},
                              diff  {diff between LINE and ROW},
                       byte   top  {top row of sub_window},
                              win  {floating top},
                              bot  {bottom row of sub_window},
                              min  {minimum window size},
                              row  {last row position},
                              col  {last col position},
             string (maxname) name)
!
external routine spec  EDI(record (edfile)name  main,sec,
                         string (255) message)
{PAM: parameter acquisition module}
constinteger  NEWGROUP=1, NODEFAULT=2
external routine spec  DEFINE PARAM alias  "PAM_DEFSTRING" -
          (string (255) name, name  variable, integer  flags)
external routine spec  DEFINE INT PARAM alias  "PAM_DEFINT" -
          (string (255) name, name  variable, integer  flags)
external routine spec  DEFINE BOOLEAN PARAMS alias  "PAM_DEFBOOL" -
    (string (255) name, name  variable, integer  flags)
external routine spec  PROCESS PARAMETERS alias  "PAM_PROCESS"(string (255) parm)
external routine spec  CONNECT EDFILE(record (edfile)name  f)
external routine spec  DISCONNECT EDFILE(record (edfile)name  f)
external string (8)fnspec  DATE
external string (5)fnspec  TIME
!
owninteger  ITEM=0;                ![high-frequency]
owninteger  LISTOUT=0 {set to 2 if listing to file}
!!  Compiler control
constinteger  ARRBIT=   16_80000000 {array bound check},
              LOOPBIT=  16_40000000 {%for loop check},
              CAPBIT=   16_20000000 {capacity check},
              OVERBIT=  16_10000000 {overflow check},
              ASSBIT=   16_08000000 {integer-unassigned check},
              STRASSBIT=16_04000000 {string-unassigned check},
              SASSBIT=  16_02000000 {short-unassigned check},
              BASSBIT=  16_01000000 {byte-unassigned check},
              ASSMASK=assbit!strassbit!sassbit!bassbit,
              LINEBIT=  16_00800000 {set line number},
              DIAGBIT=  16_00400000,
              TRACEBIT= 16_00200000 {plant TRAP 15},
              STACKBIT= 16_00100000 {stack over-run check},
              CHECKBIT= 16_00080000 {for NOCHECK},
              SYSBIT=   16_00040000 {special treatment of SIGNAL},
              STRICTBIT=16_00020000,
              VOLBIT   =16_00010000,
              HALFBIT=  16_00008000 {halfword MULT/DIV},
              LOWBIT  = 16_00004000 {low-level features permitted},
              EDITBIT=  16_00002000,
              RUNBIT=   16_00001000,
              FORCEBIT= 16_00000800,
              LOGBIT=   16_00000400 {print log},
              WARNBIT=  16_00000200 {print warnings},
              NONSBIT=  16_00000100 {nonstandard features permitted},
              PERMBIT=  16_00000080 {for PRIM compilation},
              OLDBIT=   16_00000040 {for compatibility},
              CODELIST= 16_00000020 {list code},
              DICTLIST= 16_00000010 {list dict entries},
              EXPLIST=  16_00000008 {list EXP entries},
              MAPLIST=  16_00000004 {print space map},
              TTLIST=   16_00000002 {list to terminal},
              LIST=     16_00000001 {do list}
constinteger  LISTBITS=codelist+dictlist+explist+maplist+ttlist+list
owninteger  CONTROL=warnbit+checkbit+linebit+diagbit+editbit+volbit -
                   +strassbit+assbit+arrbit+loopbit+capbit+stackbit
integer  INITCON,TIME1,TIME2,CCOND
!Events:-
constinteger  OFLOW=1, FAIL=11, DONE=12, REDO=13, ABANDON=14
!
!
constinteger  MAXINT=16_7FFFFFFF, MININT=\MAXINT
constinteger  SIGN16=\16_7FFF, SIGN=\16_7FFFFFFF
!
!!!!!!!!!!!!!!!!   Operand Representation  !!!!!!!!!!!!!!!!!!!
! Operands (largely, Expressions) are denoted by integers in a
! contiguous range as follows:
! 
! <= 0  Literals (including 'addresses' within FINAL)
!       [see LITREF and LITVAL for interpretation]
!                                    Dictionary
!                   __16___16____16____8____8____32____16___16__
! [dummy @ 0] ->    |flags|type| link| reg|mode|value|text|hlink|
! D0 [@1]  ->  R    |     |    | size|    |    |     |    |    |
!                   |     |    |xtype|    |    |     |    |    |
! D7       ->       |     |    |     |    |    |     |    |    |
! A0       ->  E    |     |    |     |    |    |     |    |    |
!                   |     |    |     |    |    |     |    |    |
! A7       ->  G    |     |    |     |    |    |     |    |    |
! INDA0    ->       |     |    |     |    |    |     |    |    |
!              S    |     |    |     |    |    |     |    |    |
! PREA7    ->       |     |    |     |    |    |     |    |    |
!              I    |     |    |     |    |    |     |    |    |
!              D    |     |    |     |    |    |     |    |    |
!              E    |     |    |     |    |    |     |    |    |
!              N    |     |    |     |    |    |     |    |    |
!              T    |     |    |     |    |    |     |    |    |
!              S    |     |    |     |    |    |     |    |    |
!                   |_____|____|_____|____|____|_____|____|____|
! DICTLIM  ->       | --  |--  |  -- | -- |mode|value| -- | -- |
!              C L  |     |    |     |    |    |     |    |    |
!              O A  |     |    |     |    |    |     |    |    |
!              M B  |     |    |     |    |    |     |    |    |
!              P S  |     |    |     |    |    |     |    |    |
!                   |_____|____|_____|____|____|_____|____|____|
! LABLIM   ->       |flags|type| act |----|mode|value|arg1|arg2|
!              C    |     |    |     |    |    |     |    |    |
!              O    |     |    |     |    |    |     |    |    |
!              M E  |     |    |     |    |    |     |    |    |
!              P X  |     |    |     |    |    |     |    |    |
!              L P  |     |    |     |    |    |     |    |    |
!              E S  |     |    |     |    |    |     |    |    |
!              X    |_____|____|_____|____|____|_____|____|____|
! EXPLIM   ->

constinteger  SMALLMIN=-1024, SMALLMAX=1023,
              LITMAX=smallmin-(smallmax+1), LITMIN=litmax-199,
              LITMITE=-255, LITQUICK=-16, ONE=-(1<<1)
constinteger  D0=1, D1=d0+1, D2=d0+2, D7=d0+7,
              A0=d0+8, A1=a0+1, A6=a0+6, A7=a0+7,
              INDA0=a0+8, INDA7=inda0+7,
              POSTA0=inda0+8, POSTA7=posta0+7,
              PREA0=posta0+8, PREA7=prea0+7,
              UNDEF=a7
owninteger    DICTLIM=1000, FINALBOUND=64  {see Init for adjustment}
integer       LABLIM,NP0,EXPLIM {continuing from DICTLIM}
integer       CHARBOUND         {derived from DICTLIM}
constinteger  LABELS=42 {enough for Pascal reserveds},
              TRIPLES=200
constinteger  AD=16384  {any item + AD >= EXPLIM}

constinteger  BREG=D0+4, LINELOC=d0+5
constinteger  F1=a0+6, GB=a0+5, MB=a0+4;  !level 1, global base, main base
constinteger  MAXDREG=d0+3, MAXAREG=a0+3; !max temp regs
constinteger  D0B=1, D1B=2, D2B=4, BREGB=16,
              A0B=16_100, A1B=16_200, A2B=16_400
constinteger  ANYDREG=16_00FF, ANYAREG=16_FF00, ANYREG=16_FFFF
constinteger  DEFAULTFREE=(2<<(maxareg-a0)-1)<<8+2<<(maxdreg-d0)-1+bregb
integer  MAXCALLDREG, MAXCALLAREG
integer  FREE

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!   Big Literals  !!!!!!!!!!!!!!!!!!!!!!!
integer  LITPOS
integerarray  LITSTORE(litmin:litmax)
!
!!!!!!!!!  Registers, Identifiers, Labels, Expressions  !!!!!!!!!
!
!   Operand attributes:
recordformat  OBJINFO -
  (short  FLAGS,TYPE,
   (short  LINK or  short  XTYPE or  short  SIZE or  short  ACT),
   byte  REG,MODE,
   integer  VAL)
recordformat  IDENTINFO -
  ((short  FLAGS,TYPE,
   (short  LINK or  short  XTYPE or  short  SIZE or  short  ACT),
    byte  REG,MODE,
    integer  VAL or  record (objinfo) DETAILS),
   (short    TEXT,HLINK or  short  X,Y))
!
!Machine addressing modes:
constinteger  AREGMODE=2_001000, INDIRMODE=2_010000,
              DISPMODE=2_101000, INDEXMODE=2_110000, ABSMODE=2_111000,
              PCMODE=2_111010, LITMODE=2_111100
!Conversion factors for address register modes (from AREGMODE)
constinteger  INDIR=8, POST=16, PRE=24
!Additional source-related modes:
constinteger  LABMODE=2_10000000+pcmode,
              PROCMODE=2_11000000+pcmode,
              GLOBALMODE=dispmode+(gb-a0),
              STATIC=2_01000000,
              CONSTMODE=static+pcmode,
              FRAMEMODE=2_10000000+dispmode
!                      +  01000000 for dynamic array
constinteger  DEFAULTOWNMODE=static+dispmode+(mb-a0)

! MODE,VAL:
!  %const simple       : LITMODE     the actual value
!  %const structure    : CONSTMODE   address in code area
!  variable etc        : mode        byte address/displacement
!  undefined label     : LABMODE     reference chain
!  undefined procedure : PROCMODE    reference chain
!  record format       : 0           size of record in bytes
!
! Significance of FLAGS:
constinteger  CAT     =16_000F, {category: typeid only}
              WRITABLE=16_0001,
              READABLE=16_0002, {not write only}
              VOLATILE=16_0004,
              ARRFLAG =16_0008, {bound check needed}
                ALT   =16_0008, {alternative proc}
              WFLAG   =16_0010, {has been written to}
              RFLAG   =16_0020, {has been read from}
              OKFLAG  =16_0040, {no unassigned check needed, CC OK for fun}
                NORET =16_0040, {routine does not return}
              MFLAG   =16_0080, {has had mem access}
              SPEC    =16_0100, {unbodied spec or forward label}
              TYPEID  =16_0200, {type identifier}
              PACKED  =16_0400,
              INDIRECT=16_0800,
              PROC    =16_3000, {procedure not data}
                PROC1 =16_1000,
                PROC2 =16_2000,
              EXT     =16_4000, {external}
              NAME    =sign16
constinteger  HERITABLE=writable+readable+volatile -
                       +wflag+rflag+okflag+arrflag
!
!CATegories (type identifiers only):
constinteger  INTY=0, CHARY=1, BOOLY=2, ENUMY=3,
              POINTY=4, REALY=5,
              STRINGY=8, ARRY=9, SETY=10,
              RECY=12, FILEY=13,
              NONORD=12

own record (objinfo) -
  DEFINEDLABEL=objinfo(_FLAGS=0,_TYPE=0,_SIZE=0,_REG=0,_MODE=labmode,_VAL=0),
  FORWARDLABEL=objinfo(_FLAGS=spec,_TYPE=0,_SIZE=0,_REG=0,_MODE=labmode,_VAL=0),
  BEGINBLOCK  =objinfo(_FLAGS=0,_TYPE=0,_SIZE=0,_REG=0,_MODE=procmode,_VAL=0),
  TYPEIDENT=objinfo(_FLAGS=typeid+recy,_TYPE=0,_SIZE=0,_REG=0,_MODE=0,_VAL=0)

!!!!!!!!!!!!!!!!!  File and control initialisation  !!!!!!!!!!!!!!!
!
constinteger  MAIN=1
record (edfile)array  FILE(1:3)
record (edfile)name  CUR
integerarray  FCONTROL(1:3)
integer  CURFILE,LASTFILE;      !current source file no (0:3)
integer  CURSTART,CURLIM;        !current source file bounds

routine  SET OPTIONS(string (255) parm)
constinteger  CHECKS=assmask+arrbit+loopbit+capbit+overbit
  define boolean params( -
  "ARR,LOOP,CAP,OVER,ASS,STRASS,SASS,BASS,LINE,DIAG,TRACE,STACK,".-
  "CHECK,SYS,STRICT,VOL,HALF,LOW,EDIT,RUN,FORCE,LOG,WARN,NONS,PERM,OLD,".-
  "CODE,DICT,EXP,MAP,TT,LIST",control,0)
  process parameters(parm)
 !NOCHECK => removal of checkbits
  control = control&(\checks) if  control&checkbit = 0
  control = control&(\editbit) if  control&listbits # 0
end 

routine  SET EXTENSION(string (maxname)name  f,string (4) ext)
integer  strip
integer fn  last4(string (*)name  s)
integer  i,e
  i = 0;  e = 0
  while  i < length(s) cycle 
    i = i+1;  e = e<<8+charno(s,i)
  repeat 
  result  = e
end 
  strip = last4(ext)
  f = mainfile and  strip = which if  f = ""
  length(f) = length(f)-4 if  last4(f)!16_202020 = strip
  f = f.ext
end 

routine  OPEN FILES
string (maxname) LISTFILE=""
  objfile = ""
  define param("SOURCE",mainfile,nodefault)
  define param("OBJ",objfile,newgroup)
  define param("LIST",listfile,0)
  define int param("IDents",dictlim,newgroup)
  define int param("KBytes",finalbound,0)
  file(main) = 0
  set options(cliparam)
!Main file
  file(main)_name = mainfile;  file(main)_flag = 32768
  time1 = time1-cputime
  connect edfile(file(main))
  time1 = time1+cputime
  stop  if  file(main)_flag # 0

!Listing file
  if  listfile # "" or  control&(list+ttlist) # 0 start 
    if  control&ttlist = 0 start 
      set extension(listfile,".lis")
      listout = 2
      open output(listout,listfile)
    finish 
    control = control&(\(editbit+ttlist))
    control = control!list if  control&listbits = 0
  finish 
  select output(listout)
  if  control&listbits # 0 start 
    control = control!list if  control&listbits # maplist
    newlines(2)
    printstring(title)
    newlines(2)
    printstring("   ");  printstring(file(main)_name)
    printstring("  compiled on ");  printstring(date)
    printstring("  at  ");  printstring(time)
    newlines(2)
  finish 
  initcon = control
end 

  time1 = 0
  open files
  dictlim = dictlim+300;  !allow for presets
  charbound = dictlim*8
  finalbound = finalbound<<10+4095;  !kilobytes -> bytes + (min) owns
  lablim = dictlim+labels
  explim = lablim+triples
  np0 = lablim+4
  file(main)_change = 16_7FFFFFFF
!
!!!!!!!!!!!!!!!!  end of file and control initialisation  !!!!!!!!
!
record (identinfo)array  DICT(0:explim-1)
!  indexing DICT:
integer  DLIM;         !dict limit (up)
integer  DLIM0
integer  DMIN;       !dict upper limit (down)
integer  DMIN0
integer  DICTSHOWN
integer  INCLIM
record (identinfo)name  DLINK,DFORMAT,DTEMP,DTEMP2,DTSPREL,DINT
integer  SUBBED
integer  RANGES

! The identifier dictionary grows as declarations are
! encountered, sequentially from 0 up, so that the
! identifiers within a declaration group and within any block
! are contiguous and may be processed thus (eg at block end).
! However, searching is always through the hash links, with a
! start-point given by the array HASHINDEX.  The final link
! value is zero.
!  Identifiers are normally added at the start of the hash list
! (hence pushing down any global instance of the same name),
! but identifiers which have been reported as 'not declared'
! are added at the end of the list, using a negative link value.
! This tail section is used to avoid repeated reports for the
! same name (and is ultra-global, ie never removed).
!
! For record formats, the format name is stored in the usual way
! and contains in LINK a pointer to the field-names which are linked
! through what is normally the hash link.  Searching for field-names
! proceeds along this chain, as if following hash links.
!
!  HLINK is the hash link (index to DICT)
!
!  TEXT is the pointer (index to CHAR) to the text of the identifier
!       stored as a standard string

!  Text of identifiers (indexed by _TEXT):
bytearray  CHAR(0:charbound)
integer  CHAR0,CHARLIM,CHARMIN;  !pointers
integer  NEWLEN

!  Hash index to DICT:
shortarray  HASHINDEX(0:255)
shortname  HEAD;                  !head of ident search list
!
!
!<

!* PRIMGEN marker 1

constinteger  NULL=41,
              PROCSTAR=42,
              INTTYPE=43,
              SHORTTYPE=46,
              HALFTYPE=49,
              BYTETYPE=52,
              MITETYPE=55,
              BOOLTYPE=58,
              CHARTYPE=61,
              STRINGSTAR=62,
              STRING1=63,
              STRINGTYPE=64,
              ARRSTAR=65,
              NULLSETTYPE=66,
              RECSTAR=67,
              REALTYPE=69,
              SIGNAL=73,
              DADDR=74,
              DSIZEOF=77,
              INDEX=78,
              LENREF=79,
              SINDEX=82,
              IMUL=86,
              IDIV=87,
              IPOW=88,
              FNEG=89,
              FADD=90,
              FSUB=91,
              FMUL=92,
              FDIV=93,
              FPOW=94,
              FLOAT=95,
              DREM=98,
              UNASS=102,
              ADOK=103,
              STACKOK=104,
              ASIZE=105,
              CONCAT=106,
              DTOSTRING=107,
              AGET=110,
              FOROK=111,
              CHECK=112,
              SCOMP=113,
              STRCOPY=114,
              STRTOSTK=115,
              DNEW=116,
              RESOLVES=118,
              DEVENTF=129,
              DEVENT=135,
              DNIL=138,
              DPRINTSTR=156,
              DWRITE=184

constinteger  OPMAX=resolves

routine  SET HASHHEAD(string (*)name  s)
integer  h,i
  h = 0
  h = h<<1!!charno(s,i) for  i = 1,1,length(s)
  head == hashindex(h&255)
end 

routine  PRESET
!* PRIMGEN marker 2
const integer  CMAX=775
const byte array  CHARINIT(0:CMAX) = 
  0,
  2,'d','0',
  2,'d','1',
  2,'d','2',
  2,'d','3',
  2,'d','4',
  2,'d','5',
  2,'d','6',
  2,'d','7',
  2,'a','0',
  2,'a','1',
  2,'a','2',
  2,'a','3',
  2,'a','4',
  2,'a','5',
  2,'a','6',
  2,'a','7',
  7,'i','n','t','e','g','e','r',
  6,'M','A','X','I','N','T',
  12,'s','h','o','r','t','i','n','t','e','g','e','r',
  11,'h','a','l','f','i','n','t','e','g','e','r',
  11,'b','y','t','e','i','n','t','e','g','e','r',
  11,'m','i','t','e','i','n','t','e','g','e','r',
  7,'B','O','O','L','E','A','N',
  5,'F','A','L','S','E',
  4,'T','R','U','E',
  4,'c','h','a','r',
  6,'s','t','r','i','n','g',
  5,'a','r','r','a','y',
  6,'r','e','c','o','r','d',
  4,'T','E','X','T',
  4,'r','e','a','l',
  8,'l','o','n','g','r','e','a','l',
  6,'S','I','G','N','A','L',
  4,'a','d','d','r',
  6,'s','i','z','e','o','f',
  5,'I','N','D','E','X',
  6,'l','e','n','g','t','h',
  6,'c','h','a','r','n','o',
  4,'I','M','U','L',
  4,'I','D','I','V',
  4,'I','P','O','W',
  4,'F','N','E','G',
  4,'F','A','D','D',
  4,'F','S','U','B',
  4,'F','M','U','L',
  4,'F','D','I','V',
  4,'F','P','O','W',
  5,'f','l','o','a','t',
  3,'r','e','m',
  5,'U','N','A','S','S',
  4,'A','D','O','K',
  7,'S','T','A','C','K','O','K',
  5,'A','S','I','Z','E',
  6,'C','O','N','C','A','T',
  8,'t','o','s','t','r','i','n','g',
  4,'A','G','E','T',
  5,'F','O','R','O','K',
  5,'C','H','E','C','K',
  5,'S','C','O','M','P',
  7,'S','T','R','C','O','P','Y',
  8,'S','T','R','T','O','S','T','K',
  3,'n','e','w',
  8,'r','e','s','o','l','v','e','s',
  9,'s','u','b','s','t','r','i','n','g',
  7,'e','v','e','n','t','f','m',
  5,'e','v','e','n','t',
  3,'s','u','b',
  4,'l','i','n','e',
  5,'e','x','t','r','a',
  7,'m','e','s','s','a','g','e',
  5,'e','v','e','n','t',
  2,'n','l',
  3,'s','n','l',
  3,'n','i','l',
  7,'d','i','s','p','o','s','e',
  5,'r','o','u','n','d',
  5,'t','r','u','n','c',
  8,'f','r','a','c','t','i','o','n',
  3,'i','n','t',
  5,'i','n','t','p','t',
  6,'f','r','a','c','p','t',
  4,'s','q','r','t',
  10,'n','e','x','t','s','y','m','b','o','l',
  10,'r','e','a','d','s','y','m','b','o','l',
  10,'s','k','i','p','s','y','m','b','o','l',
  11,'p','r','i','n','t','s','y','m','b','o','l',
  11,'p','r','i','n','t','s','t','r','i','n','g',
  9,'o','p','e','n','i','n','p','u','t',
  10,'o','p','e','n','o','u','t','p','u','t',
  11,'s','e','l','e','c','t','i','n','p','u','t',
  12,'s','e','l','e','c','t','o','u','t','p','u','t',
  8,'s','e','t','i','n','p','u','t',
  9,'s','e','t','o','u','t','p','u','t',
  10,'r','e','s','e','t','i','n','p','u','t',
  11,'r','e','s','e','t','o','u','t','p','u','t',
  10,'c','l','o','s','e','i','n','p','u','t',
  11,'c','l','o','s','e','o','u','t','p','u','t',
  6,'p','r','o','m','p','t',
  7,'n','e','w','l','i','n','e',
  5,'s','p','a','c','e',
  6,'s','p','a','c','e','s',
  8,'n','e','w','l','i','n','e','s',
  4,'r','e','a','d', 138,'r','e','a','d','s','t','r','i','n','g',
  4,'r','e','a','d', 136,'r','e','a','d','r','e','a','l',
  4,'r','e','a','d',
  5,'w','r','i','t','e',
  7,'c','p','u','t','i','m','e',
  5,'p','r','i','n','t',
  7,'p','r','i','n','t','f','l',
  8,'i','n','s','t','r','e','a','m',
  9,'o','u','t','s','t','r','e','a','m',
  8,'c','l','i','p','a','r','a','m',
0
constinteger  PREMAX=197
const short array  DICTINIT(41*6:PREMAX*6+5) = 
 516,-1,0,0,0,0,
 527,-1,0,0,0,4,
 512,43,4,56,-32768,0,
 0,-44,4,60,-32768,0,
 0,43,4,60,32767,-1,
 512,43,2,56,-32768,0,
 0,-44,2,60,-1,-32768,
 0,-44,2,60,0,32767,
 512,43,-2,56,-32768,0,
 0,-44,2,60,0,0,
 0,-44,2,60,0,-1,
 512,43,-1,56,-32768,0,
 0,-44,1,60,0,0,
 0,-44,1,60,0,255,
 512,43,1,56,-32768,0,
 0,-44,1,60,-1,-128,
 0,-44,1,60,0,127,
 514,58,1,0,0,0,
 0,58,1,60,0,0,
 0,58,1,60,0,1,
 513,61,255,0,0,0,
 520,61,0,0,0,0,
 520,-62,-2,0,0,0,
 520,-62,-256,0,0,0,
 521,0,0,0,0,0,
 522,-1,0,0,0,0,
 524,0,0,0,0,0,
 525,61,4,0,0,0,
 517,0,4,0,0,0,
 517,0,4,0,0,0,
 0,-1,0,0,0,0,
 0,-1,0,0,0,0,
 4256,42,0,56,0,16122,
 4098,75,0,56,0,0,
 0,-44,76,0,0,4,
 -32701,-1,0,2217,-1,-4,
 4098,75,0,56,0,0,
 4096,42,0,56,-32767,2861,
 4099,80,0,56,0,0,
 0,-53,81,2048,0,4,
 -32701,-63,0,2217,-1,-4,
 4099,83,0,56,0,0,
 0,-53,84,2048,0,4,
 -32701,-63,85,2217,-1,-4,
 67,-53,0,169,-1,-6,
 4256,42,0,56,0,16116,
 4256,42,0,56,0,16110,
 4096,42,0,56,0,16098,
 4096,42,0,56,0,16092,
 4096,42,0,56,0,16086,
 4096,42,0,56,0,16080,
 4096,42,0,56,0,16074,
 4096,42,0,56,0,16068,
 4096,42,0,56,0,16062,
 4098,96,0,56,0,16056,
 0,-70,97,0,0,4,
 67,-44,0,169,-1,-4,
 4098,99,0,56,0,0,
 0,-44,100,0,0,4,
 67,-44,101,169,-1,-4,
 67,-44,0,425,-1,-8,
 4096,42,0,56,-32722,2578,
 4096,42,0,56,-32704,2064,
 4096,42,0,56,-32688,2840,
 4096,42,0,56,-32664,3097,
 4096,42,0,56,-32639,2078,
 4162,108,0,56,-32609,6,
 0,-64,109,2048,0,4,
 67,-53,0,169,-1,-2,
 4096,42,0,56,-32603,2600,
 4096,42,0,56,-32563,2334,
 4096,42,0,56,-32533,1806,
 4096,42,0,56,-32519,2626,
 4096,42,0,56,-32453,2070,
 4096,42,0,56,-32431,2088,
 4103,117,0,56,0,16008,
 0,-68,76,2048,0,4,
 22786,119,0,108,0,0,
 0,-59,120,0,0,0,
 -32701,-63,121,2217,-1,-4,
 67,-65,122,2473,-1,-260,
 -32701,-63,123,2729,-1,-264,
 -32701,-63,0,2985,-1,-268,
 4162,125,0,56,-32391,19,
 0,-65,126,2048,0,4,
 -32701,-63,127,2217,-1,-4,
 67,-44,128,169,-1,-8,
 67,-44,0,425,-1,-12,
 524,0,130,0,-1,-264,
 3,52,0,0,0,0,
 3,52,0,0,0,1,
 3,46,0,0,0,2,
 3,43,0,0,0,4,
 3,64,0,0,0,8,
 67,129,0,45,0,32,
 66,43,0,60,0,10,
 66,61,0,60,0,10,
 67,67,0,56,0,0,
 4096,140,0,56,0,16002,
 0,-1,76,0,0,4,
 4098,142,0,56,0,16050,
 0,-44,143,0,0,4,
 67,-70,0,169,-1,-4,
 4098,142,0,56,0,16044,
 4098,146,0,56,0,16038,
 0,-70,143,0,0,4,
 4098,142,0,56,0,16032,
 4098,142,0,56,0,16026,
 4098,146,0,56,0,16020,
 4098,146,0,56,0,16014,
 4098,133,0,56,0,15996,
 4098,133,0,56,0,15990,
 4096,42,0,56,0,15990,
 4256,155,0,56,0,15984,
 0,-1,97,0,0,4,
 4096,157,0,56,0,15978,
 0,-1,158,0,0,4,
 67,-65,0,2217,-1,-256,
 22784,160,0,108,0,0,
 0,-1,161,0,0,0,
 67,-44,162,169,-1,-4,
 67,-65,0,2217,-1,-260,
 22784,160,0,108,0,0,
 4096,155,0,56,0,15960,
 4096,155,0,56,0,15954,
 22784,167,0,108,0,0,
 0,-1,97,0,0,0,
 22784,167,0,108,0,0,
 22784,0,0,108,0,0,
 22784,0,0,108,0,0,
 22784,0,0,108,0,0,
 22784,0,0,108,0,0,
 22784,174,0,108,0,0,
 0,-1,158,0,0,0,
 4096,42,0,56,-32372,4,
 4096,42,0,56,-32368,4,
 22784,167,0,108,0,0,
 22784,167,0,108,0,0,
 22790,180,0,108,0,0,
 0,-65,0,2048,0,0,
 22798,182,0,108,0,0,
 0,-70,0,0,0,0,
 22798,1,0,108,0,0,
 22784,185,0,108,0,0,
 0,-1,100,0,0,0,
 22790,1,0,108,0,0,
 22784,188,0,108,0,0,
 0,-1,189,0,0,0,
 67,-70,190,169,-1,-4,
 67,-44,191,425,-1,-8,
 67,-44,0,681,-1,-12,
 22784,193,0,108,0,0,
 0,-1,194,0,0,0,
 67,-70,101,169,-1,-4,
 67,43,0,45,0,392,
 67,43,0,45,0,396,
 67,64,0,45,0,464

integer  i,ci,anons
record (identinfo)name  dp

routine  PUT CHAR
  byteinteger(charlim) = charinit(ci)
  charlim = charlim+1;  ci = ci+1
end 

routine  TEXTSET(record (identinfo)name  dp)
integer  len
  dp_hlink = 0
  if  dp_type < 0 start ;     !convention for *anon*
    dp_type = \dp_type
    dp_text = 0
    anons = anons-1
    dp_hlink = ranges and  ranges = dlim if  anons = 0 and  dlim <= mitetype+2
  else 
    dp_text = ci
    if  charinit(ci+1)&32 # 0 start ;  !not upper-case
      if  deventf < dlim < devent start 
        head = dlim;  head == dp_hlink
      else 
        set hashhead(string(addr(charinit(ci))))
        dp_hlink = head;  head = dlim
        head == dp_link if  dlim = deventf
      finish 
    finish 
    len = charinit(ci)
    put char and  len = len-1 until  len < 0
    len = charinit(ci)-128
    put char and  len = len-1 while  len >= 0
    anons = 2
  finish 
end 

  hashindex(i) = 0 for  i = 0,1,255;  !hash table empty
  byteinteger(char0) = 0;  !for anon ident
  charlim = char0+1
  charmin = charlim+charbound;  !(1 over top)
  ranges = 0

  ci = 1
  anons = 100
  dict(0) = 0
  dlim = d0
  cycle 
    dp == dict(dlim)
    if  dlim <= prea7 start 
      dp = 0
      dp_flags = okflag+writable+readable;  dp_mode = dlim-d0
      dp_type = inttype
      textset(dp) if  dlim <= a7
    else 
      dp_details = record(addr(dictinit(dlim*6)))
      textset(dp)
    finish 
    dlim = dlim+1
    exit  if  control&permbit # 0 and  dlim >= signal
  repeat  until  dlim > premax
  dictshown = dlim
  i = dictlim
  cycle 
    dp == dict(i)
    dp = 0
    dp_mode = labmode
    i = i+1
  repeat  until  i = np0
dict(inttype+9)_size = -1  {byte}
dict(inttype+6)_size = -2  {half}
end ;  !preset

!<

!  The last part of DICT (from LABLIM to EXPLIM) is used for
! the intermediate representation of the components of source
! statements between the recognition stage and the code generation
! stage.
!  The part from LABLIM+4 (NP0) up is used as a temporary pipeline
! for non-expression cells (instructions, conditions, etc)
! and the part down from EXPLIM for the canonical and
! persistent representation of expressions (including name
! expressions).
! In this part of the array the ident components PLIST (etc), TEXT
!  and HLINK are replaced by ACT, X and Y representing an operation
!  and (up to) two operands.
integer  EXPLO,OLDEXPLO
integer  NP,STARTNP

!Operator codes:
! Machine operator index values 1-31:
constinteger  MOVE=1, ADD=2, SUB=3,
              CMP=4, AND=5, OR=6, EOR=7,
              NOT=8, NEG=9, LSL=10, LSR=11,
              MULS=12, DIVS=13, MULU=14, DIVU=15,
              BRA=16, BSR=17,
              BCC=20, BCS=21, BNE=22, BEQ=23,
              BVC=24, BVS=25,
              BGE=28, BLT=29, BGT=30, BLE=31
constinteger  COMPARE=cmp, GOTO=bra
! Other built-in operators
constinteger  JAMASS=32, OKASS=33, ASSIGN=34, INCASS=35,
              FORASS=36, STOP=37, RETURN=38, REPEAT=39,
              ELSE=40, JUMPOUT=41, SETTRAP=42, SWGOTO=43,
              LABEL=44, RECREF=45, PREL=46, STOREMAP=47,
              IABS=48, FABS=49, END=50
! PLUS OPERATORS DEFINED IN DICTIONARY > BOPMAX <= OPMAX
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

integer  STARTS, CYCLES
integer  CURLAB
integer  PENDOUT, PENDCOND, PENDIN, POLARITY, CONDOP
ownshortinteger  EXTSPECS=0, EXTERNS=0
!
recordformat  CONTENTINFO(short  ccx,ccy,line,part,
                          shortarray  content(d0:a7))
recordformat  BLOCKINF(integer  sp, stack, extra, totstack, free, status,
                type, localdpos, parlim, localtext, localad, vintage,
                localpc, localswpc, pid, access, forward, lab1, looplab,
                eventsp, faults, return, shorts, temps,
                dynarray, oldcontrol, mode,val,
                record (identinfo)name  dpid,
                record (contentinfo) reg)
!Flag bits
constinteger  UNKNOWN    =16_0002,
              OKCC       =16_0004,
              ONSTACK    =16_0008,
              GLOBBED    =16_0010,
              LABGLOBBED =16_0020, {Pascal}
              HADSPEC    =16_0040,
              HADSWITCH  =16_0080,
              HADON      =16_1000,
              HADORDERERR=16_2000,
              HADINST    =16_4000  {max flag}

constinteger  UNSIGNED=4           {flag for operand size}

constinteger  MAXLEVEL=7
integer  LEVEL;           !current block level
integer  VINTAGE;         !current block number
record (blockinf) C;      !info for current block
record (blockinf)array  HOLD(0:maxlevel-1); !info for global blocks
record (contentinfo)array  LREG(0:labels)

! Code storage for currently open blocks
constinteger  PROGBOUND=16383
shortarray  PROG(0:progbound)
bytearray  PFLAG(0:progbound)
constinteger  SHORTJUMP=1, JUMP=2, LONGJUMP=3,
              GLOBAL=4, {NEGGLOBAL=5, BIGGLOBAL=6,} INDGLOBAL=7,
              ZEROSHORTS=8
integer  PC,SWPC
! Final core image
bytearray  FINAL(0:finalbound)
! Declaration records (to select relevant context)
integer  CAD,
         INITBASE,INITLIM,INITHEAD,INITMODE,INITVAL,INITD1,
         INITREP,INITDATA
integer  OWNMODE,OWNVAL
!
integer  FINAL0,ACCOUNTED
integer  FIRSTENTRY, FIRSTPOS

!Memo variables for current statement:-
own integer  {ITEM,}TYPE=0,VALUE=0;      !current operand
record (identinfo)name  DITEM
integer  SPECCING
integer  DUMP

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

!!  Source file input and listing
owninteger  ATOM=0;       !current lexical atom
integer  MATCHED;         !indic that atom has been matched
integer  SYM;             !current input symbol
integer  LINE;            !current line number
owninteger  CODEFLAG=' '; !or ^
integer  LISTFLAG;        !' ' or '&' or '+' or '"'
!   Pointers to source file:
integer  LINESTART
integer  FP;              !(file pointer) current position
integer  ATOMP;           !start of current atom
integer  EXPP
!
!! Utility routines

predicate  IS SHORT(integer  v)
  false  unless  (v+32768)&(\65535) = 0
  true 
end 

predicate  IS MITE(integer  v)
  false  unless  (v+128)>>8 = 0
  true 
end 

integer fn  MITE(integer  v)
  result  = v!(\127) if  v&128 # 0
  result  = v&127
end 

integer fn  CATEGORY(integer  t)
  result  = dict(t)_flags&(packed+cat)
end 

integer fn  LITVAL(integer  y)
  result  = y if  y = 0
  if  y > litmax start ;  !not stored literal
    result  = (-y)>>1 if  y&1 = 0
    result  = \((-y)>>1)
  finish 
  result  = litstore(y)
end 
!
integer fn  ONEBIT(integer  y)
{Return BITNO for single bit operand}
integer  i
  if  y < 0 start 
   {Literal}
    y = litval(y)
    if  y&(y-1) = 0 start 
      i = -1
      i = i+1 and  y = y>>1 until  y = 0
      result  = -(i<<1)  {litref(i)}
    finish 
  else  if  np0 <= y < explim and  dict(y)_x = one and  control&volbit = 0 -
        and  dict(y)_act = lsl
   {Expression of form: 1<= 32 so need hint}
    result  = dict(y)_y
  finish 
  result  = undef
end 

integer fn  MULOP(integer  xlo,xhi,ylo,yhi)
  if  (xhi!yhi)&(\65535) = 0  start 
   {Upper bounds both %half}
    result  = mulu if  xlo!ylo >= 0
    result  = muls if  (xlo+32768)!(ylo+32768) >= 0 -
                  and  (xhi!yhi)&(\32767) = 0
  finish 
  result  = imul
end 

!!!!!!!!!!!!!! Listing, diagnostic and report routines  !!!!!!!!!!!!!!
!
integer  FAULTS, OTHERS, FAULTNUM, FAULTP
!
!!  Program statistics
integer  STATEMENTS;           !statement count
integer  COMMENTS;             !comment count
integer  ATOMS;                !atom count
integer  IDENTATOMS;           !identifier count
integer  LITATOMS;             !numeric atom count
integer  ZAPS;                 !enforced cleardown of lits/exps
integer  STEPS;                !stepping stones inserted
!%integer MAXIDENTS, MAXCHARS, MAXLITS
integer  JUMPS,SHORTS
!
string (255) REP
!
routine  PRINT LINE
  print string(rep);  print symbol(nl)
  rep = ""
end 
!
routine  PUT SYM(integer  k)
  rep = rep.tostring(k)
end 
!
routine  PUT STRING(string (255) s)
  rep = rep.s
end 
!
routine  PUT NUM(integer  val)
routine  PD(integer  v)
  pd(v//10) and  v = v-v//10*10 if  v <= -10
  put sym('0'-v)
end 
  if  val < 0 then  put sym('-') and  pd(val) -
  else  pd(-val)
end 
!
routine  PUT IDENT(integer  p,mode)
record (identinfo)name  dp
  cycle 
    print line if  length(rep) > 50
    spaces(6) if  rep = ""
    dp == dict(p)
    put sym(' ') and  put sym('"') if  mode # 0
    if  dp_text > 0 then  put string(string(char0+dp_text)) -
    else  if  dp_text < 0 then  put num(\dp_text) -
    else  put num(p)
    put sym('"') if  mode # 0
    return  if  mode <= 0
    p = dp_hlink
  repeat  until  p = 0
end 
!
{?}routine  SPACES(integer  n)
{?}  while  n > 0 cycle 
{?}    put sym(' ');  n = n-1
{?}  repeat 
{?}end 
{?}!
{?}routine  PUT SPNUM(integer  val)
{?}  put sym(' ') if  val >= 0
{?}  put num(val)
{?}end 
{?}
{?}constbytearray  hexsym(0:15) =
{?}'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
{?}
{?}routine  PUT HEX(integer  val)
{?}integer  i
{?}  put sym(hexsym(val>>i&15)) for  i = 12,-4,0
{?}end 
{?}!
{?}routine  PUT OPERAND(integer  v)
{?}integer  i
{?}routine  INTERPRET(integer  mode)
{?}switch  s(0:7)
{?}  ->s(mode>>3&7)
{?}s(0):                 !DREG
{?}  put sym('D')
{?}putrno:
{?}  put sym(mode&7+'0')
{?}  return 
{?}s(1):                 !AREG
{?}  if  mode >= framemode-dispmode then  put sym('F') else  put sym('A')
{?}  -> putrno
{?}s(4):                 !PRE
{?}  put sym('-')
{?}s(2):                 !INDIRECT
{?}ind:
{?}  put sym('(')
{?}  interpret(mode&2_11000111+aregmode)
{?}  put sym(')')
{?}  return 
{?}s(3):                 !POST
{?}  interpret(mode-8);  !ind
{?}  put sym('+')
{?}  return 
{?}s(5):                 !DISP
{?}  put num(i)
{?}  ->ind
{?}s(6):                 !INDEX
{?}  put num(mite(i))
{?}  put sym('(')
{?}  interpret(mode+(aregmode-indexmode))
{?}  put sym(',')
{?}  interpret(i>>12&15)
{?}  put sym('.')
{?}  if  i&16_800 = 0 then  put sym('W') else  put sym('L')
{?}  put sym(')')
{?}  return 
{?}s(7):                 !MISC
{?}  if  mode&63 = pcmode start 
{?}    put num(i) if  mode = pcmode;  !suppress if not explicit
{?}    put string("(PC)")
{?}    return 
{?}  finish 
{?}  if  mode <= absmode+1 start 
{?}    put sym('$')
{?}    put hex(i>>16) if  mode = absmode+1 or  not  is short(i)
{?}  else 
{?}    put sym(hexsym(mode>>4&3))
{?}    put sym(hexsym(mode&15))
{?}    put sym('_')
{?}  finish 
{?}  put hex(i)
{?}end 
{?}
{?}  if  v <= 0 start ;               !literal
{?}    v = litval(v)
{?}    put sym('#')
{?}    if  is mite(v) then  put num(v) else  start 
{?}      put sym('$')
{?}      put hex(v>>16) if  v>>16 # 0
{?}      put hex(v&16_FFFF)
{?}    finish 
{?}  else  if  v <= prea7;    !register
{?}    interpret(v-d0)
{?}  else  if  v < dictlim;  !identifier
{?}    put ident(v,0)
{?}  else  if  v < lablim;  !internal label
{?}    put sym('L')
{?}    put num(v-dictlim)
{?}  else ;                 !complex
{?}    i = dict(v)_val
{?}    interpret(dict(v)_mode)
{?}  finish 
{?}end ;  !put operand
{?}
{?}routine  MARK AT(integer  col)
{?}  put sym(' ') while  length(rep) < col;  put sym('|')
{?}end 
{?}!
{?}routine  SHOW DICT(integer  from)
{?}integer  i
{?}record (identinfo) d
{?}constbytearray  flagsym(0:15) =
{?}  'W','R','V','A','w','r','o','m','S','T','K','?','P','p','E','*'
{?}constbytearray  catsym(0:15) =
{?}  'I', 'C', 'B', 'E', '@', 'X', '?', '?',
{?}  'S', 'A', 'Z', '?', 'R', 'F', '?', '?'
{?}
{?}  return  if  from >= dlim
!<
{?}  print line if  rep # ""
{?}  byteinteger(charlim) = 0
{?}  spaces(6)
{?}  put string("___identifier____flags___type__link__par_mode___value____")
{?}  print line
{?}  cycle 
{?}    put spnum(from);  mark at(6)
{?}    d = dict(from)
{?}    put sym(' ');  put ident(from,0)
{?}    if  d_text > 0 start 
{?}      i = char0+d_text;  i = i+byteinteger(i)+1
{?}      if  byteinteger(i)&128 # 0 start 
{?}        byteinteger(i) = byteinteger(i)-128
{?}        put sym(':');  put string(string(i))
{?}        byteinteger(i) = byteinteger(i)+128
{?}      finish 
{?}    finish 
{?}    mark at(22)
{?}    if  d_flags&typeid # 0 then  put sym(catsym(d_flags&cat)) and  i = 4 -
{?}    else  put sym(' ') and  i = 0
{?}    cycle 
{?}      put sym(flagsym(i)) if  d_flags>>i&1 # 0
{?}      i = i+1
{?}    repeat  until  i > 15
{?}    mark at(30)
{?}    put spnum(d_type);  mark at(35)
{?}    put spnum(d_link);  mark at(42)
{?}    put spnum(d_reg);  mark at(46)
{?}    put spnum(d_mode);  mark at(51)
{?}    put spnum(d_val);  mark at(63)
{?}    print line
{?}    from = from+1
{?}  repeat  until  from = dlim
{?}  spaces(6)
{?}  put string("+-------------------------------------------------------+")
{?}  print line
!<
{?}end 
{?}routine  PUT MNEMONIC(integer  m)
{?}  m = m<<2
{?}  cycle 
{?}    put sym(m>>27+'A'-1)
{?}    m = m<<5
{?}  repeat  until  m = 0
{?}end 
{?}routine spec  PUT OPCODE(integer  op)
{?}routine  SHOW EXP(integer  startp)
{?}integer  p,q
{?}record (identinfo)name  dp
{?}
constinteger  bopmax=51
constintegerarray  EXTRA(32:bopmax) =
'j'<<25+('a'&31)<<20+('m'&31)<<15+('a'&31)<<10+('s'&31)<<5+('s'&31),
'o'<<25+('k'&31)<<20+('a'&31)<<15+('s'&31)<<10+('s'&31)<<5,
'a'<<25+('s'&31)<<20+('s'&31)<<15+('i'&31)<<10+('g'&31)<<5+('n'&31),
'i'<<25+('n'&31)<<20+('c'&31)<<15+('a'&31)<<10+('s'&31)<<5+('s'&31),
'f'<<25+('o'&31)<<20+('r'&31)<<15+('a'&31)<<10+('s'&31)<<5+('s'&31),
's'<<25+('t'&31)<<20+('o'&31)<<15+('p'&31)<<10,
'r'<<25+('e'&31)<<20+('t'&31)<<15+('u'&31)<<10+('r'&31)<<5+('n'&31),
'r'<<25+('e'&31)<<20+('p'&31)<<15+('e'&31)<<10+('a'&31)<<5+('t'&31),
'e'<<25+('l'&31)<<20+('s'&31)<<15+('e'&31)<<10,
'e'<<25+('x'&31)<<20+('i'&31)<<15+('t'&31)<<10,
't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10,
's'<<25+('w'&31)<<20+('g'&31)<<15+('o'&31)<<10+('t'&31)<<5+('o'&31),
'l'<<25+('a'&31)<<20+('b'&31)<<15+('e'&31)<<10+('l'&31)<<5,
'r'<<25+('e'&31)<<20+('c'&31)<<15+('r'&31)<<10+('e'&31)<<5+('f'&31),
'p'<<25+('r'&31)<<20+('e'&31)<<15+('l'&31)<<10,
's'<<25+('t'&31)<<20+('r'&31)<<15+('m'&31)<<10+('a'&31)<<5+('p'&31),
'i'<<25+('a'&31)<<20+('b'&31)<<15+('s'&31)<<10,
'f'<<25+('a'&31)<<20+('b'&31)<<15+('s'&31)<<10,
'e'<<25+('n'&31)<<20+('d'&31)<<15,
'l'<<25+('o'&31)<<20+('g'&31)<<15+('s'&31)<<10+('u'&31)<<5+('b'&31)

{?}routine  PUT OPRAND(integer  v)
{?}  put sym('#') and  v = v-ad if  v >= explim
{?}  if  v < np0 then  put operand(v) else  put num(v)
{?}end 
{?}  print line if  rep # ""
{?}  return  unless  np > np0
{?}  put string("      ______action_______first_______second____")
{?}  print line
{?}  p = np0
{?}  cycle 
{?}    if  p = np start 
{?}      p = explo
{?}      exit  if  p >= oldexplo
{?}      put string("      |---------------------------------------|")
{?}      print line
{?}    finish 
{?}    if  p = startp then  put sym('>') else  put sym(' ')
{?}    put num(p);  mark at(6)
{?}    dp == dict(p)
{?}    put sym(' ')
{?}    q = |dp_act|
{?}    if  q <= 31 then  put opcode(q) -
{?}    else  if  q <= bopmax then  put mnemonic(extra(q)) -
{?}    else  put ident(q,0)
{?}    mark at(22)
{?}    put sym(' ');  put oprand(dp_x);  mark at(34)
{?}    put sym(' ');  put oprand(dp_y);  mark at(46)
{?}    if  p >= explo start 
{?}      put spnum(dp_type)
{?}      put sym('*') if  dp_flags < 0
{?}    finish 
{?}    print line
{?}    p = p+1
{?}  repeat  until  p >= oldexplo
{?}  oldexplo = explo
{?}  put string("      +---------------------------------------+")
{?}  print line
{?}end 
{?}!
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!! Fault reporting  !!!!!!!!!!!!!!!!!!!!!!!!!!!
!
routine  CROAK(string (255) s)
  select output(0)
  put string("** ");  put string(s)
  put string(".  Compilation abandoned at line ");  put num(line)
  print line
  signal  abandon
end 

!<

!!  Fault numbers
constinteger  INTERNERR=1, PLEXERR=2, CREACHERR=3, REACHERR=4,
              NORESULT=5, DREACHERR=6,
              FORMERR=7, ATOMERR=8, NAMERR=9, CLASSERR=10,
              SIZERR=11, TYPERR=12, BOUNDSERR=13, UNENDING=14,
              LOWLEVEL=15, ACCESSERR=16, NOTINLOOP=17, NOTINROUT=18,
              NOTINFUN=19, NOTINPRED=20, DUPERR=21,
              ORDERERR=22, MATCHERR=23, RANGERR=24, NONLITERAL=25,
              MOPERR=26, NOCYCLE=27,
              NOSTART=28, NOIF=29, ILLSTARRED=30, NONSTARTER=31,
              NONVAR=32, NONREF=33, TOOFEW=34, TOOMANY=35,
              NOBEGIN=36, DUBIOUS=37, NOTINBLOCK=38,
              NONSTAND=39, NOTIN=40, ASSERR=41,
              NOEND=42, NOFINISH=43, NOREPEAT=44
constinteger  COUNTERR=45, SLABMISSING=46, IDMISSING=47
constinteger  POINT=64, WARN=-128, NOW=128
!
routine  REPORT(integer  n,id,num)
owninteger  lastchange=0
integer  mark,start,errline

routine  PRINT TEXT(integer  stream)
constinteger  esc=27
integer  k,p

conststring (15)array  MESSAGE(1:44) =
  "Internal error ", "Reg not free!",
  "Out of reach ",  " out of reach!",
  "RESULT missing", "Out of reach",
  "Faulty form", "Unknown atom",
  "Unknown name", "Wrong class",
  "Wrong size", "Wrong type",
  "Inside out", "Endless loop",
  "Low level", "Not accessible",
  "Not in loop", "Not in routine",
  "Not in fn/map", "Not in pred",
  "Duplicate",
  "Out of order", "Mismatch",
  "Out of range", "Not literal",
  "Faulty operand", "%CYCLE missing",
  "%START missing", "Extra %ELSE",
  "Ill-starred", "Non-starter",
  "Not variable", "Not reference",
  "Too few args", "Too many args",
  "%BEGIN missing",
  "Dubious usage", "Not in block",
  "Nonstandard ", "Not supported",
  " void",
  "%END missing",
  "%FINISH missing", "%REPEAT missing"

!<

  put sym(mark)
  put sym(' ') if  errline < 1000
  put sym(' ') if  errline < 100
  put sym(' ') if  errline < 10
  put num(errline)
  put sym(listflag);  put sym(' ')
  k = n&63
  if  k >= counterr start 
    if  k = counterr start 
      if  num < 0 start 
        put num(-num);  put string(" extra")
      else 
        put num(num) if  num # 0;  put string(" missing")
      finish 
      put string(" value(s) for ")
      put ident(id,0)
      return 
    finish 
    if  k # slabmissing start 
      put ident(id,1)
    else 
      put ident(id,0)
      put sym('(');  put num(num);  put sym(')')
    finish 
    put string(" missing")
mend:
    if  c_dpid_text # 0 start 
      put string(" in ")
      put ident(c_pid,-1)
    finish 
    return 
  finish 
  put ident(id,0) if  id > 0
  put string(message(k))
  put num(num) if  num > 0
  -> mend if  creacherr <= k <= noresult
  spaces(22-length(rep))
  p = start
  p = p+1 while  byteinteger(p) = ' '
  if  p < faultp-50 then  p = faultp-47 and  put string("...") -
  else  put sym(' ')
  cycle 
    k = byteintegeR(p);  p = p+1
    if  p = faultp start 
!      %if stream # 0 %then put sym('|') %else %start
!       !**V200**
!        put sym(esc);  put sym('F');  !graphics
!        put sym('~')
!        put sym(esc);  put sym('G');  !normal
!      %finish
      put sym('|')
    finish 
    exit  if  k = nl
    put sym(k)
!    %if ' ' <= k <= '~' %then put sym(k) -
!    %else put sym('[') %and put num(k) %and put sym(']')
  repeat 
  return 
end 

!Warning or error
  faultnum = 0
  if  n > 0 start 
    mark = '*'
    c_faults = c_faults+1;  faults = faults+1
  else 
    return  if  control&warnbit = 0
    mark = '?'
  finish 
  c_access = -1
!Establish what to print
  start = linestart;  errline = line
  if  n&point = 0 start 
    faultp = 0;  !no pointing
  else 
    while  start >= faultp cycle ;  !before current line
      start = start-1
      errline = errline-1 if  byteintegeR(start) = nl
    repeat 
    start = start-1 while  start # curstart and  byteintegeR(start-1) # nl
  finish 
  time1 = time1-cputime
  if  listout # 0 start ;  !listing file
    print text(listout);  print line
  finish 
  select output(0)
  if  curfile # lastfile start 
    lastfile = curfile;  put string(cur_name);  print line
  finish 
  print text(0)
  if  file(main)_start1 <= fp < lastchange {uncorrected earlier error}-
  or  n <= reacherr or  curfile # main or  control&editbit = 0 start 
    print line
    select output(listout)
    time1 = time1+cputime
  else 
    start = faultp-1 if  faultp > start
    cur_fp = start;  cur_line = line
    cur_change = 16_7FFFFFFE if  lastchange # 0
    select input(0)
    file(main+1) = 0
    edi(file(main),file(main+1),rep);  !main+1 to keep editor happy
    rep = ""
    select output(listout)
    time1 = time1+cputime
    signal  abandon if  cur_flag < 0 {abandoned}
    control = control&(\editbit) if  cur_flag = 'I'
    lastchange = cur_change and  signal  redo if  cur_change < 16_7FFFFFFE
  finish 
end ;  !report

routine  FAULT(integer  n)
!Note fault number and position of (earliest) fault
! for subsequent reporting (warnings and weak errors)
  if  faultnum = 0 or  (n > 0 and  faultnum < 0) start 
    faultnum = n;  faultp = atomp
    report(faultnum&127,0,0) if  faultnum >= now
  finish 
end 

routine  INTERN(integer  n)
  report(internerr,0,n)
end 

!!!!!!!!!!!!!!!!!!!!   CELL  CONSTRUCTORS  !!!!!!!!!!!!!!!!!!!
!
integer fn  LITREF(integer  v)
integer  i
  result  = v if  v = 0
  if  v > 0 start 
    result  = -(v<<1) if  v <= smallmax
  else 
    result  = v<<1+1 if  v >= smallmin
  finish 
  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 >= litmax
  finish 
  result  = i
end 
!
!!%routine PUT TEMP(%integer f,t,m,v)
!!  item = dmin;  ditem == dict(item)
!!  %while item < dictlim %cycle
!!    %return %if ditem_val = v %and ditem_mode = m -
!!            %and ditem_type = t %and ditem_flags = f
!!    item = item+1;  ditem == ditem[1]
!!  %repeat
!!  dmin = dmin-1
!!  croak("Too many identifiers") %if dmin <= dlim
!!  item = dmin;  ditem == dict(item)
!!  ditem = 0
!!  ditem_flags = f;  ditem_type = t
!!  ditem_mode = m;  ditem_val = v
!!  type = t
!!%end

routine  PUTEXP(integer  act,x,y,t)
  type = t
  item = explim
  item = x if  explo <= x < item
  item = y if  explo <= y < item
  cycle 
    item = item-1
    ditem == dict(item)
    if  item < explo start 
      explo = item
      ditem_act = act;  ditem_x = x;  ditem_y = y
      ditem_flags = 0;  ditem_type = t;  ditem_mode = 0
      exit 
    finish 
  repeat  until  ditem_act = act and  ditem_x = x and  ditem_y = y
end 

!$IF VAX
{%integer%fn IEEE(%integer v)
{  %result = 0 %if v = 0
{  %result = v<<16+v>>16-16_01000000
{%end
!$FINISH

%routine PUTEXP2(%integer op,first,t)
  %if item = 0 %start
!$IF VAX
{  value = ieee(value) %if type = realtype;  !vax->ieee
!$FINISH
    item = litref(value)
  %finish
  putexp(op,first,item,t)
%end

%integer%fn NORMITEM
  %result = item %if item # 0
!$IF VAX
{  value = ieee(value) %if type = realtype;  !vax->ieee
!$FINISH
  %result = litref(value)
%end

%routine TOREAL
  %if item # 0 %then putexp(float,item,0,realtype) -
  %else real(addr(value)) = value %and type = realtype
%end

%integer%fn TEMP(%integer m,v)
  dtemp_mode = m;  dtemp_val = v
  %result = lablim
%end
%integer%fn TEMPX(%integer r1,r2)
  dtemp_mode = r1+(indexmode-a0);  dtemp_val = (r2-d0)<<12+16_0800
  %result = lablim
%end
%integer%fn TEMPD(%integer a,disp)
  dtemp_mode = a+(dispmode-a0);  dtemp_val = disp
  %result = lablim
%end
%integer%fn TEMPX2(%integer r1,r2)
  dtemp2_mode = r1+(indexmode-a0);  dtemp2_val = (r2-d0)<<12+16_0800
  %result = lablim+1
%end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!    CODE  GENERATION   !!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!  The array DEF contains packed mnemonics for M68000 machine
! instructions and, for each mnemonic, the basic opcode and
! a type indicator.
!  The type indicator contains flag bits for various special cases
! and two 6-bit fields defining the operand types
! [should be const record array]
!  The mnemonics and variant distinctions broadly follow the
!  manufacturer's Assembly Language conventions
!
! Opcode index values needed globally:-
%constinteger LEA=78, PEA=55, CLR=52, DBRA=81, JSR=56,
              LINK=72, UNLK=73, RTS=68,
              MOVEM=100, TRAPI=101, DC=102

!Machine-code operand types (KINDs)
%constinteger SHIFT=32
%constinteger DREG=1, AREG=2, IREG=3,
              QREG=4, POSTAREG=5, PREAREG=6, DPRE=7,
              QUICK=8, TQUICK=9, MQUICK=10, IMM=11,
              XIMM=12, DATA=13, REL=14, LONGREL=15,
              EA=16, RWEA=17, WEA=18, REVEA=19,
              DEA=20, RWDEA=21, WDEA=22, REVDEA=23   {D=data ie not AREG},
              CEA=24, LCEA=25, REVDISP=26, DISP=27   {C=control},
              DEAA=28                                {A=Alterable tho' no W}
constinteger  DREG9=dreg+shift, QREG9=qreg+shift, IREG9=ireg+shift,
              POSTAREG9=postareg+shift,
              QUICK9=quick+shift, AREG9=areg+shift,
              EXREG9=29+shift
constinteger  SIZED=1<<15, ASIZED=1<<14, QSIZED=1<<13;  !1 spare bits

predicate  OKMODE(integer  kind,mode)
!True iff given EA MODE is valid for operand KIND
! BASIC for HI 3 bits of MODE, SPECIAL for LO 3 when HI=7
! Note BASIC bit 7 zero unless ALL special modes valid
const byte array  BASIC(0:31) =
  2_11111111,          2_00000001{DREG},
  2_00000010{AREG},    2_00000001{IREG},
  2_00000001{QREG},    2_00001000{POSTAREG},
  2_00000100{PREAREG}, 2_00000101{DPRE},
  0{QUICK},            0{TQUICK},
  0{MQUICK},           0{IMM},
  2_01111100{XIMM},    0{DATA},
  0{REL},              0{LONGREL},
  2_01111111{EA},      2_01111111{RWEA},
  2_01111111{WEA},     2_01111111{REVEA},
  2_01111101{DEA},     2_01111101{RWDEA},
  2_01111101{WDEA},    2_01111101{REVDEA},
  2_01100100{CEA},     2_01100100{LCEA},
  2_00100001{REVDISP}, 2_11111111{DISP},
  2_01111101 {DEAA}, 2_00000011 {EXREG}, 0(*)
const byte array  SPECIAL(0:31) =
  0,                   0{DREG},
  0{AREG},             2_00010000{IREG},
  2_00010000{QREG},    0{POSTAREG},
  0{PREAREG},          0{DPRE},
  2_00010000{QUICK},   2_00010000{TQUICK},
  2_00010000{MQUICK},  2_00010000{IMM},
  2_00011111{XIMM},    2_00000011{DATA},
  2_00011100{REL},     2_00011100{LONGREL},
  2_00011111{EA},      2_00000011{RWEA},
  2_00000011{WEA},     2_00011111{REVEA},
  2_00011111{DEA},     2_00000011{RWDEA},
  2_00000011{WDEA},    2_00011111{REVDEA},
  2_00001111{CEA},     2_00001111{LCEA},
  0{REVDISP},          0{DISP},
  2_00000011 {DEAA},   0{EXREG}, 0(*)
  true  if  basic(kind) & 1<<(mode>>3) # 0
  true  if  mode-7<<3 >= 0 and  special(kind) & 1<<(mode-7<<3) # 0
  false 
end 

constinteger  DEFMAX=130
constintegerarray  DEF(0:defmax+defmax) =
  0,
 {MOVE} 16_0000<<16+ ea<<6+wea+shift +sized,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10,
 {ADD} 16_D000<<16+ revea<<6+dreg9+sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15,
 {SUB} 16_9000<<16+ revea<<6+dreg9+sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15,
 {CMP} 16_B000<<16+ ea<<6+dreg9 +sized,
  'c'<<25+('m'&31)<<20+('p'&31)<<15,
 {AND} 16_C000<<16+ revdea<<6+dreg9+sized,
  'a'<<25+('n'&31)<<20+('d'&31)<<15,
 {OR} 16_8000<<16+ revdea<<6+dreg9+sized,
  'o'<<25+('r'&31)<<20,
 {EOR} 16_B100<<16+ dreg9<<6+rwdea +sized,
  'e'<<25+('o'&31)<<20+('r'&31)<<15,
 {NOT} 16_4600<<16+ rwdea +sized,
  'n'<<25+('o'&31)<<20+('t'&31)<<15,
 {NEG} 16_4400<<16+ rwdea +sized,
  'n'<<25+('e'&31)<<20+('g'&31)<<15,
 {LSL} 16_E108<<16+ qreg9<<6+dreg +sized,
  'l'<<25+('s'&31)<<20+('l'&31)<<15,
 {LSR} 16_E008<<16+ qreg9<<6+dreg +sized,
  'l'<<25+('s'&31)<<20+('r'&31)<<15,
 {MULS} 16_C1C0<<16+ dea<<6+dreg9,
  'm'<<25+('u'&31)<<20+('l'&31)<<15+('s'&31)<<10,
 {DIVS} 16_81C0<<16+ dea<<6+dreg9,
  'd'<<25+('i'&31)<<20+('v'&31)<<15+('s'&31)<<10,
 {MULU} 16_C0C0<<16+ dea<<6+dreg9,
  'm'<<25+('u'&31)<<20+('l'&31)<<15+('u'&31)<<10,
 {DIVU} 16_80C0<<16+ dea<<6+dreg9,
  'd'<<25+('i'&31)<<20+('v'&31)<<15+('u'&31)<<10,
 {BRA} 16_6000<<16+ rel,
  'b'<<25+('r'&31)<<20+('a'&31)<<15,
 {BSR} 16_6100<<16+ rel,
  'b'<<25+('s'&31)<<20+('r'&31)<<15,
 {BHI} 16_6200<<16+ rel,
  'b'<<25+('h'&31)<<20+('i'&31)<<15,
 {BLS} 16_6300<<16+ rel,
  'b'<<25+('l'&31)<<20+('s'&31)<<15,
 {BCC} 16_6400<<16+ rel,
  'b'<<25+('c'&31)<<20+('c'&31)<<15,
 {BCS} 16_6500<<16+ rel,
  'b'<<25+('c'&31)<<20+('s'&31)<<15,
 {BNE} 16_6600<<16+ rel,
  'b'<<25+('n'&31)<<20+('e'&31)<<15,
 {BEQ} 16_6700<<16+ rel,
  'b'<<25+('e'&31)<<20+('q'&31)<<15,
 {BVC} 16_6800<<16+ rel,
  'b'<<25+('v'&31)<<20+('c'&31)<<15,
 {BVS} 16_6900<<16+ rel,
  'b'<<25+('v'&31)<<20+('s'&31)<<15,
 {BPL} 16_6A00<<16+ rel,
  'b'<<25+('p'&31)<<20+('l'&31)<<15,
 {BMI} 16_6B00<<16+ rel,
  'b'<<25+('m'&31)<<20+('i'&31)<<15,
 {BGE} 16_6C00<<16+ rel,
  'b'<<25+('g'&31)<<20+('e'&31)<<15,
 {BLT} 16_6D00<<16+ rel,
  'b'<<25+('l'&31)<<20+('t'&31)<<15,
 {BGT} 16_6E00<<16+ rel,
  'b'<<25+('g'&31)<<20+('t'&31)<<15,
 {BLE} 16_6F00<<16+ rel,
  'b'<<25+('l'&31)<<20+('e'&31)<<15,
 {ASL} 16_E100<<16+ qreg9<<6+dreg +sized,
  'a'<<25+('s'&31)<<20+('l'&31)<<15,
 {ASR} 16_E000<<16+ qreg9<<6+dreg +sized,
  'a'<<25+('s'&31)<<20+('r'&31)<<15,
 {ROL} 16_E118<<16+ qreg9<<6+dreg +sized,
  'r'<<25+('o'&31)<<20+('l'&31)<<15,
 {ROR} 16_E018<<16+ qreg9<<6+dreg +sized,
  'r'<<25+('o'&31)<<20+('r'&31)<<15,
 {MOVEQ} 16_7000<<16+ mquick<<6+dreg9,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('q'&31)<<5,
 {ADDQ} 16_5000<<16+ quick9<<6+rwea +sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('q'&31)<<10,
 {SUBQ} 16_5100<<16+ quick9<<6+rwea +sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('q'&31)<<10,
 {MOVEA} 16_3040<<16+ ea<<6+areg9 +asized,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('a'&31)<<5,
 {ADDA} 16_D0C0<<16+ ea<<6+areg9 +asized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('a'&31)<<10,
 {SUBA} 16_90C0<<16+ ea<<6+areg9 +asized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('a'&31)<<10,
 {CMPA} 16_B0C0<<16+ ea<<6+areg9 +asized,
  'c'<<25+('m'&31)<<20+('p'&31)<<15+('a'&31)<<10,
 {CMPM} 16_B108<<16+ postareg<<6+postareg9,
  'c'<<25+('m'&31)<<20+('p'&31)<<15+('m'&31)<<10,
 {ADDI} 16_0600<<16+ imm<<6+rwdea +sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('i'&31)<<10,
 {SUBI} 16_0400<<16+ imm<<6+rwdea +sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('i'&31)<<10,
 {CMPI} 16_0C00<<16+ imm<<6+rwdea +sized,
  'c'<<25+('m'&31)<<20+('p'&31)<<15+('i'&31)<<10,
 {ANDI} 16_0200<<16+ imm<<6+rwdea +sized,
  'a'<<25+('n'&31)<<20+('d'&31)<<15+('i'&31)<<10,
 {ORI} 16_0000<<16+ imm<<6+rwdea +sized,
  'o'<<25+('r'&31)<<20+('i'&31)<<15,
 {EORI} 16_0A00<<16+ imm<<6+rwdea +sized,
  'e'<<25+('o'&31)<<20+('r'&31)<<15+('i'&31)<<10,
 {ROXL} 16_E110<<16+ qreg9<<6+dreg +sized,
  'r'<<25+('o'&31)<<20+('x'&31)<<15+('l'&31)<<10,
 {ROXR} 16_E010<<16+ qreg9<<6+dreg +sized,
  'r'<<25+('o'&31)<<20+('x'&31)<<15+('r'&31)<<10,
 {CLR} 16_4200<<16+ wdea +sized,
  'c'<<25+('l'&31)<<20+('r'&31)<<15,
 {NEGX} 16_4000<<16+ rwdea +sized,
  'n'<<25+('e'&31)<<20+('g'&31)<<15+('x'&31)<<10,
 {NBCD} 16_4800<<16+ rwdea,
  'n'<<25+('b'&31)<<20+('c'&31)<<15+('d'&31)<<10,
 {PEA} 16_4840<<16+ cea,
  'p'<<25+('e'&31)<<20+('a'&31)<<15,
 {JSR} 16_4E80<<16+ cea,
  'j'<<25+('s'&31)<<20+('r'&31)<<15,
 {JMP} 16_4EC0<<16+ cea,
  'j'<<25+('m'&31)<<20+('p'&31)<<15,
 {TAS} 16_4AC0<<16+ rwdea,
  't'<<25+('a'&31)<<20+('s'&31)<<15,
 {TST} 16_4A00<<16+ deaa +sized,
  't'<<25+('s'&31)<<20+('t'&31)<<15,
 {ABCD} 16_C100<<16+ dpre<<6+dreg9,
  'a'<<25+('b'&31)<<20+('c'&31)<<15+('d'&31)<<10,
 {SBCD} 16_8100<<16+ dpre<<6+dreg9,
  's'<<25+('b'&31)<<20+('c'&31)<<15+('d'&31)<<10,
 {ADDX} 16_D100<<16+ dpre<<6+dreg9 +sized,
  'a'<<25+('d'&31)<<20+('d'&31)<<15+('x'&31)<<10,
 {SUBX} 16_9100<<16+ dpre<<6+dreg9 +sized,
  's'<<25+('u'&31)<<20+('b'&31)<<15+('x'&31)<<10,
 {NOP} 16_4E71<<16,
  'n'<<25+('o'&31)<<20+('p'&31)<<15,
 {RESET} 16_4E70<<16,
  'r'<<25+('e'&31)<<20+('s'&31)<<15+('e'&31)<<10+('t'&31)<<5,
 {RTE} 16_4E73<<16,
  'r'<<25+('t'&31)<<20+('e'&31)<<15,
 {RTR} 16_4E77<<16,
  'r'<<25+('t'&31)<<20+('r'&31)<<15,
 {RTS} 16_4E75<<16,
  'r'<<25+('t'&31)<<20+('s'&31)<<15,
 {STOP} 16_4E72<<16 +imm,
  's'<<25+('t'&31)<<20+('o'&31)<<15+('p'&31)<<10,
 {TRAPV} 16_4E76<<16,
  't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10+('v'&31)<<5,
 {TRAP} 16_4E40<<16+ tquick,
  't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10,
 {LINK} 16_4E50<<16+ imm<<6+areg,
  'l'<<25+('i'&31)<<20+('n'&31)<<15+('k'&31)<<10,
 {UNLK} 16_4E58<<16+ areg,
  'u'<<25+('n'&31)<<20+('l'&31)<<15+('k'&31)<<10,
 {SWAP} 16_4840<<16+ dreg,
  's'<<25+('w'&31)<<20+('a'&31)<<15+('p'&31)<<10,
 {EXTW} 16_4880<<16+ dreg,
  'e'<<25+('x'&31)<<20+('t'&31)<<15+('w'&31)<<10,
 {EXTL} 16_48C0<<16+ dreg,
  'e'<<25+('x'&31)<<20+('t'&31)<<15+('l'&31)<<10,
 {EXG} 16_C140<<16+ exreg9<<6+dreg,
  'e'<<25+('x'&31)<<20+('g'&31)<<15,
 {LEA} 16_41C0<<16+ lcea<<6+areg9,
  'l'<<25+('e'&31)<<20+('a'&31)<<15,
 {CHK} 16_4180<<16+ dea<<6+dreg9,
  'c'<<25+('h'&31)<<20+('k'&31)<<15,
 {DBXX} 16_50C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('x'&31)<<15+('x'&31)<<10,
 {DBRA} 16_51C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('r'&31)<<15+('a'&31)<<10,
 {DBHI} 16_52C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('h'&31)<<15+('i'&31)<<10,
 {DBLS} 16_53C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('l'&31)<<15+('s'&31)<<10,
 {DBCC} 16_54C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('c'&31)<<15+('c'&31)<<10,
 {DBCS} 16_55C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('c'&31)<<15+('s'&31)<<10,
 {DBNE} 16_56C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('n'&31)<<15+('e'&31)<<10,
 {DBEQ} 16_57C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('e'&31)<<15+('q'&31)<<10,
 {DBVC} 16_58C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('v'&31)<<15+('c'&31)<<10,
 {DBVS} 16_59C8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('v'&31)<<15+('s'&31)<<10,
 {DBPL} 16_5AC8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('p'&31)<<15+('l'&31)<<10,
 {DBMI} 16_5BC8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('m'&31)<<15+('i'&31)<<10,
 {DBGE} 16_5CC8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('g'&31)<<15+('e'&31)<<10,
 {DBLT} 16_5DC8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('l'&31)<<15+('t'&31)<<10,
 {DBGT} 16_5EC8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('g'&31)<<15+('t'&31)<<10,
 {DBLE} 16_5FC8<<16+ dreg<<6+longrel,
  'd'<<25+('b'&31)<<20+('l'&31)<<15+('e'&31)<<10,
 {BCHG} 16_0140<<16+ ireg9<<6+rwdea +qsized,
  'b'<<25+('c'&31)<<20+('h'&31)<<15+('g'&31)<<10,
 {BCLR} 16_0180<<16+ ireg9<<6+wdea +qsized,
  'b'<<25+('c'&31)<<20+('l'&31)<<15+('r'&31)<<10,
 {BSET} 16_01C0<<16+ ireg9<<6+wdea +qsized,
  'b'<<25+('s'&31)<<20+('e'&31)<<15+('t'&31)<<10,
 {BTST} 16_0100<<16+ ireg9<<6+dea +qsized,
  'b'<<25+('t'&31)<<20+('s'&31)<<15+('t'&31)<<10,
 {MOVEM} 16_4880<<16+ ximm<<6+ea+asized,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('m'&31)<<5,
 {TRAPI} 16_4E40<<16+ imm<<6+tquick,
  't'<<25+('r'&31)<<20+('a'&31)<<15+('p'&31)<<10+('i'&31)<<5,
 {DC}         data,
     'd'<<25+('c'&31)<<20,
 {ST} 16_50C0<<16+ wea,
  's'<<25+('t'&31)<<20,
 {SF} 16_51C0<<16+ wea,
  's'<<25+('f'&31)<<20,
 {SHI} 16_52C0<<16+ wea,
  's'<<25+('h'&31)<<20+('i'&31)<<15,
 {SLS} 16_53C0<<16+ wea,
  's'<<25+('l'&31)<<20+('s'&31)<<15,
 {SCC} 16_54C0<<16+ wea,
  's'<<25+('c'&31)<<20+('c'&31)<<15,
 {SCS} 16_55C0<<16+ wea,
  's'<<25+('c'&31)<<20+('s'&31)<<15,
 {SNE} 16_56C0<<16+ wea,
  's'<<25+('n'&31)<<20+('e'&31)<<15,
 {SEQ} 16_57C0<<16+ wea,
  's'<<25+('e'&31)<<20+('q'&31)<<15,
 {SVC} 16_58C0<<16+ wea,
  's'<<25+('v'&31)<<20+('c'&31)<<15,
 {SVS} 16_59C0<<16+ wea,
  's'<<25+('v'&31)<<20+('s'&31)<<15,
 {SPL} 16_5AC0<<16+ wea,
  's'<<25+('p'&31)<<20+('l'&31)<<15,
 {SMI} 16_5BC0<<16+ wea,
  's'<<25+('m'&31)<<20+('i'&31)<<15,
 {SGE} 16_5CC0<<16+ wea,
  's'<<25+('g'&31)<<20+('e'&31)<<15,
 {SLT} 16_5DC0<<16+ wea,
  's'<<25+('l'&31)<<20+('t'&31)<<15,
 {SGT} 16_5EC0<<16+ wea,
  's'<<25+('g'&31)<<20+('t'&31)<<15,
 {SLE} 16_5FC0<<16+ wea,
  's'<<25+('l'&31)<<20+('e'&31)<<15,
 {MTCCR} 16_44C0<<16+ dea,
  'm'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {MTSR} 16_46C0<<16+ dea,
  'm'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {MFSR} 16_40C0<<16+ wdea,
  'm'<<25+('f'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {MTUSP} 16_4E60<<16+ areg,
  'm'<<25+('t'&31)<<20+('u'&31)<<15+('s'&31)<<10+('p'&31)<<5,
 {MFUSP} 16_4E68<<16+ areg,
  'm'<<25+('f'&31)<<20+('u'&31)<<15+('s'&31)<<10+('p'&31)<<5,
 {ATCCR} 16_023C<<16+ imm,
  'a'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {ATSR} 16_027C<<16+ imm,
  'a'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {ETCCR} 16_0A3C<<16+ imm,
  'e'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {ETSR} 16_0A7C<<16+ imm,
  'e'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {OTCCR} 16_003C<<16+ imm,
  'o'<<25+('t'&31)<<20+('c'&31)<<15+('c'&31)<<10+('r'&31)<<5,
 {OTSR} 16_007C<<16+ imm,
  'o'<<25+('t'&31)<<20+('s'&31)<<15+('r'&31)<<10,
 {MOVEP} 16_0120<<16+ revdisp<<6+dreg9+asized,
  'm'<<25+('o'&31)<<20+('v'&31)<<15+('e'&31)<<10+('p'&31)<<5

{?}routine  PUT OPCODE(integer  op)
{?}  put mnemonic(def(op+op))
{?}end 

routine  STORE(integer  v,f)
  pflag(pc) = f
!$IF VAX
{  v = v&16_FFFF;  v = v!sign16 %if v&sign16 # 0
!$FINISH
  prog(pc) <- v;  pc = pc+1
%end

%routine MAKE INIT ROOM(%integer size)
%integer newbase
  %if initlim+size >= finalbound %start
    size = (size+127)&(\127)
    initbase = initbase-size
    croak("Program too big") %if initbase <= cad
    initlim = initlim-size;  inithead = inithead-size %if inithead > 0
    newbase = initbase
    %cycle
      final(newbase) = final(newbase+size)
      newbase = newbase+1
    %repeat %until newbase >= initlim
  %finish
%end

%routine FILL CODE(%integer n)
  %while n > 0 %cycle
    final(cad) = 16_80;  cad = cad+1;  n = n-1
  %repeat
%end

%routine SET CODE WORD(%integer v)
!$IF VAX (works irrespective of host byte sex)
{  final(cad) <- v>>8;  final(cad+1) <- v
!$IF APM (for efficiency)
  shortinteger(final0+cad) <- v
!$FINISH
  cad = cad+2
%end

%integer%fn CODE WORD(%integer cad)
!$IF VAX (works irrespective of host byte sex)
{  %result = final(cad)<<8+final(cad+1)
!$IF APM (for efficiency)
  %result = shortinteger(final0+cad)
!$FINISH
%end

%routine SET CODE LONGWORD(%integer v)
  set code word(v>>16);  set code word(v)
%end

%routine PUT OWN WORD(%integer v)
  make init room(2)
!$IF VAX
{  final(initlim) <- v>>8;  final(initlim+1) <- v
!$IF APM
  shortinteger(final0+initlim) <- v
!$FINISH
  initlim = initlim+2
%end

%routine INIT ADEVAL(%integer mode,val)
! Generate INIT code to evaluate new initialisation address to A1
  %if %not is short(val) %start
    fault(dreacherr) %if mode&63 # absmode
    put own word(16_43F9);          !LEA xxxxxxxx,A1
    put own word(val>>16)
    put own word(val)
  %else %if mode&2_111000 = dispmode %and val = 0
    put own word(16_2248+mode&7);   !MOVE A?,A1
  %else
    put own word(16_43C0+mode&63);  !LEA ?,A1
    put own word(val)
  %finish
  initmode = mode;  initval = val
%end

%routine END PATTERN
! Terminate sequence of initial values stretching from INITHEAD
!   if there is one
! Implies evening up of both real and nominal addresses
%integer i
  %return %if inithead <= 0
  %if initlim&1 # 0 %start
    final(initlim) <- 16_80
    initlim = initlim+1;  initval = initval+1
  %finish
 ! Insert length of data (halfwords-1)
  shortinteger(final0+inithead) <- (initlim-inithead)>>1-2
  inithead = 0
%end

%routine START PATTERN
! Establish new header position for sequence of own values
!   unless one is ongoing
%integer i
  %return %if inithead > 0     {pattern started}
 {Plant call to COPY subroutine}
  i = initbase-initlim-14
  if  i >= -128 then  put own word(16_6100+256+i) -
  else  put own word(16_6100) and  put own word(i)
 {Plant length word}
  put own word(0);  inithead = initlim-2
end 

routine  END RUN
! Terminate run of same own initial value (byte)
!   if there is one
integer  i
  return  if  initrep <= 0      {no run}
  if  initlim&1 # 0 start       {odd byte in preceding pattern}
    final(initlim) <- initdata  {so fill it with the run value}
    initlim = initlim+1;  initrep = initrep-1
    return  if  initrep = 0
  finish 
  if  initrep >= 16 start       {worth using loop}
    end pattern
    i = initrep&(\1)-1          {DBRA value for even amount}
    if  i <= 127 start 
      put own word(16_7000+i); !MOVEQ #?,D0
    else 
      put own word(16_303C);  put own word(i); !MOVE.W #?,D0
    finish 
    if  initdata # initd1 start 
      initd1 = initdata
      put own word(16_7200+initd1&255); ! MOVEQ #?,D1
    finish 
    put own word(16_12C1);             ! MOVE.B D1,(A1)+
    put own word(16_51C8);             ! DBRA D0,#-4
    put own word(-4)
    initrep = initrep&1                {may be 1 byte left over}
  finish 
 {Put (rest) as pattern}
  if  initrep > 0 start 
!    %if inithead > 0 %start
      start pattern
      make init room(initrep)
      cycle 
        final(initlim) = initdata
        initlim = initlim+1;  initrep = initrep-1
      repeat  until  initrep = 0
!    %else
  finish 
  initrep = 0
end 

routine  PATTERN(integer  mode,val,size)
!Prepare for SIZE owns at given address
  end run
  if  mode # initmode or  val # initval start 
    end pattern
    init adeval(mode,val)
  finish 
  start pattern
  initval = initval+size
end 

routine  RUN(integer  mode,val,n,v)
!Set-up run of N bytes of value V at given address
  end run if  v # initdata
  if  mode # initmode or  val # initval start 
    end run;  end pattern
    init adeval(mode,val)
  finish 
  initdata = v;  initrep = initrep+n
  initval = initval+n
end 

routine  EXTEND STACK(integer  delta)
  c_sp = c_sp-delta
  if  c_sp < c_stack start        {max local extension so far}
    c_stack = c_sp
    c_totstack = c_stack if  c_stack < c_totstack
  finish 
end 

routine  PLANT(integer  op,y,x)
!Basic code planting procedure
! OP is an index to the array defining op-codes
!  (it can be flagged to force SIZE)
! For unary operations the operand is given by X (Y zero)
! For binary operations the operands are Y (source) and X (dest)
integer  OPCODE,PC1,I,F,EXTWORD,INFO,KIND,MODE,MODEX,SIZE,ADJUSTMENT
record (identinfo)name  DX,DY
switch  S(0:31)
constbytearray  SIZESYM(0:3) = 'L','B','W','?'

integer fn  NONLOCAL(integer  l)
integer  r
  result  = mb if  l = 0
  hold(l)_status = hold(l)_status!globbed if  l # level
  result  = f1 if  l = 1
  r = maxareg
  cycle 
    result  = r if  c_reg_content(r) = d7+l  {unique}
    r = r-1
  repeat  until  r < a0
![not good enough: 1. may need two
!                  2. FREE updated elsewhere without regard to this]
  r = maxareg
  while  a0b<<(r-a0)&free = 0 cycle 
    fault(plexerr) and  exit  if  r = a0
    r = r-1
  repeat 
  c_reg_content(r) = d7+l
  dtsprel_mode = globalmode;  dtsprel_val = l<<2
  plant(move,lablim+2,r)
  result  = r
end 

constinteger  MOVEQ=36, ADDQ=37, MOVEA=39,
              ADDA=40, ADDI=44

  if  x > 0 start 
    intern(1) and  return  if  x >= explim
    dx == dict(x)
    modex = dx_mode
    if  modex >= framemode and  modex # c_mode -
    and  modex&2_111000 # 2_111000 start 
      modex = nonlocal(modex&7)-a0+(modex&(7<<3))
    finish 
  finish  else  modex = litmode and  dx == dint
  if  y > 0 start 
    intern(1) and  return  if  y >= explim
    dy == dict(y)
    mode = dy_mode
    if  mode >= framemode and  mode # c_mode -
    and  mode&2_111000 # 2_111000 start 
      mode = nonlocal(mode&7)-a0+(mode&(7<<3))
    finish 
  finish  else  mode = litmode and  dy == dint
  size = op>>8;  op = op&255
 {Choose alternative operator if desirable}
  if  op = move start 
    if  modex&2_111000 = 0 start   {Dx}
      op = moveq if  y <= 0 and  y >= litmite and  size&3 = 0
    else  if  modex&2_110000 = 0   {Ax}
      op = movea
    finish 
  else  if  op <= cmp  {ADD,SUB,CMP}
    if  op < cmp and  y < 0 and  y >= litquick and  y&1 = 0 -
    then  op=op+(addq-add) {ADDQ,SUBQ} -
    else  if  modex&2_111000 = aregmode -
    then  op=op+(adda-add) {ADDA,SUBA,CMPA} -
    else  if  y <= 0 and  modex&2_111000 # 0 {I is slower if 1st is reg} -
    then  op=op+(addi-add) {ADDI,SUBI,CMPI}
  else  if  op <= eor  {AND,OR,EOR}
    op = op+(addi-add) if  y <= 0 -
      and  (op = eor or  modex&2_111000 # 0) {ANDI,ORI,EORI}
  finish 
 {Extract operator code + type info}
  info = def(op+op-1)
  opcode = info>>16
 {Modify opcode according to SIZE}
  if  info&sized # 0 start        {B,W,L sized}
    size = 4 if  size = 0
    if  op = move start 
      if  size = 4 then  opcode = opcode+16_2000 -
      else  if  size = 2 then  opcode = opcode+16_3000 -
      else  opcode = opcode+16_1000
    else 
      if  size = 4 then  opcode = opcode+16_80 -
      else  if  size = 2 then  opcode = opcode+16_40
    finish 
  else  if  info&asized # 0        {W,L sized}
    fault(sizerr) if  size = 1
    if  size = 0 start 
     {Can use W for short literal because of auto-extension}
      size = 4 unless  y <= 0 and  is short(litval(y)) and  op < movem
    finish 
    if  size = 4 start 
      if  op >= movem then  opcode = opcode+16_0040  {MOVEM,MOVEP} -
      else  if  op # movea then  opcode = opcode+16_0100 {ADDA,SUBA,CMPA}-
      else  opcode = opcode!!16_1000
    finish 
  finish 
{?}  if  control&codelist # 0 and  control&list # 0 start 
{?}    print line if  length(rep) >= 4
{?}    put sym(codeflag);  spaces(4-length(rep))
{?}    put opcode(op)
{?}    if  size # 0 start 
{?}      put sym('.')
{?}      put sym(sizesym(size&3))
{?}    finish 
{?}    spaces(12-length(rep))
{?}    if  info&(63<<6) # 0 start 
{?}      put operand(y)
{?}      put sym(',')
{?}    finish 
{?}    put operand(x) if  info&63 # 0
{?}    spaces(33-length(rep));  put sym(':')
{?}  finish 

  pc1 = pc;  pflag(pc1) = c_shorts;  !op-code word
  pc = pc+1
  croak("Code space exhausted") if  pc+8 >= swpc
  adjustment = 0
  -> next if  info&31<<6 = 0
  kind = info>>6
again:
  -> err if  not  okmode(kind&31,mode&63)
  -> s(kind&31)
next:
  kind = info
  if  kind # 0 start 
    dy == dx;  y = x;  mode = modex
    info = 0
    ->again
  finish 
!
s(0):
!$IF VAX
{  opcode = opcode!sign16 %if opcode&sign16 # 0
!$FINISH
  prog(pc1) <- opcode
{?}  if  control&codelist # 0 and  control&list # 0 start 
{?}    cycle 
{?}      put sym(' ')
{?}      put hex(prog(pc1))
{?}      pc1 = pc1+1
{?}    repeat  until  pc1 >= pc
{?}    print line
{?}  finish 
  return 

!Set flag value for PC-relative reference
! distinguishing GLOBAL (const access), INDIRECT GLOBAL (procedure),
! and LOCAL (label) -- the last further distinguished according to
! whether the instruction permits shortening
routine  PCREL(integer  shorten)
  if  dy_mode = labmode start 
    f = jump;  f = longjump if  shorten = 0
    if  extword > 0 start ;  !label defined
      if  shorten # 0 and  (extword-pflag(extword)-pc+c_shorts)<<1 >= -128 start 
        if  c_shorts = 255 start 
          zaps = zaps+100
        else 
          shorts = shorts+1;  c_shorts = c_shorts+1
          f = shortjump
        finish 
      finish 
    else 
      extword = -extword
      dy_val = -pc
    finish 
  else  if  dy_mode = procmode;  !procedure
    f = indglobal;  extword = y;  !rather than DY_VAL
  else  if  dy_mode = constmode;  !constant data ref
    f = global
    f = f+1 if  extword < 0
    f = f+2 if  extword > 65535
  finish 
end 

s(lcea):  !LEA
  if  mode&63 = x-(a0-indexmode) and  dy_val&255 = 0 start 
    !  LEA 0(Ax,Dy),Ax  =>  ADDA Dy,Ax
    opcode = 16_D1C0+dy_val>>12&15
    -> next
  finish 
s(cea):  !Control addressing modes
  -> ea0 unless  (op = lea or  op = pea) and  mode&63 # pcmode
  !taking address: might read or write
  dy_flags = dy_flags!(mflag+rflag+wflag)
  -> ea1
s(wea): s(wdea):
  dy_flags = dy_flags!(mflag!wflag)
  -> ea1
s(rwea): s(rwdea):
 ![for our purposes, read&write counts as neither]
  dy_flags = dy_flags!mflag
  -> ea1
s(revdisp): !MOVEP
  if  modex&2_111000 # 0 start 
    kind = shift;  info = disp
    opcode = opcode!!16_0080
    -> sreg
  finish 
  -> ea0
s(revea): s(revdea):
  !reversible cases (EA,DREG or DREG,EA)
  if  modex&2_111000 # 0 start ;  !dest not D
    kind = shift;  info = rwea
    opcode = opcode!!16_0100
    ->sreg
  finish 
s(ea):s(dea):
ea0:
  if  y <= 0 start 
    opcode = opcode+litmode;  !immediate
    ->simm
  finish 
  if  dy_flags&(ext+spec+rflag+wflag) = ext+spec -
  and  dy_flags&proc # 0 start 
   ! Create transfer vector for external procedure
   ! ** check whether this is adequate to even up **
    ownval = ownval+1 if  ownval&1 # 0
    dy_val = ownval
    ownval = ownval+6                          {6 bytes for %system}
    ownval = ownval+6 if  dy_flags&proc2 # 0   {12 for %external}
  finish 
s(deaa):
  dy_flags = dy_flags!(mflag+rflag)
s(disp):
ea1:
  extword = dy_val+adjustment
  if  mode = c_mode start ;  !local
    mode = dispmode+7;  extword = extword-c_sp;  !convert to use SP
    if  extword < 0 start 
      intern(4) if  extword < -4
      mode = aregmode+pre+7
      extend stack(-extword)
      extword = 0
    finish 
  finish 
  mode = mode&63;   !strip extra flags
  if  mode >= dispmode start ;  !+extra
    f = 0
    if  mode = pcmode start 
      pcrel(0)
    finish 
    if  mode <= dispmode+7 start 
      if  extword = 0 start 
        ! Premode (just created) or Dispmode (=>Indmode)
        mode = mode+(indirmode-dispmode) if  mode >= dispmode
      else 
        fault(dreacherr) unless  -32768 <= extword <= 32767
        store(extword,f)
      finish 
    else 
      mode = absmode+1 if  mode = absmode and  not  is short(extword)
      store(extword>>16,0) if  mode = absmode+1
      store(extword,f)
    finish 
  finish 
  mode = ((mode&7)<<3 + mode>>3)<<6 if  kind&shift # 0
  opcode = opcode!!mode
  -> next

s(exreg9&31):  !EXG (D,D / A,A / D,A)
  if  mode&2_111000 = 0 start ;  !D
    if  modex&2_111000 # 0 start ;  !not D
      opcode = opcode!!16_C8;  info = areg
    finish 
    -> sreg
  finish 
  opcode = opcode+8;  info = areg
  -> sareg
s(dpre):
  -> sreg if  mode&2_111000 = 0;  !D
  opcode = opcode+8;  info = preareg+shift
s(preareg):
  mode = mode+(post-pre)
s(postareg):
  mode = mode-post
s(areg): sareg:
  mode = mode-8
s(dreg): sreg:
  -> err unless  mode&(\7) = 0
  mode = mode<<9 if  kind&shift # 0
  opcode = opcode+mode
  ->next

s(qreg):  !Shift formats -- quick,Dx / Dy,Dx / 1,<ea> (W)
  opcode = opcode+16_20 and  ->sreg if  y > 0
  if  y = one and  size = 2 and  modex&2_111000 # 0 start 
    opcode = opcode!!16_290
    ->next
  finish 
s(quick):
  -> err if  y >= 0
  y = litval(y)
  ->err unless  y <= 8
  opcode = opcode+(y&7)<<9;  !(always aligned to bit9)
  ->next

s(tquick):  !(TRAP)
  ->err unless  y >= -30 and  y&1 = 0;  ! 0 <= litval(y) <= 15
s(mquick):
  ->err unless  y >= litmite
  y = litval(y)
  opcode = opcode+y&255
  ->next
s(rel):
  ->s(mquick) if  y <= 0 and  y >= litmite
s(longrel):
  ->simm if  y <= 0
  dy_flags = dy_flags!rflag
  extword = dy_val
  f = 0
  pcrel(longrel-kind&31)
  store(extword,f)
  ->next

s(ireg):  !immediate or dreg (BTST etc)
  if  y > 0 start 
!    %if size # 0 %start
!      %if modex&2_111000 = 0 %start
!        fault(sizerr) %if size # 4
!      %else
!        fault(sizerr) %if size # 1
!      %finish
!    %finish
    ->sreg
  finish 
  opcode = opcode!!16_900
  y = litval(y)
  if  modex&2_111000 # 0 and  size > 1 start   {2nd not reg, not byte}
    adjustment = size
    adjustment = adjustment-1 and  y = y-8 until  y < 0
    y = y+8
    modex = modex+(dispmode-indirmode) if  adjustment # 0 -
       and  modex&2_111000 = indirmode
  finish 
  store(y,0)
  -> next
s(imm):
simm:
  y = litval(y)
  store(y>>16,0) if  size = 4
put:
  store(y,0)
  ->next
s(ximm):  !MOVEM (IMM,EA or EA,IMM)
  if  y > 0 start ;  !EA,IMM
    opcode = opcode!!16_0400
    i = x;  x = y;  y = i
    dx == dy;  modex = mode
  finish 
  y = litval(y)
  if  prea0 <= x <= prea7 start ;  !-(SP)
    i = 0;  !Reverse bits
    i = i<<1+y&1 and  y = y>>1 for  extword = 1,1,16
    y = i
  finish 
  ->put
s(data):
  opcode = dy_val
  ->next
s(*):
err:
  fault(moperr)
  ->next
end ;  !plant

routine  PLANTLIT(integer  op,v,x)
  if  v >= 0 start 
    if  v <= smallmax start 
      plant(op,-(v<<1),x)
      return 
    finish 
  else 
    if  v >= smallmin start 
      plant(op,v<<1+1,x)
      return 
    finish 
  finish 
  litstore(litmax) = v;  plant(op,litmax,x)
end 

routine  PLANTLIT2(integer  op,y,v)
  if  v >= 0 start 
    if  v <= smallmax start 
      plant(op,y,-(v<<1))
      return 
    finish 
  else 
    if  v >= smallmin start 
      plant(op,y,v<<1+1)
      return 
    finish 
  finish 
  litstore(litmax) = v;  plant(op,y,litmax)
end 

routine  ALIGN(integername  AD, integer  size)
!Impose alignment requirements on address AD for
! operand of length SIZE
!provisional basis for bit addressing
! -- multiples of 16 on Word boundary
! -- multiples of 8 on Byte boundary
! -- other < 32 within one Longword
!%constinteger BITMASK=16_E0000000
!  %if size&7 = 0 %start
!    ad = (ad&(\bitmask))+1 %if ad&bitmask # 0;  !ensure on byte boundary
!    %return %if size&8 # 0
!  %else
!    %return %if size < 16
!    %return %if ad>>29+(ad&1)<<3+size <= 32
!    ad = (ad&(\bitmask))+1 %if ad&bitmask # 0
!  %finish
  ad = ad+1 if  ad&1 # 0 and  size # 1
end 

routine  FORGET(integer  r)
  c_reg_content(r) = undef
end 
routine  REMEMBER(integer  r,v)
  c_reg_content(r) = v
  c_reg_part = c_reg_part&(\(16_0101<<(r-d0))) if  r < a0
end 
routine  PARTSET(integer  r,s)
  if  s = 1 then  c_reg_part = c_reg_part!16_0101<<(r-d0) -
  else  c_reg_part = c_reg_part!1<<(r-d0)
end 

routine  ADDIMM(integer  bytes,dest)
  if  bytes <= 0 start 
    return  if  bytes = 0
    if  bytes >= -8 start 
      plantlit(sub,-bytes,dest)
      return 
    finish 
  else  if  bytes <= 8
    plantlit(add,bytes,dest)
    return 
  finish 
  if  a0 <= dest <= a7 and  is short(bytes) start 
    plant(lea,tempd(dest,bytes),dest)
    return 
  finish 
  plantlit(add,bytes,dest)
end 

integer fn  FREE REG(integer  rset)
integer  r,r1
  r = d0;  rset = rset&free
  if  rset = 0 then  fault(plexerr) else  start 
    r = r+1 and  rset = rset>>1 while  rset&1 = 0
    r1 = r
    while  c_reg_content(r) # undef cycle 
      r = r+1;  rset = rset>>1
      r = r1 and  exit  if  rset = 0
      r = r+1 and  rset = rset>>1 while  rset&1 = 0
    repeat 
    free = free-1<<(r-d0)
  finish 
  result  = r
end 

routine  MOVE BLOCK(integer  source,dest,bytes)
!Generate code to move a fixed number of bytes
! from SOURCE (0,reg,pre,post) to DEST (pre,post)
! -- source & dest addresses both even if BYTES even
integer  op,f,r,pc1
  op = move;  op = clr if  source = 0
  if  bytes <= 16 and  bytes&1 = 0 start 
    plant(op,source,dest) and  bytes = bytes-4 while  bytes >= 4
    plant(op+2<<8,source,dest) if  bytes >= 2
  else ;  !use loop
    op = op+1<<8
    if  bytes&1 = 0 start 
      bytes = bytes>>1;  op = op+1<<8;  !.B -> .W
      if  bytes&1 = 0 start 
        bytes = bytes>>1;  op = op+2<<8;  !.W -> .L
      finish 
    finish 
    f = free
    if  bytes <= 32768 and  free&(anydreg-bregb) # 0 start 
      r = free reg(anydreg-bregb)
      plantlit(move,bytes-1,r)
      pc1 = pc
      plant(op,source,dest)
      plantlit2(dbra,r,(pc1-pc-1)<<1)
    else 
      r = free reg(anydreg)
      plantlit(move,bytes,r)
      pc1 = pc
      plant(op,source,dest)
      plant(sub,one,r)
      plantlit2(bne,0,(pc1-pc-1)<<1)
    finish 
    forget(r)                          {not worth noting}
!** why not FREE = F ? **
    free = free!1<<(r-d0)
  finish 
end 

routine  UPDATE SP
  return  if  c_val = 0
  if  c_val < 0 start 
    addimm(-c_val,a7);  c_sp = c_sp-c_val
  else 
    if  control&assmask = 0 then  addimm(-c_val,a7) {no unass check} -
    else  move block(d7,prea7,c_val)
    extend stack(c_val)
  finish 
  c_val = 0
end 

integer fn  LOWER(integer  t)
record (identinfo)name  tp
  tp == dict(t)
  result  = 0 if  tp_type = t # inttype {enum}
  result  = minint if  tp[1]_mode # litmode
  result  = tp[1]_val
end 

integer fn  UPPER(integer  t)
record (identinfo)name  tp
  tp == dict(t)
  result  = tp_size if  tp_type = t # inttype {enum}
  result  = maxint if  tp[2]_mode # litmode
  result  = tp[2]_val
end 

integer fn spec  size(integer  t)

integer fn  NSIZE(record (identinfo)name  dp)
  result  = 4 if  dp_flags&(name+indirect) # 0
  result  = 0 if  dp_flags&proc # 0;       ![??]
  result  = size(dp_type)
end 

routine  GET ARRAY INFO(record (identinfo)name  atp,
                       integer name  size,lo,hi)
  size = nsize(atp)
  lo = lower(atp_xtype);  hi = upper(atp_xtype)
end 

integer fn  SIZE(integer  t)
!Storage size for given object type in bytes
! > 0 for operand passable in register
! < 0 otherwise
integer  s,ss,lo,hi
record (identinfo)name  tp
  tp == dict(t)
  if  tp_flags&nonord = 0 start 
    result  = |tp_size| if  tp_type # t;  !subrange
    result  = 4 if  tp_type = inttype
    result  = 1 if  tp_size <= 255
    result  = 2
  finish 
  result  = tp_val if  tp_flags&cat = recy
  result  = tp_size if  tp_flags&cat # arry
  result  = 0 if  tp_mode >= framemode;  !dynamic bounds
  get array info(tp,s,lo,hi)
  result  = 0 if  lo = minint or  hi = maxint
  ss = (hi-lo+1)*s
  result  = ss if  ss <= 0
  if  s = 1 start ;  !byte element size (not nec aligned)
    result  = ss if  ss = 1
  else ;  !word,long element size (aligned)
    result  = ss if  ss <= 4
  finish 
  result  = -ss
end 

integer fn  REPSIZE(integer  t)
!Representation/size for loadable object of type T
! > 0 for signed, < 0 unsigned
record (identinfo)name  tp
  tp == dict(t)
  result  = size(t) if  tp_flags&nonord # 0  {not ordinal}
  result  = tp_size if  tp_type # t;  !subrange
  result  = 4 if  tp_type = inttype
 ! Enumeration
  result  = -1 if  tp_size <= 255   {unsigned byte}
  result  = 2                       {short - better than half}
end 

integer fn  TSIZE(integer  x)
  result  = 4 if  x <= 0 or  x >= explim
  result  = size(dict(x)_type)
end 

routine  FORGET CC
  c_reg_ccy = undef
end 
routine  FORGET REGS
short name  cc==c_reg_content(maxareg)
  cycle 
    cc = undef
    exit  if  cc == c_reg_content(d0)
    cc == cc[-1]
  repeat 
  c_reg_ccy = undef;  c_reg_line = -9
end 
routine  FORGET TRIPLES
  litpos = litmin;  explo = explim;  oldexplo = explim
end 
routine  FORGET ALL
integer  i,j
record (contentinfo)name  lr
  forget regs
  j = dictlim
  cycle 
    j = j+1
    exit  if  j >= curlab
    lr == lreg(j-dictlim)
    lr_content(i) = undef for  i = d0,1,maxareg
    lr_ccx = undef
  repeat 
  forget triples
end 

routine  DEFINE JUMPS(integer  chain)
integer  i,j,k
  chain = -chain
  return  if  chain <= 0;  !no jumps to this label
  c_forward = c_forward-1;  c_access = 1
  cycle 
    i = prog(chain)
    if  pflag(chain) = jump start ;  !shortenable
      j = chain-pflag(chain-1);  !adjusted jump position
      k = (pc-c_shorts-j)<<1;  !displacement
      if  k > 2 and  k <= 127 start 
        if  c_shorts = 255 start 
          zaps = zaps+100
        else 
          c_shorts = c_shorts+1;  shorts = shorts+1
          pflag(chain) = shortjump
          j = chain
          cycle 
            pflag(j) = pflag(j)+1 if  pflag(j) >= zeroshorts
            j = j+1
          repeat  until  j = pc
        finish 
      finish 
    finish 
    prog(chain) = pc
    chain = i
  repeat  until  chain <= 0
end 

routine  SAVE CONTEXT(integer  l)
!Store register content associated with label L
! (prior to generating forward branch)
integer  r
record (contentinfo)name  lr
  return  if  l-dictlim < 0  {user label}
  lr == lreg(l-dictlim)
  if  dict(l)_val >= 0 start ;  !first jump to this label
    dict(l)_val = 0
    lr = c_reg
    c_forward = c_forward+1
  else 
    lr_part = lr_part!c_reg_part
    for  r = d0,1,maxareg cycle 
      lr_content(r) = undef if  lr_content(r) # c_reg_content(r)
    repeat 
    lr_ccy = undef if  lr_ccx # c_reg_ccx or  lr_ccy # c_reg_ccy
    lr_line = -9 if  lr_line # c_reg_line
  finish 
end 

routine  SRCALL(integer  x)
routine  PUT PRIM(record (identinfo)name  DX)
!<
!* PRIMGEN marker 3
const short array  PRIMCODE(1:403) <- 
16_1541,16_7272,16_6179,16_2062,16_6F75,16_6E64,16_7320,16_6578,
16_6365,16_6564,16_6564,16_B098,16_6E06,16_9098,16_6C10,16_D0A0,
16_41FA,16_FFDE,16_2400,16_7202,16_7076,16_4EF8,16_3EFA,16_4A58,
16_660C,16_4840,16_4A40,16_6610,16_4840,16_C0D8,16_4E75,
16_2F01,16_2200,16_C2E8,16_FFFE,16_6008,16_2F01,16_2200,16_4840,
16_C2D0,16_4841,16_C0D8,16_D081,16_221F,16_4E75,
16_1355,16_6E61,16_7373,16_6967,16_6E65,16_6420,16_7661,16_7269,
16_6162,16_6C65,16_660C,16_41FA,16_FFE8,16_7201,16_7058,16_4EF8,
16_3EFA,16_4E75,
16_0F49,16_6E76,16_616C,16_6964,16_2061,16_6464,16_7265,16_7373,
16_6E0C,16_41FA,16_FFEC,16_7201,16_7058,16_4EF8,16_3EFA,16_4E75,
16_1553,16_7461,16_636B,16_2073,16_7061,16_6365,16_2065,16_7868,
16_6175,16_7374,16_6564,16_D88F,16_B8AD,16_017C,16_620E,16_4284,
16_41FA,16_FFDE,16_7203,16_7055,16_4EF8,16_3EFA,16_4284,16_4E75,
16_1741,16_7272,16_6179,16_2062,16_6F75,16_6E64,16_7320,16_696E,
16_7369,16_6465,16_206F,16_7574,16_9282,16_6F0C,16_41FA,16_FFE2,
16_7203,16_7055,16_4EF8,16_3EFA,16_4481,16_5281,16_4EF8,16_3EF4,
16_4E75,
16_0E53,16_7472,16_696E,16_6720,16_746F,16_6F20,16_6269,16_6780,
16_4281,16_1211,16_9001,16_6504,16_9010,16_640C,16_41FA,16_FFE2,
16_7203,16_7051,16_4EF8,16_3EFA,16_1018,16_670C,16_D111,16_1398,
16_1801,16_5201,16_5300,16_66F6,16_2049,16_4E75,
16_3F00,16_7001,16_1E80,16_204F,16_548F,16_4E75,
16_124E,16_6F20,16_7370,16_6163,16_6520,16_666F,16_7220,16_6172,
16_7261,16_7980,16_5680,16_E480,16_E588,16_6D0E,16_204F,16_91C0,
16_90FC,16_0100,16_B1ED,16_017C,16_6E0E,16_2400,16_41FA,16_FFD2,
16_7201,16_7072,16_4EF8,16_3EFA,16_205F,16_E488,16_6004,16_4840,
16_2F07,16_51C8,16_FFFC,16_4840,16_51C8,16_FFF4,16_4ED0,16_4E75,
16_1149,16_6E76,16_616C,16_6964,16_2025,16_666F,16_7220,16_6C6F,
16_6F70,16_2F00,16_9082,16_6720,16_2F01,16_6708,16_4EB8,16_3EEE,
16_4A80,16_6D0E,16_508F,16_41FA,16_FFD8,16_7201,16_7055,16_4EF8,
16_3EFA,16_4A81,16_66EE,16_221F,16_201F,16_4E75,
16_0C4F,16_7574,16_206F,16_6620,16_7261,16_6E67,16_6580,16_41FA,
16_FFF0,16_7201,16_7056,16_4EF8,16_3EFA,16_4E75,
16_1355,16_6E61,16_7373,16_6967,16_6E65,16_6420,16_7661,16_7269,
16_6162,16_6C65,16_B0FC,16_0000,16_6F1A,16_B2FC,16_0000,16_6F14,
16_BE10,16_6606,16_BE28,16_0001,16_670A,16_BE11,16_6612,16_BE29,
16_0001,16_660C,16_41FA,16_FFCA,16_7202,16_7054,16_4EF8,16_3EFA,
16_48E7,16_C0C0,16_4240,16_1018,16_6730,16_4241,16_1219,16_6722,
16_5380,16_5381,16_B041,16_6E12,16_9240,16_B109,16_56C8,16_FFFC,
16_6602,16_4441,16_4CDF,16_0303,16_4E75,
16_B109,16_56C9,16_FFFC,16_66F2,16_7201,16_4CDF,16_0303,16_4E75,
16_1011,16_4440,16_4CDF,16_0303,16_4E75,
16_0E53,16_7472,16_696E,16_6720,16_746F,16_6F20,16_6269,16_6780,
16_B010,16_640C,16_41FA,16_FFEA,16_7203,16_7051,16_4EF8,16_3EFA,
16_4280,16_1010,16_12D8,16_51C8,16_FFFC,16_4E75,
16_0E53,16_7472,16_696E,16_6720,16_746F,16_6F20,16_6269,16_6780,
16_B010,16_640C,16_41FA,16_FFEA,16_7201,16_7056,16_4EF8,16_3EFA,
16_C07C,16_00FE,16_221F,16_9EC0,16_558F,16_224F,16_BFC8,16_6F10,
16_1018,16_5289,16_D0C0,16_D2C0,16_1320,16_51C8,16_FFFC,16_6008,
16_1010,16_12D8,16_51C8,16_FFFC,16_204F,16_224F,16_2F01,16_4E75,
16_4A80,16_6F1C,16_B210,16_6218,16_43F0,16_1801,16_9280,16_6D10,
16_204F,16_2001,16_1121,16_51C9,16_FFFC,16_5280,16_1100,16_4E75,
16_41FA,16_0000,16_4E75,
16_700A,16_4EF8,16_3E70,16_4E75,
16_7020,16_4EF8,16_3E70,16_4E75

!<
integer  start,limit
record (identinfo)name  DDX
  fill code(1) if  cad&1 # 0
  start = dx_val>>16&511;  limit = start+dx_val&255
  dx_val = cad+dx_val>>7&(255<<1);  !entry
  dx_mode = procmode
  if  start = limit start ;  !range check
    ddx == dict(check)
    put prim(ddx) and  dx_val = cad if  ddx_mode = absmode
    set code word(16_0C80);  !CMPI.L #?,D0
    set code longword(dx[1]_val);  !lower
    set code word(16_6D00);  !BLT
    set code word(ddx_val-cad)
    set code word(16_0C80);  !CMPI.L #?,D0
    set code longword(dx[2]_val);  !upper
    set code word(16_6E00);  !BGT
    set code word(ddx_val-cad)
    set code word(16_4E75);  !RTS
  else 
    set code word(primcode(start)) and  start=start+1 until  start >= limit
  finish 
end 

record (identinfo)name  dx==dict(x),tp==dict(dx_type)
  if  dx_mode = absmode and  dx_val < 0 start ;  !prim routine
   ![**for now**: the convention is inadequate because excludes abs neg]
    put prim(dx)
  else 
    c_status = c_status!unknown if  tp_val <= 0
    c_totstack = c_sp-|tp_val| if  c_sp-|tp_val| < c_totstack
  finish 
  if  dx_mode&63 = pcmode start ;  !internal
    c_forward = c_forward+1 if  dx_flags&spec # 0 and  dx_flags&rflag = 0
    plant(bsr,0,x)
  else 
    plant(jsr,0,x)
  finish 
end ;  !srcall
!
routine  DEFINE LABEL(integer  lab)
integer  r,chain
record (contentinfo)name  lr
  chain = dict(lab)_val
  if  chain >= 0 start ;  !label before jumps
    update sp
    forget regs
  else 
    lr == lreg(lab-dictlim)
    if  c_access = 0 start ;  !no fall-through
      c_reg = lr;  !so just incoming context
    else ;  !join
      c_reg_part = c_reg_part!lr_part
      for  r = d0,1,maxareg cycle 
        forget(r) if  c_reg_content(r) # lr_content(r)
      repeat 
      forget cc if  c_reg_ccx # lr_ccx or  c_reg_ccy # lr_ccy
      c_reg_line = -9 if  lr_line # c_reg_line
    finish 
  finish 
  define jumps(chain)
  dict(lab)_val = pc
{?}  put operand(lab) if  control&codelist # 0 and  control&list # 0
end ;  !define label

routine  SET USER LABEL(integername  chain)
  update sp
  addimm(c_temps,a7) if  c_temps # 0 and  c_access # 0  {remove temps}
  define jumps(chain)
  chain = pc
  c_access = 1;  !anyway
  addimm(-c_temps,a7) if  c_temps # 0  {restore temps}
  forget regs
  forget triples if  curlab = c_lab1
end 

routine  FLUSH
  if  pendcond < 0 start ;  !indicator for line num update
    litstore(litpos) = line
    if  control&tracebit # 0 then  plantlit2(trapi,litpos,15) -
    else  if  line-c_reg_line > 8 then  plant(move+2<<8,litpos,lineloc) -
    else  plantlit(add+2<<8,line-c_reg_line,lineloc)
    forget cc;  c_reg_line = line
  else 
    if  pendout # 0 start 
      pendcond = pendcond&15
      c_access = 0 if  pendcond = 0
      if  pendcond # 1 start 
        save context(pendout)
        plant(bra+pendcond,0,pendout)
      finish 
    finish 
    define label(pendin) if  pendin # 0
  finish 
  pendcond = 0
end 

!!!!!!!!!!!!!!!!   Main code generation procedure  !!!!!!!!!!!!!!!!!!!!!

constinteger  INST=1<<30

routine  EVAL(integername  pp, integer  rset)
!Evaluate the operand identified by PP as defined by RSET:
!  RSET = boolean vector of acceptable registers
!  + SIGN to indicate that stopping at EA is acceptable
!  + 1<<16 to indicate only 8 bits needed
!  + 2<<16 to indicate only 16 bits needed
!  + STACK if stack ok [not fully yet: too complex]
constinteger  VAL=sign+anyreg, DVAL=sign+anydreg, REF=sign,
              SIZESHIFT=16,
              TO8=1<<sizeshift, TO16=2<<sizeshift, {4 not sig}
              TOSTACK=1<<19, ASAD=1<<20, MOD=1<<21

constinteger  ASL=32,
              CMPM=43,
              TRAPV=70,
              SWAP=74, EXTL=76,
              JMP=57, TST=59, DBNE=86, BTST=99
              
constinteger  MOVEW=move+2<<8, ADDW=add+2<<8,
              MOVEB=move+1<<8, ADDB=add+1<<8,
              SUBB=sub+1<<8, CMPB=cmp+1<<8,
              CMPMB=cmpm+1<<8

switch  DO(0:opmax)
owninteger  STSIZ=0;  !this variable is used to convey a
    !rarely required 3rd parameter to EVAL
    !Its value is captured into STSIZE on entry
    !A negative value indicates a string;
    ! a positive value a fixed length structure
    ! * CF normal use of negative/positive size *
integer  I,J,P,ACT,X,Y,XX,YY,WX,WY,SX,SY,R,OLDFREE,FREED
integer  M,V,SP,STSIZE,OP,CASE
record (identinfo)name  DP,DX,DY,TX

integer fn  FREE DREG
  result  = free reg(anydreg-bregb)
end 

integer fn  FREE AREG(integer  content)
integer  r
  r = free reg(anyareg)
  c_reg_content(r) = content
  result  = r
end 

routine  PUSH(integer  x)
  plant(move,x,prea7);  extend stack(4)
end 
routine  POP(integer  x)
  plant(move,posta7,x);  c_sp = c_sp+4
end 
routine  PUSHS(integer  x,s)
  s = s&3
  plant(move+s<<8,x,prea7)
  if  s # 0 then  extend stack(2) else  extend stack(4)
end 

routine  PUSH BLOCK(integer  areg,bytes)
  if  bytes <= 4 then  move block(areg+indir,prea7,bytes) -
  else  addimm(bytes,areg) and  move block(areg+pre,prea7,bytes)
  extend stack(bytes)
end 

routine  COMPILE UNCOND BRANCH(integer  l)
  if  pendcond # 0 start 
    if  pendcond < 0 start 
      pendcond = 0;  !ok?
    else  if  pendin # 0
      flush;                ![safe - improvable?]
    else 
      pendcond = pendcond!!1
      c_access = -2 if  pp+1 < np and  dict(pp+1)_act = else
    finish 
  finish 
  pendcond = pendcond&15
  c_access = 0 if  pendcond = 0
  plant(bra+pendcond,0,l) if  pendcond # 1
  pendcond = 0
end 

integer fn  CLEAN REG
integer  r
  free = free-bregb and  result  = breg if  free&bregb # 0
  r = free dreg
  plant(clr,0,r)
  result  = r
end 

integer fn  WEIGHT(integer  p)
!(Heuristic: can't anticipate all generation decisions)
integer  a,wy
record (identinfo)name  dp
  p = p-ad if  p >= explim
  result  = 1 if  p < np0
  dp == dict(p)
  a = dp_act
  result  = 1 if  a < 0
  result  = 999 if  a >= imul;  !funcall,mapcall
  wy = weight(dp_y)
  result  = wy if  wy >= 999
  result  = wy+weight(dp_x)
end 

routine  CHECK ADDRESS(integer  v)
  if  a0 <= v <= a7 then  plant(cmp+2<<8,0,v) else  plant(tst,0,v)
  srcall(adok)
  forget cc
end 

!!!!!!!!!!!!!!!!!!!  Procedure call  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!      _____ACT_________X__________Y____
! P -> | procident | param 1 | param 2 |
!      |     0     | param 3 | param 4 |
!      .           .         .         .
!
routine  CALL
!Load parameters following P and call procedure ACT (DX)
! Update PP for RCALL
integer  sp,stage,maxq

routine  EVAL PARLIST(integer  arg,q)
record (identinfo)name  darg,dv
integer  v,w,f,r,s
  return  if  arg = 0
  darg == dict(arg)
  q = q+1;  maxq = q if  q > maxq
  if  q&1 = 0 then  v = dict(p+q>>1)_x else  v = dict(p+q>>1)_y
  r = darg_reg&15;  s = size(darg_type)
  if  darg_val > 0 start ;  !passed on stack
    eval parlist(darg_link,q)
    return  if  stage # 0
    if  darg_flags < 0 start ;     !name
      f = free
!      eval(v,ref)
!      plant(pea,0,v);  extend stack(4)
      eval(v,anyareg)
      push(v)
      free = f
      return 
    finish 
    if  s > 0 start ;              !simple value
      f = free;  eval(v,val)
      pushs(v,s)
      free = f
    else ;                        !structure by value
      stsiz = s
      stsiz = -stsiz if  category(darg_type) # stringy
      eval(v,tostack)
    finish 
    return 
  finish 
  if  s <= 0 and  darg_flags >= 0 start 
    !structure by value -- ad in reg
    v = v-ad if  v >= explim
    if  v >= np0 start ;                     !actual is complex
      dv == dict(v)
      if  dv_act >= concat and  dv_mode = 0 start 
        !string/record function
        if  stage = 0 start 
          stsiz = s
          stsiz = -stsiz if  category(darg_type) # stringy
          r = v;  eval(r,tostack)
          free = free!a0b;  ![?here?]
          remember(a0,v+ad)
          dv_val = c_sp
          eval parlist(darg_link,q)
        else 
          eval parlist(darg_link,q)
          if  c_reg_content(r+d0) # v+ad start 
            dv_mode = c_mode
            plant(lea,v,r+d0)
            dv_mode = 0
          finish 
          free = free&(\(1<<r))
        finish 
        return 
      finish 
    finish 
    v = v+ad
  finish 
  w = weight(v)
  if  w >= 999 start 
    eval parlist(darg_link,q)
    return  if  stage # 0
  else 
    if  w >= 2 and  stage # 0 start 
      eval(v,1<<r)
      eval parlist(darg_link,q)
      return 
    finish 
    eval parlist(darg_link,q)
    return  if  stage = 0
  finish 
  eval(v,1<<r)
end 

  push(mb) if  dx_flags&proc2 # 0 -
           and  (dx_flags&ext = 0 or  dx_flags&spec # 0);  !param or external
  sp = c_sp
  maxq = 0
  stage = 0
  eval parlist(dict(dx_type)_link,-1)
  stage = 1
  eval parlist(dict(dx_type)_link,-1)
  srcall(act)
  if  c_sp # sp start 
    addimm(sp-c_sp,a7);  c_sp = sp
  finish 
  pop(mb) if  dx_flags&proc2 # 0 -
           and  (dx_flags&ext = 0 or  dx_flags&spec # 0)
  pp = p+maxq>>1 if  p < np;  !update for RCALL + RESOL
  forget regs
  c_reg_line = line if  dx_flags&(ext+proc) = ext+proc1;  !%system
end ;  !call
!
routine  STRUCTCALL(integer  entry,size)
  size = mite(-size-1) and  forget(breg) if  size <= 0;  !string
  plantlit(move,size,d0)
  srcall(entry)
  forget(d0)
end 

routine  PUSH STRUCTURE
  if  stsize <= 0 start ;               !string
    structcall(strtostk,stsize)
    forget(a0);  forget(a1);  forget(a0+2)
    extend stack(256-(stsize&254))
  else ;                               !fixed size structure
    push block(a0,(stsize+1)&(\1))
  finish 
end 

routine  COPY(integer name  r,integer  to)
integer  s=0
  if  r < a0 -
  and  c_reg_part&1<<(r-d0) # 0 start   {part reg}
    s = 2
    s = 1 if  c_reg_part&16_0100<<(r-d0) # 0
  finish 
  remember(to,pp)
  if  to < a0 start 
    partset(to,s) if  s # 0
    c_reg_ccx = pp;  c_reg_ccy = 0
  finish 
  plant(move+s<<8,r,to)
  r = to
end 

routine  OK AREG(integer  got,ok)
  r = got
  if  1<<(got-d0)&ok = 0 start 
    r = free reg(ok);  plant(move,got,r)
  finish 
end 

routine  LOAD ADDRESS(integer  p)
integer  i,f
  if  rset&anyareg&free # 0 start 
    if  dp_mode&2_111000 = indexmode and  dp_val&255 = 0 start 
      i = a0b<<(dp_mode&7)
      rset = i if  rset&free&i # 0
    finish 
    r = free reg(rset&anyareg)
    plant(lea,p,r)
  else 
    f = free
    i = free areg(p+ad);  plant(lea,p,i)
    free = f
    r = free reg(rset&(\bregb));  plant(move,i,r)
  finish 
end 

routine  COMMANDEER(integer  regs)
integer  r
  freed = \free&regs
  if  freed # 0 start 
    regs = freed;  r = d0
    while  regs # 0 cycle 
      push(r) and  forget cc if  regs&1 # 0
      regs = regs>>1;  r = r+1
    repeat 
    free = free!freed;  rset = rset&(\freed)
  finish 
end 
routine  RESTORE(integer  regs)
integer  r
  r = a7
  while  regs # 0 cycle 
    if  regs&16_8000 # 0 start 
      pop(r);  forget(r);  !*should have remembered it*
      forget cc
    finish 
    regs = regs<<1&16_FFFF;  r = r-1
  repeat 
end 

integer fn  LCR(integer  t1,t2)
!Lowest common representation size for loadable types T1 and T2
integer  r1=repsize(t1), r2=repsize(t2)
  result  = r1 if  r1 = r2
  if  r1 < r2 start 
    result  = r2 if  r1 > 0           {both signed: max}
    result  = r1 if  r2 < 0           {both unsigned: min}
    result  = r2 if  r2 > |r1|        {R2 signed, R1 unsigned}
    result  = |r1|<<1
  else 
    result  = r1 if  r2 > 0           {both signed: max}
    result  = r2 if  r1 < 0           {both unsigned: min}
    result  = r1 if  r1 > |r2|        {R1 signed, R2 unsigned}
    result  = |r2|<<1
  finish 
end 

routine  PARTREG
! Something smaller than integer has been loaded to R
! Determine what else to do (using SX,SY)
  while  |sy| < sx cycle 
    if  sy > 0 start ;  !signed
      plant(extl-2+sy,0,r);  !ext.w,ext.l
      sy = sy+sy
    else 
      if  sy = -1 start ;  !unsigned byte
        plantlit(and+sx<<8,255,r)
      else ;            !unsigned word (half)
        plantlit(and,16_FFFF,r)
      finish 
      sy = sx
    finish 
  repeat 
end 

!!Start of EVAL

  stsize = stsiz;  !additional parameter (for TOSTACK cases)
  p = pp;  p = p-ad if  p >= explim
  rset = rset-asad and  pp = p+ad if  rset&asad # 0
  if  p <= 0 then  dp == dint else  dp == dict(p)
  rset = rset&(\anyareg) if  rset&to8 # 0
  rset = rset&free if  rset&mod # 0
  oldfree = free;  freed = 0

if  rset # inst start 
  unless  dp_mode&2_110000 = 0 and  p < np0 start ;  !not already reg
    r = pp
    if  rset&(anydreg{+tostack}) # 0 start ;  !data reg acceptable
      i = d0
      cycle ;  !See if available
        r = i and  exit  if  c_reg_content(i) = r
        i = i+1;  i = a0 if  i = maxdreg+1
      repeat  until  i > maxareg
    else  if  rset&anyareg # 0;  !try address regs first
      i = maxareg
      cycle 
        r = i and  exit  if  c_reg_content(i) = r
        i = i-1;  i = maxdreg if  i = a0-1
      repeat  until  i < d0
    else  if  r < explim and  rset # tostack;  !REF: try for address
      i = a0
      cycle 
        if  c_reg_content(i) = r+ad start 
          free = free&(\(1<<(i-d0)))
          dp_flags = dp_flags!(rflag+wflag)
          pp = i+indir
          return 
        finish 
        i = i+1
      repeat  until  i > maxareg
    finish 
  else ;  !already reg
    r = dp_mode+d0;       !in case reg alias
    if  dp_flags >= 0 start    {value}
      fault(nonref) if  pp >= explim  {address wanted}
    else  if  pp < explim      {indirect value wanted}
      r = r+indir
      p = r and  -> fetch if  rset >= 0
    finish 
    pp = r and  return  if  rset = ref
  finish 

  if  0 < r <= a7 start ;  !operand (in) reg
    dp_flags = dp_flags!rflag
    if  r < a0 and  c_reg_part&1<<(r-d0) # 0 start  {partreg}
      sx = rset>>sizeshift&3;  sx = 4 if  sx = 0
      sy = 2;  sy = 1 if  c_reg_part&16_0100<<(r-d0) # 0
      if  sy < sx start 
        sy = -sy if  repsize(dp_type) = -sy  {unsigned,not extended}
        c_reg_ccx = pp;  c_reg_ccy = 0
        partreg
        c_reg_part = c_reg_part&(\(16_0101<<(r-d0)))
        c_reg_part = c_reg_part&(\(1<<(r-d0))) if  sy = 4
      finish 
    finish 
    -> endinr
  finish 

  if  p <= 0 start ;  !literal
    return  if  rset < 0
    if  rset = tostack start 
      i = constmode;  i = pcmode if  p = 0;  !null string [sneaky]
      plant(lea,temp(i,litval(p)),a0);           !A0 must be free
      forget(a0)
      push structure
      return 
    finish 
    if  pp < explim start ;  !normal value
      rset = rset&(\bregb) if  p < -(255<<1) or  p&1 # 0;  !0:255 ok
      r = free reg(rset)
      if  r < a0 or  p # 0 then  plant(move,p,r) -
      else  plant(sub,r,r)
    else ;                    !address within FINAL
      i = constmode;  i = pcmode if  p = 0;  !null string [sneaky]
      load address(temp(i,litval(p)))
    finish 
    c_reg_ccx = pp and  c_reg_ccy = 0 if  r < a0
    sy = 4
    ->endload
  finish 
finish 
  if  p >= np0 start ;  !complex
more:
    act = |dp_act|;  x = dp_x;  y = dp_y
    xx = x;  yy = y
    -> proccall if  act > opmax
    -> do(act)
  finish 

do(move):
load:
  i = 0
  i = i+1 if  dp_flags&indirect # 0
  i = i+2 if  dp_flags < 0
  if  pp >= explim start             {address wanted}
    if  i = 0 start 
      free = oldfree
      load address(p)
    else 
      if  i = 3 start               {indirect name}
        free = oldfree
        r = free areg(undef);  plant(move,p,r)
        p = r+indir
      finish 
      pp = p and  return  if  rset < 0
      free = oldfree
      r = free reg(rset&(\bregb));  plant(move,p,r)
    finish 
    c_reg_ccx = pp and  c_reg_ccy = 0 if  r < a0
    sy = 4
  else                               {value wanted}
    if  i > 0 start                  {indirection needed}
      free = oldfree
      r = maxareg+1
      cycle 
        r = r-1
        if  r < a0 start 
          r = free areg(p+ad)
          plant(move,p,r)            {direct move}
          plant(move,r+indir,r) if  i = 3
          check address(r) if  i > 1 and  control&assbit # 0
          exit 
        finish 
      repeat  until  c_reg_content(r) = p+ad
      free = free&(\(1<<(r-d0)))
      p = r+indir
    finish 
fetch:
    pp = p and  return  if  rset = ref
    sx = rset>>sizeshift&3;  sx = 4 if  sx = 0
    sy = size(dp_type)
    i = dp_flags
    if  c_localdpos <= p < dlim and  i&okflag = 0 and  c_forward = 0 start 
      !local, simple, always accessed
      if  i&wflag = 0 start ;  !unassigned
        report(asserr+warn,p,0) if  c_faults = 0
      finish 
      dp_flags = dp_flags+okflag if  dp_flags >= 0 and  sy > 0
    finish 
    if  rset = tostack start 
      free = oldfree
      plant(lea,p,a0);           !A0 must be free
      forget(a0)
      push structure
      return 
    finish 
    intern(5) and  return  if  sy <= 0
    i = i!okflag if  control&bassbit>>1<<sy = 0
    if  i&okflag # 0 and  rset < 0 start ;  !not necessary to load?
      if  sy = sx start ;  !same size
         pp = p
        return 
      finish 
    finish 
    free = oldfree
    if  i&okflag # 0 then  i = -1 else  i = sy
    sy = repsize(dp_type)                        {neg if UNsigned}
    if  sy = -1 start ;  !unsigned byte
      if  free&bregb # 0 start 
        if  rset&bregb # 0 start 
          rset = bregb
        else 
          plant(moveb,p,breg)
          forget(breg)
          p = breg;  sy = 4
        finish 
      finish 
    finish  else  rset = rset&(\bregb)
    if  sy < 2 or  sx = 1 start 
     ! Source unsigned or byte, or target 8 bits
      if  rset&anydreg = 0 start 
      !Can't load bytes,mites,halfs to address regs
      ! or store bytes from them
        r = free dreg
        plant(move+|sy|<<8,p,r)
        partreg
        p = r;  free = oldfree
      finish  else  rset = rset&(\anyareg)
    finish 
    if  sy = 2 and  rset&anyareg&free # 0 start 
      rset = rset&anyareg;  !prefer areg for word (auto-extend)
    finish 
    r = free reg(rset)
    if  r < a0 start 
      if  sy < 0 and  |sy| < sx and  r # breg -
      and  dict(p)_mode # r-d0 -
      and  (dict(p)_mode&2_111000 # indexmode or  dp_val>>12&15 # r-d0) start 
        plant(clr,0,r)
        plant(move+|sy|<<8,p,r);  sy = 4
      else 
        plant(move+|sy|<<8,p,r);  sy = 4 if  r = breg
      finish 
      c_reg_ccx = pp;  c_reg_ccy = 0
      partreg if  sy # 4
    else 
      plant(move+|sy|<<8,p,r);  sy = 4
    finish 
    if  i >= 0 start         {unassigned check required}
      plant(cmp+i<<8,r,d7)
      srcall(unass)
      forget cc
    finish 
  finish 
endload:
  remember(r,pp)
  partset(r,sy&3) if  sy&3 # 0
endload1:
  free = free&(\(1<<(r-d0)))
  r = r+indir if  rset = ref
  pp = r
  return 

dataload:
  eval(p,anydreg-bregb)
  r = p
!The operand has been evaluated into a (full) register
endloadr:
  free = oldfree
  remember(r,pp)
!The operand is in a register: is it ok?
endinr:
  if  rset&1<<(r-d0) = 0 and  rset # ref start   {not ok}
    if  rset&free = 0 and  rset&tostack # 0 start 
      push structure;  r = a7
  !    push(got);  r = a7
  !    c_reg_ccx = pp;  c_reg_ccy = 0
    else 
      copy(r,freereg(rset&(\bregb)))
    finish 
  finish 
  restore(freed)
  -> endload1

!!!!!!!!!!!!!!!!   Array   /   Record    /   Map   !!!!!!!!!!!!!!!!!!

routine  ADEVAL(integer  x,y,q)
!Base X, scaled index Y, displacement Q
integer  i,j
routine  LOAD AREG(integer  xx,for)
!Use the register component of M if alterable
! to avoid excessive dissipation of address registers
integer  i
  i = m&7
  if  oldfree&a0b<<i = 0 or  m > indexmode+7 start 
   ! Areg component not free or not Areg component
    i = free areg(for)
  else 
    free = free&(\(a0b<<i))
    i = i+a0;  remember(i,for)
  finish 
  return  if  xx = x and  m = i+(dispmode-a0) and  v = 0
  plant(lea,xx,i)
  m = i+(dispmode-a0);  v = 0
end 
  if  x <= 0 start ;  !%const
    m = constmode;  v = litval(x)
  else 
    eval(x,ref)
    m = dict(x)_mode;  v = dict(x)_val
    if  m = c_mode and  v < 0 start 
     !*Assertion: SP will have same value when address used
      m = dispmode+7;  v = v-c_sp
    else  if  m&2_111000 = indirmode
      m = m+(dispmode-indirmode)
    finish 
  finish 
  eval(y,anyreg) if  y # 0;  !subscript
  if  m&2_111000 = indexmode start ;  !X already involves index
    if  y = 0 start 
     !See if Q can be combined with existing disp
      j = mite(v)
      i = j+q
      if  is mite(i) start 
        v = v-j+i&255
        return 
      finish 
    finish 
    load areg(x,x+ad)
  finish 
  if  y # 0 start 
    if  m&63 = pcmode start 
      load areg(temp(m,v+q),undef)
      q = 0
    else  if  not  is mite(v+q);  !indexmode out
      if  not  is mite(q) start ; !& out even if V absorbed
        if  is short(v+q) start 
          load areg(temp(m,v+q),undef)
        else 
          load areg(x,undef)
          addimm(q,m&7+a0)
        finish 
        q = 0
      else 
        load areg(x,x+ad)
      finish 
    finish 
  finish 
  v = v+q
  if  y # 0 start 
    m = m+(indexmode-dispmode)
    v = (y-d0)<<12+16_0800+v&255
  finish 
end 

do(index):
!  P      => {index,ARRAY,SUBSCRIPT}
!  ARRAY  => ARRID
!         or {index,ARRAY,SUBSCRIPT}
!         or {recref,RECORD,ARRAY}
!  TYPE INFO : TYPE = ELTYPE, XTYPE = INDEX-TYPE
!              MODE,VAL = DOPE ADDRESS
  dx == dict(x)
  i = dx_type;                   !array type cell
  tx == dict(i)
  get array info(tx,m,sx,sy)
  m = |m|
 !ARRFLAG is set for either ABC requested or dynamic
  if  dx_flags&arrflag # 0 and  (y > 0 or  sx = minint or  m = 0) start 
    commandeer(d0b+d1b+a0b);  ![D1 ??]
   ! subscript
    eval(y,d0b)
   ! dope vector
    j = 0
    j = j+12 and  i = i+1 and  tx == dict(i) while  tx_mode = 0
    if  tx_flags&indirect # 0 start 
      plant(move,i,a0)
      addimm(j,a0) if  j # 0
    else 
      if  tx_val = 0 and  tx_mode = constmode start 
      ! dope info not yet created
        fill code(1) if  cad&1 # 0
        tx_val = cad
        set code longword(sy)
        set code longword(sx)
        set code longword(m)
      finish 
      plant(lea,i,a0)
    finish 
    srcall(index)
    forget(d0);  forget(a0)
    restore(freed&(\d0b))
    free = oldfree&(\d0b)
    freed = freed&d0b
    i = x;  eval(i,anyareg!mod!asad)
    plant(add,d0,i)
    if  dp_flags < 0 then  forget(i) {ad of ad of P} -
    else  remember(i,p+ad)
    free = free!d0b if  freed = 0
    restore(freed);  freed = 0
    m = i+(dispmode-a0);  v = 0
    -> setflags
  finish 
index1:
  !deal with subscript
  j = 0
  if  y <= 0 start ;  !literal subscript
    j = litval(y);  y = 0
  finish 
  if  y >= np0 and  dict(y)_act = add -
   and  dict(y)_y <= 0 start ;  !Y => {add,exp,lit}
    j = litval(dict(y)_y);  y = dict(y)_x
  finish 
  if  m > 1 start 
    if  y # 0 start 
      i = imul
      i = mulop(sx,sy,m,m) if  m&(m-1) # 0   {not power of 2}
      putexp(i,y,litref(m),inttype)
      y = item
    finish 
  finish 
  if  dx_flags&(name+ext+arrflag+indirect) = indirect and  sx # 0 start 
    dx_val = dx_val+4;  !0-based
    adeval(x,y,j*m)
    dx_val = dx_val-4
  else 
    j = j-sx;  j = j*m if  m > 1
    adeval(x,y,j);  !array,index,displacement
  finish 
setflags:
  dx_flags = dx_flags!(mflag+wflag+rflag);  !don't know
setmode:
![what about FRAMEMODE?]
  if  dispmode <= m < indexmode start 
    unless  isshort(v) start 
      ok areg(m+(a0-dispmode),oldfree&anyareg)
      addimm(v,r);  forget(r)
      m = r-(a0-dispmode);  v = 0
    finish 
    if  pp >= explim and  v = 0 and  rset # ref and  dp_flags >= 0 start 
    !address wanted, disp zero, as value, not name
    ! so the address is simply in the register
      r = m+(a0-dispmode)
      -> endloadr
    finish 
  finish 
  dp_mode = m;  dp_val = v
  ->load

do(recref):
!  P => {recref,RECORD,SUBEL}
  dx == dict(x)
  adeval(x,0,dict(y)_val);  !record,subscript,displacement
  ->setflags

do(storemap):
  v = 0
  if  y >= explim start 
    y = y-ad;  eval(y,ref)
    m = dict(y)_mode;  v = dict(y)_val
  else 
    if  y >= np0 start 
      if  dict(y)_act = add start 
        m = dict(y)_y
        y = dict(y)_x and  v = litval(m) if  m <= 0
!       eval(y,val) %if y >= dictlim
      finish ;! %else eval(y,val)
    finish 
    eval(y,anyareg)
    check address(y) if  control&assbit # 0 and  pp < explim
    m = y+(dispmode-a0)
  finish 
  -> setmode

do(lenref):
do(sindex):
  x = x-ad if  x >= explim
  dx == dict(x)
  if  y <= 0 start 
    adeval(x,0,litval(y))
  else 
    eval(y,anydreg);  adeval(x,y,0)
  finish 
  -> setflags

do(dnew):
  commandeer(c_free)
  plant(move,y,d0)
  srcall(act)
  forget regs
  c_reg_line = line
  -> endmap

do(dtostring):
proccall:
  dx == dict(act)
  -> rcall if  p < np
  -> funcall if  dx_flags&writable = 0
!mapcall
  commandeer(c_free)
  call
endmap:
  free = oldfree
  r = a0
  ok areg(a0,\freed&anyareg) if  rset # ref
  restore(freed);  freed = 0
  free = free&(\(1<<(r-d0)))
  remember(r,p+ad)
  m = r+(dispmode-a0);  v = 0;  !0(A?)
  ->setmode

funcall:
  commandeer(c_free)
  call
  r = dict(dx_type)_reg&15+d0
  c_reg_ccx = pp and  c_reg_ccy = 0 if  dx_flags&okflag # 0
  ->endloadr

rcall:
  flush if  pendcond # 0
  update sp
!<
  while  act = dprintstr and  x >= np0 and  dict(x)_act = concat cycle 
    dp_x = dict(x)_x;  !first of pair
    call;  free = c_free
    x = dict(x)_y;  dp_x = x
  repeat 
!<
  call
  c_access = 0 if  dx_flags&noret # 0
  forget triples if  pp+1 = np and  curlab = c_lab1 -
                 and  dict(curlab)_val >= 0 and  dict(curlab+1)_val >= 0
  return 

!!!!!!!!!!!!!!!!!!!!!!!!!   Operators   !!!!!!!!!!!!!!!!!!!!!!!!!!!

routine  EVALXY
  commandeer(d0b+d1b)
  if  999 > weight(x) < weight(y) start 
    eval(y,d1b);  eval(x,d0b)
  else 
    eval(x,d0b);  eval(y,d1b)
  finish 
end 

routine  STACKOP(integer  s)
  stsiz = s
  sp = c_sp
  eval(x,tostack)
  free = free!a0b
  eval(y,a0b+asad)
  plant(move,a7,a1);      !dest (stack)
  structcall(act,s)
  forget(a0);  forget(a1);  forget(a0+2)
end 

!<
do(prel):
!  P => {prel,BASENAME,INDEX}
  dx == dict(x)
  m = |size(dx_type)|
  sx = 0;  sy = 999999
  -> index1

!<

do(check):        !CHECK rangetype,value
  commandeer(d0b)
  eval(y,d0b)
  srcall(x)
  r = d0
  -> endloadr

routine  SWOP
  wx = weight(x)
  if  wx <= 1 and  y <= 0 and  y >= litmite and  rset&anydreg # 0 start 
    rset = rset&anydreg
    i = x;  x = y;  y = i
  else  if  999 > wx < weight(y)
    i = x;  x = y;  y = i
  finish 
end 
routine  LITYTOREG
!Bring 2nd operand to register if it can be done by MOVEQ
! [since MOVEQ + EA=dreg is shorter than EA=immediate-long]
  eval(y,anydreg) if  y < 0 and  y >= litmite and  free&(anydreg-bregb) # 0
end 
predicate  ISBYTE(integer  y)
  true  if  y <= 0 and  y >= -510 and  y&1 = 0
  false 
end 

![Note that all literal subtraction comes through as ADD]
do(add):
  if  control&overbit # 0 start 
    -> dataload if  rset&anydreg = 0
    rset = rset&anydreg
  finish 
  if  y < 0 start 
    if  y >= litquick start ;  !(ADDQ,SUBQ)
      y = y-1 and  act = sub if  y&1 # 0;  !'negate' if 'negative'
      eval(x,rset&free&(\bregb))
      oldfree = free
      ->opv
    finish 
    if  y = -(128<<1) start ;  !+128
      act = sub;  y = y+1;  !- -128 (MOVEQ)
      -> addop
    finish 
  finish 
  swop
addop:
  eval(x,rset&free&(\bregb))
  oldfree = free
  litytoreg
  eval(y,val)
opv:
  plant(act,y,x)
endopv:
  plant(trapv,0,0) if  control&overbit # 0
endop:
  free = oldfree
enduop:
  pp = x
  remember(x,p)
  c_reg_ccx = p;  c_reg_ccy = 0
  if  act>>8 # 0 start             {part-size added}
    forget cc                      {a bit extreme}
  finish 
  return 
do(sub):
  if  control&overbit # 0 start 
    -> dataload if  rset&anydreg = 0
    rset = rset&anydreg
  finish 
  -> addop
do(and):
  -> dataload if  rset&anydreg = 0
  swop
  eval(x,rset&free&anydreg)
  oldfree = free
  litytoreg
  if  y > d7 start 
    sy = tsize(y)
    if  sy <= 2 and  (isbyte(yy) or  x = breg) start 
      eval(y,dval+sy<<sizeshift)
      act = act+sy<<8
    finish  else  eval(y,dval)
  finish  else  eval(y,dval)
logop:
  plant(act,y,x)
  -> endop
do(or):
  -> dataload if  rset&anydreg = 0
  swop
  rset = rset&(\bregb) if  not  isbyte(y)
  eval(x,rset&free&anydreg)
  oldfree = free
  litytoreg
!  sy = tsize(y)
!  eval(y,dval+sy<
!  act = act+sy<<8
  eval(y,dval)
  -> logop
do(eor):
  -> dataload if  rset&anydreg = 0
  swop
  eval(x,rset&free&(anydreg-bregb))
  oldfree = free
  litytoreg
  eval(y,anydreg) if  y > d7
  -> logop

do(lsl): do(lsr):
  -> dataload if  rset&anydreg = 0
  eval(x,rset&free&(anydreg-bregb))
  oldfree = free
  if  y < 0 and  y >= litquick start 
    act = act!!(lsl!!lsr) and  y = y-1 if  y&1 # 0;  !negate if neg
  else 
    eval(y,anydreg)
  finish 
  -> logop

routine  SHORTOP
  eval(x,rset&free&(anydreg-bregb))
  oldfree = free
  eval(y,dval+to16)
end 

do(muls): do(mulu):
  -> dataload if  rset&anydreg = 0
  shortop
  -> opv

do(neg):
  if  y # 0 start 
    r = y;  y = x;  x = r
    act = sub
    -> do(sub)
  finish 
do(not):
  -> dataload if  rset&anydreg = 0
  eval(x,rset&free&(anydreg-bregb))
  plant(act,0,x)
  -> enduop
do(iabs):
  -> dataload if  rset&anydreg = 0
  x = y
  eval(x,rset&free&(anydreg-bregb))
  plant(move,x,x) if  c_reg_ccx # y or  c_reg_ccy # 0
  plantlit2(bge,0,2)
  plant(neg,0,x)
  oldfree = free
  ->endopv
do(fabs):
  -> dataload if  rset&anydreg = 0
  x = y
  eval(x,rset&free&(anydreg-bregb))
  plantlit(and,16_7FFFFFFF,x)
  ->enduop

routine  DO SHIFT
integer  i
  i = 0;  i = i+1 and  j = j>>1 until  j&1 # 0
  if  i = 1 then  plant(add,x,x) else  start 
    i = litref(i)
    eval(i,anydreg) if  i < litquick
    plant(asl,i,x)
  finish 
end 

do(imul):
  -> dataload if  rset&anydreg = 0
  rset = rset&(anydreg-bregb)
 !Test for power of 2 or pair of powers of 2
  if  y < 0 start 
    j = litval(y)
    i = j&(j-1)
    if  i = 0 or  i&(i-1) = 0 start 
      eval(x,rset&free)
      oldfree = free
      do shift if  j&1 = 0
      if  j # 1 start 
        plant(move,x,prea7)
        free = oldfree
        do shift
        plant(add,posta7,x)
      finish 
      ->endopv
    finish 
  finish 
do(fsub): do(fdiv):
do(ipow): do(fpow):
do(fadd): do(fmul):
  evalxy
  srcall(act)
  plant(trapv,0,0) if  act = imul and  control&overbit # 0
  forget(d1);  r = d0
  forget cc
  -> endloadr

do(idiv): do(drem):
  if  control&halfbit # 0 start 
    act = divs if  act = idiv
do(divs): do(divu):
    -> dataload if  rset&anydreg = 0
    shortop
    if  act = drem then  plant(divs,y,x) and  plant(swap,0,x) -
    else  plant(act,y,x)
    plant(extl,0,x)
    -> endop
  finish 
  evalxy
  srcall(idiv)
  putexp(act!!(idiv!!drem),xx,yy,inttype)
  if  act = idiv start 
    remember(d1,item);  r = d0
  else 
    remember(d0,item);  r = d1
  finish 
  forget cc
  ->endloadr

do(float):
do(fneg):
  commandeer(d0b)
  eval(x,d0b)
  srcall(act)
  forget cc
  r = d0
  ->endloadr

do(concat):      !not special case
![they have to be free]  commandeer(d0b+d1b+a0b+a1b)
  fault(plexerr) if  free&(a0b+a1b+d0b+d1b) # a0b+a1b+d0b+d1b
  stackop(-256)
endconc:
  if  rset&tostack = 0 start 
    if  c_sp # sp start 
      addimm(sp-c_sp,a7);  c_sp = sp
    finish 
  finish  else  rset = a0b
  r = a0
  ->endloadr

!!!!!!!!!!!!!!!!!!!!!   Conditions   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

routine  CONDSWOP
!Swop condition operands, adjusting operator accordingly
integer  temp
  temp = x;  x = y;  y = temp
  temp = xx;  xx = yy;  yy = temp
  temp = sx;  sx = sy;  sy = temp
  temp = wx;  wx = wy;  wy = temp
  case = case!!3 if  case&8 # 0;  !no change for '=','#'
end 

routine  UNSIGNED
  if  case&8 # 0 start ;  !no change for '=','#'
    case = case!!8
    case = case!!4 if  case&2 # 0
  finish 
end 

![Some confusion here of which operand (weightier) to evaluate first
![                   and which to bring to register
![EVAL improvements make possible greater finesse:
![               1. Decide which to evaluate first (weightier)
![               2. EVAL both 'val'
![               3. If either in register, OK
![               4. Load one
![*for IMP, conditions cannot be embedded in other expressions;
![*for Pascal, they can.  This needs improvement to cover that.
do(compare):
  flush if  pendcond # 0
  update sp
  sp = c_sp
  pp = pp+1;  dp == dp[1]
  case = dp_act
  if  x <= 0 start ;  ![1st literal: only for true,false]
    case = case!!1 if  x = 0;  !invert for false
    pendcond = case&1+bra
    -> endcomp
  finish 
  if  x >= explim start ;        !address
    dx == dict(x-ad);  sx = 4
  else 
    dx == dict(x)
    tx == dict(dx_type);  sx = size(dx_type)
  finish 
  dx_flags = dx_flags!rflag
  sy = tsize(y)
  m = 4
  if  sx > 0 and  sx < 4 start  {< 32 bits}
    if  y <= 0 start 
      m = repsize(dx_type)
    else  if  sy < 4
      m = lcr(dx_type,dict(y)_type)
    finish 
    unsigned if  m < 0
  finish 
  wx = 0 and  wy = 0 and  condswop if  c_reg_ccx = y and  c_reg_ccy = x
  if  c_reg_ccx # x or  c_reg_ccy # y start 
    if  y # 0 start ;  !not comparison with zero
      wx = weight(x);  wy = weight(y)
      condswop if  wy > wx < 999
      if  x >= explim or  y >= explim start ;  !one or other is address
        !swop if Y is not name (to use LEA)
        condswop if  0 <= y-ad < dictlim and  dict(y-ad)_flags >= 0
        eval(x,anyareg)
        eval(y,sign+anyareg)
        plant(cmp,y,x)
        c_reg_ccx = xx;  c_reg_ccy = yy
      else  if  sx > 0;  !simple operand
        if  tx_flags&cat = realy start 
          eval(x,d0b);  eval(y,d1b)
          srcall(fsub)
          forget(x)
          c_reg_ccx = xx;  c_reg_ccy = yy
        else  if  y < 0;         !comparison with literal
          eval(x,sx<<sizeshift+val)
         ! Bring Y to reg if (a) MOVEQ-able, long, and reg available
         !                or (b) X mode is pcmode (no use for CMPI)
          if  (y >= litmite and  sx = 4 and  free&(anydreg-bregb) # 0) -
          or  (x > a7 and  dx_mode&63 >= pcmode) start 
            eval(y,anydreg-bregb)
            condswop and  sx = sy unless  0 < x <= d7
          else 
            sx = 2 if  a0 <= x <= a7 and  is short(litval(y))
          finish 
          plant(cmp+sx<<8,y,x)
          c_reg_ccx = xx;  c_reg_ccy = yy
        else ;  !Y not literal
          condswop if  sy < sx
          eval(x,anyreg+|m|<<sizeshift)
!          %if sy <= 2 %and sy = sx %and (sy=1 %or x < a0) %start
            eval(y,val+|m|<<sizeshift)
            plant(cmp+|m|<<8,y,x)
!          %else
!            eval(y,val)
!            plant(cmp,y,x)
            c_reg_ccx = xx;  c_reg_ccy = yy
!          %finish
        finish 
      else ;            !structure
        stsiz = sx;  stsiz = -stsiz if  tx_flags&cat # stringy
        if  (case&8 = 0 and  control&strassbit = 0) -
        or  stringy # tx_flags&cat # sety start 
          !equals,notequals or rec,array
          if  wy >= 999 start ;  !both complex
            eval(x,tostack)
            eval(y,anyareg!mod!asad)
            x = freeareg(undef)
            plant(move,a7,x)
          else 
            eval(x,anyareg!mod!asad)
            forget(x)
            eval(y,anyareg!mod!asad)
          finish 
          i = free dreg
          if  tx_flags&cat = stringy start ;  !string comparison
            plant(clr,0,i)
            plant(moveb,x+indir,i)
          else 
            plantlit(move,-sx-1,i)
          finish 
          plant(cmpmb,x+post,y+post)
          plantlit2(dbne,i,-4)
          forget(i);  forget(y)
        else 
          if  wy >= 999 start ;  !both complex
            eval(x,tostack);  eval(y,a1b+asad)
            x = a0
            plant(move,a7,x)
          else 
            eval(x,a0b+asad);  eval(y,a1b+asad)
          finish 
!<
          srcall(scomp)
          unsigned
!<
        finish 
        forget cc
      finish 
    else ;  !comparison with zero
      if  sx <= 0 {structure} -
      or  (sx = 1 and  okmode(deaa,dx_mode&63)) {byte, TSTable} start 
        if  tx_flags&cat = stringy or  sx = 1 start 
          eval(x,ref)
          plant(tst+1<<8,0,x)
          forget cc;  !*for now*
          unsigned
        else 
          eval(x,anyareg!mod!asad)
          i = free dreg
          plantlit(move,-sx-1,i)
          plant(tst+1<<8,0,x+post)
          plantlit2(dbne,i,-4)
          forget(i);  forget(x)
        finish 
      else  if  np0 <= x < explim and  dx_act = and -
            and  case&8 = 0 and  onebit(dx_y) # undef
       ! Testing one bit =0 or <>0
        y = onebit(dx_y)
        eval(y,anydreg) if  y > 0
        x = dx_x
        sx = tsize(x)
        if  sx = 1 or  y <= 0 then  eval(x,sx<<sizeshift+dval) -
        else  eval(x,sx<<sizeshift+anydreg)
        plant(btst+sx<<8,y,x)               {NB size}
        c_reg_ccx = xx;  c_reg_ccy = 0
      else 
        eval(x,anydreg)
        if  c_reg_ccx # xx or  c_reg_ccy # 0 start 
          plant(move,x,x);  c_reg_ccx = xx;  c_reg_ccy = 0
        finish 
      finish 
    finish 
  finish 
  pendcond = case
endcomp:
  pendin = dp_x;  pendout = dp_y
checksp:
  if  c_sp # sp start 
    addimm(sp-c_sp,a7);  c_sp = sp
  finish 
!<
  return 

do(resolves):
  flush if  pendcond # 0
  update sp
  sp = c_sp
!  push(mb)
!  eval(x,a0b+asad);  !string to be resolved
!  act = dict(y)_act;  x = dict(y)_x;  y = dict(y)_y
!  eval(x,a1b);  eval(act,a0b<<2);  eval(y,a0b<<3);  !match, fore, aft
!  srcall(resolves)
!  pop(mb)
!  forget regs
  dx == dict(act)
  call
  pp = pp+2;  dp == dict(pp)
  pendcond = dp_act
  -> endcomp

!<
!!!!!!!!!!!!!!!!!!!!!!!!   Assignment   !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
predicate  EASY(integer  y)
! Determine if structure assignment can be done by store-to-store op(s)
!  and if so, do it.
integer  r1,f
record (identinfo)name  dy
owninteger  s=0
  false  if  y < np0
  dy == dict(y)
  false  if  dy_act > concat or  dy_act = prel
  f = free
  if  dy_x = x start ;  !recursion ends, successfully
    s = tsize(x);  s = -s if  dy_act # concat;  !+ve unless string
    eval(x,a1b+asad)
  else 
    false  if  dy_y >= np0 or  dy_y = x -
    or  not  easy(dy_x)
  finish 
  y = dy_y
  if  y >= np0 and  dict(y)_act = dtostring start 
    y = dict(y)_x;  eval(y,to8+dval);  !character value
    r1 = clean reg
    plant(addb,one,x+indir);              !inc length(dest)
    plant(moveb,x+indir,r1)
    plant(moveb,y,tempx(x,r1));          !append char
    forget(r1)
  else 
    eval(y,a0b+asad)
    structcall(dy_act,s)
    forget(a0);  forget(a1)
    forget(d1);  forget(d2)
  finish 
  free = f&(\a1b)
  true 
end 

routine  BEWARE(integer  dest)
![not foolproof: ?too expensive to do properly
!                 too inefficient to fail safe]
integer  r,d
predicate  UNSAFE(integer  p)
![a bit cavalier]
  cycle 
    true  if  p = dest or  p = d {%or d >= np0
    %false %if p <= undef;        !literal, basereg or undef
    p = p-ad %if p >= explim
    %false %if p < np0
    %true %if dict(p)_act > opmax;  !funcall,mapcall
    %true %unless dest # dict(p)_y < np0
    p = dict(p)_x
  %repeat
%end
  forget(dest) %and %return %if dest <= a7
  d = dest;  d = d-ad %if d >= explim
  %for r = d0,1,maxareg %cycle
    forget(r) %if r = dest %or unsafe(c_reg_content(r))
  %repeat
  forget cc %if unsafe(c_reg_ccx) %or unsafe(c_reg_ccy)
%end

%routine TOSTORE(%integer act,y)
! Global XX, X, SX, WX, DX
  %if y <= 0 %start             {literal}
    eval(x,ref)
    if  y # 0 start             {except for NEG,NOT}
      if  act&(\1) = add or  (act&(\1) = lsl and  x <= d7) start 
        if  y >= litquick start ;  !-8:-1 or 1:8
          act = act+1 and  y = y-1 if  y&1 # 0;  !negate if neg
          -> past
        finish 
        act = act+1 and  y = y+1 if  y = -(128<<1);  !128=>-128
      finish 
      eval(y,anydreg) if  y >= litmite and  sx&3 = 0 -
                      and  free&(anydreg-bregb) # 0
    finish 
  else  if  x <= a7 {reg}
    eval(y,val)
  else 
    if  999 > wx < weight(y) then  eval(y,anydreg) and  eval(x,ref) -
    else  eval(x,ref) and  eval(y,anydreg)
  finish 
past:
  plant(act+sx<<8,y,x)
  plant(trapv,0,0) if  control&overbit # 0 and  act <= sub
  beware(xx)
  c_reg_ccx = xx;  c_reg_ccy = 0
end 

routine  REGASSIGN(integer  v)
! Global X, SX
integer  f,b,vv
record (identinfo)name  dp
predicate  XFREE(integer  y)
record (identinfo)name  dp
  cycle 
    y = y-ad if  y >= explim
    true  if  y <= 0
    dp == dict(y)
    exit  if  y < dictlim                {simple operand}
    false  if  not  xfree(dp_y) and  |dp_act| # recref
    y = dp_x
  repeat 
  false  if  dp_mode&63+d0 = x           {same as LHS reg}
  true 
end 
  f = free;  b = 1<<(x-d0)
  vv = v;  vv = vv-ad if  vv >= explim
  if  vv >= dictlim start                {complex}
    dp == dict(vv)
    if  xfree(dp_y) or  |dp_act| = recref start 
      free = free!b
    else 
      free = free&(\b)
    finish 
    if  |dp_act| <= cmp or  (|dp_act| <= divu and  x < a0) start 
      dp_y = x and  free = free!b if  dp_y = dp_x
      if  free&b # 0 start 
        regassign(dp_x)
        free = free&(\b)
        tostore(dp_act,dp_y)
        free = f
        return 
      finish 
    finish 
    eval(v,val) if  free&b = 0
  else 
    return  if  vv > 0 and  dict(vv)_mode&63+d0 = x
  finish 
  free = free!b
  eval(v,b)
  free = f
end 

!<
do(forass):  !FORASS:loopvar:start'
             ! --   :inc    :end
  eval(y,d0b)
  pp = pp+1;  dp == dp[1]
  i = dp_x;  eval(i,d1b);  i = dp_y;  eval(i,d2b)
  srcall(forok)
!<= explim %start;  !ad of ...
    wx = weight(xx-ad)
    dx == dict(xx-ad)
    sx = 4
  %else
    wx = weight(xx)
    dx == dict(xx)
    sx = size(dx_type)
  %finish
  tx == dict(dx_type)
  sp = c_sp-c_val
  %if sx <= 0 %start;  !structure assignment
    !Structure
    ![for rec/string assignment beware corruption of stacked
    ! structure in computing DEST]
    update sp
    %if tx_flags&cat = stringy %start
      sx = -256 %if sx = 0;   !string(*)
      op = -1;  op = dict(y)_act %if y >= np0
      %if y = 0 %start;  !""
        eval(x,ref)
        plant(clr+1<<8,0,x)
      %else %if op = dtostring
        y = dict(y)_x
        eval(y,to8+dval);  !character value
        eval(x,anyareg!mod!asad)
        plant(moveb,one,x+post)
        plant(moveb,y,x+indir)
        forget(x)
        forget cc
      %else %if act = jamass %or %not easy(y)
        %if op >= concat %and wx > 1 %start
        ! Danger of corruption of RHS
          stsiz = sx
          eval(y,tostack)
          free = free!a0b
          eval(x,a1b+asad)
          plant(move,a7,a0);  y = a0
          structcall(strcopy,sx)
        %else %if act # assign %or sx = -256 %or control&capbit = 0
        ! No check needed
          %if wx > 1 -
          %then eval(x,anyareg!mod!asad) %and eval(y,anyareg!mod!asad) -
          %else eval(y,anyareg!mod!asad) %and eval(x,anyareg!mod!asad)
!not worth %if sx >= -4 %and act # jamass %start
!            %cycle
!              plant(moveb,y+post,x+post)
!              sx = sx+1
!            %repeat %until sx >= 0
!          %else
            i = free reg(anydreg)
            %if act = jamass %start
              plantlit(move,mite(-sx-1),i)
              plant(moveb,i,x+post)
              plant(cmpb,y+post,i)
              plantlit2(bcs,0,6);     ! 3 2-byte instructions **
              plant(sub,one,x)
              plant(moveb,y+pre,i)
            %else
              plant(moveb,y+indir,i);   !length (dirty OK) [2 bytes]
            %finish
            plant(moveb,y+post,x+post)
            plant(subb,one,i)
            plantlit2(bcc,0,-6)
            forget(i)
!          %finish
        %else
          %if wx > 1 %then eval(x,a1b+asad) %and eval(y,a0b+asad) -
          %else eval(y,a0b+asad) %and eval(x,a1b+asad)
          structcall(strcopy,sx)
        %finish
        forget(x);  forget(y)
        forget cc
      %finish
    %else %if %not easy(y)
      eval(x,anyareg&free+asad) %if y = 0 %or wx > 1
      %if y # 0 %start
        sx = tsize(y) %if sx = 0
        eval(y,anyareg!mod!asad)
        forget(y)
        y = y+post
        eval(x,anyareg!mod!asad) %if wx <= 1
      %finish
      forget(x)
      %if sx = 0 %then fault(sizerr) %else move block(y,x+post,-sx)
    %finish
    beware(xx)
    -> checksp
  %finish
!Simple operand
  %if c_val # 0 %start
    %if dx_mode = c_mode -
    %and (dx_val = sp %or (dx_val+sx = sp+c_val %and y <= 0)) %start
    ! current frame -- last or first in pending stack extension
      c_val = (c_val-sx)&(\1)
      update sp %if dx_val = sp
    %finish %else update sp
  %finish
  op = move
  %if sx # 4 %and act = assign %and control&capbit # 0 %start
    eval(y,d0b)
    srcall(dx_type);  !range check
  %finish
  %if dx_mode&2_110000 = 0 %start;  !explicit assignment to reg
    x = dx_mode+d0
    regassign(y)
    c_reg_ccx = xx %and c_reg_ccy = 0 %if x <= d7
  %else
    case = val;  case = case+sx<= explim
    %if i >= np0 %start                        {RHS complex}
      %if dx_flags&okflag # 0 %or control&bassbit>>1<= explim %start
!          %if dy_act = prel %and dy_x = x-ad -
!          %and (dy_y < 0 %or dy_type = bytetype) %start
!            y = dy_y
!            y = litref(litval(y)*|size(dy_type)|) %if dy_type # bytetype
!            tostore(add,y)
!            -> endass
!          %finish
!        %else
          %if dy_x = x -
          %and (0 <= dy_act < neg %or (dy_act = neg %and dy_y = 0)) %start
            tostore(dy_act,dy_y)
            -> endass
          %finish
        %finish
!      %finish
      %if wx < 999 %then eval(y,case) %and eval(x,ref) -
      %else eval(x,ref) %and eval(y,case)
    %else                                  {RHS simple}
      eval(x,ref)
      %if y <= 0 %start;  !literal
        %if y = 0 %and dx_flags&readable # 0 %start
          op = clr
        %else %if y >= litmite %and sx = 4 %and free&(anydreg-bregb) # 0
          eval(y,anydreg)
        %finish
      %else
        eval(y,case)
      %finish
    %finish
    %if 0 < y <= maxareg %and 0 < yy = c_reg_content(y) %start
      beware(xx)
      c_reg_content(y) = xx   {'part' as was}
    %finish %else beware(xx)
    plant(op+sx<<8,y,x)
    c_reg_ccx = xx;  c_reg_ccy = 0
  %finish
endass:
  dx_flags = dx_flags!okflag %if c_localdpos <= xx < dictlim -
           %and c_forward = 0
  %return

do(incass):  !(for %for loop)
  flush %if pendcond # 0
  dx == dict(xx)
  sx = size(dx_type)
  wx = weight(x)
  tostore(add,y)
  ->endass


!!!!!!!!!!!!!!!!!!!!!!   Returns and jumps   !!!!!!!!!!!!!!!!!!!!!!!!
!
do(return):                 !terminate procedure
  update sp
  %if c_type # 0 %start;       !function,map
    r = dict(c_dpid_type)_reg&15
    %if c_type > 0 %and size(c_type) > 0 %start;  !simple fn
      flush %if pendcond # 0 %and pendin # 0
      i = y
     ![Tested here to avoid flush if no inst needed]
      %if c_reg_content(r+d0) # y -
      %or (r < a0 %and c_reg_part&1< 0;  !ie struct fn
      sp = c_sp
      eval(y,1< 0 %and pendin # 0
  save context(y) %if y # x;  !exit not continue
  compile uncond branch(y)
  %return

do(repeat):
  update sp
  compile uncond branch(x)
  define label(x+1) %if dict(x+1)_val < 0
  %if y < 0 %start;  !temp(s) declared
    c_val = y;  c_temps = c_temps+y;  !decrement temps
    update sp
  %finish
  %return

do(else):
  %if c_access # 0 %and c_access # -2 %start
    save context(y)
    compile uncond branch(y);  !outward branch for %else
  %finish
  define label(x) %if x # 0 %and dict(x)_val < 0;  !inward from false cond
  %return

do(goto):                        !user jump
  update sp
  c_forward = c_forward+1 %if dict(y)_val = 0
  addimm(c_temps,a7) %if c_temps # 0
  i = pendcond
  compile uncond branch(y)
  addimm(-c_temps,a7) %if i # 0 %and c_temps # 0
  %return

do(label):
  update sp
  define label(x)
  %return

do(stop):
  update sp
  flush %if pendcond # 0
  plant(clr,0,d0)
  srcall(signal)
  c_access = 0
  %return

do(signal):
  update sp
  flush %if pendcond # 0
  sp = c_sp
  pp = pp+1;  dp == dp[1]
  xx = dp_x;  yy = dp_y
  x = litval(x)
  %if yy # undef %start
    eval(yy,a0b+asad);  x = x+64
  %finish
  %if xx # undef %start
    eval(xx,d2b);  x = x+32
  %finish
  %if y # undef %start
    eval(y,d1b);  x = x+16
  %finish
  x = litref(x)
  eval(x,d0b)
  %if control&sysbit # 0 %then plant(jmp,0,signal) %else plant(jsr,0,signal)
  %if c_sp # sp %start;  ![earlier?]
    addimm(sp-c_sp,a7);  c_sp = sp
  %finish
  c_access = 0
  %return

do(settrap):
  update sp
  push(d0+6);                     ![historical]
  push(mb)
  plant(pea,0,temp(pcmode,10));  !address of mask [2+2+2+4]
  c_sp = c_sp-4
  push(gb+indir);                ![2 bytes]
  plant(move,a7,gb+indir);       ![2 bytes]
  c_eventsp = c_sp
  c_forward = c_forward+1
  lreg(c_lab1-dictlim) = c_reg;  !regs for %finish
  plant(bra,0,c_lab1);           ![4 bytes]
  pflag(pc-1) = longjump;  !**not to be shortened
  forget regs
  plant(dc,0,temp(absmode,litval(y)));  !event mask
!  store(litval(y),0);  !event mask
  %return

do(swgoto):                     !switch jump
  flush %if pendcond # 0
  update sp
  dx == dict(x)
  dx_flags = dx_flags!rflag
  dy == dict(dx_type)
  get array info(dy,i,sx,sy)
  i = dx_val;  !start of table
  %if y <= 0 %start;  !literal subscript
    y = litval(y)
    i = i+y-sx
    addimm(c_temps,a7) %if c_temps # 0
    plant(bra,0,temp(labmode,prog(i)))
    prog(i) = dtemp_val;               !updated by PCREL
  %else
    eval(y,d0b)
    %if i > pc %start;                  !first jump (I >= SWPC)
      c_forward = c_forward+(sy-sx+1)
      %if dx_flags&arrflag = 0 %start;  !no check
        addimm(c_temps,a7) %if c_temps # 0
        plant(lea,temp(pcmode,10-sx-sx),a0); !LEA ?(PC),A0
        plant(add,d0,d0);                 !ADD D0,D0
      %else
        wx = 12
        %if c_temps # 0 %start
          wx = wx+2;  wx = wx+2 %if c_temps > 8
        %finish
        plant(lea,temp(pcmode,wx),a0)
        srcall(index)
        addimm(c_temps,a7) %if c_temps # 0
      %finish
      plant(add+2<<8,tempx(a0,d0),a0); !ADD.W 0(A0,D0),A0
      plant(jmp,0,a0+indir);         !JUMP (A0)
      %if dx_flags&arrflag # 0 %start
        store(sy>>16,0);  store(sy,0)
        store(sx>>16,0);  store(sx,0)
        store(0,0);  store(2,0)
      %finish
      dx_val = pc
      %cycle
        store(prog(i),0)
        swpc = swpc+1 %if i = swpc;  i = i+1
        sx = sx+1
      %repeat %until sx > sy
    %else;  !just branch to earlier sequence
            ![gives wrong line number for error]
            ![wrong if temps]
      i = i-7 %if dx_flags&arrflag # 0
      plant(bra,0,temp(labmode,i-6))
    %finish
  %finish
  c_access = 0
  %return

do(asize):
  %if y # 0 %start;  !first: prime D0
    update sp
    eval(y,d0b);  !basic itemsize
  %else
    srcall(asize)
  %finish
  pp = pp+1;  dp == dp[1]
  xx = dp_x;  yy = dp_y
  free = c_free&(\d0b);  !not d0
  eval(xx,d1b);  !lower
  eval(yy,d2b);  !upper
  push(d0);  !size
  push(d1);  push(d2)
  forget regs
  free = free!(d1b+d2b)
  dict(x)_val = c_sp
  %return
!
do(adok):  ![spare code]
!Push size of dynamic array (& 0-base value) for AGET
  update sp
  %if x # 0 %start
    %if x # d0 %then eval(x,d0b) %else srcall(asize)
  %finish
  push(y) %if y # 0
  push(d0)
  %return

do(aget):
  plant(move,x,d0)
  srcall(aget)
  plant(move,a7,x)
  %if y # 0 %start
    dx == dict(x)
    dx_val = dx_val+4
    plant(move,a7,d0)
    plant(add,d0,x)
    dx_val = dx_val-4
  %finish
  forget(d0);  forget(a0)
  %return

%routine COMPILE ENTRY(%integer linked,arg)
!Entry sequence generated at end
%integer i,r,vsp,lastvsp,holdsp
%record(identinfo)%name darg,tp
  holdsp = c_sp
  c_sp = 0;  lastvsp = 0
  c_stack = c_stack-4 %if linked > 0;  !allow for link
  %if linked = 0 %and c_status&onstack # 0 %start
    !justify addressing assumed for onstack parameters
    c_sp = 4;  holdsp = holdsp-4;  c_stack = c_stack-4
  %finish
  c_stack = c_stack-4;              !and return address
  c_totstack = c_stack %if c_stack < c_totstack
  %if control&stackbit # 0 -
  %and (c_status&unknown # 0 %or c_totstack < -128) %start
    plantlit(move,c_stack,breg);  !*ok - gets cleared*
    srcall(stackok)
  %finish
  %if level > 0 %and linked > 0 %start;  !link required
    %if level > 1 %start
      plant(move,tempd(gb,level<<2),prea7);  !MOVE ?(GB),-(SP)
      plant(move,a7,tempd(gb,level<<2));  !MOVE SP,?(GB)
    %else
      plant(link,0,f1);       !LINK #0,Ax
    %finish
  %finish
  darg == dict(arg)
  %cycle
    arg = darg_link
    %exit %if arg = 0
    darg == dict(arg)
    %if darg_val <= 0 %and darg_mode&2_110000 # 0 %start
    ! Passed in reg, not on stack, and not reg
      vsp = darg_val
      r = darg_reg&15+d0
      %if darg_flags&mflag # 0 %or linked > 0 %start
        addimm(lastvsp-c_sp,a7);  c_sp = lastvsp
        i = nsize(darg)
        %if i > 0 %start
          ! name or simple operand by value
         !NB MOVE.B transfers to hi byte
          plant(move+i<<8,r,prea7)
        %else %if darg_flags&proc # 0;  !proc as param
          plant(move,r,prea7)
          plantlit(movew,16_4EF9,prea7); !JMP
        %else;                          !structure by value
          tp == dict(darg_type)
          fault(plexerr) %if free&bregb = 0
          %if tp_flags&cat = stringy %start
            %if control&capbit # 0 %and tp_size > -256 %start
              plantlit(cmp+1<<8,-tp_size,r+indir)
              plantlit2(bcs,0,4)
              srcall(check)
            %finish
            i = c_sp-vsp
            addimm(-i,a7);            !SP = SP-bytes
            extend stack(i)
           !MOVE.B length,Dx
            plant(moveb,r+indir,breg)
           !MOVE.B 0(Ay,Dx),0(SP,Dx)
            plant(moveb,tempx(r,breg),tempx2(a7,breg))
            plant(subb,one,breg)
            plantlit2(bcc,0,-10)
          %else;  !fixed length structure
            free = bregb
            push block(r,c_sp-vsp)
          %finish
        %finish
        c_sp = vsp
      %finish
      lastvsp = vsp
    %finish
  %repeat
  %if c_sp # 0 %start;  !there are accesses to params
    addimm(lastvsp-c_sp,a7)
    c_sp = holdsp
  %finish %else c_sp = holdsp-lastvsp;  !reduce
%end

do(end):
  compile entry(c_status&globbed,c_dpid_type)
  %return

do(*): intern(8)
do(0):  !null action
%end;  !eval

%routine COMPILE(%integer startp)
%integer p
{?}  show exp(startp) %if control&explist # 0 %and control&list # 0
  np = np0 %and %return %if faultnum > 0
  pendcond = 0
  p = startp-1
  %cycle
    free = c_free
    p = p+1
    %if p >= np %start
      %if startp = np0 %start
        np = np0
        flush %if pendcond > 0
        %return
      %finish
      np = startp;  startp = np0;  p = startp
    %finish
    %if c_reg_line # line %and control&(tracebit!linebit) # 0 %start
      flush %if pendcond > 0
      forget cc;  pendcond = -1
    %finish
    eval(p,inst)
  %repeat
%end;  !compile

%routine SET FIRST ENTRY
%integer j,k,p
%record(identinfo)%name dp
  firstpos = dictlim;  firstentry = finalbound
  p = 0
  %cycle
    p = p+1
    %exit %if p >= dlim
    dp == dict(p)
    %continue %if dp_mode # procmode
    %continue %if dp_val >= firstentry
    j = dp_val
    %if j <= 0 %start;         !procedure not yet encountered
      %continue %if j = 0
      k = -j;                  !find earliest (first) call
      %cycle
        j = k<<1
        k = code word(j)&16_FFFF
      %repeat %until k = 0
      %continue %if j >= firstentry
    %finish
    firstentry = j;  firstpos = p
  %repeat
%end

%routine DEFINE ENTRY(%integer chain,entry,pid)
%integer j
  %cycle
    chain = chain<<1
    report(reacherr,pid,0) %unless is short(entry-chain)
    j = code word(chain)&16_FFFF
!$IF VAX
{  final(chain) <- (entry-chain)>>8;  final(chain+1) <- entry-chain
!$IF APM
  shortinteger(final0+chain) <- entry-chain
!$FINISH
    chain = j
  %repeat %until chain = 0
%end

%routine CHECK REACH(%integer blocksize)
!Add stepping stones if necessary
%integer i
  %cycle
    i = blocksize+cad
    croak("Program too big") %if i >= initbase
    %return %if i-firstentry < 31000;  !enough leeway
    %return %if blocksize >= 32000 %or cad-firstentry >= 32760;  !hopeless
    %if dict(firstpos)_val < 0 %start
      define entry(-dict(firstpos)_val,cad,firstpos)
      set code word(16_6000);  !BRA
      dict(firstpos)_val = -cad>>1
      set code word(0)
    %else
      dict(firstpos)_val = cad
      set code word(16_6000);  !BRA
      set code word(firstentry-cad)
    %finish
    steps = steps+2
    set first entry
  %repeat
%end

%routine PUT WORD(%integer v)
    printsymbol(v>>8&255);  printsymbol(v&255)
%end

%routine DO EXTERNALS(%integer chain,specs)
%integer k,t,a,b
%record(identinfo)%name dp,tp
  %integer%fn CHAR(%integer ad)
    %result = byteinteger(ad) %if byteinteger(ad) < 'a' %or control&oldbit # 0
    %result = byteinteger(ad)-32
  %end

  byteinteger(charlim) = 0;  ![see test for %alias]
  value = 2
  %cycle
    dp == dict(chain)
    a = dp_text+char0;  b = byteinteger(a)
    %if byteinteger(a+b+1)&128 # 0 %start;  !aliased
      a = a+b+1;  b = byteinteger(a)-128
    %finish
    value = value+(b+14)&(\1)
    %if specs >= 0  %start;  !for real
      put word(dp_flags&(ext+proc)!sign16)
      put word(dp_mode)
      k = 0
      %if dp_flags&proc # 0 %start
       !create type word
        tp == dict(dp_type)
        k = 4;  k = 6 %if tp_type # 0;  !100:R 11x:F,M
        %cycle
          k = k+1 %if tp_reg&8 # 0;    !0:dreg, 1:areg
          %exit %if tp_link <= 0
          tp == dict(tp_link);  k = k<<1
        %repeat
        k = k+2 %if k = 9 %and tp_type = stringtype %and tp_flags >= 0
      %finish
      put word(k>>16);  put word(k)
      put word(dp_val>>16);  put word(dp_val)
      put word(b<<8+char(a+1))
      %cycle
        a = a+2;  b = b-2
        %exit %if b < 0
        k = char(a)<<8
        k = k+char(a+1) %if b > 0
        put word(k)
      %repeat
    %finish
    chain = dp_link
  %repeat %until chain = 0
  %if specs >= 0 %start
    put word(0)
    put word(0) %if value&3 # 0
  %finish
  value = (value+3)&(\3)
%end
!
%routine PUTACT(%integer act,x,y)
  dict(np)_act = act;  dict(np)_x = x;  dict(np)_y = y
  np = np+1
%end

%routine COMPILE END
%integer i,j,x,y,entry,lim
  %if c_reg_line # line %and control&(linebit+tracebit) # 0 -
  %and level > 0 %and c_access # 0 %start
    pendcond = -1
    flush
  %finish
  !Pop event block
  %if c_eventsp # 0 %start
    plant(move,temp(c_mode,c_eventsp),gb+indir)
    forget cc
  %finish
!Put pre-amble
  codeflag = '^';  x = pc;  !preserve
  putact(end,0,0)
  compile(np0)
  fill code(1) %if cad&1 # 0
  check reach((pc-c_localpc)<<1)
  entry = cad
  y = x
  %while y < pc %cycle
    %if pflag(y) = indglobal %then set code word(dict(prog(y))_val-cad) -
    %else set code word(prog(y))
    y = y+1
  %repeat
  codeflag = ' ';  pc = x;  !restore
!Generate final sequence
  %if c_access # 0 %start
    %if level > 0 %and c_status&globbed # 0 %start
      %if level > 1 %start;  !display in store
        plant(move,tempd(gb,level<<2),a7);     !MOVE ?(GB),SP
        plant(move,posta7,tempd(gb,level<<2)); !MOVE (SP)+,?(GB)
        forget cc
      %else
        plant(unlk,0,f1)
      %finish
    %else %if c_sp < 0;  !some stack extension
      addimm(-c_sp,a7)
    %finish
    %if level > 0 %start
      %if c_type # 0 %start
        c_dpid_flags = c_dpid_flags!okflag %if c_status&okcc # 0 -
                          %and c_reg_ccx!c_reg_ccy = 0 {not undeffed}
      %finish
      plant(rts,0,0)
    %else
      plant(move,0,d0);  srcall(signal);  !%stop
    %finish
  %else;  !no return from procedure
    c_dpid_flags = c_dpid_flags!noret
  %finish
!Set start address
  x = c_dpid_val
  define entry(-x,entry,c_pid) %if x < 0;  !forward refs in FINAL
  c_dpid_val = entry
!
  lim = cad+(pc-c_localpc-c_shorts+zeroshorts)<<1
  x = c_localpc;  c_shorts = zeroshorts;  !reset
  %while x < pc %cycle
    y = prog(x);  j = pflag(x)
    %if j # 0 %start
      %if j < zeroshorts %start
        %if j <= longjump %start;  !shortjump/jump/longjump
          jumps = jumps+1
          y = (y-pflag(y)-x+c_shorts)<<1
          %if j = shortjump %start
            cad = cad-2
            y = prog(x-1)+y&255
            c_shorts = c_shorts+1
          %finish
        %else %if j = indglobal;  !procedure
          i = dict(y)_val
          %if i <= 0 %start;  !not yet encountered
            dict(y)_val = -(cad>>1);  y = -i
          %else
            i = i-cad
            report(reacherr,y,0) %unless is short(i)
            y = i
          %finish
        %else {global,negglobal,bigglobal}
          %if j # global+1 %start
            y = y&16_FFFF
            y = y+65536 %if j # global;  !bigglobal
          %finish
          y = y-cad
          %unless is short(y) %start
            %if prog(x-1)&16_F1FF # 16_41FA %start;  !LEA (PC),Ax
              report(creacherr,0,cad)
            %else
              i = cad;  cad = lim
              set code word(prog(x-1)!!(16_41FA!!16_207C)); !MOVEI #,Ax
              set code longword(y-2)
              set code word(prog(x-1)!!(16_41FA!!16_D1D7)); !ADD (SP),Ax
              set code word(16_4E75);                       !RTS
              lim = cad;  cad = i-2
              set code word(16_6100);  !BSR
              y = lim-10-cad
              steps = steps+5
            %finish
          %finish
        %finish
      %finish
    %finish
!$IF VAX
{    final(cad) <- y>>8;  final(cad+1) <- y
!$IF APM
    shortinteger(final0+cad) <- y
!$FINISH
    cad = cad+2
    x = x+1
  %repeat
  cad = lim
  forget all
%end;  !compile end

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!  end of Code Generation  !!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
!<t want to let LIT/EXP
                 ! get out of hand so RESET CONTEXT forgets triples
  croak("Too many levels") if  level = maxlevel
  c_oldcontrol = control
  hold(level) = c;  level = level+1;  vintage = vintage+1
  reset context(pid,c_free)
  c_access = 1;  c_localad = cad-accounted
end ;  !OPEN BLOCK

predicate  PARMATCH(integer  apos,bpos)
record (identinfo)name  ap,bp,atp,btp
  cycle 
    ap == dict(apos);  bp == dict(bpos)
    false  if  ap_flags!!bp_flags < 0
    {%false %if ap_mode # bp_mode}
    if  ap_type # bp_type start 
      ![for now -- nominal]
      atp == dict(ap_type);  btp == dict(bp_type)
      false  unless  atp_flags&cat = arry = btp_flags&cat
    finish 
    apos = ap_link;  bpos = bp_link
    if  apos = 0 start 
      false  if  bpos # 0
      true 
    else  if  bpos = 0
      false 
    finish 
  repeat 
end 

integer fn  CRUNCHED(integer  p)
record (identinfo)name  dq,dp==dict(p)
owninteger  q=0,l=0
  dp_text = 0;  q = 0
  l = dp_link
  if  l # 0 start 
    l = crunched(l) if  dp_type < p
    result  = p if  p <= l
    dp_link = l
    q = l-1
  finish 
  dq == dict(q)
  while  q < p cycle 
    if  dq_type = dp_type -
    and  dq_link = l and  dq_reg = dp_reg and  dq_val = dp_val start 
      dlim = p
      result  = q
    finish 
    q = q+1;  dq == dq[1]
  repeat 
  result  = p
end 

routine  FIXUP SWITCH VECTOR(integer  pos,record (identinfo)name  dp)
integer  x,y,j,default,temp,lo,hi
record (identinfo)name  tp==dict(dp_type)
  x = dp_val
  default = dp_link;  default = pc if  default = 0
  get array info(tp,j,lo,hi)
  if  dp_flags&arrflag = 0 then  j = pflag(x-1)+lo -
  else  j = pflag(x-7);  !allow for dope info
  j = x-j;  !base position
  while  lo <= hi cycle ;  !For each element
    y = prog(x)
    if  y <= 0 start ;  !not set
      if  dp_link = 0 start ;  !no default
        report(slabmissing+warn,pos,lo)
        c_access = 1
      finish 
      if  y < 0 start ;  !explicit jump(s) to this one
        y = -y
        cycle ;  !define jumps to default
          temp = y;  y = prog(temp);  prog(temp) = default
        repeat  until  y = 0
      finish 
      y = default
    finish 
    prog(x) = (y-pflag(y)-j)<<1
    x = x+1;  lo = lo+1
  repeat 
end 

routine  CHECK USAGE(integer  base)
integer  miss=0,under=0,pos,idmiss=idmissing+warn
record (identinfo)name  dp
  pos = dlim;  dp == dict(pos)
  while  pos > base cycle 
    pos = pos-1;  dp == dp[-1]
    if  dp_flags&ext = 0 start 
!<
!<
      if  dp_text > 0 start ;               !user id
        set hashhead(string(dp_text+char0))
        if  head = pos start ;              !still active
          head = dp_hlink;                  !remove from hash list
check:    if  dp_flags&spec # 0 start 
            dp_hlink = miss;  miss = pos
            idmiss = idmissing if  dp_val # 0  {hard error if used}
          else  if  ((dp_flags&(readable+rflag) = readable -
                      and  dp_mode # litmode) -
            or  (dp_flags&(writable+okflag+wflag+spec) = writable)) -
            and  pos >= c_localdpos and  dp_mode # 0 and  dp_flags&typeid = 0 -
            and  control&(list!maplist) # 0
            dp_hlink = under;  under = pos
          finish 
        finish 
      finish 
    else  if  level = 0;  !external, external spec
      if  dp_flags&spec = 0 start ;  !external object
        dp_link = externs;  externs = pos
      finish  else  if  dp_flags&(rflag+wflag) # 0 start 
       !external spec (used)
        dp_link = extspecs;  extspecs = pos
      finish 
    finish 
  repeat 
  report(idmiss,miss,0) if  miss # 0
  if  under # 0 and  c_faults = 0 start 
    put ident(under,1)
    put string(" underused")
    print line
  finish 
  return  if  base = 0
  dlim = c_parlim
!  %for i = 0,1,255 %cycle
!    hashindex(i) = dict(hashindex(i))_hlink %while hashindex(i) >= c_localdpos
!  %repeat
  charlim = c_localtext
  ranges = dict(ranges)_hlink while  ranges >= c_parlim
  set first entry if  firstpos >= dlim
  dictshown = dlim if  dictshown > dlim
  starts = 0;  cycles = 0
end 

routine  CLOSE BLOCK
integer  pos; record (identinfo)name  dp
 ! For a function etc, C_STATUS&OKCC is set if all results
 ! have correct CC.  CCX and CCY are set to special values
 ! so that if the exit sequence changes, OKFLAG will not be
 ! set.
  c_reg_ccx = 0 and  c_reg_ccy = 0 if  c_status&okcc # 0
  if  c_return # 0 start 
    if  c_return = -(pc-1) and  c_access = 0 start 
      c_return = -prog(pc-1);  pc = pc-2 
    finish 
    define jumps(c_return);  !must precede switch fixup
    c_access = -1
  finish 
  pflag(pc) = c_shorts;      !in case of terminal switch labels
  if  c_status&hadswitch # 0 start 
    pos = c_localdpos
    while  pos < dlim cycle 
      dp == dict(pos)
      fixup switch vector(pos,dp) if  dp_mode = labmode and  dp_type # 0
      pos = pos+1
    repeat 
  finish 
  compile end
  c_totstack = c_totstack-c_extra
  c_totstack = -c_totstack if  c_status&unknown = 0;  !positive if firm
  dict(c_dpid_type)_val = c_totstack
{?}  if  control&maplist # 0 start 
{?}    put ident(c_pid,-1)
{?}    mark at(20)
{?}    put string(" code:")
{?}    put num(cad-c_localad-accounted)
{?}    put string("  entry:")
{?}    put num(c_dpid_val-c_localad-accounted)
{?}    put string("  stack:");  put num(-c_stack)
{?}    putsym('/');  put num(|c_totstack|)
{?}    put sym('+') if  c_totstack < 0
{?}    accounted = cad-c_localad
{?}    print line
{?}  finish 
  pc = c_localpc;  swpc = c_localswpc;  curlab = c_lab1
  if  level = 0 then  check usage(0) else  start 
    check usage(c_localdpos)
    c_dpid_type = crunched(c_dpid_type)
    level = level-1;  c = hold(level)
    control = control&editbit ! c_oldcontrol&(\editbit)
  finish 
end ;  !CLOSE BLOCK

routine  ERROR(integer  case)
  faultp = atomp
  report(case,0,0)
  signal  fail
end 

constinteger  DUD=63
routine  SYNTAX ERROR
  if  atom = dud then  error(atomerr+point) else  error(formerr+point)
end 

routine  EXPFAULT(integer  case)
  if  faultnum = 0 or  expp < faultp start 
    faultnum = case!point;  faultp = expp
  finish 
end 

routine  NONSTANDARD(integer  case)
integer  b
owninteger  hadit=0
  b = 1<<case
  if  b&hadit = 0 and  control&nonsbit = 0 and  faultnum = 0 start 
    hadit = hadit+b;  faultp = atomp
    if  control&strictbit # 0 then  report(nonstand+point,0,case) -
    else  report(nonstand+point+warn,0,case)
  finish 
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.
  if  item >= 0 start ;  !first time
    fault(namerr+point+now)
    if  charmin-newlen-80 >= charlim start 
      dmin = dmin-1;  dmin0 = dmin
      charmin = charmin-newlen-1
      string(charmin) = string(charlim)
      dict(dmin)_text = charmin-char0
      head == dict(head)_hlink while  head > 0;  !find last link
      dict(dmin)_hlink = head;  head = -dmin
    finish 
  finish  else  others = others+1
  signal  fail
end 

routine  FIND OP(integer  mnemonic,integername  op,types)
integer  i
  i = 0
  cycle 
    i = i+2
    error(namerr) if  i > defmax+defmax
  repeat  until  def(i) = mnemonic 
  types = def(i-1);  op = i>>1
end 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Source input  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

routine  READ LINE(integer  flag)
! Read (or otherwise make available) the next source line
!     Output any pending error report;                 *NB*
!     Skip remnant of previous line if SYM # NL        *NB*
!     Set LINESTART to point to start of new line
!     Print new line on list output stream if listing requested
!       (Direct output routines CF diagnostics)
  report(faultnum,0,0) if  faultnum # 0
  while  sym > nl cycle ;               !Skip remnant
    sym = byteintegeR(fp);  fp = fp+1
  repeat 
  line = line+1
  while  fp = curlim cycle 
    if  curlim # cur_lim2 start ;  !in part1 of file
      fp = cur_start2
    else  if  curfile = main;      !on main
      signal  done
    else 
      cur_flag = -1
      disconnect edfile(cur)
      curfile = curfile-1
      cur == file(curfile)
      fp = cur_fp;  line = cur_line
      control = fcontrol(curfile)
      inclim = dlim if  level = 0 and  c_status < hadon
    finish 
    curstart = cur_start2;  curlim = cur_lim2
    if  fp < curstart or  fp > curlim start 
      curstart = cur_start1;  curlim = cur_lim1
    finish 
  repeat 
  linestart = fp
  if  flag = 0 start 
    flag = ' ';  flag = '&' if  curfile # main
  finish 
  listflag = flag
  if  control&list # 0 start 
    time1 = time1-cputime
    print line if  rep # ""
    show dict(dictshown) if  control&dictlist # 0
    dictshown = dlim
    write(line,4);  print symbol(listflag)
    print symbol(' ')
    cycle 
      sym = byteintegeR(fp);  fp = fp+1
      print symbol(sym)
    repeat  until  sym <= nl
    fp = linestart
    time1 = time1+cputime
  finish 
  sym = 0
end ;  !READ LINE

!<

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Lexical processing  !!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

constinteger  CASEBIT=32
owninteger  PERCENT=0, SUBATOM=0
!
!~!!!!!!!  Keyword codes -- used by KEYGEN to produce tables  !!
constinteger  KEYEND=1 {end},
  KEYREPEAT=2   {repeat},
  KEYFINISH=3   {finish},
  KEYELSE=4     {else},
  KEYBEGIN=5    {begin},
  EXIT=6        {exit_1,continue_0},
  KEYRETURN=7   {return},
  TF=8          {true_1,false_0},
  KEYRESULT=9   {result},
  KEYSTOP=10    {stop},
  KEYGOTO=11    {goto},
  KEYSIGNAL=12  {signal},
  KEYMONITOR=13 {monitor},
  KEYON=14      {on},
  IU=15         {if_0,unless_1},
  KEYWHILE=16   {while},
  KEYUNTIL=17   {until_1},
  KEYFOR=18     {for},
  KEYTHEN=19    {then},
  KEYSTART=20   {start},
  KEYCYCLE=21   {cycle},
  KEYLABEL=22   {label},
  KEYCONST=23   {const,constant},
  KEYOWN=24     {own},
  KEYEXT=25     {external_6,system_5,dynamic_7},
  KATTRIB=26    {readonly_0,writeonly_1,volatile_2,register_3},
  KTYPE=27      {short_3,half_6,byte_9,mite_12,boolean_15,char_18,text_25},
  KEYINTEGER=28 {integer},
  KEYLONG=29    {long},
  KEYREAL=30    {real},
  KEYSTRING=31  {string_0,cstring_1},
  KEYRECORD=32  {record},
  KEYNAME=33    {name},
  KEYFORMAT=34  {format},
  FNMAP=35      {fn_0,function_0,map_1},
  RPRED=36      {routine_0,predicate_1},
  KEYSPEC=37    {spec},
  KEYARRAY=38   {array},
  KEYSWITCH=39  {switch},
  KEYOF=40      {of},
  KEYFILE=41    {file},
  KEYPROGRAM=42 {program},
  KEYLIST=43    {list},
  KEYCONTROL=44 {control},
  KEYCOMMENT=45 {comment},
  KEYEVENT=46   {event},
  KEYINCLUDE=47 {include},
  KEYOPTION=48  {option},
  KEYALIAS=49   {alias},
  KEYNOT=50     {not},
  KEYAND=72     {and},
  KEYOR=73      {or}
!!  end of keyword codes
!
!Symbol lexical codes other than operators:
constinteger  TERMINATOR=51, CONST=52, IDENT=53, MODSIGN=54,
              COLON=59, COMMA=60, RIGHT=61, RIGHTB=62, DOLLAR=64,
              QUERY=65
{DUD=63}
constinteger  LEFT=55, LEFTB=56, ATSIGN=57, UNDERLINE=58

constinteger  ARROW=74, EQEQ=75, NOTEQEQ=76,
              EQUALS=77, NOTEQ=78, LESSEQ=79,
              LESS=80, GREATEQ=81, GREATER=82
constinteger  PLUS=83, MINUS=84, EXCLAM=85, EXCLAM2=86, DOT=87
constinteger  STAR=88, SLASH2=89, SLASH=90, AMPERSAND=91
constinteger  STAR2=92, BACKSLASH=93, UPARROW=94,
              BACKSLASH2=95, UPARROW2=96,
              TILDE=97,
              LSHIFT=98, RSHIFT=99, UMINUS=100
constinteger  ATOMMAX=100
constinteger  ALEFT=left, ARIGHT=right, RECSUB=underline,
              OVER=slash2, SCONC=dot, HASHSIGN=noteq

constinteger  SIMPLE=atommax+1, VSIMPLE=simple+1,
              MAJOR=plus, SCOND=arrow, COND=keyand, CONDQ=71
!
integer fn  NEXT ATOM
!Encode next atom from source file
![Time-critical]
switch  s(0:255)
constinteger  TAB=9,
              MAX10=maxint//10, MAXDIG=maxint-max10*10
integer  i,j,p,radix,hash
real  rval
constbytearray  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

!~!!!!!!!!!!!!!!!  Ex KEYGEN  !!!!!!!!!!!!!!!!!!!!
CONSTSHORTINTEGERARRAY  SYMINIT(97:122) =  -
2,15,31,72,79,102,133,137,141,1,1,156,169,183,190,205,
1,220,264,304,316,326,334,1,1,1

CONSTBYTEINTEGERARRAY  SYMBOL(1:347) =  -
128,114,114,97,121,166,108,105,97,115,177,110,100,200,101,103,
105,110,133,121,116,101,155,111,111,108,101,97,110,155,111,110,
116,105,110,117,101,134,121,99,108,101,149,104,97,114,155,115,
116,114,105,110,103,159,109,109,101,110,116,173,115,116,97,110,
116,151,151,114,111,108,172,121,110,97,109,105,99,153,110,100,
129,108,115,101,132,120,105,116,134,118,101,110,116,174,116,101,
114,110,97,108,153,105,110,105,115,104,131,97,108,115,101,136,
111,114,109,97,116,162,110,163,117,110,99,116,105,111,110,163,
146,108,101,169,111,116,111,139,97,108,102,155,102,143,110,116,
101,103,101,114,156,99,108,117,100,101,175,97,98,101,108,150,
111,110,103,157,105,115,116,171,111,110,105,116,111,114,141,105,
116,101,155,97,112,163,97,109,101,161,111,116,178,110,142,119,
110,152,102,168,112,116,105,111,110,176,114,201,114,101,100,105,
99,97,116,101,164,111,103,114,97,109,170,101,112,101,97,116,
130,111,117,116,105,110,101,164,116,117,114,110,135,115,117,108,
116,137,97,100,111,110,108,121,154,103,105,115,116,101,114,154,
99,111,114,100,160,108,158,116,111,112,138,105,103,110,97,108,
140,121,115,116,101,109,153,104,111,114,116,155,112,101,99,165,
119,105,116,99,104,167,97,114,116,148,114,105,110,103,159,114,
117,101,136,104,101,110,147,101,120,116,155,110,108,101,115,115,
143,116,105,108,145,111,108,97,116,105,108,101,154,104,105,108,
101,144,114,105,116,101,111,110,108,121,154

CONSTBYTEINTEGERARRAY  ALTDISP(1:347) =  -
0,5,0,0,0,0,5,0,0,0,0,0,0,0,5,0,
0,0,0,4,0,0,9,0,0,0,0,0,0,15,8,23,
28,34,0,0,0,0,5,0,0,0,0,4,0,0,18,0,
0,0,0,0,0,1,0,0,0,0,0,0,0,0,4,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,7,3,0,
0,4,0,0,0,4,8,0,1,0,0,0,0,0,0,0,
0,0,0,0,6,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,6,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,12,0,0,1,4,0,0,0,0,0,0,2,0,3,
0,0,2,0,6,0,0,0,0,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,7,18,0,0,0,0,0,7,0,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,5,5,0,0,0,3,4,0,0,0,
0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,4,
0,0,1,4,0,0,0,0,0,0,25,0,5,0,0,0,
1,0,0,0,1,0,0,0,0,0,0,0,2,5,0,0,
0,0,0,0,0,0,0,0,0,0,1


!! end of generated tables

routine  GET SYM
  cycle 
    sym = byteintegeR(fp);  fp = fp+1
  repeat  until  sym # ' '
  i = sym-'0'
  if  i >= 10 start 
    i = sym!casebit-'a';  i = i+10 if  i >= 0
  finish 
end 

  matched = 0
again: s(tab):
  read line(0) if  sym = nl
again1:
  cycle 
    sym = byteintegeR(fp);  fp = fp+1
  repeat  until  sym # ' '
  atomp = fp;     !(actually one after)
  atoms = atoms+1
  -> s(sym)
linebreak: s(nl):
  result  = terminator if  atom # comma
continuation:
  read line('+')
  -> again1

s('{'):
  comments = comments+1
  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) = '>'
        -> continuation 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) = '\'
        fp = fp+1 and  result  = noteq if  byteinteger(fp) = '='
        result  = backslash
s('^'): fp = fp+1 and  result  = uparrow2 if  byteintegeR(fp) = '^'
        result  = uparrow
s('~'): result  = tilde
s('!'): fp = fp+1 and  result  = exclam2 if  byteintegeR(fp) = '!'
        result  = exclam
s('&'): result  = ampersand
s('.'): rval = 0 and  -> fraction if  '0' <= byteinteger(fp) <= '9'
        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  = leftb
s(')'): result  = right
s(']'): result  = rightb
s('|'): result  = modsign
s('@'): result  = atsign
s('$'): result  = dollar
s('?'): result  = query

s('M'): s('m'):
  fp = fp+1 and  -> charconst if  byteintegeR(fp) = ''''
s('A'):s('B'):s('C'):s('D'):s('E'):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('c'):s('d'):s('e'):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
  newlen = charlim+1;  hash = sym!casebit;  !lower-case (if letter)
  byteinteger(newlen) = hash
  cycle 
    sym = byteintegeR(fp);  fp = fp+1
  repeat  until  sym # ' '
  if  sym = '''' start ;  !damned IBM-style literals
    radix = 16 and  ->ibm if  hash = 'x'
    radix = 8 and  ->ibm if  hash = 'k'
    radix = 2 and  ->ibm if  hash = 'b'
  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
  if  subbed # 0 then  head == dformat_link -
  else  head == hashindex(hash&255)
  item = head
  if  item # 0 start 
    cycle 
      ditem == dict(|item|)
      exit  if  string(ditem_text+char0) = string(charlim) -
            and  (item > a7 or  item < 0 or  control&lowbit # 0)
      item = ditem_hlink
    repeat  until  item = 0
  finish 
  identatoms = identatoms+1
  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) > 127
    atom = altdisp(p)
    if  atom = 0 start 
      result  = dud unless  sym!casebit = 'c' and  byteintegeR(fp) = nl
      ->continuation
    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

ibm:
  nonstandard(20)
  item = -1;  value = 0
  -> ibm1
s('0'):s('1'):s('2'):s('3'):s('4'):s('5'):s('6'):s('7'):s('8'):s('9'):
  item = 0;  type = inttype
  radix = 10;  value = 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
        fault(rangerr+point+warn) if  value > max10 or  (value=max10 and  i > maxdig)
        value = (value<<2+value)<<1+i
      else 
        i = sym!casebit-'a'+10 if  i >= 10
        exit  if  i < 0 or  i >= radix
        j = radix
        cycle 
          i = i+value if  j&1 # 0
          value = value<<1;  j = j>>1
        repeat  until  j = 0
        value = i
      finish 
    repeat 
    exit  unless  sym = '_'
    radix = value
    result  = dud if  radix = 0
    value = 0
  repeat 
  if  item < 0 start ;  !IBM-style
    result  = dud if  sym # ''''
    item = 0
  else 
    j = 0
    if  sym = '.' start 
      rval = value if  type = inttype
fraction:
      j = 0
      type = realtype
      cycle 
        get sym
        exit  unless  0 <= i < radix
        rval = rval*radix+i;  j = j-1
      repeat 
      result  = dud if  j = 0
    finish 
    if  sym = '@' start 
      type = realtype and  rval = value if  type = inttype
      get sym
      value = 0
      if  sym = '+' then  get sym -
      else  if  sym = '-' then  value = 1 and  get sym
      result  = dud unless  0 <= i < radix
      p = 0
      cycle 
        p = p*radix+i
        get sym
      repeat  until  not  0 <= i < radix
      p = -p if  value # 0
      j = j+p
    finish 
    if  type = realtype start 
      rval = rval*radix^j if  j # 0
      value = integer(addr(rval)) if  type = realtype
    finish 
    fp = fp-1;  sym = 0
  finish 
  litatoms = litatoms+1
  result  = const

s(''''):
charconst:
  item = 0;  type = inttype
  value = 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 
    value = value<<8+sym
  repeat 
  result  = const if  value # 0
  result  = dud

s('"'):
  item = 0
  value = cad;  type = stringtype
  i = line;  j = linestart;  p = 0
  cycle 
    sym = byteintegeR(fp);  fp = fp+1
    if  sym = '"' start 
      exit  if  byteintegeR(fp) # '"'
      fp = fp+1
    finish 
    p = p+1
    if  p > 255 start 
      sym = 0
      fp = atomp;  linestart = j
      result  = dud
    finish 
    final(value+p) = sym
    read line('"') if  sym = nl
  repeat 
  if  p # 0 start ;  !not empty string
    final(value) = p
    cad = cad+(p+1)
  finish  else  value = 0
  litatoms = litatoms+1
  result  = const

s(*):
  result  = dud
end ;  !NEXT ATOM

!<

{%volatile}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,0)
!  %signal fail
%end

!< 0 %and f&ext = 0;  !already exists
  charlim = charlim+newlen+1
  croak("Identifier space exhausted") %if charlim+80 >= charmin
  k = charlim-newlen-1-char0
  %if f&ext # 0 %and a(keyalias) %start
    get LITSTRING
    string(charlim) = string(final0+value)
    byteinteger(charlim) = byteinteger(charlim)+128
    charlim = charlim+byteinteger(charlim)-127
  %finish
  %result = k
%end

%routine DECLARE(%record(objinfo)%name d)
%integer i
%record(identinfo)%name dp
  dp == dict(dlim)
  %if speccing = 0 %start;  !not within spec params
    %if item >= c_localdpos %start;  !there already
      %if d_flags&spec = 0 %and ditem_flags&spec # 0 %start
        !body after spec (proc,label,typeid)
        %if d_flags&(ext+proc+typeid) = ditem_flags&(ext+proc+typeid) %start
          i = item
          %if d_flags&ext # 0 %start
            ![can't allow %ext%spec, then use, then %ext object]
            ->ok %if ditem_flags&rflag # 0;  ![so create new entry]
            ditem_mode = d_mode;  ditem_val = d_val
            %if a(keyalias) %start
              get LITSTRING;  !ignore [should be identical]
              item = i
            %finish
          %finish
          %if d_flags&proc = 0 %start
            ditem_flags = ditem_flags&(\(spec+indirect))
          %finish
          %return
        %finish
        %if ditem_flags&(ext+proc) = proc1 %and d_flags&ext # 0 -
            %and d_flags&proc # 0 %start;  !(internal) %spec then %ext
          ditem_flags = ditem_flags-proc1+(d_flags&(ext+proc))
          ditem_text = idtext(ext);  !in case alias
          %return
        %finish
      %finish
!<= dmin %start
{?}    show dict(0) if  control&logbit # 0
    croak("Too many identifiers")
  finish 
end ;  !DECLARE

routine  DECLARE ANON(record (objinfo)name  d)
  speccing = speccing+1
  item = 0
  declare(d)
  speccing = speccing-1
end 
!
record (objinfo)map  DETAILS(integer  f,t,m,v)
ownrecord (objinfo) D=0
  d_flags = f;  d_type = t
  d_mode = m;  d_val = v
  result  == d
end 

routine  DECLARE TEMP(integer  t)
  c_val = c_val+4;  c_temps = c_temps+4
  declare anon(details(okflag+writable+readable,t,c_mode,c_sp-c_val))
end 
!
routine  DECLARE RANGE(integer  type,lower,upper)
!Type ident just declared
integer  s
integer fn  OK(integer  l,u,s)
  result  = s if  l <= lower and  upper <= u
  result  = -s if  0 <= lower and  upper <= u-l
  result  = 0
end 
  s = ok(-128,127,1)
  s = ok(-32768,32767,2) if  s = 0
  s = 4 if  s = 0
  ditem_details = details(typeid,type,absmode,sign)
  ditem_size = s
  declare anon(details(okflag,type,litmode,lower))
  declare anon(details(okflag,type,litmode,upper))
  ditem_hlink = ranges;  ranges = item
  item = item-2
end 

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Expressions  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

owninteger  LITERAL=0, JAMMY=0

routine spec  GET EXPRESSION(integer  rank,etype)
!
predicate  VALOK(integer  wanted,t)
integer  lo,hi,l,h,wc,tc
record (identinfo)name  wp,tp
  true  if  wanted = t # recstar
  wp == dict(wanted);  tp == dict(t)
  wc = wp_flags&(packed+cat);  tc = tp_flags&(packed+cat)
  if  wc = tc start ;  !same class
    if  wc&nonord = 0 start ;  !ordinal wanted
      if  wp_type = tp_type start ;  !same base-type
        true  if  wp_type = wanted;  !base-type (rather than subrange)
        lo = lower(wanted);  hi = upper(wanted)
        if  item = 0 start ;  !literal
          true  if  lo <= value <= hi
          jammy = jammy!!1
        else 
          jammy = jammy!!1 and  true  if  tp_type = t
          l = lower(t);  h = upper(t)
          if  l >= lo start 
            true  if  h <= hi
            jammy = jammy!!1
            true  if  l <= hi
          else 
            jammy = jammy!!1
            true  if  h >= lo
          finish 
        finish 
        expfault(rangerr) if  jammy # 0
        true 
      finish 
    else  if  wc = realy
      true 
    else  if  wc = stringy;  !string wanted
      true  if  wanted = stringstar
      if  item = 0 start 
        true  if  value = 0;  !empty string
        l = final(value)+1
      else 
        l = |tp_size|
        l = 256 if  l = 0
      finish 
      if  l > |wp_size| # 0 start 
        jammy = jammy!!1
        expfault(rangerr) if  item = 0 and  jammy # 0
      finish 
      true 
!<
    else  if  wc&cat = arry
      true  if  wp_type = tp_type and  valok(wp_xtype,tp_xtype)
!<
    else ;                          !record etc
      if  wanted = recstar start 
        true  if  t # recstar
      else 
        true  if  t = recstar or  item!value = 0
      finish 
    finish 
  else ;                            !category difference
    if  tc = inty start 
      true  if  wc = recy and  item!value = 0;  !RECORD = 0
      toreal and  true  if  wc = realy;         !REAL   = INT
    else  if  wc = stringy and  t = chartype;   !STRING = CHAR
      if  item = 0 start 
        final(cad) = 1;  final(cad+1) = value
        value = cad;  cad = cad+2
        type = stringtype
      finish  else  putexp(dtostring,normitem,0,string1)
      true 
!<
! sets again
!<
    finish 
  finish 
  false 
end 
!
routine  GET VALUE(integer  valtype)
  get EXPRESSION(major,valtype)
end ;  !GET VALUE
!
routine  GET LITERAL(integer  valtype)
  literal = literal+2
  get EXPRESSION(major,valtype)
  literal = literal-2
end 
!
!!!!!!!!!!!!!!!!!!!!!!  Machine-code  !!!!!!!!!!!!!!!!!!!!!!!!!!
!
routine  GET MIDENT(integer  min,max)
  get(ident)
  if  item <= 0 start 
    name error if  string(charlim) # "sp"
    item = a7
    ditem == dict(item)
  finish 
  if  ditem_mode = litmode start 
    value = ditem_val;  item = 0
  finish 
  syntax error unless  min <= item <= max -
     or  min <= ditem_mode+d0 <= a7 {in case reg alias}
end 

routine  GET REGSET
integer  hold,set
  set = 0
  cycle 
    get mident(d0,a7)
    hold = ditem_mode
    get mident(hold,a7) if  a(minus)
    cycle 
      set = set!1<<hold
      hold = hold+1
    repeat  until  hold > ditem_mode
  repeat  until  not  a(slash)
  value = set                   {item = reg if singleton}
end 

routine  get MCODE
integer  op,x,y,types

integer fn  OPSIZE(integer  okbyte)
  result  = 0 if  not  a(dot)
  sym = byteinteger(fp)&(\casebit);  fp = fp+1
  result  = 4 if  sym = 'L'
  result  = 2 if  sym = 'W'
  result  = 1 if  sym = okbyte
  syntax error
end 

routine  get MOP(integer  i)
!Get Mcode operand
integer  sign,hold,holdval,m
  if  a(hashsign) start 
    get LITERAL(inttype)
    return 
  finish 
  sign = 0;  hold = -1;  holdval = 0
  sign = 1 if  a(minus)
  if  a(ident) start 
    matched = 0
    get mident(0,dlim)
    hold = item
    if  hold # 0 start 
      syntax error if  sign # 0
      if  item > a7 start 
        matched = 0;  literal = -1
        get EXPRESSION(simple,0)
        return 
      finish 
      if  op&255 = movem and  item > 0 start 
        matched = 0
        get regset;  item = 0
      finish 
      return 
    finish 
    holdval = value
  else  if  a(const)
    hold = 0;  holdval = value
  finish 
  holdval = -holdval if  sign # 0
  if  a(left) start 
    get mident(a0,a7)
    item = ditem_mode+d0
    if  hold < 0 start 
      get(right)
      if  sign # 0 then  item = item+pre -
      else  if  not  a(plus) then  item = item+indir -
      else  item = item+post
      return 
    finish 
    m = item+(dispmode-a0)
    if  a(comma) start 
      get mident(d0,a7)
      fault(rangerr) unless  is mite(holdval)
      m = m+(indexmode-dispmode)
      holdval = ditem_mode<<12+holdval&255
      holdval = holdval+16_0800 if  opsize(0) # 2
    finish 
    get(right)
  else 
    syntax error if  hold < 0
    m = absmode
  finish 
  item = i;  ditem == dict(item)
  ditem_mode = m;  ditem_val = holdval
end 

constinteger  TEMPDEF='t'<<25+('e'&31)<<20+('m'&31)<<15+('p'&31)<<10

  update sp
!Pack mnemonic
  atomp = fp+1
  x = 0
  cycle 
    sym = byteinteger(fp);  fp = fp+1
    exit  unless  'A' <= sym&(\casebit) <= 'Z'
    sym = sym&31
    x = x<<5+sym
  repeat 
  fp = fp-1;  sym = 0
  syntax error if  x = 0
  x = x<<5 until  x&(31<<25) # 0
  x = x!16_C0000000
  if  x = tempdef start 
    c_free = defaultfree
    if  a(ident) start 
      matched = 0;  get regset
      c_free = value
    else  if  a(const)
      c_free = value
    finish 
    return 
  finish 
  find op(x,op,types)
  if  types&(sized!qsized) # 0 then  op = op+opsize('B')<<8 -
  else  if  types&asized # 0 then  op = op+opsize(0)<<8
  x = 0;  y = 0
  if  types>>6&63 # 0 start 
    get MOP(lablim)
    x = normitem
    get(comma)
  finish 
  if  types&63 # 0 start 
    get MOP(lablim+1)
    y = normitem
  finish 
  plant(op,x,y)
  forget regs;  c_access = -1
end ;  !get MCODE

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

predicate  REFOK(integer  wanted,t)
record (identinfo)name  wp,tp
  true  if  t = wanted or  wanted = 0 or  t = 0 or  item!value = 0
  wp == dict(wanted);  tp == dict(t)
  if  (wp_flags!!tp_flags)&(name+packed+cat) = 0 start 
    if  wp_flags&cat = arry start 
      !**check index compatible
      true  if  refok(wp_type,tp_type)
    else  if  wp_flags&cat = stringy
      true  if  t = stringstar or  wanted = stringstar
!<
!<
    else 
      true  if  t = recstar or  wanted = recstar
    finish 
  finish 
  false 
end 

routine  TOREF
  atomp=expp and  error(nonref+point) if  item <= 0 -
    or  (ditem_mode < dispmode and  ditem_flags >= 0)
  if  item >= dictlim start 
    if  ditem_act = prel and  (ditem_y < 0 or  ditem_type = bytetype) start 
      value = ditem_y
      value = litref(litval(value)*|size(ditem_type)|) if  ditem_type # bytetype
      putexp(add,ditem_x+ad,value,ditem_type)
      return 
    finish 
  else 
    if  ditem_mode = absmode and  ditem_flags >= 0 start 
      item = 0;  value = ditem_val
      return 
    finish 
  finish 
  item = item+ad
end 
!
routine  COPY DOWN(integer  np1)
  while  np > np1 cycle 
    np = np-1;  explo = explo-1
    dict(explo) = dict(np)
  repeat 
end 

routine  GET REFERENCE(integer  type)
  get EXPRESSION(simple,type!sign16)
end 

routine  GET VARIABLE(integer  type)
  get EXPRESSION(simple,type)
  atomp=expp and  error(nonvar+point) if  ditem_flags&(writable!typeid) = 0
end 

routine  GET PARLIST(integer  special)
integer  procnp,pact,hold,count,headitem,arg,p,q,restype
record (identinfo)name  hp,tp
record (identinfo)name  darg

routine  PUT ACTUAL
  item = litref(value) if  item = 0
  if  count&1 = 0 then  hold = item -
  else  putact(pact,hold,item) and  pact = 0
  count = count+1
end 

predicate  NO ALT(record (identinfo)name  oldhp)
  if  oldhp_flags&alt = 0 start ;  !no alternative
    expfault(typerr)
    true 
  finish 
  headitem = oldhp_hlink
  cycle 
    report(internerr,0,6) and  signal  fail if  headitem <= 0
    hp == dict(headitem)
    exit  if  string(hp_text+char0) = string(oldhp_text+char0)
    headitem = hp_hlink
  repeat 
  pact = headitem
  arg = hp_type;  darg == dict(arg);  restype = darg_type
  arg = darg_link;  darg == dict(arg)
  false 
end 

routine  PUT BOUNDS(integer  ft{formal-type},at{actual-type})
integer  maxarg=arg
record (identinfo)name  ftp,atp,fxp,axp
cycle 
  ftp == dict(ft);  atp == dict(at)
  if  ftp_xtype >= arg start 
    fxp == dict(ftp_xtype);  axp == dict(atp_xtype)
    if  fxp[1]_mode # litmode start ;  !non-literal lower
      item = atp_xtype+1
      item = 0 and  value = axp[1]_val if  axp[1]_mode = litmode
      put actual
      maxarg = ftp_xtype+1 if  ftp_xtype >= maxarg
    finish 
    if  fxp[2]_mode # litmode start ;  !non-literal upper
      item = atp_xtype+2
      item = 0 and  value = axp[2]_val if  axp[2]_mode = litmode
      put actual
      maxarg = ftp_xtype+2 if  ftp_xtype+1 >= maxarg
    finish 
  finish 
  ft = ftp_type;  at = atp_type
repeat  until  ft <= arg
arg = maxarg;  darg == dict(arg)
end 

  count = 0;  hold = 0
  procnp = np
  headitem = item;  pact = headitem;  hp == ditem
  arg = hp_type;  darg == dict(arg);  restype = darg_type
  if  a(left) start 
    cycle 
      arg = darg_link
      if  arg = 0 start 
        error(toomany+point) if  special = 0
        get VARIABLE(0)
        value = item;  !save extra item
        cycle 
          if  type = realtype start 
            exit  if  restype = realtype;  !no coercion
          else 
            exit  if  valok(type,restype)
          finish 
        repeat  until  no alt(hp)
        special = 0
      else 
        darg == dict(arg)
        if  darg_flags&proc # 0 start 
          get(ident)
          name error if  item <= 0
          fault(typerr+point) if  ditem_flags&proc = 0 -
                              or  not  parmatch(darg_type,ditem_type)
          fault(classerr+point) if  item > headitem -
                                and  ditem_mode = procmode {procparm OK?}
          item = item+ad
          put actual
        else  if  darg_flags >= 0
          jammy = 0
          get EXPRESSION(major,0)
          cycle 
            exit  if  valok(darg_type,type)
          repeat  until  no alt(hp)
          putexp(check,darg_type,item,darg_type) if  jammy # 0 -
                                        and  control&capbit # 0 -
                                        and  category(darg_type) < realy
          put actual
        else ;  !name
          get REFERENCE(0)
          cycle 
            exit  if  refok(darg_type,type)
          repeat  until  no alt(hp)
          put actual
          tp == dict(darg_type)
          if  tp_flags&cat = arry -
          and  dict(arg+1)_type # darg_type -
          and  tp_mode >= framemode start 
            !array name (last in group) with dynamic bounds
            put bounds(darg_type,type)
          finish 
        finish 
      finish 
    repeat  until  not  a(comma)
    error(toofew+point) if  darg_link # 0 or  special # 0
    get(right)
  else ;                              !no LEFT
    error(toofew+point) if  darg_link # 0
  finish 
  put act(pact,hold,0) if  count&1 # 0 or  count = 0
  type = restype;  count = 0
  if  type # 0 start ;  !not routine
    if  hp_flags&writable # 0 start ;  !map
      if  headitem <= sindex start 
       {length, charno}
        if  hold >= explim then  count = dict(hold-ad)_mode -
        else  count = dict(hold)_mode
      finish  else  count = dispmode
    finish 
    if  hp_flags&volatile = 0 start 
      p = explo
      while  p < explim cycle 
        if  dict(p)_act = headitem start ;  ![enough?]
          item = p;  q = procnp
          cycle 
            exit  if  dict(p)_x # dict(q)_x or  dict(p)_y # dict(q)_y
            p = p+1;  q = q+1
            ->okf if  q >= np
          repeat 
        finish 
        p = p+1
      repeat 
    finish 
    copy down(procnp)
    item = explo
okf:ditem == dict(item)
    ditem_flags = hp_flags&heritable
    ditem_mode = count
    ditem_type = type
    np = procnp
  finish 
end ;  !get PARLIST

!<

routine  get RESOLUTION(integer  t,item1)
integer  fore,ftype,s
!  type check needed
  s = size(t)
  s = -256 if  s = 0
  fore = 0
  if  not  a(left) start 
    get VARIABLE(stringstar)
    fore = item+ad;  ftype = type
    get(dot);  get(left)
  finish 
  get VALUE(stringtype);  get(right)
  if  item = 0 start 
    item = litref(value);  s = s+final(value)
  finish 
  fault(rangerr+warn) if  fore # 0 and  s < size(ftype) # 0
  putact(resolves,item1+ad,item+ad)   {RESOLVES expects %names ?}
  item = 0
  if  a(dot) start 
    get VARIABLE(stringstar)
    fault(rangerr+warn) if  s < size(type) # 0
    item = item+ad
  finish 
  putact(0,fore,item)
  putact(0,0,0);       !preserve 'parity'
end 

integer fn  ANON(record (objinfo)name  d)
  dict(lablim+3)_details = d
  result  = lablim+3
end 

predicate  A ASSOP(integer  t)
  jammy = 0
  if  t <= 0 start 
    false  if  not  a(eqeq)
  else 
    atom = next atom if  matched # 0
    if  atom # equals start 
      false  unless  atom = less and  byteintegeR(fp) = '-'
      jammy = 1;  fp = fp+1
    finish 
    matched = 1
  finish 
  true 
end 

!<

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
routine  GET EXPRESSION(integer  rank,etype)
!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
integer  atomp0,item1,type1,cat1,val1,double,op
record (identinfo)name  ditem1,tp
constinteger  nop=0;  !to distinguish from numeric zero in OPVAL

routine  GET RECORD
![literal only at this stage]
integer  fid,ad,arg,hold,count,max,s
record (identinfo)name  darg,fidp
  fill code(1) if  cad&1 # 0
  ad = cad
  fid = item;  fidp == ditem
  arg = fidp_link
  count = 0;  max = -1
  get(left)
  cycle 
    ![*beware premature lexical coding: may alter CAD*]
    cycle 
      error(toomany+point) if  arg <= 0
      darg == dict(arg)
      exit  if  ad+darg_val-cad >= 0
      arg = darg_hlink
    repeat 
    fill code(ad+darg_val-cad)
   ! [*now OK to code atom*]
    if  a(recsub) start 
      dformat == fidp
      subbed = 1;  get(ident);  subbed = 0
      name error if  item < arg
      fill code(ditem_val-darg_val)
      arg = item;  darg == ditem
      syntax error if  not  a assop(darg_flags&name+darg_type)
    finish 
    s = nsize(darg)
    if  not  a(comma) start 
      get LITERAL(darg_flags&name+darg_type)
      if  s > 0 start 
        if  s = 4 start 
!$IF VAX
{          value = ieee(value) %if darg_type = realtype %and darg_flags >= 0
!$FINISH
          set code longword(value)
        %else %if s = 2
         set code word(value)
        %else
          final(cad) <- value;  cad = cad+1
        %finish
      %finish
      %exit %if a(right)
      get(comma)
    %else %if s > 0
      fill code(s)
    %finish
    arg = darg_hlink
  %repeat
  fill code(ad+|fidp_val|-cad)
  item = 0;  value = ad
%end

%routine SWOP
%integer temp
  temp = item1;  item1 = item;  item = temp
  temp = val1;  val1 = value;  value = temp
  temp = type1;  type1 = type;  type = temp
%end

%constinteger INTOK=1<>(cat1&cat)&1 = 0 %start
    %if cat1 = inty %and ok&realok # 0 %start
      toreal;  cat1 = realy
    %else %if ok&stringok # 0 %and valok(stringtype,type)
      cat1 = stringy
    %else
      fault(typerr+point)
    %finish
  %finish
  type1 = type;  item1 = item;  val1 = value
%end

%integer%fn FROZEN LIT(%integer t,v)
! Used when the type of a literal will not be recoverable from context
%integer hold,res
  hold = item
  putexp(move,0,litref(v),t);  !NO-OP (distinctive Y)
  ditem_flags = okflag+wflag
  ditem_mode = constmode;  ditem_val = v
  res = item;  item = hold
  %result = res
%end

%routine COERCE(%integer c)
  %if c = inty %and cat1 = realy %start
    toreal
  %else %if cat1 = inty %and c = realy
    ![rather sloppy]
    %if item1 # 0 %start
      val1 = item;  item = item1
      toreal
      item1 = item;  item = val1
    %finish %else real(addr(val1)) = val1
    type1 = realtype;  cat1 = realy
  %else
    expfault(typerr)
  %finish
%end

%routine GET ARITH(%integer rank)
  get EXPRESSION(rank,0)
  rank = category(type)
  coerce(rank) %if rank # cat1
%end

%integer%fn RCOND(%integer op)
%constinteger EQUAL=2_1001000010,
              LESS =2_1010000001,
            GREATER=2_0101000001
%integer which,c
!<= 0
    double = item
  %else %if double < 0
    double = -2
  %finish
!< 0 %or item1!val1 = 0 %or item!value = 0 %start
        !non-structure (compile-time)
        ![integer tests ok for real?]
        %if val1 < value %then which = less -
        %else %if val1 = value %then which = equal -
        %else which = greater
        %result = which>>(op-bne)&1
      %finish
      item1 = frozen lit(type1,val1)
    %else
      swop
      op = op!!3 %if op&8 # 0;  !no change for '=','#'
    %finish
  %finish
  %result = op
%end;  !RCOND
!< op(atom)
op(plus):
  check1(numok+setok)
  get ARITH(star)
  %if cat1 = inty %start
    %if item1 = 0 %start
      %result = val1+value %if item = 0
      swop
    %finish
    %result = nop %if item!value = 0
    type = inttype
    %result = add
  %else
    %if item1 = 0 %start
      %if item = 0 %start
        real(addr(val1)) = real(addr(val1))+real(addr(value))
        %result = val1
      %finish
      swop
    %finish
    %result = nop %if item!value = 0
    %result = fadd
  %finish
op(minus):op(uminus):
  check1(numok+setok)
  get ARITH(star)
  %if cat1 = inty %start
    %if item1 = 0 %start
      %result = val1-value %if item = 0
      swop %and %result = neg %if val1 = 0
    %finish
    type = inttype
    %if item = 0 %start
      %result = nop %if value = 0
      value = -value %if value # minint
      %result = add
    %finish
    %result = sub
  %else
    %if item = 0 %start
      %if item1 = 0 %start
        real(addr(val1)) = real(addr(val1))-real(addr(value))
        %result = val1
      %finish
      %result = nop %if value = 0
    %finish
    %result = fsub
  %finish
op(exclam):
  check1(intok);  get EXPRESSION(star,inttype)
  %if item1 = 0 %start
    %result = val1!value %if item = 0
    swop
  %finish
  %result = nop %if item!value = 0
  type = inttype
  %result = or
op(exclam2):
  check1(intok);  get EXPRESSION(star,inttype)
  %if item1 = 0 %start
    %result = val1!!value %if item = 0
    swop
  %finish
  %result = nop %if item!value = 0
  type = inttype
  %result = eor
op(ampersand):
  check1(intok);  get EXPRESSION(star2,inttype)
  %if item1 = 0 %start
    %result = val1&value %if item = 0
    swop
  %finish
  item1 = 0 %and %result = 0 %if item!value = 0
  type = inttype
  %result = and
op(star):
  check1(numok+setok)
  get ARITH(star2)
  item1 = 0 %and %result = 0 %if item!value = 0
  %if cat1 = inty %start
    %if item1 = 0 %start
      %result = val1*value %if item = 0
      swop
    %finish
    val1 = type;  type = inttype
    %result = muls %if control&halfbit # 0
    %result = imul %if type1 = inttype
    %if item = 0 %start
      %result = imul %if value&(value-1) = 0  {power of 2}
      val1 = value
    else 
      val1 = lower(type);  value = upper(type)
    finish 
    result  = mulop(lower(type1),upper(type1),val1,value)
  else 
    if  item1 = 0 start 
      if  item = 0 start 
        real(addr(val1)) = real(addr(val1))*real(addr(value))
        result  = val1
      finish 
      swop
    finish 
    result  = fmul
  finish 
op(over):
  check1(intok);  get EXPRESSION(star2,inttype)
  if  item = 0 start 
    fault(rangerr) and  result  = nop if  value = 0
    result  = val1//value if  item1 = 0
  finish 
  type = inttype
  result  = idiv
op(slash):
  check1(realok)
  get EXPRESSION(star2,realtype)
  if  item = 0 start 
    fault(rangerr) and  result  = nop if  value = 0
    if  item1 = 0 start 
      real(addr(val1)) = real(addr(val1))/real(addr(value))
      result  = val1
    finish 
  finish 
  result  = fdiv
op(backslash2): op(uparrow2):
  check1(intok);  get EXPRESSION(simple,inttype)
  if  item = 0 start 
    result  = val1\\value if  item1 = 0
    item1 = 0 and  result  = 1 if  value = 0
    result  = nop if  value = 1
    item = item1 and  result  = imul if  value = 2
  finish 
  type = inttype
  result  = ipow
op(backslash): op(uparrow): op(star2):
  check1(realok)
  get EXPRESSION(simple,inttype)
  type = realtype
  if  item!item1 = 0 start 
    real(addr(val1)) = real(addr(val1))\value
    result  = val1
  finish 
  result  = fpow
op(lshift):
  check1(intok);  get EXPRESSION(simple,inttype)
  if  item = 0 start 
    result  = val1<<value if  item1 = 0
    result  = nop if  value = 0
  finish 
  type = inttype
  result  = lsl
op(rshift):
  check1(intok);  get EXPRESSION(simple,inttype)
  if  item = 0 start 
    result  = val1>>value if  item1 = 0
    result  = nop if  value = 0
  finish 
  type = inttype
  result  = lsr
op(tilde):
  check1(intok)
  get EXPRESSION(simple,inttype)
  result  = \value if  item = 0
  swop
  type = inttype
  result  = not
op(sconc):
  check1(stringok);  get EXPRESSION(dot+1,stringtype)
  if  item = 0 start 
    if  item1 = 0 start 
      result  = val1 if  value = 0
      result  = value if  val1 = 0
      if  final(val1)+final(value) <= 255 start 
        string(final0+val1) = string(final0+val1) -
                                 . string(final0+value)
        cad = cad-1
      finish  else  fault(rangerr)
      result  = val1
    finish 
    result  = nop if  value = 0
  else  if  item1!val1 = 0
    item1 = item;  val1 = value;  type1 = type
    result  = nop
  finish 
  type = stringtype
  result  = concat
op(equals):
  result  = RCOND(beq)
op(noteq):
  result  = RCOND(bne)
op(lesseq):
  result  = RCOND(ble)
op(less):
  result  = RCOND(blt)
op(greateq):
  result  = RCOND(bge)
op(greater):
  result  = RCOND(bgt)
integer fn  RACOND(integer  op)
  toref
  item1 = normitem;  type1 = type
  get REFERENCE(type1)
  val1 = 0 and  swop if  item1 = 0
  syntax error if  arrow <= atom <= greater
  double = -2
  result  = op
end 
op(eqeq):
  result  = RACOND(beq)
op(noteqeq):
  result  = RACOND(bne)
op(arrow):
  check1(stringok)
  item1 = litref(val1) if  item1 = 0
  get RESOLUTION(type,item1)
  item1 = np-3
  condop = bne!!polarity
  type1 = booltype
  result  = nop
op(keyand):
  topred if  condop = 0
  item1 = np;  type1 = booltype
  putact(condop!!polarity!!1+polarity<<7,item,0)
  condop = 0
  get EXPRESSION(scond,booltype)
  dict(item1)_y = item
  syntax error if  a(keyor)
  result  = nop
op(keyor):
  topred if  condop = 0
  item1 = np;  type1 = booltype
  putact(condop!!polarity+(polarity!!1)<<7,item,0)
  condop = 0
  get EXPRESSION(scond,booltype)
  dict(item1)_y = item
  syntax error if  a(keyand)
  result  = nop
end 

routine  PUT INDEX(integer  op)
integer  size,lo,hi
  if  item = 0 and  ditem1_flags&(name+indirect) = 0 -
  and  (item1 < dictlim or  ditem1_act < 0) start 
    size = 1;  lo = 0
    get array info(tp,size,lo,hi) if  op # sindex
    if  size # 0 and  lo # minint start     {known lower bound}
      putexp2(-op,item1,tp_type)
      ditem_mode = ditem1_mode;  ditem_val = ditem1_val+(value-lo)*|size|
      return 
    finish 
  finish 
  putexp2(op,item1,tp_type)
  ditem_mode = ditem1_mode
end 

!Get leading operand
  atom = next atom if  matched # 0
  atomp0 = atomp;  jammy = jammy<<1;  !preserve
  if  atom = ident start 
    matched = 1
    name error if  item <= 0 or  (ditem_mode = labmode and  item < c_localdpos)
    fault(namerr+point) if  item >= dlim0
    type = ditem_type
    if  ditem_flags&typeid # 0 start 
      item1 = item;  ditem1 == ditem
      if  a(less) start ;  !typeid - type coercion
        get VALUE(0);  get(greater)
        type = item1
      else  if  ditem_flags&cat = recy and  item > dnil
        get RECORD
        return 
      else 
        get(left);          !store mapping
        get VALUE(inttype)
        get(right)
        putexp2(storemap,item1,item1)
        ditem_flags = writable!readable
        ditem_mode = dispmode
      finish 
    else  if  ditem_mode = litmode
      item = 0;  value = ditem_val
    else ;                                    !non-literal ident
      cycle 
        if  ditem_flags&proc # 0 start 
          if  item = daddr or  item = dsizeof or  item = dnew start 
            get(left)
            item1 = item
            get REFERENCE(0)
            if  item1 = daddr start 
              type = inttype
            else 
              value = |size(type)|
              expfault(sizerr) if  value = 0
              if  item1 = dsizeof start 
                item = 0;  type = inttype
              else 
                putexp(dnew,0,litref(value),0)
                ditem_mode = dispmode
              finish 
            finish 
            get(right)
!          %else %if item = dsnl
!            putexp(dtostring,nl,0,string1)
          else 
            exit  if  literal < 0    {proc name only}
            get PARLIST(0)
            atomp=atomp0 and  error(classerr+point) if  type = 0;  !routine
          finish 
        else ;                                   !not procedure
          atom = next atom if  matched # 0
          exit  unless  aleft <= atom <= recsub and  rank <= simple
          matched = 1
          if  atom = aleft start ;  !array subscript
            cycle 
              item1 = item;  ditem1 == ditem
              tp == dict(type)
              if  tp_flags&cat = stringy start 
                nonstandard(2)
                get VALUE(bytetype)
                put index(sindex)
              else 
                syntax error unless  tp_flags&cat = arry
                get VALUE(tp_xtype);  !get index
                put index(index)
              finish 
              ditem_flags = ditem1_flags&heritable
            repeat  until  not  a(comma)
            ditem_flags = ditem_flags+(tp_flags&name)
            get(right)
          else  if  atom = recsub;  !record subfield
            item1 = item;  ditem1 == ditem
            dformat == dict(ditem_type)
            syntax error unless  dformat_flags&cat = recy
            subbed = 1;  get(ident);  subbed = 0
            error(namerr+point) if  item <= 0
val1 = ditem_flags;  val1 = val1!ditem1_flags&heritable
!            val1 = ditem1_flags&heritable!ditem_flags
            if  (ditem1_flags&(name+indirect) = 0 -
                 or  ditem1_mode&2_111000 = aregmode) -
            and  (item1 < dictlim or  ditem1_act < 0) start 
              {compile-time ad eval}
              value = ditem_val
              putexp2(-recref,item1,ditem_type)
              ditem_mode = ditem1_mode;  ditem_val = ditem1_val+value
              if  ditem_mode&2_111000 = aregmode -
              then  ditem_mode = ditem_mode+(dispmode-aregmode)
            else 
              putexp2(recref,item1,ditem_type)
              ditem_mode = ditem1_mode
            finish 
            ditem_flags = val1
          else  if  atom = atsign
            nonstandard(4)
            syntax error if  ditem_flags&typeid = 0
            ditem1 == ditem;  item1 = item
            get EXPRESSION(vsimple,inttype)
            putexp2(storemap,item1,item1)
            ditem_flags = writable!readable
            ditem_mode = dispmode
          else ;  !leftb: pointer relative
            error(nonref+point) if  ditem_mode < dispmode
            fault(sizerr) if  size(ditem_type) = 0
            ditem1 == ditem;  item1 = item
            get VALUE(inttype);  get(rightb)
            putexp2(prel,item1,ditem1_type)
            ditem_flags = writable!readable
            ditem_mode = ditem1_mode
          finish 
        finish 
      repeat 
    finish 
  else 
    if  atom = const start 
      matched = 1
    else  if  atom = minus;  !leave unmatched
      item = 0;  value = 0;  type = inttype
      atom = uminus;         !bang up precedence
    else  if  atom = left
      matched = 1
      if  rank < major start ;  !condition
        get EXPRESSION(condq,0)
      else 
        get EXPRESSION(major,0)
      finish 
      get(right)
    else  if  atom = hashsign
      matched = 1;  literal = literal-8
      get REFERENCE(0)
      literal = literal+8
      type = inttype
    else  if  a(keynot)
      syntax error if  rank >= major
      polarity = polarity!!1
      get EXPRESSION(scond,booltype)
      if  item = 0 then  value = value!!1
      polarity = polarity!!1
    else  if  atom = backslash
      item = 0;  value = 0;  type = inttype
      atom = tilde
    else  if  a(modsign)
      get EXPRESSION(major,0)
      if  valok(inttype,type) start 
        if  item = 0 start 
          if  value < 0 start 
            if  value # minint then  value = -value else  expfault(rangerr)
          finish 
        else 
          putexp2(iabs,0,inttype)
        finish 
      else  if  valok(realtype,type)
        putexp2(fabs,0,realtype)
      else 
        error(typerr+point)
      finish 
      get(modsign)
    else 
      syntax error
    finish 
  finish 

  atom = next atom if  matched # 0;  ![always primed on return]

  if  etype < 0 start ;  !reference required
    expp = atomp0;  jammy = jammy>>1;  !restore
    toref
    expfault(typerr) if  not  refok(etype-sign16,type)
  else 
    while  atom >= rank cycle 
      matched = 1
      double = -1
      op = opval
      if  item1!item = 0 start ;  !both literal
        if  double # -1 start 
          if  double >= 0 start 
            literal = literal+2;  !enforce all literal
            op = op&opval
            literal = literal-2
          finish 
          type = booltype
        finish 
        value = op
      else  if  double = -1;         !not relop
        if  op # 0 start 
          item1 = litref(val1) if  item1 = 0
          putexp(op,item1,normitem,type)
        else ;         !nop
          item = item1;  type = type1
        finish 
      else ;                      !conditional operation
        condop = op!!polarity
        putact(compare,item1,normitem)
        item = np-1
        if  double >= 0 start 
          putact(condop!!polarity!!1+polarity<<7,np-1,np+1);  !implicit %and
          item = double;  ![TYPE,VALUE unchanged]
          matched = 1
          op = opval
          error(nonliteral) if  item1!item = 0;  !mixed non-lit, lit
          condop = op!!polarity
          putact(compare,item1,normitem)
          item = np-2
        finish 
        type = booltype
      finish 
    repeat 
    expp = atomp0;  jammy = jammy>>1
    if  etype # 0 start 
      if  type = booltype start 
        topred if  (rank = cond or  rank = scond) and  condop = 0
      finish 
      expfault(typerr) if  not  valok(etype,type)
    finish 
  finish 
  if  (literal > 0 and  item # 0) -
  or  (literal < 0 and  item >= dictlim and  ditem_act >= 0) start 
    atomp = expp;  error(nonliteral+point)
  finish 
end ;  !get EXPRESSION
  
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Conditions and loops  !!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
routine  GET CONDITION
integer  maxlab,condnp

routine  ASSIGN LABELS(integer  p,lab,pol)
integer  base=maxlab
record (identinfo)name  dp
  while  (p-condnp)&1 # 0 cycle ;  !compound
    dp == dict(p);  p = dp_y
    if  dp_act&1<<7 = pol then  assign labels(dp_x,lab,pol) -
    else  maxlab = base+1 and  assign labels(dp_x,maxlab,pol!!1<<7)
  repeat 
  dp == dict(p+1);  dp == dp[2] if  dp_act = 0;  !resolution
  if  maxlab > base then  dp_x = maxlab and  maxlab = base -
  else  dp_x = 0
  dp_y = lab
  dp_act = dp_act&127
end 

  condnp = np
  polarity = subatom;  condop = 0
  get EXPRESSION(cond,booltype)
  putact(condop!!1,item,0)
  return  if  faultnum > 0
  maxlab = curlab+1
  assign labels(item,maxlab,0)
end ;  !get CONDITION

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

routine  DO DYNAMIC ARRAYS
  update sp
  c_mode = c_mode!2_01000000;   !bar to SP rel addressing
  c_status = c_status!globbed;  !needs link
  while  c_dynarray # 0 cycle 
    if  c_dynarray < 0 then  putact(aget,-c_dynarray,one) -
    else  putact(aget,c_dynarray,0)
    c_dynarray = dict(|c_dynarray|)_link
  repeat 
  compile(np0)
end 

routine  GET STATEMENTS(integer  stopper)
! STOPPER = 0          -- initial call
!          -1          -- %section
!           1 (END)    -- for procedure or block body
!           2 (REPEAT) -- for loop body
!           3 (FINISH) -- for condition body (ELSE not valid)
!           4 (ELSE)   --         "          (ELSE valid)
switch  initial(0:atommax)
integer  forinf,endval,loopstart

routine  THIS IS INST
  if  c_status < hadinst start ;  !first in block
    c_status = c_status+hadinst
    fault(ordererr) if  stopper <= 0
  finish 
  fault(accesserr+warn) if  c_access = 0 and  np = np0
  do dynamic arrays if  c_dynarray # 0
end 

routine  PUTACT2(integer  act,item1)
  putact(act,item1,normitem)
end 

routine  GET RESULT
  get VALUE(c_type)
!  fault(rangerr+warn) %if c_type > 0 %and item # 0 -
!                      %and |size(type)| > |size(c_type)|
end 

routine  GET INSTRUCTION
integer  item1
record (identinfo)name  tp
  this is inst
  cycle 
    if  a(ident) start 
      name error if  item <= 0
      if  ditem_flags&(writable!typeid) # 0 start 
        matched = 0
        get EXPRESSION(simple,0)
        item1 = item
        if  a(equals) start 
          jammy = 0
          get VALUE(type)
          putact2(okass+jammy,item1);  !okass,assign
        else  if  a(eqeq)
          syntax error if  ditem_flags >= 0
          get REFERENCE(type)
          putact2(assign,item1+ad)
        else  if  atom = less and  byteintegeR(fp) = '-'
          fp = fp+1;  matched = 1
          jammy = 1
          get VALUE(type)
          putact2(jamass+jammy,item1);  !jamass,okass
        else 
          syntax error if  not  a(arrow)
          get RESOLUTION(type,item1)
          putact(bne,0,curlab)
          putact(signal,litref(7),undef)
          putact(0,undef,undef)
        finish 
      else 
        error(classerr+point) if  ditem_flags&proc = 0
        tp == dict(ditem_type)
        if  tp_type # 0 start ;  !function as routine
          get PARLIST(tp_type)
          putact2(assign,value)
        else 
          get PARLIST(0)
        finish 
      finish 
    else 
      c_access = 0 if  np = np0;  !unconditional
      if  a(keymonitor) start 
        c_access = 1
!        fault(monitor<<8)
     else  if  a(exit);  !%exit, %continue
        if  c_looplab = 0 then  fault(notinloop+point) -
        else  putact(jumpout,c_looplab,c_looplab+subatom)
        exit 
     else  if  a(keyreturn)
        item = 0;  value = 0
        get RESULT if  c_type # 0
        putact2(return,0)
        exit 
     else  if  a(keyresult)
        error(notinfun+point) if  c_type = 0
        syntax error if  not  a assop(c_type)
        get RESULT
        putact2(return,0)
        exit 
     else  if  a(tf);  !%true, %false
        if  c_type # booltype then  fault(notinpred+point) -
        else  putact(return,0,litref(subatom))
        exit 
     else  if  a(arrow) or  a(keygoto)
        nonstandard(5) if  atom = keygoto
        get(ident)
        if  byteinteger(fp) # '(' start 
          declare(forwardlabel) if  item < c_localdpos {new} -
                                or  ditem_type # 0 {error}
          putact2(goto,0)
        else 
          name error if  item < c_localdpos
          error(classerr+point) unless  ditem_mode = labmode -
                                and  ditem_type # 0
          item1 = item
          get(left)
          get VALUE(dict(ditem_type)_xtype);  !index
          get(right)
          putact2(swgoto,item1)
        finish 
        exit 
     else  if  a(keystop)
        putact(stop,0,0)
        exit 
     else  if  a(keysignal)
        c_access = 1
        allow(keyevent)
        get LITERAL(inttype)
        expfault(rangerr) unless  0 <= value <= 15
        item1 = litref(value);  item = undef
        if  a(comma) start 
l1:       if  a(comma) then  matched = 0 else  get VALUE(bytetype)
        finish 
        putact2(signal,item1)
        item = undef
        if  a(comma) start 
l2:       if  a(comma) then  matched = 0 else  get VALUE(inttype)
        finish 
        item1 = normitem;  item = undef
        get VALUE(stringtype) if  a(comma)
        putact2(0,item1)
        exit 
      else 
        syntax error
      finish 
    finish 
  repeat  until  not  a(keyand)
end ;  !GET INSTRUCTION

routine  GET FOR CLAUSE
!Global: FORINF,ENDVAL
integer  loopvar,lvtype,k,s,start,sval,i,inc,ival,e,n
integer  end
record (identinfo)name  tp
  forinf = 0
  get(ident)
  name error if  item <= 0
  lvtype = ditem_type;  tp == dict(lvtype)
  fault(typerr+point) if  tp_flags&nonord # 0
  loopvar = item
  get(equals)
  get VALUE(lvtype)
  start = item;  sval = value
  get(comma)
  get VALUE(lvtype)
  inc = item;  ival = value
  expfault(rangerr) and  ival = 1 if  inc = 0 = ival
!Deal with INC and replace START by START-INC
  k = undef
  k = dict(start)_y if  start >= np0 and  dict(start)_act = add
  if  inc = 0 start ;  !literal increment
    i = litref(ival)
    if  start = 0 start ;  !START and INC both literal
      sval = sval-ival;  item = litref(sval)
    else  if  k <= 0;  !START is x+lit
      k = litval(k)-ival
      item = dict(start)_x
      putexp(add,item,litref(k),inttype) if  k # 0
    else 
      putexp(add,start,litref(-ival),inttype)
    finish 
  else ;  !variable
    i = inc
    if  control&volbit # 0 start 
      declare temp(inttype);  i = item
      putact(assign,i,inc);  forinf = forinf-4
    finish 
    if  start = inc start ;  !identical
      item = 0;  sval = 0
    else  if  k = inc;  !START is x+INC
      item = dict(start)_x
    else 
      item = start;  item = litref(sval) if  item = 0
      putexp(sub,item,i,inttype)
    finish 
  finish 
  s = item
!Get end-value
  get(comma)
  get VALUE(lvtype)
  end = item
  if  end = 0 start ;  !literal end-value
    e = litref(value);  endval = value
  else 
    e = item
    if  control&volbit # 0 start 
      declare temp(inttype);  e = item
      putact(assign,e,end);  forinf = forinf-4
    finish 
  finish 
  if  start!inc!end # 0 and  control&loopbit # 0 start 
    putact(forass,loopvar,s)
    putact(forass,i,e)
  else 
    putact(assign,loopvar,s)
  finish 
  putact(label,curlab,0)
  if  start!inc!end = 0 start ;  !all literal
    k = endval-sval;  n = k//ival
    if  n = 0 start 
      fault(dubious+warn)
      putact(else,0,curlab+1);  !ie unconditional branch
      return 
    finish 
    fault(boundserr) if  n < 0
    fault(unending) if  n*ival # k
    forinf = loopvar
  else 
    putact(compare,loopvar,e)
    putact(beq,0,curlab+1)
  finish 
  putact(incass,loopvar,i)
end ;  !get FORCLAUSE

routine  GET LOOP BODY
integer  hold=c_looplab
  c_looplab = curlab;  curlab = curlab+2
  get STATEMENTS(keyrepeat)
  curlab = curlab-2;  c_looplab = hold
end 

routine  GET SWITCH INDEX
integer  i
record (identinfo)name  dp,tp
routine  SET LABEL(shortname  p)
  value = p
  expfault(duperr) if  value > 0
  set user label(value)
  p = value
end 
  dp == ditem;  tp == dict(ditem_type)
  get(left)
  if  a(star) start 
    set label(dp_link)
  else 
    get VALUE(tp_xtype)
   !beware faulty declaration or index
    if  tp_xtype > inttype and  faultnum = 0 start 
      i = value-lower(tp_xtype)+dp_val
      c_forward = c_forward-1 if  i < pc;  !(had goto)
      set label(prog(i))
    finish 
  finish 
  get(right)
end 

![unsure of efficiency implications of trapping overflow lower down]
on  event  oflow,fail,done start 
  if  event_event = 0 start ;  !failure in %option,%include or ^Y
    stop  if  event_sub # 0
    signal  abandon
  finish 
  if  event_event = done start 
    croak("Premature end of input") if  stopper # 0
    close block
    c_dpid_val = 0;  !zero entry-point
    return 
  finish 
  fault(rangerr+now) if  event_event = oflow
  -> ignore
finish 
!!!!!!!!!!!!!!!!!!!  Start of new statement  !!!!!!!!!!!!!!!!!!!
next:
  statements = statements+1
  compile(startnp) if  np > np0
  define label(curlab) if  dict(curlab)_val < 0
  define label(curlab+1) if  dict(curlab+1)_val < 0
next1:
  report(faultnum,0,0) if  faultnum # 0
  dlim0 = dlim;  dmin = dmin0
  speccing = 0;  subbed = 0
  literal = 0;  jammy = 0;  condop = 0
  dict(curlab)_val = 0;  dict(curlab+1)_val = 0
  np = np0;  startnp = np0
  maxcalldreg = maxdreg;  maxcallareg = maxareg
  zaps = zaps+1 and  forget all if  explo < np0+50
  zaps = zaps+1000 and  forget all if  litpos > litmax-40
  value = 0
!
initial(terminator):
  atom = next atom;  matched = 1
  -> initial(atom)

{initial(keycomment):} initial(exclam): initial(exclam2):
  comments = comments+1
  read line(0)
  -> next1
term:
  get(terminator)
  -> next

ignore:
  c_access = -1
  if  atom # terminator start 
    cycle 
      subatom = atom;  atom = next atom
    repeat  until  atom = terminator
    starts = starts+1 if  subatom = keystart
    cycles = cycles+1 if  subatom = keycycle
  finish 
  -> next1

initial(dud):
  syntax error;  !ie atom error

routine  get IEF
!Get IF(+1), ELSE(0), FINISH(-1) after dollar-sign
! update CCOND accordingly
  percent = 1                        {fool NEXT ATOM}
  if  a(iu) start 
    value = 1;  ccond = ccond<<2!3
  else 
    error(noif) if  ccond = 0
    if  a(keyelse) start 
      value = 0
    else 
      get(keyfinish)
      value = -1;  ccond = ccond>>2
    finish 
  finish 
end 

routine  get CCOND
integer  hold=ccond>>2
cycle 
  if  value > 0 start                  {$IF}
    literal = 1;  condop = 0;  polarity = subatom
    syntax error if  polarity # 0
    get EXPRESSION(equals,booltype)    {get condition}
    return  if  value # 0              {condition true}
  finish 
 {Ignore}
  cycle 
    cycle 
      read line('-')
      cycle 
        sym = byteintegeR(fp);  fp = fp+1
      repeat  until  sym # ' '
    repeat  until  sym = '$'
    matched = 1
    get ief
    if  value < 0 start            {$FINISH}
      return  if  ccond = hold
    else  if  value = 0 and  ccond>>2 = hold  {$ELSE}
      error(noif) if  ccond&1 = 0
      percent = 1
      value = 1                    {$ELSE IF}
      ccond = ccond-1 and  percent = 0 and  return  if  not  a(iu)
      exit 
    finish 
  repeat 
repeat 
end 
initial(dollar):
  get ief
  if  value >= 0 start       {$IF, $ELSE}
    error(noif) if  value = 0 and  ccond&1 = 0 {$ELSE after $ELSE}
    get ccond
  finish 
  -> term

initial(*):
  error(nonstarter+point)

initial(ident):
  if  byteintegeR(fp) = ':' start ;  !simple label
    fp = fp+1
    declare(definedlabel)
    set user label(ditem_val)
    ->next
  finish 
  name error if  item <= 0
  if  ditem_mode = labmode and  ditem_type # 0 start 
    literal = 1
    get SWITCH INDEX
    get(colon)
    ->next
  finish 
initial(keyreturn): initial(keyresult): initial(tf):
initial(keystop): initial(keysignal): initial(keymonitor):
initial(exit): initial(keygoto): initial(arrow):
  matched = 0
  get INSTRUCTION
  -> next if  a(terminator)
  c_access = 1
  if  a(iu) start 
    startnp = np
    get CONDITION
  else  if  a(keywhile)
    putact(repeat,curlab,0);  !append repeat
    startnp = np
    define label(curlab)
    get CONDITION
 else  if  a(keyfor)
    putact(0,0,0)
    putact(0,0,0)
    putact(repeat,curlab,0);  !append repeat
    startnp = np
    get FOR CLAUSE
    value = np;  np = startnp-3
    if  forinf > 0 start 
      putact(compare,forinf,litref(endval))
      putact(beq,0,curlab)
    finish  else  np = np+2
    putact(repeat,curlab,forinf)
    np = value
  else 
    syntax error if  not  a(keyuntil)
    get CONDITION
    putact(repeat,curlab,0)
    define label(curlab)
  finish 
  -> term

initial(iu):  !if , unless 
  this is inst
  cycle 
    get CONDITION
    if  a(keythen) and  not  a(keystart) start 
      get INSTRUCTION
    else 
      matched = 0;   ![unsee %start]
      get(keystart)
      cycle 
        get(terminator)
        curlab = curlab+2
        get STATEMENTS(keyelse)
        curlab = curlab-2
        exit  if  atom # keyelse;  !%finish ->
        putact(else,curlab+1,curlab)
        -> exit2 if  not  a(iu)
        get CONDITION
      repeat 
      -> initial(keyend) if  atom = keyend
    finish 
    -> term if  not  a(keyelse)
    putact(else,curlab+1,curlab)
  repeat  until  not  a(iu)
  if  not  a(keystart) start 
    get INSTRUCTION
  else 
exit2:
    get(terminator)
    curlab = curlab+2
    get STATEMENTS(keyfinish)
    curlab = curlab-2
    -> initial(keyend) if  atom = keyend
  finish 
  -> term

initial(keycycle):
  this is inst
  if  a(terminator) start 
    define label(curlab)
    get LOOP BODY
    ->initial(keyend) if  atom = keyend
    get CONDITION if  a(keyuntil)
    putact(repeat,curlab,0)
    -> term
  finish 
  nonstandard(22)
  get FOR CLAUSE
  -> for1
initial(keywhile):
  this is inst
  define label(curlab)
  get CONDITION
  get(keycycle)
  get(terminator)
  compile(np0)
  get LOOP BODY
  -> initial(keyend) if  atom = keyend
  nonstandard(6) and  get CONDITION if  a(keyuntil)
  putact(repeat,curlab,0)
  ->term
initial(keyfor):
  this is inst
  get FOR CLAUSE
  get(keycycle)
for1:
  get(terminator)
  compile(np0)
  if  forinf > 0 start ;           !Literal for loop
   !%continue must come to end for increment
    loopstart = dict(curlab)_val;  !save start position
    dict(curlab)_val = 0
  finish 
  get LOOP BODY
  -> initial(keyend) if  atom = keyend
  if  forinf > 0 start ;  !literal FOR loop
    define label(curlab)
    dict(curlab)_val = loopstart;  !restore
    putact(compare,forinf,litref(endval))
    putact(beq,0,curlab)
  finish 
  putact(repeat,curlab,forinf)
  -> term

initial(keyon):
  fault(ordererr+point) if  c_status >= hadon or  stopper <= 0
  do dynamic arrays if  c_dynarray # 0
  c_status = c_status!hadon
  matched = 1
  allow(keyevent)
  dump = 0
  cycle 
    get LITERAL(inttype)
    expfault(rangerr) unless  0 <= value <= 15
    dump = dump!1<<value
  repeat  until  not  a(comma)
  get(keystart)
  putact(settrap,0,litref(dump))
  curlab = curlab+2
  get STATEMENTS(keyfinish)
  curlab = curlab-2
  -> initial(keyend) if  atom = keyend
  -> term
!
initial(keyelse):
  -> ignore if  starts # 0
  return  if  stopper = keyelse
  error(noif) if  stopper = keyfinish
initial(keyfinish):
  starts = starts-1 and  -> ignore if  starts # 0
  return  if  stopper = keyfinish or  stopper = keyelse
  error(nostart)
initial(keyrepeat):
  cycles = cycles-1 and  -> ignore if  cycles # 0
  return  if  stopper = keyrepeat
  error(nocycle)

routine  LOW
  if  control&lowbit = 0 start 
    fault(lowlevel+warn+point);  control = control!lowbit
  finish 
end 

initial(star):
  low
  matched = 1
  if  byteinteger(fp) = '=' start 
    fp = fp+1
    get LITERAL(inttype)
    plant(dc,0,temp(absmode,value))
  else 
    get MCODE
  finish 
  ->term

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!  Declarations  !!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
routine  DECLARE LIT RANGE(integer  basetype,lo,hi)
own record (objinfo) D=0
  fault(boundserr) and  hi = lo if  lo > hi
  item = ranges
  cycle 
    ditem == dict(item)
    item = item-2 and  return  if  ditem_val = hi and  ditem_type = basetype -
          and  ditem[-1]_val = lo
    item = ditem_hlink
  repeat  until  item = 0
  declare anon(d);               !blank (for updating)
  declare range(basetype,lo,hi)
end 

routine  DECLARE STRING TYPE(integer  size)
  item = stringtype and  return  if  size = -256
  item = string1 and  return  if  size = -2
  item = ranges
  cycle 
    ditem == dict(item)
    return  if  ditem_size = size and  ditem_type = chartype
    item = ditem_hlink
  repeat  until  item = 0
  declare anon(details(typeid+stringy,chartype,0,0))
  ditem_size = size
  ditem_hlink = ranges;  ranges = item
end 

routine  GET LIT RANGE(integer  basetype)
integer  holdval
  get LITERAL(basetype);  holdval = value
  get(colon)
  get LITERAL(basetype)
  declare lit range(basetype,holdval,value)
end 

routine  GET IDENTLIST(record (objinfo)name  d)
  dlim0 = dlim
  get(ident) and  declare(d) until  not  a(comma)
end 

routine  RECALIGN(integername  val)
  align(val,2)
  val = -val if  val > 4
end 

routine  GET DECLARATION(integer  FLAGS,MODE,integer name  DISP,integer  DEPTH)
record (objinfo) DECL
record (identinfo)name  DFHOLD
owninteger  ITEMTYPE=0,ITEMSIZE=0,ADIM=0
integer  BASE,HOLD,MAX,STMAX,DREG,AREG

routine spec  GET VAR BOUND

routine  GET DATA TYPE
switch  s(ktype:keyname)
  atom = next atom if  matched # 0
  syntax error unless  ktype <= atom <= keyname
  matched = 1
  -> s(atom)
s(ktype):
  itemtype = inttype+subatom
  itemsize = size(itemtype)
  nonstandard(7) if  itemtype >= mitetype
  allow(keyinteger)
  return 
s(keyinteger):                    !integer 
  itemtype = inttype;  itemsize = 4
  if  a(left) start 
    nonstandard(8)
    get LIT RANGE(inttype)
    get(right)
    itemtype = item
    itemsize = |dict(itemtype)_size|
  finish 
  return 
s(keylong):                   !long 
  itemtype = inttype;  itemsize = 4;  !**for now**
  if  a(keyinteger) then  fault(notin+point+warn) -
  else  itemtype = realtype and  get(keyreal)
  return 
s(keyreal):                   !real 
  itemtype = realtype;  itemsize = 4
  return 
s(keystring):                 !string 
  itemsize = 0
  if  a(left) start 
    atom = next atom
!    %if depth # 0 %and ktype <= atom <= keyinteger %start
!      get VAR BOUND
!      itemtype = stringstar
!    %else %if a(star)
    if  a(star) start 
      itemtype = stringstar
    else 
      get LITERAL(bytetype)
      itemsize = -(value+1)
      declare string type(itemsize)
      itemtype = item
    finish 
    get(right)
  else 
    syntax error if  mode # constmode
    itemtype = stringtype
  finish 
  return 
s(keyrecord):                    !record 
  get(left)
  if  not  a(star) start 
    if  not  a(ident) start 
      declare anon(typeident)
      hold = item;  dfhold == dformat
      dformat == ditem
      get DECLARATION(writable+readable,0,dformat_val,0)
      recalign(dformat_val)
      ditem == dformat
      dformat == dfhold;  item = hold
    finish 
    name error if  item <= 0
    error(classerr+point) if  ditem_flags&(\spec) # typeid+recy
    itemtype = item;  itemsize = ditem_val
  else 
    itemtype = recstar;  itemsize = 0
  finish 
  get(right)
  return 
s(keyname):    !untyped name  - leave unmatched
  itemtype = 0;  matched = 0
end 

routine  ASSIGN ADDRESS(integer  size)

routine  ASSIGN STACK ADDRESS
  align(stmax,2);  ditem_val = stmax
  stmax = stmax+|size|
  c_status = c_status!onstack if  depth = 1 and  speccing = 0
end 

integer fn  MAXFREE(integer  regset)
integer  r=a7
  if  regset = 0 start 
    fault(plexerr)
  else 
    r = r-1 and  regset = regset<<1 while  regset&16_8000 = 0
  finish 
  result  = r
end 

  size = -4 if  ditem_flags&(name+indirect) # 0
  if  mode # 0 and  decl_mode&2_110000 = 0 start ;  !%register
    if  decl_mode # a7-d0 start     {register given}
      decl_mode = decl_mode+1       {for next time}
    else  if  depth # 0                  {parameter}
      if  size > 0 start 
        fault(plexerr) if  dreg > maxcalldreg
        ditem_mode = dreg-d0;  dreg = dreg+1
      else 
        fault(plexerr) if  areg > maxcallareg
        ditem_mode = areg-d0;  areg = areg+1
      finish 
    else 
      if  size > 0 start 
        ditem_mode = maxfree(c_free&(anydreg-bregb))-d0
      else 
        ditem_mode = maxfree(c_free&anyareg)-d0
      finish 
    finish 
    if  depth # 0 start 
      ditem_reg = ditem_mode
      dlink_link = item;  dlink == ditem
    finish 
    c_free = c_free&(\(1<<ditem_mode)) if  speccing = 0
    ditem_val = 0
    return 
  finish 
  if  depth # 0 start 
    dlink_link = item;  dlink == ditem
    if  size > 0 start 
     !simple value
      if  dreg > maxcalldreg start 
        assign stack address
        return 
      finish 
      remember(dreg,item) if  speccing = 0
      ditem_reg = dreg-d0;  dreg = dreg+1
    else 
      if  areg > maxcallareg start 
        assign stack address
        ditem_reg = 8                {would have been AREG}
        return 
      finish 
      remember(areg,item+ad) if  speccing = 0 and  ditem_flags < 0
      ditem_reg = areg-d0;  areg = areg+1
    finish 
  finish 
  ditem_val = disp
  if  ditem_mode&2_11000000 # static start 
    disp = disp+|size|
    if  ditem_mode >= framemode start 
      align(disp,2)                 {*always kept even*}
      ditem_val = c_sp-disp;  !neg stack disp.
    finish 
  finish 
end 
!
routine  FIELD IDENT
  head == dformat_link;  item = head
  if  item > 0 start 
    cycle 
      ditem == dict(item)
      fault(duperr+point) if  string(ditem_text+char0) = string(charlim)
      head == ditem_hlink;  item = head
    repeat  until  item <= 0
  finish 
end 

!<
routine  DUMP CONST(integer  v,n)
! Plant N replications of value V (of type ITEMTYPE and size ITEMSIZE)
! For simple operand V is value, otherwise V is address in FINAL
! Alignment requirement has been enforced (since it depends on context)
integer  i,j,k,kk,vv
  k = itemsize
  if  k <= 0 start ;  !structure
    k = -k
    k = final(v)+1 if  k = 0;  ![string]
    cad = v if  v # 0;  !reset cad
  finish 
  kk = k
  return  if  n < 1
  kk = kk*n if  n > 1
  if  mode = constmode start 
    i = cad;  cad = cad+kk
    croak("Program too big") if  cad >= initbase
    if  v = 0 start 
      final(i) = 0 and  i = i+1 until  i >= cad
      return 
    finish 
  else 
    if  v = 0 start 
      run(ownmode,ownval,kk,v)
      ownval = ownval+kk
      return 
    finish 
    pattern(ownmode,ownval,kk)
    make init room(kk)
    i = initlim;  initlim = initlim+kk
    ownval = ownval+kk
  finish 
  if  itemsize <= 0 start ;            !structure
    while  n > 0 cycle 
      n = n-1;  j = i+k
      vv = v
      cycle 
        final(i) = final(vv)
        i = i+1;  vv = vv+1
      repeat  until  i =j
    repeat 
  else 
!$IF VAX
{    v = ieee(v) %if itemtype = realtype;  !vax->ieee
!$FINISH
    %while n > 0 %cycle
      n = n-1
      %if itemsize >= 2 %start
        %if itemsize > 2 %start;  !longword
          final(i) <- v>>24
          final(i+1) <- v>>16
          i = i+2
        %finish
        final(i) <- v>>8
        i = i+1
      %finish
      final(i) <- v
      i = i+1
    %repeat
  %finish
%end;  !dump const
!<= framemode %start
    ditem_flags = ditem_flags!mflag
    assign address(4)
  %finish
%end

%routine GET ARRAY DECLARATION(%integer dim)
%integer pos,dlim1,holdval,holdz,jam,elements,totsize,lo1,size1
%record(identinfo)%name dp
%ownrecord(objinfo) ATYPE=0

%integer%fn XTYPE
  declare anon(details(typeid,inttype,0,0))
  %result = item
%end
%routine GET REST
%integer e,r,lo,loval,hi,hival
  r = 0
  atom = next atom %if matched # 0
  %if decl_flags < 0 %start;  !%array%name
    %if depth > 0 %and ktype <= atom <= keyinteger %start;  !variable
      r = xtype;  get VAR BOUND
    %else %if a(star)
      fault(notin+point)
      r = xtype;  declare bound(decl_mode,0)
    %else
      get LITERAL(inttype)
    %finish
  %else;                   !%array
    get VALUE(inttype)
  %finish
  loval = value;  lo = item
  loval = minint %if lo # 0
  get(colon)
  atom = next atom %if matched # 0
  %if decl_flags < 0 %start
    %if depth > 0 %and ktype <= atom <= keyinteger %start;  !variable
      %if r = 0 %start
        r = xtype;  declare bound(litmode,loval)
      %finish
      get VAR BOUND
    %else
      %if dim!r = 0 %and a(star) %start
        item = 0;  value = maxint
      %else
        get LITERAL(inttype)
        declare bound(litmode,value) %if r # 0
      %finish
    %finish
  %else
    get VALUE(inttype)
  %finish
  hival = value;  hi = item
  hival = maxint %if hi # 0
  e = maxint
  %if r = 0 %start;  !no range yet declared
    %if lo!hi = 0 %start
      e = hival-loval %if hival!!loval >= 0 %or minint+hival-loval < 0
      e = e+1 %if e # maxint
      e = 0 %if hival = maxint
      declare lit range(inttype,loval,hival)
    %else
      declare anon(typeident);               !blank (for updating)
      declare range(inttype,loval,hival)
    %finish
    r = item
  %finish
  elements = e
  %if a(comma) %start
    dim = dim+1
    get REST
    %if elements # maxint %and e # maxint %start
      elements = elements*e
    %else
      elements = maxint
    %finish
  %finish
  atype_xtype = r
  size1 = totsize;  lo1 = loval;       !for outer dimension
  %if elements = maxint %start;             !non-literal bounds
    atype_mode = mode
    declare anon(atype)
    atype_type = item;          !save type id
    %if decl_flags >= 0 %or (depth = 1 %and speccing = 0) %start
      lo = litref(loval) %if lo = 0
      hi = litref(hival) %if hi = 0
      putact(asize,item,litref(totsize))
      putact(0,lo,hi)
      %if decl_flags >= 0  %start
        compile(np0)
        dict(r+1)_mode = c_mode %and dict(r+1)_val = c_sp+4 %if lo > 0
        dict(r+2)_mode = c_mode %and dict(r+2)_val = c_sp %if hi > 0
      %finish
    %finish
    totsize = 0
  %else;  !literal bounds
    item = 0
    %cycle
      ditem == dict(item)
      %exit %if ditem_type = atype_type %and ditem_xtype = atype_xtype -
            %and ditem_flags = atype_flags
      item = item+1
      %if item = dlim %start
        declare anon(atype)
        %exit
      %finish
    %repeat
    atype_type = item
    totsize = totsize*e
  %finish
%end;  !get REST

%routine PUT BOUNDS
%integer i
  i = xtype;                         !index type
  declare bound(mode,0);             !lower
  declare bound(mode,0);             !upper
  dim = dim-1
  put bounds %if dim > 0
  atype_xtype = i
  declare anon(atype);                  !array type
  %if speccing = 0 %start
    putact(asize,item,litref(totsize))
    putact(0,i+1,i+2)
  %finish
  totsize = 0;  lo1 = minint
  atype_type = item
%end

  pos = dlim0;  dlim1 = dlim;  dp == ditem
  atype_flags = typeid+arry+okflag;  atype_type = itemtype
  %if atype_type < 0 %start
    atype_flags = atype_flags+name;  atype_type = atype_type-name
  %finish
  atype_mode = constmode
  totsize = |itemsize|
  %if dim > 0 %start;  !%array(n)%name
    atype_mode = mode
    put bounds
    elements = maxint
  %else;  !left parenthesis recognised
    get REST
    get(right)
  %finish
  dp_type = atype_type
  %if mode&2_11000000 # static %start {dynamic array}
    holdval = d0
    while  pos # dlim1 cycle 
      dp == dict(pos)
      dp_type = atype_type
      if  mode >= framemode start 
        dp_flags = dp_flags!arrflag if  lo1 = minint or  size1 = 0
        if  decl_flags >= 0 start ;  !%array not %array%name
          if  totsize # 0 {all literal bounds} -
          and  totsize<<1-c_sp+disp <= 32000 start 
            !if array will occupy less than half remaining reach
            !then allocate directly on stack
            disp = disp+totsize
            align(disp,2)
          else 
            fault(ordererr) if  c_mode&2_01000000 # 0; !hard order error
            if  totsize # 0 start ;  !known bounds but too big
              c_extra = c_extra+totsize
              holdval = litref(totsize)
            finish 
            ![ADOK updates C_SP]
            holdz = 0;  holdz = litref(-lo1*size1) if  dp_flags&arrflag = 0
            putact(adok,holdval,holdz);  !compute & store space needed
            compile(np0)
            dp_flags = dp_flags+indirect
            dp_link = c_dynarray
            c_dynarray = pos;  c_dynarray = -c_dynarray if  holdz # 0
            c_status = c_status!unknown
            holdval = 0
          finish 
          dp_val = c_sp-disp
        finish 
      else  if  decl_flags >= 0;  !record field or absolute
                                 !name already allocated
        dp_val = disp;  disp = disp+totsize
      finish 
      pos = pos+1
    repeat 
  else ;                           !const,own
    if  decl_flags&(name+indirect) # 0 start 
      syntax error if  mode = constmode
      disp = disp+4
    else 
      if  a assop(itemtype) start 
        jam = jammy
        dp_flags = dp_flags!okflag;  ![hum]
        allow(terminator)
        cycle 
          jammy = jam
          get VALUE(itemtype)
          faultnum = rangerr+point+warn if  faultnum = rangerr+point
          holdval = value
          value = 1
          if  a(left) start 
            value = elements
            get LITERAL(halftype) if  not  a(star)
            get(right)
          finish 
          elements = elements-value
          value = value+elements if  elements < 0
          dump const(holdval,value)
        repeat  until  not  a(comma)
        if  faultnum = 0 and  elements # 0 start 
          if  elements < 0 then  report(counterr,pos,elements) -
          else  report(counterr+warn,pos,elements)
        finish 
      finish 
      if  elements > 0 start 
        elements = elements*|itemsize|
        if  mode = constmode then  fill code(elements) -
        else  disp = disp+elements
      finish 
    finish 
  finish 
end ;  !get ARRAY DECLARATION
!
routine  GET PROCEDURE DECLARATION
integer  pos,dlim1,argmode,argad,restype,stack
record (identinfo)name  headditem,dhold

predicate  DUPOK
!Check that the proc being declared can reasonably alias existing id
record (identinfo)name  tp
  false  if  ditem_flags&proc = 0
  tp == dict(ditem_type)
  if  restype = 0 start ;  !routine
    false  if  tp_type # 0 or  tp_link = 0; !not routine, or no pars
  else 
    false  if  restype = tp_type;  !function of same type
  finish 
  true 
end 

  restype = itemtype
  stack = 0;  !unknown
  decl_flags = decl_flags&(\okflag)
  decl_type = procstar;             !by default
  if  mode = 255 start ;              !mode not explicit
    mode = procmode;  decl_val = 0
    if  decl_flags&ext = 0 start ;  !not external
      decl_flags = decl_flags+spec if  a(keyspec)
      decl_flags = decl_flags!proc1
    else  if  a(keyspec)
      mode = ownmode
      decl_flags = decl_flags+(spec+indirect)
    finish 
  else  if  depth # 0;             !procedure as param
    decl_flags = decl_flags!proc2;  ![must push MB in case external]
  else ;                            !@...
    decl_flags = decl_flags!proc1
    decl_val = disp
    stack = 4
  finish 
  decl_mode = mode
  if  {decl_flags&ext # 0 %and} a(keyalias) start 
    nonstandard(9)
    get(ident)
    if  item <= 0 start 
      fault(namerr+point)
    else 
      item = 0 and  decl_flags = decl_flags!alt if  dupok
    finish 
  else 
    get(ident)
  finish 
  declare(decl)
  headditem == ditem
  assign address(-6) if  depth # 0
  argmode = c_mode&(\2_01000000)+1
  if  decl_flags&spec # 0 or  decl_mode # procmode start 
    speccing = speccing+1
  else 
    c_forward = c_forward-1 if  ditem_flags&rflag # 0
    open block(item)
    c_type = restype
    if  c_type # 0 start 
      c_type = c_type!sign16 if  decl_flags&writable # 0 {%map}
      c_status = c_status!okcc
    finish 
  finish 
  dlim1 = dlim
  declare anon(details(0,restype,0,stack))
  ditem_reg = 8 if  restype # 0 and  (decl_flags&writable # 0 {%map} -
                or  size(restype) <= 0 {structure fn});  !result @A0
!Declare parameters
  argad = c_sp;     !ok for both spec and body
  if  a(left) start 
    dhold == dlink;  dlink == ditem
    get DECLARATION(okflag+writable+readable,argmode,argad,1)
    dlink == dhold
    get(right)
  finish 
  if  speccing # 0 start 
    speccing = speccing-1
    pos = crunched(dlim1)
    if  pos < dlim1 or  speccing = 0 start 
      headditem_type = pos
    else ;                    !proc as param
      fault(classerr);  dlim = dlim1
    finish 
  else ;                        !procedure body
    if  c_dpid_flags&spec # 0 start 
      c_dpid_flags = c_dpid_flags-spec
      if  not  parmatch(c_dpid_type,dlim1) start 
        if  c_pid = dlim1-2 then  fault(matcherr+warn) -
        else  fault(matcherr)
      finish 
    finish 
    headditem_type = dlim1
    c_parlim = dlim
    c_sp = -argad
    compile(np0)
    get(terminator)
    get STATEMENTS(keyend)
  finish 
end ;  !get procedure declaration

routine  GET INITIAL VALUE(record (identinfo)name  dp)
  if  itemtype >= 0 and  itemsize > 0  {value,simple} -
  and  a(query) start 
    prompt(string(char0+dp_text).": ")
    item = 0;  read(value)
  finish  else  get VALUE(itemtype)
  dp_flags = dp_flags!okflag
  if  mode = constmode start 
    if  itemtype < 0 start ;  !name
      dp_flags = writable+readable
      dp_mode = absmode;  dp_val = value
    else 
      faultnum = rangerr+point+warn if  faultnum = rangerr+point
      if  itemsize <= 0 then  dump const(value,1) -
      else  dp_mode = litmode and  dp_val = value
    finish 
  else  if  static <= mode < framemode;  !own
    faultnum = rangerr+point+warn if  faultnum = rangerr+point
    dump const(value,1)
  else ;  !dynamic initialisation
    atomp = expp and  nonstandard(1) if  item # 0
    if  itemtype < 0 start 
      putact(okass,dlim0+ad,normitem)
    else 
      putact(okass+jammy,dlim0,normitem)
    finish 
    compile(np0)
  finish 
end ;  !get initial value

dreg = d0;  areg = a0;  stmax = 8;  !allow for RETAD & LINK
base = disp;  max = base
cycle 
  disp = base
  cycle 
    decl = 0
    decl_flags = flags;  decl_mode = mode
    adim = -1
    while  a(kattrib) cycle 
      if  subatom = 3 start ;  !%register
        low
        decl_mode = a7-d0;  decl_val = c_free
        if  a(left) start 
          get regset
          if  value&(value-1) = 0 start  {unit set}
            decl_mode = item-d0
          else 
            decl_val = decl_val&value;    ![*for use later*]
          finish 
          get(right)
        finish 
      else 
        decl_flags = decl_flags!!(1<<subatom)
      finish 
    repeat 
    if  depth = 0 and  a(left) start ;  !start of sub-group
!      align(disp,2)
!      ad_cat = ad_cat+1 %if mode = 0
      get DECLARATION(flags,mode,disp,0);  get(right)
!      ad_cat = ad_cat-1 %if mode = 0
    else  if  a(rpred);  !%routine,%predicate
      if  subatom # 0 start ;  !pred
        decl_flags = decl_flags&(\(writable))
        decl_flags = decl_flags!volatile if  control&volbit # 0
        itemtype = booltype
      else 
        decl_flags = decl_flags&(\(writable+readable))
        itemtype = 0
      finish 
      get PROCEDURE DECLARATION
      return  if  depth = 0
    else 
      get DATA TYPE
      !Appendages
      if  a(fnmap) start ;  !%fn, %map
        decl_flags = decl_flags!volatile if  control&volbit # 0
        if  subatom = 0 start 
          decl_flags = decl_flags&(\writable)
          fault(illstarred) if  itemsize = 0
        finish 
        get PROCEDURE DECLARATION
        return  if  depth = 0
      else 
        decl_flags = decl_flags&(\proc)
        decl_type = itemtype
        if  a(keyname) start 
          decl_flags = decl_flags+name;  itemtype = itemtype+name
          itemsize = 4
        finish 
        if  a(keyarray) start 
          fault(illstarred) if  itemtype = recstar
          adim = 0
          decl_flags = decl_flags&(\name);  decl_type = arrstar
          decl_flags = decl_flags!arrflag if  control&arrbit # 0
          if  a(left) start 
            fault(notin+point) if  depth = 0
            get LITERAL(inttype)
            if  value&(\7) # 0 then  expfault(rangerr) else  adim = value
            get(right)
            get(keyname);  matched = 0
          finish 
          decl_flags = decl_flags+name if  a(keyname)
        finish 
        if  decl_mode = 255 start ;       !not explicitly specified
          if  decl_flags&ext = 0 start ;  !main declaration
            fault(notinblock) if  stopper <= 0
            if  c_status >= hadon start 
              if  c_forward!c_return # 0 or  curlab # c_lab1 start 
                fault(ordererr)
              else  if  c_status&hadordererr = 0
                fault(ordererr+warn);  c_status = c_status+hadordererr
              finish 
            finish 
            mode = c_mode
          else  if  a(keyspec);            !external spec
            mode = ownmode
            decl_flags = decl_flags!(spec+indirect)
          else ;                           !external
            mode = ownmode;  disp == ownval
          finish 
          decl_mode = mode
        finish 
        fault(illstarred) if  itemsize = 0 and  decl_flags >= 0 -
                          and  decl_mode # constmode -
                          and  decl_mode&63 # absmode
       !Read identifier list
        cycle 
          dlim0 = dlim
          unless  decl_type = arrstar start    {not array}
            if  disp&1 # 0 start 
              align(disp,2) unless  itemsize = 1 -
                 or  (itemtype > 0 and  category(itemtype)&cat = stringy) -
                 or  literal >= 99
            finish 
            if  not  a(ident) start 
              get(star)
              disp = disp+|itemsize|
            else 
              subbed = 0
              field ident if  mode = 0
              declare(decl)
              assign address(itemsize)
              if  mode # 0 and  depth = 0 start 
                if  decl_flags&spec = 0 start 
                  if  a assop(itemtype) start 
                    get INITIAL VALUE(ditem)
                  else  if  mode = constmode
                    syntax error
                  else  if  static <= mode < framemode
                    disp = disp+|itemsize|
                  finish 
                finish  else  disp = disp+4
              finish 
            finish 
          else                               {array}
            align(disp,2) unless  literal >= 99
            cycle 
              get(ident)
              field ident if  mode = 0
              declare(decl)
              assign address(0)              {(4 if name)}
              exit  if  not  a(comma)
              atom = next atom
              if  atom # ident start 
                if  adim = 0 start 
                  syntax error if  decl_flags >= 0
                  adim = 1
                finish 
                get ARRAY DECLARATION(adim)
                -> exit22
              finish 
            repeat 
            if  adim # 0 or  not  a(left) start 
               if  adim = 0 start 
                 syntax error if  decl_flags >= 0
                 adim = 1
               finish 
               get ARRAY DECLARATION(adim)
               -> exit2
            finish 
            get ARRAY DECLARATION(adim)
          finish 
          -> exit2 if  not  a(comma)
          atom = next atom
        repeat  until  atom # ident and  atom # star
exit22:
        continue 
      finish 
    finish 
    exit  if  not  a(comma);  ![NB %continue above]
  repeat 
exit2:
  max = disp if  disp > max
repeat  until  not  a(keyor)
disp = max
end ;  !get declaration

initial(keyconst):
  literal = 1
  get DECLARATION(okflag+readable,constmode,cad,0)
  -> term

routine  GET ADDRESS(integer name  mode,val)
routine  GET AD
  get EXPRESSION(major,inttype)
  if  item # 0 start 
    error(nonliteral) unless  a0 <= item <= a7
    mode = item+(dispmode-a0)
  else 
    val = val+value
    if  a(left) start 
      get ad;  get(right)
    finish 
  finish 
end 
  mode = absmode;  val = 0
  get ad
end 

initial(keyown):
  if  a(equals) start 
    low
    get address(ownmode,ownval)
  else 
    literal = 1
    get DECLARATION(writable+readable,ownmode,ownval,0)
  finish 
  -> term

routine  GET AT(integer  flags)
integer  mode,val
  low
  if  a(hashsign) start           {@# ident}
    literal = -1
    get EXPRESSION(simple,0)
    if  item <= dlim and  a(plus) start     {increment actual ident address}
      literal = 1
      get DECLARATION(ditem_flags&(writable+readable+okflag),
                      ditem_mode,ditem_val,0)
      return 
    finish 
    mode = ditem_mode;  val = ditem_val
  else 
    get address(mode,val)
  finish 
  mode = mode!static if  a(keyown)
  literal = 99
  get DECLARATION(flags!(okflag+writable+readable),mode,val,0)
end 

initial(atsign):
  get at(0)
  -> term

initial(keyext):
  fault(ordererr) if  level # 0
  literal = 1
  dump = subatom<<12
  if  a(atsign) start 
    get at(dump)
  else 
    if  a(leftb) start 
      get LITERAL(inttype);  get(rightb)
      maxcalldreg = (d0-1)+value&15
      maxcallareg = (a0-1)+value>>4&15
      dump = dump!!(value&(\255))
    finish 
    get DECLARATION(dump!(writable+readable),255,ownval,0)
  finish 
  -> term

initial(keyrecord):
  if  not  a(left) start 
    get(keyformat)
    if  a(keyspec) start 
      typeident_flags = typeid+spec+recy
      get(ident);  declare(typeident)
    else 
      typeident_flags = typeid+recy
      get(ident);  declare(typeident)
      get(left)
      dformat == ditem
      get DECLARATION(writable+readable,0,dformat_val,0)
      recalign(dformat_val)
      get(right)
    finish 
    -> term
  finish 
  fp = fp-1;  atom = keyrecord;  !back-up
initial(ktype): initial(keylong):
initial(keyinteger): initial(keyreal):
initial(kattrib): initial(keystring):
initial(rpred):
  matched = 0
  get DECLARATION(writable+readable,255,c_val,0)
  -> term

initial(keylabel):
  get IDENTLIST(forwardlabel)
  -> term

routine  GET SWITCH DECLARATION
integer  i,lo,hi,dlim1
ownrecord (objinfo) d=0
  matched = 1
  cycle 
    d_type = arrstar;  !(in case of error)
    d_flags = d_flags+arrflag if  control&arrbit # 0
    d_mode = labmode
    get IDENTLIST(d)
    dlim1 = dlim
    declare anon(details(typeid+arry,0,0,0))
    get(left);  get LIT RANGE(inttype);  get(right)
    dict(dlim1)_xtype = item
    lo = lower(item);  hi = upper(item)
    cycle ;  !For each ident in group
      for  i = lo,1,hi cycle 
        swpc = swpc-1;  prog(swpc) = 0
        croak("Code space exhausted") if  swpc <= pc
      repeat 
      dict(dlim0)_val = swpc
      dict(dlim0)_type = dlim1
      dlim0 = dlim0+1
    repeat  until  dlim0 = dlim1
  repeat  until  not  a(comma)
end 
initial(keyswitch):
  literal = 1
  get SWITCH DECLARATION
  c_status = c_status!hadswitch
  ->term

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!  Control statements  !!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
routine  OPT
integer  c=control
  set options(string(final0+value))
  select output(listout);  !**for now - PAM may alter**
  control = control&(\list) if  (initcon!c)&list = 0
  control = control!list if  control&(\c)&(ttlist+codelist+explist+dictlist) # 0
end 

initial(keyoption):
  get LITSTRING
  get(terminator)
  opt if  faultnum = 0
  -> next

initial(keyinclude):
  get LITSTRING
  get(terminator)
  if  faultnum = 0 start 
    croak("Too many nested includes") if  curfile = 3
    line = line+1 if  sym = nl
    cur_fp = fp;  cur_line = line
    fcontrol(curfile) = control
    control = control&(\list) if  control&(codelist+explist+dictlist) = 0
    curfile = curfile+1
    lastfile = -1 if  curfile = lastfile
    cur == file(curfile);  cur = 0
    time1 = time1-cputime
    define param("INC",cur_name,nodefault)
    opt
    connect edfile(cur)
    time1 = time1+cputime
    signal  abandon if  cur_flag # 0
    line = 0;  sym = nl
    curstart = cur_start2;  curlim = cur_lim2
    fp = cur_start2
  finish 
  ->next

initial(keycontrol):
  get LITERAL(inttype)
  control = 0 if  value = 0
  control = control!!value
  show dict(0) if  control&dictlist # 0
  ->term

initial(keylist):
  control = control!list
  ->term

!initial(keysection):
initial(keycomment):  !*for testing*
  get(terminator)
  error(ordererr) if  stopper # 0
  c_parlim = dlim;  c_localtext = charlim
  get STATEMENTS(-1)
  check usage(c_parlim)
  -> term

initial(keybegin):
  get(terminator)
  if  stopper = 0 start ;  !first %begin
    c_localdpos = dlim;  c_parlim = dlim
    c_access = 1
    get STATEMENTS(keyend)
    return 
  finish 
  declare anon(beginblock)
  open block(dlim0)
  get STATEMENTS(keyend)
  update sp
  this is inst
  srcall(dlim-1)
  -> term

initial(keyend):
  if  stopper > keyend start 
    if  stopper = keyrepeat then  fault(norepeat+now) -
    else  fault(nofinish+now)
    ![caller will revert to INITIAL(KEYEND)]
  else 
    if  a(keyof) start 
      if  a(keylist) start 
        control = control&(\list)
        ->term
      finish 
      if  a(keyfile) start 
       fp = curlim;  sym = nl
        ->next
      finish 
      get(keyprogram)
      fault(noend+now) if  level # 0
    finish 
    fault(nobegin+now) if  stopper = 0
    if  c_access > 0 start 
      fault(noresult+now) if  c_type # 0;  !fn/map/pred
    finish 
    close block if  stopper >= 0
  finish 
end ;  !GET STATEMENTS

!<

routine  ANNOUNCE(integer  value,string (255) message)
  write(value,1);  space;  printstring(message)
  printsymbol('s') if  value # 1
end 

routine  OUTPUT OBJECT FILE
constinteger  OBJOUT=1
integer  i,reset,totsize
  reset = 0
  end run;  end pattern
  if  initlim # initbase start 
    if  inithead >= 0 start ;     !copy routine needed
      set code word(16_205F);       !   move.l (sp)+,a0
      set code word(16_3018);       !   move.w (a0)+,d0
      set code word(16_32D8);       !l1 move.w (a0)+,(a1)+
      set code word(16_51C8);       !   dbra d0,l1
      set code word(-4)
      set code word(16_4ED0);       !   jmp (a0)
    finish 
    reset = cad;                    !entry-point for RESET
    put own word(16_4E75);             !   rts
  finish 
  totsize = cad+(initlim-initbase);  !total code size
  set extension(objfile,".mob")
  time1 = time1-cputime
  open output(objout,objfile)
  select output(objout)
  put word(16_FE02);  !object module flag, version
  put word(control>>20<<4);  !checking options
  value = 0
  do externals(externs,-1) if  externs # 0;  !find size
  put word(value);        !length of exports
  value = 0
  do externals(extspecs,-1) if  extspecs # 0;  !find size
  put word(value);        !length of imports
  put word(totsize>>16);  !length of code + init pattern
  put word(totsize)
  put word(reset>>1);     !reset entry-point
  put word(c_dpid_val>>1);  !main entry-point
  ownval = 0 if  ownmode # defaultownmode  {not good enough}
  put word(ownval>>16);       !static data requirement
  put word(ownval)
  put word(c_totstack>>16);  !stack requirement
  put word(c_totstack)
  put word(0);            !spare for diag
  put word(0)
  put word(0)
  put word(0)
  do externals(externs,0) if  externs # 0
  do externals(extspecs,1) if  extspecs # 0
  final(0) = 16_4E;  final(1) = 16_75;  !RTS (as null reset,main?)
  i = 0
  cycle 
    print symbol(final(i));  i = i+1
  repeat  until  i = cad
  if  initlim # initbase start 
    i = initbase
    cycle 
      print symbol(final(i))
      i = i+1
    repeat  until  i = initlim
  finish 
  time1 = time1+cputime
end 

routine  CLOSE EDIT
!_FLAG is negative if edit abandoned
!_CHANGE is untouched (inf) if no changes
  if  file(main)_flag >= 0 and  0 < file(main)_change # 16_7FFFFFFF start 
    file(main)_name = mainfile;  ![in case modified by OPEN IN]
    time1 = time1-cputime
    disconnect edfile(file(main))
    printstring(file(main)_name."  updated");  newline
    time1 = time1+cputime
  finish 
end 

begin 
on  event  redo,abandon start 
  close edit and  stop  if  event_event = abandon
finish 
  time2 = cputime-time1
  statements = 1;  comments = 0;  atoms = 0
  identatoms = 0;  litatoms = 0
  faults = 0;  others = 0;  faultnum = 0
  zaps = 0;  steps = 0;  jumps = 0;  shorts = 0
  rep = ""
  forget triples;  !reset LITPOS,EXPLO,OLDEXPLO
  char0 = addr(char(0));  final0 = addr(final(0))
  preset
  dint == dict(inttype)
  dtemp == dict(lablim);  dtemp2 == dtemp[1]
  dtsprel == dtemp2[1]
  dtemp = 0;  dtemp2 = 0;  dtsprel = 0
  dmin = dictlim;  dmin0 = dmin
  inclim = 0
  accounted = 0
  firstentry = finalbound;  firstpos = dictlim
  pc = 1;  swpc = progbound+1
  cad = 2
  final(0) = 0;  !for empty string (compile-time only)
  initbase = finalbound-4095;  initlim = initbase
  inithead = -1;  initmode = 255;  initval = 0
  initd1 = -1;  initrep = 0;  initdata = 0
  ownmode = defaultownmode;  ownval = 0
  level = 0;  vintage = 1
  pendout = 0;  pendin = 0;  polarity = 0
  curlab = dictlim+1
  reset context(procstar,defaultfree)
  c_sp = -4;   !allow for BSR

  control = initcon;  ccond = 0
  lastfile = main
  curfile = main;  cur == file(main)
  curstart = file(main)_start1;  curlim = file(main)_lim1
  fp = file(main)_start1
  line = 0;  sym = nl
  np = np0
!<
  get STATEMENTS(0)
!<
end 

  time2 = cputime-time2-time1
  close edit
  output object file if  faults = 0 or  control&forcebit # 0
  cycle 
    select output(listout)
    printstring(file(main)_name)
    if  faults = 0 or  control&forcebit # 0 start 
      printstring(" compiled:")
      announce(statements,"statement")
      print string(" (+")
      announce(comments,"comment")
      printstring(") to")
      announce(cad,"byte")
      printstring(" (+");  write(initlim-initbase,1)
      printsymbol(')')
      newline
    finish 
    if  faults # 0 start 
      printsymbol(':')
      announce(faults,"fault")
      printstring(" reported")
      if  others # 0 start 
        printstring(" (+");  announce(others,"other")
        printsymbol(')')
      finish 
      newline
    finish 
    if  control&logbit # 0 start 
      printstring(-
"  CODE  OWNS  JUMPS SHORT STEPS  ZAPS | ATOMS LITS IDS  TIME")
      newline
      write(cad,5)
      write(ownval,5)
      write(jumps,6);  write(shorts,5)
      write(steps,5);  write(zaps,5)
      print(atoms/statements,5,1)
      print(litatoms/statements,2,1)
      print(identatoms/statements,1,1)
      print(time2/statements,2,3)
      printsymbol('+')
      print(time1/statements,0,3)
      newline
    finish 
    exit  if  listout = 0
    listout = 0
  repeat 
!<
endofprogram