perm filename ARRAY[S,AIL]2 blob sn#010851 filedate 1972-08-09 generic text, type T, neo UTF8
COMMENT ⊗   VALID 00016 PAGES VERSION 16-2(11)
RECORD PAGE   DESCRIPTION
 00001 00001
 00003 00002	HISTORY
 00005 00003	Array Semblk, Routine Descriptions
 00013 00004	Array Routine Data
 00017 00005	Array Declaration Routines -- STARY, ENTARY
 00020 00006	 ARRSUB
 00023 00007	 ARRDEC
 00029 00008	OWNARR:	MOVE	ARRBIT,ARYLST		#ARRAYS WITH THESE DIMENSIONS
 00035 00009	
 00040 00010	ADCND:
 00043 00011	DSCR LDYBEG, LDYREP, LDYNO
 00049 00012	DSCR ARYIDX, ARRSBY, ARRSB1
 00051 00013	 FIRST PART SETS UP ARRBIT TO INDICATE EXACT CONDITIONS
 00057 00014	 CHECK UPPER BOUNDS
 00062 00015	DSCR SUBSCR
 00068 00016	DSCR DOSFTY
 00069 ENDMK
⊗;
COMMENT ⊗HISTORY
AUTHOR,REASON
021  202000000013  ⊗;


COMMENT ⊗
VERSION 16-2(11) 11-6-72 BY JRL ALLOW PRELOADED ITEMVAR ARRAYS
VERSION 16-2(10) 8-29-72 BY KVL FIX SMALL BUG IN LEAP ARRAYS - ARRDEC
VERSION 16-2(9) 8-9-72 BY JRL NEW "GLOBAL" ARRAY HACK
VERSION 16-2(8) 7-18-72 BY DCS BUG #IQ# MAKE JUMP TO ARRAY DECL HAPPEN BEFORE BOUNDS CHECK
VERSION 16-2(7) 6-6-72 BY DCS BUG #HN# ALLOCATE 0 FOR ALL DYNAMIC ARRAYS
VERSION 16-2(6) 5-2-72 BY JRL CHANGE PARAM TO LPCALL(ITMRY)
VERSION 15-2(5) 4-29-72 BY RHT PUT IN MAKE_SAFE & MAKE_UNSAFE FEATURE
VERSION 15-2(4) 2-7-72 BY DCS BUG #GP# WARN IF ATTEMPT TO PRELOAD DYNAMIC ARRAY
VERSION 15-2(3) 2-5-72 BY DCS BUG #GJ# ADD LSTON LISTING CONTROL STUFF
VERSION 15-2(2) 1-10-72 BY DCS BUG #FP# FIX NEGAT BUG ON INDEX FETCH
VERSION 15-2(1) 12-2-71 BY DCS INSTALL VERSION NUMBER

⊗;
SUBTTL	Array Semblk, Routine Descriptions
	LSTON	(ARRAY)

BEGIN ARRAY
Comment ⊗ (a la D. Poole)
Here are the GRAND and GLORIOUS routines for talking about arrays:


An array descriptor has the form:

ARR:	→BNDBLK,,→next bucket element
	<$PNAME,BITS of various varieties>
TOTDSP:	total displacement(see below),,fixup for array variable
NUMDIM:	#dims,,ACNO of array address
ARLOC:	addr of first data word, if known(lh -1 for STRING)
$VAL2:	global # or item # const semantics if LPARRAY
	<ring pointers>

BNDBLK is the bounds block for this array, described below.
ARLOC(rh) has the address of the first data word of compiled-in
	arrays (OWN on in TBITS) -- top level arrays. (lh as above)
TOTDSP (lh) has [0,0,0] location for array, if known

When a subscript calculation needs to be made, a block of the
	following form is created:

IDXBLK:	→partial-calculations,,→array descriptor
DIMPRC:	#dimensions processed so far
BNDPNT:	BNDPTR (see below)
NUMDIM:	# dimensions
	<others 0>


Partial-calcs is a TEMP block describing partial index
	calculations to date.

BNDBLK is a block containing information about any constant array
	bounds, if the dimensionality of the array is ≤ 5.

BNDPTR is a pointer to the set of 2 words in BNDBLK describing
	the current index:

	bits,,upper bound for this dimension
	lower bound,,π[i←(current dim+1) to n](size(dimension i)) (mult factor)

bits:	100000 -- NOMUL -- when on, can not do IMULI for size calc
	 40000 -- MULMUL -- ¬NOMUL
	   200 -- LOWFIX -- lower bound fixed
	    40 -- LOWVAR -- ¬LOWFIX
	    20 -- BOTFIX -- lower and upper fixed
	     4 -- SOMVAR -- ¬BOTFIX

The array routines are divided into two sections:
two routines called to declare
arrays (ARRSUB and ARRDEC), and three called to calculate
a subscript when a subscripted variable occurs in an expression
or assignment statement (ARYIDX, ARRSBY, and SUBSCR).


The syntactic contexts for these routines are:

ARDEC E : E SG → ARDEC		ARRSUB
ARDEC E : E ] → ARDEC		ARRDEC

@IARY [ → ARID			ARYIDX
@ARY E , → @ARY			ARRSBY
ARID E ] → ]			ARRSB1  SUBSCR


Instructions of the following form will be emitted by ARRSUB for each
	index.  ARRX is an AC containing a pointer to the first
	data word of the array (dimension info below it in core).
	AC is the AC containing current index calculations.  The
	conditions under which each kind of instruction is issued
	is given to its right.  Instructions not separated by
	blank lines are alternatives.  There is for each 
	kind of instr. at least one circumstance under which
	no instruction at all will be issued:

MOVE	AC,INDEX			;index not in AC

SKIPL	AC				;¬SAFE ∧ ¬BOTFIX ∧ (¬LSTDX ∨ ¬LOWFIX)
CAIL	AC,lowbnd			;¬SAFE ∧ LOWFIX ∧ ¬BOTFIX ∧ ¬LSTDX

CAMLE	AC,-1-3*dimno+1(ARRX)		;¬SAFE ∧ ¬BOTFIX
CAILE	AC,totsiz			;¬SAFE ∧ BOTFIX

ARERR	dimno,"array name"		;¬SAFE

IMUL	AC,-1-3*dimno+2(ARRX)		;¬LSTDX ∧ ¬NOMUL
IMULI	AC,π(dimno)			;¬LSTDX ∧ NOMUL

ADD	AC,old calculation		;not the first index calc

There is also the feature of preloading the array with good things.
For this operation, the routines LDYBEG, LDYREP, and LDYNO are
called to record on a generalized stack the arguments to load into
the array.


⊗

TOTDSP←←$ADR		;TOTAL DISPLACEMENT (CONSTANT) FOR THIS ARRAY
ARLOC ←←$VAL		;LOCATION OF ARRAY
BNDPNT←←$DATA2		;→CURRENT ENTRY IN BNDBLK (FOUND IN IDXBLK)
DIMPRC←←$DATA		;#DIMENSIONS PROCESSED TO DATE
NUMDIM←←$ACNO		;NUMBER OF DIMENSIONS FOR THIS ARRAY

ARRBIT←←TBITS2		;BITS AND THINGS ABOUT THIS INDEX
TBLIDX←←SBITS2		;OFTEN HOLDS INDICES (IN ARRSBY)

; BITS USED IN ARRAY ROUTINES
; * INDICATES SUPPLIED BY BNDBLK
; ⊗ INDICATES USED IN ARRSBY
; + INDICATES USED IN SBSCRP


↑ARRBTS:
BIT(SPARE,400000)
BIT(DATMR,200000)	;IF ARRAY IS DATUM OF SOME ITEM		⊗
BIT(NOMUL,100000)	;IF IMULI CANNOT BE DONE THIS INDEX	⊗*
BIT(MULMUL,40000)	;¬NOMUL					⊗*
BIT(ONED,20000)		;ONE DIMENSIONAL ARRAY			⊗
BIT(MANYD,10000)	;¬ONED					⊗
BIT(LSTIDX,4000)	;PROCESSING LAST INDEX			⊗
BIT(NOTLST,2000)	;¬LSTIDX				⊗
BIT(IDXCON,1000)	;THIS INDEX IS A CONSTANT		⊗
BIT(IDXVAR,400)		;¬IDXCON				⊗
BIT(LOWFIX,200)		;LOWER BOUND IS CONSTANT		⊗*
;OWN  ←←   100		;BUILT-IN ARRAY (FROM TBITS)		+
BIT(GOTARR,100)		;HAD TO GET ARRAY DESCR. INTO AN AC	⊗
BIT(LOWVAR,40)		;¬LOWFIX				⊗*
;KNOWALL←←  20		;KNOW ENTIRE OFFSET (FROM SBITS)	+
BIT(SPARE,20)
BIT(BOTFIX,10)		;LOWER AND UPPER BOUNDS CONSTANT	⊗*
NOTCLC←←10		;NO PARTIAL CALCS WHEN SBSCRP CALLED	+
BIT(SOMVAR,4)		;¬BOTFIX				⊗*
SOMCLC←←4		;¬NOTCLC				+
BIT(DANGAR,2)		;NON-SAFE ARRAY (FROM TBITS)		⊗
BIT(SAFEAR,1)		;¬DANGAR				⊗
IFN FTDEBUG,<BLOCK =18>
SUBTTL	Array Routine Data

ZERODATA (ARRAY VARIABLES)

;ABLKPT -- Indirect ptr for ARRSUB for indexing a BNDBLK
↓ABLKPT:  0

;ARRDSP -- used to collect total constant displacement (from
;   [0,0,0] loc) during array declarations
↓ARRDSP: 0

;ARRSIZ -- collects total array size during declaration
;  (only used if all bounds constant, and Array is OWN)
↓ARRSIZ: 0

COMMENT ⊗
ARYBITS -- STARY puts the contents of BITS here when the ARRAY
   attribute is seen during declaration.  This is done because
   many arrays may share the same declarations, and we want these
   bits to remain safe over the entire process
⊗
↑↑ARYBITS: 0

;ARYBLK -- prototype BNDBLK for array.  See ARRAY DSCRs for details
↓ARYBLK: BLOCK	=15

;ARYLST -- count of number of arrays with same dimensions, etc.
↓ARYLST: 0

;ARYPDL -- QSTACK descriptor (QPDP) to hold Semantics of all
; Arrays with the same types and dimensions. Stored here until 
; the dimensions are known and the arrays can be allocated.
↓ARYPDL: 0

↓BLKOK: 0		;TEMP ARRAY VARIABLE

↓CURENT: 0		;REPEAT FACTOR DURING PRELOAD SPECS

↓DIMNO: 0		;COUNTS # DIMS DURING ARRAY DECLARATION

↓LDYFLG: 0		;ON DURING ARRAY ALLOC IF PRELOADED ARRAY

;LDYSTK -- QSTACK dscrptr. -- each word is [XWD rept,Semantics of const]
;   for a PRELOAD value -- collected during PRELOAD spec, used when
;   array is allocated
↓LDYSTK: 0

;LDYTAK -- QSTACK dscrptr of first entry in LDYSTK Qstack.  Used to
;    remove elements in order of insertion (via QTAK).
↓LDYTAK: 0

↓LDYTOT: 0		;TOTAL # WORDS IN PRELOAD SPEC

↓LEFMRK: 0		;STRING/ARITH DIFFERENTIATOR DURING DECL.

;NOMULT -- flag during declarations -- turned on if multiples
;   may are no longer constant (must use dope vector for remaining
;   dimensions)
↓NOMULT:  0

↓OWNWD:  0		;TEMP DURING ARRAY DECLARATIONS

↓SIZZ:   0		;TEMP WHILE GENERATING ARRAY-INDEXING CODE

ENDDATA

SUBTTL	Array Declaration Routines -- STARY, ENTARY

DSCR  ARRAY DECLARATION CODE
DES Most Declaration routines are in GEN, but these were moved to
 be close to their variables (OHHHHHHH).
 ENTARY enters an Array name, saves its semantics in ARYPDL
 STARY sets up array variables prior to dimension and size scanning
PRO ENTARY STARY
⊗

↑STARY:	MOVE	B,BITS			;CURRENT COLLECTION OF BITS.
	TLO	B,SBSCRP

↑↑HELSPC: SETZM	OWNWD		;CLEAR TEMP ARRDEC CELLS
	SETZM	ARRSIZ
	SETZM	ARRDSP
	SETZM	SIZZ
	SETZM	BLKOK
	SETZM	ARYBLK
	MOVE	TEMP,[XWD ARYBLK,ARYBLK+1] ;CLEAR PROTOTYPE BNDBLK
	BLT	TEMP,ARYBLK+=10-1

	TLNN	FF,TOPLEV		;IF TOPLEV ∧ ¬EXTERNAL,
	 JRST	 EXRAY
	TDNN	B,[XWD EXTRNL,GLOBL]		;MARK ARRAY "OWN".
	 TLO	B,OWN			; SO IT WILL BE COMPILED IN

EXRAY:
	MOVEM	B,ARYBITS		;KEEP THEM SAFE FROM CONSTANTS, ETC.
	MOVEM	B,BITS
	POPJ	P,

↑ENTARY: MOVE	B,ARYBITS		;SAVED BITS
	MOVEM	B,BITS
;;#IQ#3↓ 7-18-72 DCS MOVED FROM ARRSUB TO HAPPEN BEFORE BOUNDS CALCS
	TLNN	B,OWN			;HOME ANY JUMP, IF DYNAMIC ARRAY
	PUSHJ	P,ENDJMP
	JFCL				;SKIP-RETURNS UNIMPORTANT
	PUSHJ	P,ENTID
	MOVE	A,LPSA
	QPUSH	(ARYPDL)		;SAVE SEMANTICS FOR STARLP CODE
	AOS	ARYLST			;COUNT # ARRAYS WITH SAME DIMS
	SETZM	DIMNO			;NUMBER OF DIMENSIONS
	POPJ	P,			;GO AWAY
SUBTTL	 ARRSUB

DSCR ARRSUB, ARRDEC
PRO ARRSUB ARRDEC
DES ARRSUB collects bounds information -- runs once for each pair
 ARRDEC issues declaration code for all arrays with same type and
 bounds.
SEE Comments at beginning of ARRAY for details
⊗

↑ARRSUB:
	AOS	TEMP,DIMNO		;COUNT DIMENSIONS
	CAILE	TEMP,5			;TOO MANY TO PLAY WITH BLOCK?
	 JRST	 TOMNY			; YES

	LSH	TEMP,1			;*2 TO INDEX ARYBLK
	ADDI	TEMP,ARYBLK-1		;2D WORD OF THIS ENTRY IN ARYBLK
	MOVEM	TEMP,ABLKPT		;STORE IN CORE

TOMNY:	MOVE	TBITS,ARYBITS		;BITS DESCRIBING ARRAY
	TLNE	TBITS,EXTRNL		;IF EXTERNAL, DON'T ALLOCATE
	 POPJ	 P,

	MOVSI	ARRBIT,SOMVAR!LOWVAR!MULMUL	;ASSUME NOT OWN ARRAY
	TLNE	TBITS,OWN		;TEST ASSUMPTION
; OWN (BUILT-IN) ARRAY
	 TLO	 ARRBIT,400000		;INVALID ASSUMPTION
;;#IQ# 7-18-72 DCS ENDJMP CODE MOVED TO ENTARY
	MOVE	PNT,GENLEF+3		;LOWER BOUND SEMANTICS
	GENMOV	(CONV,INSIST!GETD,INTEGR)
	JUMPL	ARRBIT,NOSTKL		;DON'T STACK IF TOP-LEVEL
	GENMOV	(STACK)			;STACK LOWER BOUND

NOSTKL:	TLNN	TBITS,CNST		;IF IT IS CONSTANT,
	 JRST	 NOLOCN
	MOVE	TEMP,$VAL(PNT)		;GET VALUE
	MOVEM	TEMP,@ABLKPT		; SAVE LOWER BOUND
	TLC	ARRBIT,LOWFIX!LOWVAR	; AND INDICATE FIXEDNESS	

NOLOCN:	MOVE	PNT,GENLEF+1		;UPPER BOUND SEMANTICS
	GENMOV	(CONV,INSIST!GETD,INTEGR)
	JUMPL	ARRBIT,NOSTKH		;NO STACKING ETC.
	GENMOV	(STACK)

NOSTKH:	TLNE	ARRBIT,LOWFIX		;DON'T GO FURTHER IF LOWBND VBL
	TLNN	TBITS,CNST		; OR UPPER VBL
	 JRST	 NOHICN

	MOVE	TEMP,$VAL(PNT)		;UPPER BOUND
	SOS	ABLKPT			;SAVE THIS TOO
	HRRM	TEMP,@ABLKPT		;SAVE IT
	TLCA	ARRBIT,BOTFIX!SOMVAR	;MARK BOTH FIXED

NOHICN: SOS	ABLKPT
	JUMPGE	ARRBIT,OKFXD		;BE SURE ALL IS CONST IF
	TLNN	ARRBIT,BOTFIX		; TOPLEV
	 ERR	 <CONSTANT BOUNDS REQD FOR TOP-LEVEL ARRAY>,1
OKFXD:	TLZ	ARRBIT,400000
	HLLM	ARRBIT,@ABLKPT		;UPDATED BITS
	POPJ	P,			;THAT'S ALL
SUBTTL	 ARRDEC

↑ARRDEC:

; FIRST GET A DECENT ARYBLK, FULL OF GOOD THINGS

	MOVE	A,DIMNO			;#DIMENSIONS FOR THESE ARRAYS
	CAIG	A,5			;IF > 5-DM FORGET THE REST OF THIS
	 JRST	BECLEVER		;OTHERWISE PREPARE TO BE CLEVER
	SETOM	BLKOK			;CAN'T USE THE BLOCK
	JRST	MAKARY			;GO MAKE AN ARRAY

BECLEVER:
	SETZM	NOMULT			;WHEN ON, NUMUL GOES
					; ON IN REMAINING BITS
	LSH	A,1			;2*DIMNO FOR INDEXING TABLE
	ADDI	A,1			;FIRST SOJE WILL HAVE NO EFFECT
	MOVEI	C,1			;FIRST MULTIPLIER
	MOVEI	D,0			;COLLECT TOTAL CONSTANT DISPLACMENT
	MOVE	TBITS,ARYBITS		;GET GOOD BITS
	MOVSI	B,BOTFIX		;MAKE TLNN TAKE FIRST TIME

; THIS LOOP CONDITIONS THE ENTRIES IN ARYBLK TO LOOK LIKE THE ABOVE 
; COMMENTS SAID THEY WOULD LOOK -- COMPUTES THE π VALUES, MAKES NOMUL
; BIT CORRECT IN EACH ENTRY. ALSO COLLECTS THE TOTAL CONSTANT DISPLACEMENT
; WHICH CAN BE USED TO MAKE ARRAY CALCULATIONS FASTER.
; IF "GOGOL", ALSO STACKS (ACTUALLY) THE BOUNDS FOR (ACTUAL) CALL ON ARMAK.


CLEVLUP:
	SOJE	A,MAKARY
	TLNN	B,BOTFIX		;WILL WE STILL BE ABLE TO USE
	 SETOM	 NOMULT			; CONSTANT MULTIPLIERS? -- NO
	MOVE	TEMP,ARYBLK-1(A)	;LOWBND

GAG <;STACK LOWER BOUND IF BUILT-IN
	TLNE	TBITS,OWN	;CAN WE DO IT?
	PUSH	P,TEMP		;NOT ONLY CAN WE, ....
>;GAG

	HRLM	TEMP,ARYBLK-1(A)	;SAVE IN LH
	HRRM	C,ARYBLK-1(A)		;SAVE MULTIPLIER
	HLLZ	B,ARYBLK-2(A)		;BITS
	TLNN	B,LOWFIX		;IF LOWFIX, 
	 JRST	 CHKMUL
	IMUL	TEMP,C			;COMPILE TOTAL DISPLACEMENT
	SKIPN	NOMULT			; (IF STILL COLLECTING IT)
	 ADD	 D,TEMP			; IN D
	HRRE	TEMP,ARYBLK-2(A)	;UPPER BOUND THIS DIM

GAG <;STACK UPPER BOUND IF POSSIBLE
	TLNE	TBITS,OWN
	PUSH	P,TEMP
>;GAG

	TLNN	B,BOTFIX		;IGNORE IF CAN'T USE
	 JRST	 CHKMUL
	HLRE	PNT,ARYBLK-1(A)		;LOWER BOUND
	SUB	TEMP,PNT		;-LOWER BOUND
	ADDI	TEMP,1			; +1 IS TOTAL SIZE
	SKIPGE	TEMP
	 ERR.	 1,[ASCIZ /UPPER BOUND < LOWER BOUND IN ARRAY DECLARATION/]
	IMUL	C,TEMP			;UPDATE MULTIPLIER
CHKMUL:	SKIPE	NOMULT
	 TLC	 B,NOMUL!MULMUL		;CAN'T USE CONST MULTS NO MORE
	HLLM	B,ARYBLK-2(A)		;STORE PERHAPS UPDATED BITS

	SOJA	A,CLEVLUP		;GO BE MORE CLEVER

MAKARY: TLNN	B,LOWFIX		;CAN'T ASSUME KNOWALL IF HIGH-ORDER
	 SETOM	 NOMULT			;LOW BOUND NOT CONSTANT
	SETZM	LEFMRK			;WILL BE -1 FOR STRING, 0 ELSE
	MOVE	TBITS,ARYBITS		;DESCRIBE THESE ARRAYS
	TRNN	TBITS,STRING		;DOUBLE SIZES FOR STRING ARRAYS
	 JRST	 MKRY1
	SETOM	LEFMRK
	LSH	C,1
	LSH	D,1
MKRY1:	MOVEM	C,ARRSIZ		;SAVE TOTAL ARRAY SIZE
	MOVEM	D,ARRDSP		;AND TOTAL CONSTANT DISPLACMENT
	TLNE	TBITS,EXTRNL		;HANDLE EXTERNALS IN COMPLETELY
	 JRST	 EXARST			; DISJOINT FASHION
	TLNE	TBITS,OWN		;HANDLE OWN ARRAYS SOMEWHAT
	 JRST	 OWNARR			; DIFFERENTLY (DON'T PUT OUT CALLS)

; FINISH SETTING UP CALLING SEQUENCE FOR DYNAMIC ARRAYS

;;#GP# DCS 2-7-72 (1-2) WARNING ON ATTEMPT TO PRELOAD DYNAMIC ARRAY
	SKIPE	LDYFLG			;DON'T LET PRELOADS GO UNNOTED
	 ERR	 <DON'T PRELOAD DYNAMICALLY ALLOCATED ARRAYS>,1
;;#GP# (1)
	MOVE	A,DIMNO			;NUMBER OF DIMENSIONS.
	HRL	A,LEFMRK		;-1 FOR STRING, 0 OTHERWISE
	PUSHJ	P,CREINT		;MAKE AN INTEGER
	GENMOV	(STACK,0)		;STACK IT.
	XPREP
	MOVE	SBITS2,DIMNO		;JUST A PLACE THAT WON'T CHANGE.

	MOVE	A,DIMNO
	LSH	A,1			;MULTIPLY BY TWO
	ADDI	A,1			;AND ACCOUNT FOR WORD WITH #OF DIMS.
	MOVN	TEMP,A			;ALSO RESTORE ADEPTH TO NORMAL
	ADDM	TEMP,ADEPTH

	HRLS	A			;AND COPY IN BOTH HALVES.
	PUSHJ	P,CREINT		;AND MAKE AN INTEGER OF IT.
	MOVE	PNT2,PNT		;SEMANTICS OF THE INTEGER.
	MOVE	ARRBIT,ARYLST		;#ARRAYS WITH THESE DIMENSIONS
	SETZM	OWNWD			;NOT OWN ARRAY
	JRST	STARLP			;GO ALLOCATE ARRAYS
OWNARR:	MOVE	ARRBIT,ARYLST		;#ARRAYS WITH THESE DIMENSIONS

GAG <;ACTUALLY STACK #DIMENSIONS FOR CALL ON ARMAK
	MOVE	TEMP,DIMNO
	HRL	TEMP,LEFMRK		;STRING OR NOT
	PUSH	P,TEMP			;STACK IT
	LSH	TEMP,1			;GET ADD COUNT FOR STACK ADJUSTMENT
	HRRI	PNT2,1(TEMP)		;SEE ABOVE
	HRLS	PNT2
>;GAG

	SETOM	OWNWD			;MARK OWN ARRAY



Comment ⊗ For each array, either issue call to set it up,
	or assemble it in line  ⊗

STARLP:	QPOP	(ARYPDL)		;RESCUE THE SEMANTICS FROM QSTACK
	PUSH	P,A			;SAVE  SEMANTICS UNTIL LATER
	SKIPE	OWNWD			;DYNAMIC OR OWN?
	 JRST	 STOWN			; OWN


AG1:	MOVEI	D,1			;RESTORE THE MAGIC AC NUMBER
AG:	MOVE	LPSA,A			;SEMANTICS OF THIS ARRAY
	PUSHJ	P,GETADL		;FILL UP THINGS.
LEP <
GLOC <
	TRNN	TBITS,GLOBL		;IF EITHER OF THESE, THEN...
>;GLOC
	TLNN	TBITS,SBSCRP		;NOT IF REAL ARRAY.
	 JRST	[PUSH	P,PNT		;REMEMBER
		 TRNN	TBITS,LPARRAY	;IF ITEM TYPE, THEN
		 JRST 	LXXL		;
		 MOVE	PNT,$VAL2(PNT)	;PICK UP SEMANTICS OF ITEM NO.
		 EMIT	<PUSH RP,NOUSAC> ;AND STACK ITEM NUMBER.
	LXXL:	 LDB	B,[POINT 1,TBITS,29];THE LPARRAY BIT FROM TBITS.
		 LSH	B,3		;CHANGE INTO ARRTYP BIT
;ABOVE CAUSED BY NEW ITEM TYPE INFOTAB CODES. ARRTYP = 15
;BUT THE SINGLE BIT SHOULD CATCH.
		 HRLZM	B,BYTES		;THIS IS USED BY LPCALL.
GLOC <
		 TRNN	TBITS,GLOBL	;...
		 JRST	LXXXL
		 AOS	LEPGLB		;SAY IT IS GLOBAL.
		PUSHJ	P,GLBST2	;LET GLOBAL REALLY KNOW
>;GLOC
	LXXXL:	 LPCALL	(ITMRY)		;THIS WILL DO ALL THE WORK.
		 POP	P,PNT		;RESTORE.
		 JRST	AG0]
>;LEP
	XCALL	<ARMAK>
AG0:	
	HRRI	FF,0
	TLNE	TBITS,SBSCRP		;IF A REGULAR ARRAY.
	GENMOV	(PUT)			;STORE THE AC1 ANSWER.
TESTIT:	TRNN ARRBIT,777776
	JRST ADCND
	MOVE A,[ADD RP,NOUSAC]
	MOVE PNT,PNT2
	PUSHJ P,EMITER
	JRST	ADCND

STOWN:
REN <
	PUSHJ	P,LOSET			;SWITCH TO DATA PC
>;REN
	SETOM	OWNWD			;OWN ARRAY
	SKIPE	BLKOK			;>5-D OUTER ARRAYS CAUSE TROUBLE
	 ERR	 <OUTER LEVEL ARRAYS OF OVER 5-D DON'T WORK>,1
	MOVE	TBITS,ARYBITS

NOGAG <;ALL THIS GOES AWAY IN "GOGOL"

REN <
	SKIPE	HISW			;JUMPING AROUND ARRAYS NOT
	 JRST	 NOJ			; NECESSARY IN RE-ENTRANT PROGRAM
>;REN
	MOVE	TEMP,TPROC		;IF JUMP AROUND PROCEDURES HAS
	HLRZ	TEMP,%TLINK(TEMP)	; BEEN ISSUED, WE'LL JUST USE
	MOVE	A,[JRST NOUSAC!NOADDR]
	SKIPN	$SBITS(TEMP)		; IT BELOW TO GET AROUND ARRAY
	PUSHJ	P,EMITER		;OTHERWISE ISSUE JUMP

NOJ:	PUSH	P,PCNT			;WILL NEED FOR FIXUP LATER
	EMIT	<NORLC!NOADDR!NOUSAC>	;0, BECOMES A POINTER LATER
	MOVN	TEMP,DIMNO
	IMULI	TEMP,3
	SUB	TEMP,ARRSIZ
	SUBI	TEMP,5			;-(ARRAY SIZE + 5+3*DIMNO)
	MOVE	A,[XWD -1,NORLC!NOUSAC!USADDR]
	HRL	C,TEMP
	PUSHJ	P,EMITER		;ARRAY SIZE WORD
	HRL	A,LEFMRK		;-1 FOR STRING, 0 OTHERWISE
	HRRI	A,NOUSAC!NOADDR		;WILL BE 0,0,0 WORD
	PUSHJ	P,EMITER		;LEAVE ROOM
	MOVE	D,DIMNO			;THIS LOOP AGAIN!
	LSH	D,1			;*2 TO INDEX BLOCK
	ADDI	D,1			;NULLIFY FIRST SOJE

HEDLUP:	SOJE	D,FINHED
	HLLE	C,ARYBLK-1(D) 		;LOWER BOUND
	HRL	A,C
	HRRI	A,USADDR!NORLC!NOUSAC	;PUT IT OUT
	PUSHJ	P,EMITER
	HRLE	C,ARYBLK-2(D)		;UPPER BOUND THIS DIM
	HRL	A,C			;PUT OUT UPPER
	PUSHJ	P,EMITER		; BOUND
	HRL	C,ARYBLK-1(D) 		;MULTIPLY FACTOR
	EMIT	<USADDR!NORLC!NOUSAC> 	;PUT IT THERE TOO
	SOJA	D,HEDLUP

FINHED:	MOVE	TEMP,DIMNO		;ONE MORE TIME
	TRNE	TBITS,STRING
	MOVNS	TEMP			;#DIMENSIONS, - IF STRING
	HRL	A,TEMP
	HRRI	A,NOUSAC!NORLC!USADDR
	HRL	C,ARRSIZ
	PUSHJ	P,EMITER		;#DIMS,,TOTAL SIZE
	HRL	B,(P)			;FIXUP ADR OF HEAD OF ARRAY
	HRR	B,PCNT			;ADR OF 1ST DATA WORD
	HRRM	B,OWNWD			;SAVE IT
	PUSHJ	P,FBOUT			;LET HDR → 1ST DATA WORD
	SKIPN	LDYFLG			;IS THIS A PRELOADED ARRAY ?
	JRST	NOPRE			;NO -- GO AHEAD AS USUAL.....

	PUSHJ	P,LDYOUT		;PUT OUT CONSTANTS INTO ARRAY
	JRST	NOADPC			;DON'T ADD TO PCNT AGAIN

NOPRE:	PUSHJ	P,FRBT			;FORCE OUT BINARY
	MOVE	TEMP,ARRSIZ		;GET OVER ARRAY
	ADDM	TEMP,PCNT		;BY THIS MUCH
NOADPC:	HRL	C,(P)			;HDR ADDRESS AGAIN
	MOVE	A,[XWD 400000,USADDR!NOUSAC]
	PUSHJ	P,EMITER		;SIGN BIT,,ADDR OF HEAD
	TRNN	TBITS,STRING		;PUT OUT LINKAGE 
	 JRST	 NSTR			; BLOCK IF STRING ARRAY
IFN PATSW, <
	EMIT	<NOADDR!NOUSAC>		;ACTIVE WORD, CURRENTLY MEANINGLESS
>;IFN PATSW
	HRRZ	TEMP,ARRSIZ		;COMPUTE NUMBER OF STRINGS
	LSH	TEMP,-1
	HRL	A,TEMP
	HRL	C,OWNWD			;ARRAY LOCATION (1ST STRING)
	HRRI	A,NOUSAC!USADDR	
	PUSHJ	P,EMITER		;PUT IT OUT
	EMIT	<NOADDR!NOUSAC>		;LINK GOES THRU HERE
	MOVEI	B,1			;STRING LINK BLOCK.
	PUSHJ	P,LNKOUT		;PUT OUT LINK BLOCK

NSTR:
REN <
	PUSHJ	P,HISET			;SWITCH BACK TO PROGRAM PC
>;REN
	PUSHJ	P,ENDJMP		;FIX UP JUMP AROUND PROC TO HERE, IF NECC.
	 JRST	 ALJMPD			; NO MORE NEEDED (SEE ENDDEC,PRDEC)
	MOVE	B,(P)			;HDR ADDR
	SUBI	B,1			;JRST ADDR
	HRL	B,PCNT

REN <
	SKIPN	HISW			;DON'T DO JUMP IF RE-ENTRANT PROG
>;REN
	PUSHJ	P,FBOSWP		;JRST FIXUP
>;NOGAG
ALJMPD:
GAG <;THIS GETS AN ARRAY OF JUST THE RIGHT FLAVOR , LOADS IT IF NECESSARY
	PUSHJ	P,ARMAK			;CHECK LEAP**********
	TRNE	ARRBIT,777776		;MORE TO COME?
	ADD	P,PNT2			;YEP, PUT PARAMS BACK ON STACK
	TRNE	TBITS,STRING		;ARMAK IS TOO CLEVER ABOUT INCREMENTING
	SUBI	A,1			;1ST DATA WORD ADDR FOR STRING ARRAYS
	HRRZM	A,OWNWD			;STORE ADDR WITH A STRAIGHT FACE
	SKIPE	LDYFLG			;MUST WE TRANSFER DATA?
	PUSHJ	P,LDYOUT		;YES, DO IT
>;GAG
	HRL	C,OWNWD			;ARRAY LOCATION
	MOVE	A,[SETZM NOUSAC!USADDR]	;SETZM 1ST DATA WORD.
	SKIPN	LDYFLG
	PUSHJ	P,EMITER		;PUT IT OUT IF NOT PRE-LOADED ARRAY.
	MOVE	A,[HRLI RTEMP,NOUSAC!USADDR]	;HRLI TEMP, 1ST WORD.
	TRNN	TBITS,LPARRAY		;ALWAYS IF LEAP TYPE ARRAY
	SKIPN	LDYFLG
	PUSHJ	P,EMITER
LEP <
	TRNE	TBITS,ITEM
	TRNN	TBITS,LPARRAY
	JRST	NORCIT
	PUSH	P,C
; NOW THIS C, THE ARRAY HEADER PCNT, AND THE ARRAY SEMANTICS ARE IN THE PSTACK
	MOVE	PNT,-2(P)		;SO THIS IS HOW TO GET SEMANTICS
	MOVE	PNT,$VAL2(PNT)		;POINTER TO INTEGER AGAIN.
	EMIT	<PUSH RP,NOUSAC>
	LPCALL	(ITMYR)		;ALL THE WORK IS DONE HERE.
	POP	P,C
NORCIT:
>;LEP
	SKIPE	LDYFLG			;PRELOADING ?
	JRST	FXBLK			;YES -- FINISH UP...
	ADD	C,[XWD 1,0]
	EMIT	<HRRI RTEMP,NOUSAC!USADDR> ;HRRI TEMP,2D WORD
	HRRZ	TEMP,OWNWD		;ARRAY LOC
	ADD	TEMP,ARRSIZ
	HRLI	C,-1(TEMP)		;LAST WORD
	EMIT	<BLT RTEMP,NOUSAC!USADDR> ;BLT TEMP,LAST WORD
FXBLK:	TRNE	TBITS,STRING		;NAME ARRAY LOC IF BILTIN
	 AOS	 OWNWD			;1 PAST IF STRING

NOGAG <;MORE UNECESSARY THINGS IN "GOGOL"

	POP	P,B			;HDR ADDR, ONE MORE TIME
	ADDI	B,2			;ADDR OF 0,0,0 WORD
	MOVE	TEMP,OWNWD		;UPDATED ARRAY LOC
	SUB	TEMP,ARRDSP		;TOTAL DISPLACEMENT
	HRL	B,TEMP
	MOVSS	B			;ADDR,FIXUP
	PUSHJ	P,FBOUT
>;NOGAG
ADCND:

; NOW MAKE A BLOCK FOR EACH ARRAY, SET UP #DIMS, STORE ADDRESS

	MOVE	A,DIMNO			;#DIMENSIONS
;;#HN#↓ 6-6-72 DCS USE LEFMRK ONLY IF OWNWD (BUILT-IN)-- 0 IF DYNAMIC!
	SKIPE	B,OWNWD			;ADDR OF BEGINNING OF ARRAY
	HRL	B,LEFMRK		;-1 FOR STRING, 0 ELSE
	MOVEI	C,0			;ASSUME ¬KNOWALL
	SKIPN	NOMULT			;TEST ASSUMPTION
	MOVSI	C,KNOWALL		;WRONG
	MOVE	D,OWNWD
	SUB	D,ARRDSP		;DISPLACEMENT, IF KNOWN

	POP	P,PNT		;USE SEMANTICS OF THIS ARRAY, SAVED AT STARLP
	HRLM	A,NUMDIM(PNT)		;NUMBER OF DIMENSIONS

GAG <;PUT ARRAY ADDRESS IN ALLOCATED VARIABLE
	HRRM	B,@$ADR(PNT)		;STORE ARRAY ADDRESS IN VBL
>;GAG

	HRLM	D,TOTDSP(PNT)		;DISPLACEMENT IF KNOWN
	MOVEM	B,ARLOC(PNT)		;LOCATION IF KNOWN
	ORM	C,$SBITS(PNT)		;ADD KNOWALL BIT
	SKIPE	BLKOK			;CAN WE PREPARE A BOUNDS BLOCK?
	 JRST	 NOBDBK			; NO BNDBLK

	GETBLK	<LPSA>			;NEW BLOCK TO HOLD IT
	MOVSI	TEMP,ARYBLK		;SOURCE
	HRR	TEMP,LPSA		;DEST
	BLT	TEMP,=10-1(LPSA)	;SAVE BNDBLK INFO
	HRLM	LPSA,%TLINK(PNT)	;→BNDBLK
NOBDBK:	SOJG	ARRBIT,STARLP		;GET THEM ALL

FINIT:	SETZM	ARYLST			;CLEAR SOMETHING ANYHOW
	SKIPN	LDYFLG			;PRELOADING ?
	POPJ	P,			;ALL DONE HERE
FINLUP:	QPOP	(LDYSTK)	;POP OFF THINGS.
	JUMPN	A,FINLUP		;UNTIL THE 0 THAT STARTED THINGS.
	SETZM	LDYFLG			;FOR NEXT TIME.
	POPJ	P,			;DONE AT LAST.


EXARST:	MOVE	B,ARYLST		;ONLY THE ESSENTIALS
	MOVE	SBITS2,DIMNO		;FOR EXTERNAL ARRAYS
;;#GP# DCS 2-7-72 (2-2) WARNING ON PRELOADED EXTERNAL ARRAYS
	SKIPE	LDYFLG			;DID HE REALLY DO THIS?
	 ERR	 <YOU CAN'T LOAD THAT ARRAY FROM HERE>,1
;;#GP# (2)
	
AGEX:	QPOP	(ARYPDL)		;SEMANTICS FOR THIS ARRAY
	HRLM	SBITS2,$ACNO(A)		;STORE NUMBER OF DIMENSIONS
	SOJG	B,AGEX		;DON'T QUIT UNTIL DONE
	JRST	FINIT			;NOW STOP
DSCR LDYBEG, LDYREP, LDYNO
PRO LDYBEG LDYREP LDYNO
DES EXECS for PRELOAD specifications
⊗
↑LDYBEG: MOVEI	A,0
	QPUSH	(LDYSTK)		;PUSH IT ON.
	MOVE	A,LDYSTK
	MOVEM	A,LDYTAK		;FOR THE QTAKE OPERATION.
	SETZM	CURENT
	SETOM	LDYFLG			;TO TELL ARRDEC.
	SETZM	LDYTOT			;AND TOTAL SIZE.
	POPJ	P,

↑LDYREP: GETSEM	(1)			;REPEAT ARGUMENT
	TLNN	TBITS,CNST		;MUST BE CONSTANT.
	ERR	<VARIABLE REPEAT ARGUMENT>,1
	MOVE	A,$VAL(PNT)		;CONSTANT
	HRLM	A,CURENT		;AND SAVE IT.
	POPJ	P,

↑LDYNO:	GETSEM	(1)			;THE CONSTANT TO LOAD
	TLNN	TBITS,CNST		;A REAL CONSTANT?
	ERR	<VARIABLE IN PRELOAD>,1
	MOVE	A,PNT
	HLL	A,CURENT
	TLNN	A,-1			;IF SOME REPEAT ARG.
	TLO	A,1
	SETZM	CURENT
	QPUSH	(LDYSTK)		;STACK IT.
	HLRZ	A,A
	ADDM	A,LDYTOT		;UPDATE TOTAL SIZE.
	POPJ	P,




LDYOUT:	TRNN	TBITS,ITMVAR,INTEGR!FLOTNG!STRING	;ONLY FOR THESE TYPES.
	JRST	[ERR <ONLY ALGEBRAIC PRELOADED ARRAYS>,1
		 JRST LPOPJ]
	MOVE	A,LDYTOT		;ACCUMULATED TOTALS.
	LSH	A,1			;MULTIPLY BY TWO
	TRNE	TBITS,STRING
	MOVEM	A,LDYTOT		;AND RECORD IF NECESSARY.
	PUSH	P,ARRSIZ		;SAVE IT
	PUSH	P,PNT			;GET AN ACCUMULATOR
	PUSH	P,SBITS			;AND ANOTHER
	PUSH	P,TBITS			;AND A THIRD.
GAG <; ONE MORE
	PUSH	P,OWNWD			;USED TO INDIRECTLY LOAD (REAL LIVE) ARRAY
>;GAG

	MOVE	B,LDYTAK		;THE QTAKE POINTER.
LDYLOP:	QTAKE	(LDYSTK) ;GET AN ENTRY   XWD REPEAT #,,SEMANTICS OF CONSTANT.
	JRST	LDYFIQ			;NO MORE LEFT.....
	PUSH	P,B			;SAVE QTAKE POINTER.
	MOVE	PNT,A
	HLRZ	D,A			;REPEAT COUNT.
	PUSHJ	P,GETAD			;GET THE GOOD BITS.
	TLNN	TBITS,CNST		;IF NOT, YOU HAVE LOST VERY BIG......
	ERR	<CONSTANTS ONLY IN LOADED ARRAYS>,1

NOGAG <;PUT OUT WORDS TO .REL FILE IF NOT "GOGOL"

	MOVE	B,-1(P)			;TYPE OF ARRAY
	TRZ	B,ITEM!ITMVAR!LPARRAY	;NOT THESE TYPES.
	GENMOV	(CONV,INSIST)		;ALRIGHT BOYS....
LDYG2:	MOVE	A,$VAL(PNT)		;THIS IS THE CONSTANT.....
	TRNE	TBITS,STRING		;WOW -----
	HRRZ	A,$PNAME(PNT)		;GET THE LENGTH WORD.
	TLZ	FF,RELOC
	PUSHJ	P,CODOUT		;AND PUT OUT THE WORD.....
	TRNN	TBITS,STRING		;ANOTHER WORD IF STRING.
	JRST	LDYG1			;LOOP OTHERWISE.
	MOVS	C,PCNT			;OH DEAR
	EXCH	C,$VAL(PNT)		;HERE (FOR STRINOS) WE STORE THE FIXUP.
	MOVE	A,[POINT 7,USADDR!NOUSAC]
	PUSHJ	P,EMITER		;AND EMIT IT.....
	SOS	ARRSIZ			;DECREASE SIZE LEFT.

>;NOGAG

GAG <;PUT DIRECTLY INTO ARRAY IF "GOGOL"
LDYG2:	MOVE	A,$VAL(PNT)		;GET NUMBER
	TRNE	TBITS,STRING		;NOT A NUMBER?
	MOVE	A,$PNAME(PNT)		;NO HARM DONE
	MOVEM	A,@OWNWD		;PUT IN ARRAY
	AOS	OWNWD
	TRNN	TBITS,STRING		;ONE MORE?
	 JRST	 LDYG1			; YES
	MOVE	A,$PNAME+1(PNT)
	MOVEM	A,@OWNWD
	AOS	OWNWD			;MOVE UP
	SOS	ARRSIZ			;DECREASE
>;GAG

LDYG1:	SOSG	ARRSIZ			;MORE LEFT?
	JRST	LDYFIN			;NO
	SOJG	D,LDYG2			;LOOP UNTIL REPEAT EXHAUSTED.
	POP	P,B			;QTAKE POINTER
	JRST	LDYLOP			;AND KEEP GOING.
LDYFIN:	POP	P,B
LDYFIQ:

GAG <;GET IT BACK
	POP	P,OWNWD
>;GAG
	POP	P,TBITS			;RESTORE ALL THE SAVED AC'S
	POP	P,SBITS
	POP	P,PNT
	POP	P,ARRSIZ		;AND THE SIZE
	MOVE	B,ARRSIZ		;THE TOTAL SIZE.
	SUB	B,LDYTOT		;ACCUMULATED TOTAL OF SPECIFICATIONS.
	JUMPE	B,LPOPJ			;FITS JUST FINE.
	JUMPL	B,[ERR <WARNING -- PRELOADED RANGES TOO LARGE>,1
		   JRST LPOPJ]
NOGAG <;NO NEED IN "GOGOL"
	MOVEI	A,0
	TLZ	FF,RELOC
	PUSHJ	P,CODOUT		;MAKE UP THE DIFFERENCE
	SOJG	B,.-1
>;NOGAG
LPOPJ:	POPJ	P,			;DONE
DSCR ARYIDX, ARRSBY, ARRSB1
PRO ARYIDX ARRSBY ARRSB1
DES ARYIDX initializes for an array-subscripting operation
 ARRSBY is called for every actual index but the last
 ARRSB1 is called for the last index, issues final code
SEE Comments at beginning of ARRAY for details
⊗
↑ARYIDX:
	GETBLK	<PNT2>			;PNT2→IDXBLK
	GETSEM	(1)			;SEMANTICS OF ARR
	HRRZM	PNT,%TBUCK(PNT2)	;SAVE → ARR IN IDXBLK
	HLRZ	TEMP,%TLINK(PNT)	;→BNDBLK FOR THIS ARRAY
	MOVEM	TEMP,BNDPNT(PNT2)	;SAVE IN IDXBLK
	HLRZ	TEMP,NUMDIM(PNT)		;#DIMENSIONS
	TLNE	TBITS,FORMAL		;∞ IF FORMAL
	TRO	TEMP,-1			; (DON'T KNOW REAL NUMBER)
	MOVEM	TEMP,NUMDIM(PNT2)
	MOVEM	PNT2,GENRIG		;THIS IS THE ANSWER
	POPJ	P,

		 JRST LPOPJ]
; FIRST PART SETS UP ARRBIT TO INDICATE EXACT CONDITIONS

↑ARRSBY: SKIPA	ARRBIT,[XWD MANYD!NOTLST!IDXVAR!DANGAR,0] ;NOT LAST INDEX
↑ARRSB1: MOVSI  ARRBIT,MANYD!LSTIDX!IDXVAR!DANGAR	;LAST INDEX
	HRRZ	PNT2,GENLEF+2		;IDXBLK SEMANTICS
	AOS	TBLIDX,DIMPRC(PNT2)	;COUNT #DIMS PROCESSED
	CAMLE	TBLIDX,NUMDIM(PNT2)	;TOO MANY?
	 ERR	 <TOO MANY DIMENSIONS IN SUBSCRIPT>,1
	SOJN	TBLIDX,NOTONE		;CHECK 1-D ARRAY
	TLNE	ARRBIT,LSTIDX		;LSTIDX∧DIMPRC=1⊃ONED
	TLC	ARRBIT,ONED!MANYD	;RESET CONDITIONS

NOTONE:	MOVNI	TBLIDX,1(TBLIDX)	; -DIMNO
	IMULI	TBLIDX,3		;INDEX INTO ARRAY DESCRIPTOR
	HRRZ	PNT,%TBUCK(PNT2)	;SEMANTICS OF ARRAY
	PUSHJ	P,GETAD
	TRNE	TBITS,STRING		;IF STRING ARRAY, ADJUST 
	 SUBI	 TBLIDX,1		; DISPLACEMENT INTO TABLE
	TLNE	TBITS,SAFE		;ADJUST FOR SAFETY
	 TLC	 ARRBIT,SAFEAR!DANGAR
	TLNE	SBITS,ARTEMP		;IF ARTEMP, THEN DATUM OF ITEMVAR
	 TLO	 ARRBIT,DATMR
	SETZM	SIZZ			;IN CASE NO BITS KNOWN
	SKIPN	B,BNDPNT(PNT2)		;BOUNDS BLOCK POINTER
	 TLO	 ARRBIT,NOMUL!LOWVAR!SOMVAR ;NO BITS, ADD DEFAULT ONES
	 JUMPE	 B,MKTST		; AND SKIP BIT LOAD
	OR	ARRBIT,(B)		;SET UP BITS FROM BOUNDS BLOCK
	MOVEW	(SIZZ,<1(B)>)		;LOWER BOUND AND π FOR THIS DIM.
	ADDI	B,2
	MOVEM	B,BNDPNT(PNT2)		;UPDATE BOUNDS POINTER

; FINISH SETTING BITS

MKTST:	MOVE	TEMP,GENLEF+1		;INDEX SEMANTICS
	MOVE	TEMP,$TBITS(TEMP)	;TBITS FOR INDEX
	TLNE	TEMP,CNST		;CONSTANT INDEX?
	 TLC	 ARRBIT,IDXCON!IDXVAR	; YES, MAYBE SIMPLER
	TLNE	ARRBIT,LSTIDX		;IF LAST INDEX,
	 TLZ	 ARRBIT,MULMUL!NOMUL	; EASE OF MULTIPLICATION IRRELEVANT


; NOW LOAD ARRAY ADDRESS IF NUMUL∨¬SAFE∧SOMVAR

	TLNN	ARRBIT,NOMUL		;MUST IF HAVE TO DO IMUL
	TLNN	ARRBIT,SAFEAR!BOTFIX	;ALSO IF DANGAR∧SOMVAR
	 JRST	[TLO	ARRBIT,GOTARR	;AND GOT ARRAY INTO AC.
		 GENMOV  (GET,INDX)	;NO HELP FOR IT.
		 HRROS	ACKTAB(D)	;PROTECT OVER GETTING THE INDEX VARB.
		 HRLS	D		;COPY FOR DOING INDEXING.
		 JRST	.+1]

; MAKE SURE INDEX IS LOADED IF HAVE TO EMIT BOUNDS-CHECKING CODE

	MOVE	PNT,GENLEF+1		;INDEX SEMANTICS
;;#FP#  1-10-72 DCS (1-1)
	GENMOV	(CONV,INSIST!GETD!POSIT!INDX,INTEGR);REQUIRE THESE
				;THINGS, DON'T GET UNLESS NEEDED
; WAS	GENMOV	(CONV,INSIST!GETD,INTEGR) ;REQUIRE AT LEAST THIS MUCH 
;;#FP#   This will avoid some redundant instructions
	MOVEM	PNT,GENLEF+1		;SAVE ANY NEW SEMANTICS
	MOVE	SP,$VAL(PNT)		;IN CASE CONSTANT
	TLNE	ARRBIT,SAFEAR		;FORGET IF SAFE
	 JRST	 GUDGUY

	HRRI	FF,INDX!POSIT		;IN CASE HAVE TO LOAD
	TLNE	ARRBIT,IDXVAR!SOMVAR	;IF IDXCON∧BOTFIX, DON'T LOAD
	 GENMOV	(GET)			;1 INSTR ONLY
	MOVEM	PNT,GENLEF+1		;IN CASE SEMANTICS CHANGED

; DO BOUNDS CHECKING -- LOWER

LOWCHK:	HRRI	C,1			;BITS FOR CA(M/I)L
	TLNN	ARRBIT,IDXVAR!LOWVAR	;IF NOTHING MOVES
	 JRST	[HLRE  TEMP,SIZZ	;LOWER
		 CAMGE SP,TEMP		;UNDERFLOW?
		  ERR	 <YOU'LL HAVE SUBSCRIPT UNDERFLOW>,1
		 JRST  CHKOVF]
	TLNN	ARRBIT,IDXVAR!SOMVAR	;WILL WE ISSUE 2D INST?
	MOVEI	C,5			;NO, BITS FOR CA(M/I)GE
	TLNN	ARRBIT,LOWFIX		;TRY FOR "CAIL"?
	 JRST	 DOCAML			; NO, GET FROM ARRAY TABLE

	HLL	C,SIZZ			;LOWER BOUND
	TLNN	C,400000		;NEGATIVE??
	 JRST	 DOCAIL			; NO, WE WIN

	HLRE	A,C		;MAKE INTEGER CONSTANT
	PUSHJ	P,CREINT
	MOVE	A,[CAM USCOND]	;WILL USE CAML
	JRST	LOUT

DOCAML:	HRLI	C,-1(TBLIDX)		;-1-3*DIMNO
	SKIPA	A,[CAM USADDR!NORLC!USX!USCOND] ;WORST CASE
DOCAIL:	MOVE	A,[CAI USADDR!NORLC!USCOND]	;BEST CASE
LOUT:	PUSHJ	P,EMITER
; CHECK UPPER BOUNDS

CHKOVF:	TLNN	ARRBIT,IDXVAR!SOMVAR	;IF NOTHING MOVES
	JRST	[CAILE SP,(ARRBIT)	;CHECK AT COMPILE TIME
		  ERR	<YOU'LL HAVE SUBSCRIPT OVERFLOW>,1
		 JRST  GUDGUY]		;AND OUT

	TLNN	ARRBIT,BOTFIX		;DON'T WORRY ABOUT HIFIX ONLY
	 JRST	 NOCAILE

	HRL	C,ARRBIT		;UPPER BOUND
	TRNN	C,400000		;SEE ABOVE
	 JRST	 DOIMM
	HLRE	A,C
	PUSHJ	P,CREINT
	MOVE	A,[CAMLE]
	JRST	LEOUT

NOCAILE: HRLI	C,-1+1(TBLIDX)		;-1-*DIMNO+1(ARRX)
	SKIPA	A,[CAMLE USADDR!USX!NORLC]
DOIMM:	MOVE	A,[CAILE USADDR!NORLC]
LEOUT:	PUSHJ	P,EMITER		;BOUNDS CHECK INSTRUCTION

; PUT OUT ERROR UUO

MKERR:	MOVEI	TEMP,PNAME-1
	MOVSI	A,(<ARERR>)
	HRRZ	PNT,%TBUCK(PNT2)	;→ARRAY SEMANTICS
	TLNE	ARRBIT,DATMR		;IS THIS THE DATUM OF AN ARRAY?
	MOVE	PNT,$VAL(PNT)
	PUSH	TEMP,$PNAME(PNT)	;MAKE STRING CONSTANT FOR ERROR GUY
	PUSH	TEMP,$PNAME+1(PNT)
	PUSHJ	P,STRINS

EMNAM:	EXCH	D,DIMPRC(PNT2)		;THIS DIMENSION AS AC FIELD
	PUSHJ	P,EMITER		;ARERR DIMNO,"ARRAY NAME"
	EXCH	D,DIMPRC(PNT2)

; NOW SEE IF INDEX NEEDED IN AC FOR MULTIPLYING PURPOSES (OR ONED)

GUDGUY:	TLNN	ARRBIT,NOMUL!IDXVAR	;CAN IT ALL BE DONE NOW?
	 JRST	[HRRZ	TEMP,SIZZ	;MULTIPLY FACTOR (π)
		 TLNE	ARRBIT,MULMUL	;SHOULD MULTIPLY BE DONE?
		 IMUL	SP,TEMP		;YES, DO IT
		 ADDM	SP,$VAL(PNT2)	;UPDATE TOTAL DISPLACEMENT
		 MOVE	PNT,GENLEF+1	;ALSO REMOP THE INDEX EXPRESSION.
		 JRST	REVR1]		; AND UNPROTECT THE ARRAY AC
	TLNN	ARRBIT,NOTLST!ONED!DANGAR ;CAN WE ADD INSTEAD OF MOVE?
	 JRST	 ADDREV			;YES

SEMGET:	MOVE	PNT,GENLEF+1		;GET INDEX SEMANTICS AGAIN
	GENMOV	(GET,INDX!POSIT!INSIST!GETD,INTEGR) ;LOAD IT, IF NOT ALREADY
	PUSHJ	P,REMOP			;DO NOT FORGET TO REMOP INDEX.
	TLNE	ARRBIT,LSTIDX		;NEED WE MULTIPLY?
	 JRST	 NOMLT			; NOPE
	TLNE	ARRBIT,NOMUL		;CAN WE DO AN IMULI?
	 JRST	 DOMUL			; NO, AN IMUL

DOMULI:	HRL	C,SIZZ			;MULTIPLY FACTOR
	TLNN	C,-1			;0 MULTIPLE INVALID
	 ERR	 <DRYROT --0 MULTIPLE??>
	TLNN	C,777776		;1?
	 JRST	 NOMLT			; DON'T MULTIPLY BY 1
	EMIT	<IMULI NORLC!USADDR>
	JRST	NOMLT

DOMUL:	HRLI	C,1(TBLIDX)		;-1-3*DIMNO+2 -- MULTIPLY FACTOR
	EMIT	<IMUL USADDR+USX+NORLC> ;IMUL AC,-1-3*DIMNO+2(ARRX)

; NOW ADD OR CREATE PARTIAL TEMP

NOMLT:	PUSHJ	P,MARKINT		;MARK AS INTEGER.
	LEFT	PNT2,%TLINK,,
	HRLM	PNT,%TLINK(PNT2)	;GET OLD SEMANTICS, STORE NEW
	MOVEI	PNT,0			;MAKE REMOP HARMLESS IF JUMP IS TAKEN
	JUMPE	LPSA,REVR1;		;FRST INDX CLC, UNPROTECT ARRAY AC
	PUSHJ	P,GETADL		;SEMANTICS OF OLD PARTIAL
REVRET:	EMIT	<ADD>			;ADD AC,OLD PARTIAL
REVR1:	MOVS	TEMP,D			;ARRAY INDEX REG
	TLNE	ARRBIT,GOTARR		;UNPRTCT IF WE PICKED UP ARRAY DSCRPTR
	HRRZS	ACKTAB(TEMP)
	JRST	REMOP			;REMOVE OLD AND RETURN

ADDREV:	HLRZ	PNT,%TLINK(PNT2)	;ADD IN THE OPPOSITE DIRECTION
	JUMPE	PNT,SEMGET		; UNLESS THIS IS FIRST INDEX
					;(IT SHOULDN'T BE BECAUSE OF ABOVE CONDITIONS
	GENMOV	(GET,INDX!GETD)		;GET OLD TEMP BACK
	MOVE	PNT,GENLEF+1		;SEMANTICS OF THIS INDEX
	GENMOV	(CONV,INSIST!POSIT!GETD,INTEGR)	;MAKE SURE IT IS THE RIGHT SHAPE
	JRST	REVRET			;ADD IN INVERSE ORDER


DSCR SUBSCR
PRO SUBSCR
DES Issues final code for array subscripting operation
⊗
↑SUBSCR: HRRZ	PNT2,GENLEF+2		;IDXBLK SEMANTICS
	HRRZ	LPSA,%TBUCK(PNT2)	;SEMANTICS OF ARRAY
	HLRZ	PNT,%TLINK(PNT2)	;SEMANTICS OF PARTIAL CALCS
	HRRE	TEMP,NUMDIM(PNT2)	;CHECK CORRECT CALL
	JUMPL	TEMP,SUBIGN		;CAN'T CHECK IT
	CAME	TEMP,DIMPRC(PNT2)	;CHECK IT
	 ERR	 <NOT ENOUGH SUBSCRIPTS SUPPLIED TO >,3
SUBIGN:	EXCH	LPSA,PNT2		;PNT2 IS ARRAY SEMANTICS
	MOVE	B,DIMPRC(LPSA)		;ACTUAL NUMBER OF DIMENSIONS SEEN.
	MOVE	TBLIDX,$VAL(LPSA)	;GET TOTAL CONTRIBUTION OF CONSTS
	FREBLK	()			;RELEASE IDXBLK
	MOVE	SP,$TBITS(PNT2)		;TBITS FROM ARRAY (GET OWN)
	MOVEI	ARRBIT,0		;FLAGS FOR THIS CALC
	SKIPE	PNT			;ANY PARTIAL CALCS?
	 TLO	 ARRBIT,NOTCLC!SOMCLC	; YES (NOTCLC STORED INVERTED)
	TLNN	SP,OWN			;BUILT-IN ARRAY?
	 TLO	 ARRBIT,OWN		; NO, SET INVERTED SENSE
	TRNE	SP,STRING		;STRING ARRAY?
	 LSH	 TBLIDX,1		; YES, SHIFT THIS
	MOVE	TEMP,$SBITS(PNT2)	;NOW CHECK TOTDSP KNOWLEDGE
	TLNN	TEMP,KNOWALL		;HAVE WE GOT ENTIRE OFFSET?
	 TLO	 ARRBIT,KNOWALL		;NO (KNOWALL STORED INVERTED)
	JUMPE	PNT,NOGT		;NO PARTIAL CALCS
	GENMOV	(GET,GETD!INDX)		;MAKE SURE IN AC
	HRL	SP,D			;SAVE AC OF PARTIAL CALCS
	HRLI	C,1			;GET READY FOR LSH IF STRING
	MOVE	A,[LSH USADDR!NORLC]
	TRNE	SP,STRING
	PUSHJ	P,EMITER		;DOUBLE INDEX
NOGT:	EXCH	PNT,PNT2		;NOW PNT IS ARRAY SEMANTICS
	PUSHJ	P,GETAD			;GET BITS

	TLCN	ARRBIT,NOTCLC!OWN!KNOWALL ;INVERT AND TEST
	 JRST	 FXDARR			;CAN DO IT ALLL AT COMPILE TIME

; NOW ADJUST DISPLACEMENT BY TOTDSP IF KNOWALL

	TLNN	ARRBIT,KNOWALL		;WELL?
	 JRST	 DONKNO			;NEED [0,0,0] WORD

	HLRE	TEMP,TOTDSP(PNT)	;TOTDSP&POSSIBLY ARRAY ADDR
	ADD	TBLIDX,TEMP		;NOW TBLIDX HAS GOOD DISPL FIELD
	TLNE	ARRBIT,OWN!NOTCLC	;IF ¬OWN∧PARTIAL CALCS,
	 JRST	 GETARP			; CAN ADD ARRAY PTR
	EMIT	<ADD>			;DO IT
	JRST	MRKIDX			;MAKE AN INDEXED TEMP, FINISH OUT

GETARP:	TLNE	ARRBIT,OWN		;KNOWALL,¬OWN,¬PARTIAL CALCS?
	 JRST	 MRKIDX			;NO, KNOWALL,OWN,PARTIAL CALCS

	GENMOV	(GET,INDX)		;GET ARRAY ADDR TO INDXABLE AC
	JRST	MRKIDX

DONKNO:	GENMOV	(GET,INDX)		;MAKE SURE ARRAY ADDR IS UP
	HRLS	D			;SAVE AC AS INDEX POS
	HLR	D,SP			;GET AC OF PARTIAL CALCS BACK
;	MOVE	B,DIMPRC(IDXBLK)	;NUMBER OF DIMENSIONS ACTUALLY SEEN.
	IMULI	B,-3
	TRNE	TBITS,STRING		;GET POINTER TO [0,0,0] WORD
	 ADDI	 B,-1
	HRLI	C,-2(B)			;TO ADDR FIELD FOR EMITER
	JUMPN	PNT2,ADD000		;CAN ADD IF HAVE PARTIAL CALCS
	PUSHJ	P,GETAN0		;NEED INDEXABLE AC FOR 000 WORD
	SKIPA	A,[MOVE USX!USADDR!NORLC]

ADD000:	MOVE	A,[ADD USX!USADDR!NORLC]
	PUSHJ	P,EMITER		;GAIN ACCESS

MRKIDX:	MOVE	ARRBIT,$TBITS(PNT)	;GET TYPE BITS BACK
	PUSHJ	P,REMOP			;REMOVE ARRAY
	SKIPE	PNT,PNT2		;PARTIAL CALCS
	PUSHJ	P,REMOP			; REMOVE IF ANY
	PUSHJ	P,MARKINT		;MAKE AN INTEGER TEMP.
	TLZ	ARRBIT,-1≠OWN		;TURN OFF MOST LH BITS
	MOVEM	ARRBIT,$TBITS(PNT)	;THESE ARE THE REAL THING
	MOVSI	SBITS,INUSE!ARTEMP!INDXED!PTRAC
	MOVEM	SBITS,$SBITS(PNT)	;ALWAYS THE SAME
	MOVEM	TBLIDX,$VAL(PNT)	;DISPL FOR REFERENCES
	MOVEM	PNT,GENRIG		;RESULTS
	POPJ	P,

FXDARR:	HLRE	TEMP,TOTDSP(PNT)	;GET ALWAYS CONSTANT DISPL
	ADD	TBLIDX,TEMP		;INCREMENT BY CONSTANT CONTRIBUTIONS
	TLZ	TBITS,-1		;TYPE OF RESULT IN RH
	MOVSI	SBITS,FIXARR		;SPECIAL RESULT
	PUSHJ	P,GETTEM		;NEED TEMP BLOCK
	MOVEM	TBLIDX,$ADR(LPSA)	;NON-FIXUPABLE ADDRESS RESULT
	MOVEM	LPSA,GENRIG		;RESULT
	JRST	REMOP			;REMOVE "ARRAY" FROM USE
DSCR DOSFTY
DES   EXEC TO CHANGE THE SAFETY STATUS OF ARRAYS
⊗

↑DOSFTY:
	MOVE	LPSA,GENLEF+1		;PICK UP ARRAY ID
	MOVE	TBITS,$TBITS(LPSA)	;TYPEE BITS
	JRST	.+1(B)			; SKIP IF MAKE_UNSAFE
	TLOA	TBITS,SAFE		;MAKE SAFE
	TLZ	TBITS,SAFE		;MAKE UNSAFE
	MOVEM	TBITS,$TBITS(LPSA)	;PUT BITS BACK
	POPJ	P,


BEND ARRAY

SUBTTL	EXECS for Binary Algebraic Operators