|
|
@@ -81,6 +81,8 @@ CONST
|
|
|
MaxPend = 400 ;
|
|
|
MaxFields = 2000 ; (* record fields, in a table of their own: a
|
|
|
field is scoped to its record, not global *)
|
|
|
+ MaxArrs = 1000 ; (* array SHAPES, likewise: a symbol points at
|
|
|
+ one, and 2-D indexing needs both ranges *)
|
|
|
|
|
|
(* type codes (TP3 vartp) *)
|
|
|
TNone = 0 ; TArray = 1 ; TRecord = 2 ; TSet = 3 ;
|
|
|
@@ -163,6 +165,7 @@ TYPE
|
|
|
`set of T' can size its base. *)
|
|
|
fldFirst, fldLast : CARDINAL ; (* a RECORD type's field range in the
|
|
|
field table (0,0 when not a record) *)
|
|
|
+ arrIdx : CARDINAL ; (* an ARRAY type's shape in ArrRec (0 = no) *)
|
|
|
level : CARDINAL ;
|
|
|
local : BOOLEAN ;
|
|
|
resvar : CARDINAL ;
|
|
|
@@ -216,6 +219,13 @@ TYPE
|
|
|
lo, hi : LONGINT ; (* bounds, for a subrange/enum field *)
|
|
|
END ;
|
|
|
|
|
|
+ ArrRec =
|
|
|
+ RECORD
|
|
|
+ n : CARDINAL ; (* number of ranges (1 for array[1..5]) *)
|
|
|
+ lo, hi : ARRAY [0..3] OF LONGINT ;
|
|
|
+ elem : CARDINAL ; (* element size in bytes *)
|
|
|
+ END ;
|
|
|
+
|
|
|
(* ---------------------------------------------------------------- *)
|
|
|
(* state *)
|
|
|
(* ---------------------------------------------------------------- *)
|
|
|
@@ -240,6 +250,11 @@ VAR
|
|
|
fields : ARRAY [0..MaxFields - 1] OF FldRec ;
|
|
|
fldTop : CARDINAL ; (* next free field-table slot *)
|
|
|
recFldFirst, recFldLast : CARDINAL ; (* field range ParseType just built *)
|
|
|
+ arrs : ARRAY [0..MaxArrs - 1] OF ArrRec ;
|
|
|
+ arrTop : CARDINAL ; (* next free array-shape slot *)
|
|
|
+ newArrIdx : CARDINAL ; (* ArrRec index+1 for the type just parsed *)
|
|
|
+ constBlob : ARRAY [0..511] OF CHAR ; (* bytes of a set/array typed constant
|
|
|
+ while it is being built *)
|
|
|
|
|
|
wrd : ARRAY [0..MaxName] OF CHAR ;
|
|
|
|
|
|
@@ -1451,6 +1466,7 @@ BEGIN
|
|
|
e.hi := 0 ;
|
|
|
e.fldFirst := 0 ;
|
|
|
e.fldLast := 0 ;
|
|
|
+ e.arrIdx := 0 ;
|
|
|
e.level := lexnest ;
|
|
|
e.local := local ;
|
|
|
e.resvar := 0 ;
|
|
|
@@ -2163,8 +2179,13 @@ BEGIN
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
ELSIF symtab [r.idx].cls = TArray THEN
|
|
|
- r.boff := W16 (VAL (LONGINT, r.boff)
|
|
|
- + t.imm * VAL (LONGINT, symtab [r.idx].elem))
|
|
|
+ (* A constant array subscript. The element's WIDTH is not the
|
|
|
+ array's, so folding the address here and leaving the size at the
|
|
|
+ array's would make `b[1] := 2' store the whole array. Element
|
|
|
+ addressing (a width on the expression) is the next increment;
|
|
|
+ until then this is LOUD, not a wrong store. *)
|
|
|
+ Err (ENoLib) ;
|
|
|
+ RETURN
|
|
|
ELSE
|
|
|
Err (ESimpType) ;
|
|
|
RETURN
|
|
|
@@ -3959,10 +3980,12 @@ VAR tok : CARDINAL ;
|
|
|
subcls : CARDINAL ;
|
|
|
strf : BOOLEAN ;
|
|
|
consumed : BOOLEAN ;
|
|
|
- running, groupFirst, i : CARDINAL ;
|
|
|
+ running, groupFirst, i, an : CARDINAL ;
|
|
|
+ alo, ahi : ARRAY [0..3] OF LONGINT ;
|
|
|
BEGIN
|
|
|
cls := TNone ; size := 0 ; elem := 0 ;
|
|
|
consumed := FALSE ;
|
|
|
+ newArrIdx := 0 ;
|
|
|
Skip () ; (* after ':' / '=' : skip blanks *)
|
|
|
IF CurCh () = '(' THEN
|
|
|
(* An enumeration: `(Constant, Formula, Txt, ...)'. Each enumerator
|
|
|
@@ -4005,21 +4028,62 @@ BEGIN
|
|
|
tok := TkNone
|
|
|
END ;
|
|
|
IF tok = TkArray THEN
|
|
|
+ (* array [range, range, ...] of T. Several ranges are allowed; the LAST
|
|
|
+ varies fastest (row-major), so `Sheet[fx,fy]' strides the first range
|
|
|
+ by the second's count (RESUME-TP3.md §2). The shape is kept in the
|
|
|
+ array table; the symbol carries a pointer to it (SymEntry.arrIdx) so
|
|
|
+ indexing can scale by the element size and subtract each lower bound. *)
|
|
|
ExpectDelim ('[', ENoSemi) ;
|
|
|
- RdConst (lo, subcls, strf) ;
|
|
|
- IF NOT MatchRange () THEN
|
|
|
- Err (ESimpType)
|
|
|
+ an := 0 ;
|
|
|
+ LOOP
|
|
|
+ RdConst (lo, subcls, strf) ;
|
|
|
+ IF NOT MatchRange () THEN
|
|
|
+ Err (ESimpType) ;
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ RdConst (hi, subcls, strf) ;
|
|
|
+ IF an < 4 THEN
|
|
|
+ alo [an] := lo ;
|
|
|
+ ahi [an] := hi ;
|
|
|
+ INC (an)
|
|
|
+ END ;
|
|
|
+ IF MatchDelim (',') THEN
|
|
|
+ (* another range *)
|
|
|
+ ELSE
|
|
|
+ EXIT
|
|
|
+ END
|
|
|
END ;
|
|
|
- RdConst (hi, subcls, strf) ;
|
|
|
ExpectDelim (']', ENoSemi) ;
|
|
|
IF NOT (MatchKey (tok) AND (tok = TkOf)) THEN
|
|
|
- Err (ENoSemi)
|
|
|
+ Err (ENoSemi) ;
|
|
|
+ RETURN
|
|
|
END ;
|
|
|
ParseType (cls, s2, e2) ;
|
|
|
cls := TArray ;
|
|
|
elem := s2 ;
|
|
|
- size := s2 * (W16 (VAL (LONGINT, W16 (hi))
|
|
|
- - VAL (LONGINT, W16 (lo)) + 1))
|
|
|
+ size := s2 ;
|
|
|
+ i := 0 ;
|
|
|
+ WHILE i < an DO
|
|
|
+ size := size * W16 (VAL (LONGINT, W16 (ahi [i]))
|
|
|
+ - VAL (LONGINT, W16 (alo [i])) + 1) ;
|
|
|
+ INC (i)
|
|
|
+ END ;
|
|
|
+ (* register the shape so indexing can scale by element size and subtract
|
|
|
+ each lower bound; the symbol points at this slot *)
|
|
|
+ IF arrTop < MaxArrs THEN
|
|
|
+ arrs [arrTop].n := an ;
|
|
|
+ arrs [arrTop].elem := s2 ;
|
|
|
+ i := 0 ;
|
|
|
+ WHILE i < an DO
|
|
|
+ arrs [arrTop].lo [i] := alo [i] ;
|
|
|
+ arrs [arrTop].hi [i] := ahi [i] ;
|
|
|
+ INC (i)
|
|
|
+ END ;
|
|
|
+ newArrIdx := arrTop + 1 ;
|
|
|
+ INC (arrTop)
|
|
|
+ ELSE
|
|
|
+ Err (ECompOvf)
|
|
|
+ END
|
|
|
ELSIF tok = TkString THEN
|
|
|
cls := TString ;
|
|
|
size := 256 ;
|
|
|
@@ -4127,7 +4191,8 @@ BEGIN
|
|
|
enumLo := symtab [idx].lo ;
|
|
|
enumHi := symtab [idx].hi ;
|
|
|
recFldFirst := symtab [idx].fldFirst ;
|
|
|
- recFldLast := symtab [idx].fldLast
|
|
|
+ recFldLast := symtab [idx].fldLast ;
|
|
|
+ newArrIdx := symtab [idx].arrIdx
|
|
|
ELSE
|
|
|
Err (EUnknown)
|
|
|
END
|
|
|
@@ -4198,7 +4263,8 @@ BEGIN
|
|
|
ParseType (cls, size, elem) ;
|
|
|
IF OK () THEN
|
|
|
IF lexnest = 0 THEN
|
|
|
- IF (size > 2) AND (cls # TString) AND (cls # TRecord) THEN
|
|
|
+ IF (size > 2) AND (cls # TString) AND (cls # TRecord)
|
|
|
+ AND (cls # TArray) THEN
|
|
|
(* Still the catch-all for a type whose storage this compiler does
|
|
|
not lay out yet (an ARRAY at its point of use, a RECORD, ...).
|
|
|
A STRING is the exception now: its layout is length byte +
|
|
|
@@ -4225,6 +4291,7 @@ BEGIN
|
|
|
symtab [i].elem := elem ; symtab [i].off := off ;
|
|
|
symtab [i].fldFirst := recFldFirst ;
|
|
|
symtab [i].fldLast := recFldLast ;
|
|
|
+ symtab [i].arrIdx := newArrIdx ;
|
|
|
INC (i)
|
|
|
END
|
|
|
ELSE
|
|
|
@@ -4234,13 +4301,15 @@ BEGIN
|
|
|
symtab [i].elem := elem ; symtab [i].off := dc ;
|
|
|
symtab [i].fldFirst := recFldFirst ;
|
|
|
symtab [i].fldLast := recFldLast ;
|
|
|
+ symtab [i].arrIdx := newArrIdx ;
|
|
|
dc := dc + size ;
|
|
|
INC (i)
|
|
|
END
|
|
|
END ;
|
|
|
varspc := varspc + size * (symTop - first)
|
|
|
ELSE
|
|
|
- IF (size > 2) AND (cls # TString) AND (cls # TRecord) THEN
|
|
|
+ IF (size > 2) AND (cls # TString) AND (cls # TRecord)
|
|
|
+ AND (cls # TArray) THEN
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
@@ -4263,6 +4332,7 @@ BEGIN
|
|
|
symtab [i].elem := elem ;
|
|
|
symtab [i].fldFirst := recFldFirst ;
|
|
|
symtab [i].fldLast := recFldLast ;
|
|
|
+ symtab [i].arrIdx := newArrIdx ;
|
|
|
symtab [i].off := (locFree - size + 1) MOD 10000H ;
|
|
|
locFree := (locFree - size) MOD 10000H ;
|
|
|
INC (i)
|
|
|
@@ -4291,11 +4361,11 @@ END DefVar ;
|
|
|
PROCEDURE DefConst () ;
|
|
|
VAR nm : ARRAY [0..MaxName] OF CHAR ;
|
|
|
v : LONGINT ;
|
|
|
- cls, typCls, typSize, typElem, soff : CARDINAL ;
|
|
|
+ cls, typCls, typSize, typElem, soff, ci : CARDINAL ;
|
|
|
isStr : BOOLEAN ;
|
|
|
tok : CARDINAL ;
|
|
|
- typed, setTyped : BOOLEAN ;
|
|
|
- sbuf : ARRAY [0..31] OF CHAR ;
|
|
|
+ typed, setTyped, arrTyped : BOOLEAN ;
|
|
|
+ nb, k, divi, w : CARDINAL ;
|
|
|
BEGIN
|
|
|
LOOP
|
|
|
PeekKw (tok) ;
|
|
|
@@ -4324,6 +4394,7 @@ BEGIN
|
|
|
refused loudly - those layouts come later. *)
|
|
|
typed := FALSE ;
|
|
|
setTyped := FALSE ;
|
|
|
+ arrTyped := FALSE ;
|
|
|
Skip () ;
|
|
|
IF CurCh () = ':' THEN
|
|
|
DropCh (GetCh ()) ;
|
|
|
@@ -4331,6 +4402,8 @@ BEGIN
|
|
|
IF OK () THEN
|
|
|
IF typCls = TSet THEN
|
|
|
setTyped := TRUE
|
|
|
+ ELSIF typCls = TArray THEN
|
|
|
+ arrTyped := TRUE
|
|
|
ELSIF typSize > 2 THEN
|
|
|
Err (ENoLib)
|
|
|
ELSE
|
|
|
@@ -4340,10 +4413,45 @@ BEGIN
|
|
|
END ;
|
|
|
IF OK () AND setTyped THEN
|
|
|
ExpectDelim ('=', ENoSemi) ;
|
|
|
- IF RdSetLiteral (typElem, typSize, sbuf) THEN
|
|
|
- soff := EmSetBlob (sbuf, typSize) ;
|
|
|
+ IF RdSetLiteral (typElem, typSize, constBlob) THEN
|
|
|
+ soff := EmSetBlob (constBlob, typSize) ;
|
|
|
DropC (NewSym (nm, KVar, TSet, typSize, typElem, soff, 0, FALSE))
|
|
|
END
|
|
|
+ ELSIF OK () AND arrTyped THEN
|
|
|
+ (* array typed constant: `(v1, v2, ...)' in element order, each value
|
|
|
+ written little-endian in typElem bytes. CALC's is XPOS (seven
|
|
|
+ Integers, 14 bytes). An element that is a STRING (CALC.INC's
|
|
|
+ StandardfunctionNames) is a later increment, and is refused here. *)
|
|
|
+ ExpectDelim ('=', ENoSemi) ;
|
|
|
+ ExpectDelim ('(', ENoSemi) ;
|
|
|
+ nb := 0 ;
|
|
|
+ LOOP
|
|
|
+ RdConst (v, cls, isStr) ;
|
|
|
+ IF isStr OR (nb + typElem > 512) THEN
|
|
|
+ Err (ENoLib) ;
|
|
|
+ EXIT
|
|
|
+ END ;
|
|
|
+ w := VAL (CARDINAL, W16 (v)) ;
|
|
|
+ divi := 1 ;
|
|
|
+ k := 0 ;
|
|
|
+ WHILE k < typElem DO
|
|
|
+ constBlob [nb] := CHR ((w DIV divi) MOD 256) ;
|
|
|
+ divi := divi * 256 ;
|
|
|
+ INC (nb) ;
|
|
|
+ INC (k)
|
|
|
+ END ;
|
|
|
+ IF MatchDelim (',') THEN
|
|
|
+ (* another element *)
|
|
|
+ ELSE
|
|
|
+ EXIT
|
|
|
+ END
|
|
|
+ END ;
|
|
|
+ ExpectDelim (')', ENoSemi) ;
|
|
|
+ IF OK () THEN
|
|
|
+ soff := EmSetBlob (constBlob, typSize) ;
|
|
|
+ ci := NewSym (nm, KVar, TArray, typSize, typElem, soff, 0, FALSE) ;
|
|
|
+ symtab [ci].arrIdx := newArrIdx
|
|
|
+ END
|
|
|
ELSIF OK () THEN
|
|
|
ExpectDelim ('=', ENoSemi) ;
|
|
|
RdConst (v, cls, isStr) ;
|
|
|
@@ -4640,6 +4748,9 @@ BEGIN
|
|
|
symtab [tidx].fldFirst := recFldFirst ;
|
|
|
symtab [tidx].fldLast := recFldLast
|
|
|
END ;
|
|
|
+ IF cls = TArray THEN
|
|
|
+ symtab [tidx].arrIdx := newArrIdx
|
|
|
+ END ;
|
|
|
DropC (tidx) ;
|
|
|
IF NOT MatchDelim (';') THEN
|
|
|
Err (ENoSemi) ;
|