|
|
@@ -58,6 +58,9 @@ VAR
|
|
|
(InvalidType when the callee is an ordinary procedure). Set by
|
|
|
Design, consumed by the following ArgList. *)
|
|
|
methCls: SymTab.TypeIndex;
|
|
|
+ (* Class of the type of the innermost `TypeName{...}` brace
|
|
|
+ constructor (ClSet or ClArray); dispatches BraceElem. *)
|
|
|
+ braceCls: INTEGER;
|
|
|
|
|
|
CHARACTERS
|
|
|
eol = CHR(13) .
|
|
|
@@ -650,12 +653,19 @@ PRODUCTIONS
|
|
|
"="
|
|
|
Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
cls := SymTab.ClassOf(t);
|
|
|
- IF cls = SymTab.ClStr THEN
|
|
|
+ IF cls = SymTab.ClArray THEN
|
|
|
+ (* an array constructor: qv is
|
|
|
+ its pooled descriptor
|
|
|
+ address; no scalar data *)
|
|
|
+ SymTab.SetSymVal(n, qv)
|
|
|
+ ELSIF cls = SymTab.ClStr THEN
|
|
|
SemError(230)
|
|
|
ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
- SemError(230) END;
|
|
|
- SymTab.SetSymVal(n, qv);
|
|
|
- QbeGen.DeclConst(n, qv, t); .) .
|
|
|
+ SemError(230)
|
|
|
+ ELSE
|
|
|
+ SymTab.SetSymVal(n, qv);
|
|
|
+ QbeGen.DeclConst(n, qv, t)
|
|
|
+ END; .) .
|
|
|
VarBlock
|
|
|
= "VAR" { VarDecl ";" } .
|
|
|
VarDecl (. VAR nm: SymTab.Name;
|
|
|
@@ -1625,6 +1635,17 @@ PRODUCTIONS
|
|
|
cls = SymTab.ClReal,
|
|
|
q)
|
|
|
END
|
|
|
+ ELSIF (cls = SymTab.ClArray)
|
|
|
+ OR (cls = SymTab.ClStr)
|
|
|
+ OR (cls = SymTab.ClUStr) THEN
|
|
|
+ (* aggregate constant:
|
|
|
+ its value IS the
|
|
|
+ descriptor address *)
|
|
|
+ IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ QbeGen.CopyOp(cv, q)
|
|
|
+ ELSE
|
|
|
+ QbeGen.CopyOp("0", q)
|
|
|
+ END
|
|
|
ELSE
|
|
|
IF t #
|
|
|
SymTab.InvalidType THEN
|
|
|
@@ -2291,7 +2312,7 @@ PRODUCTIONS
|
|
|
SymTab.ClRecord)) THEN
|
|
|
QbeGen.NoteAddr(qd, qd)
|
|
|
END; .)
|
|
|
- [ TypedSetLit<dt, q> (. t := dt; .) ]
|
|
|
+ [ TypedBraceLit<dt, q> (. t := dt; .) ]
|
|
|
[ ArgList<qn, dt, qd, TRUE, methCls, ct2, q2, called>
|
|
|
(. t := ct2;
|
|
|
QbeGen.CopyOp(q2, q); .) ]
|
|
|
@@ -2599,21 +2620,125 @@ PRODUCTIONS
|
|
|
QbeGen.SetZero(q, 8); .)
|
|
|
[ SetElem<t, q> { "," SetElem<t, q> } ]
|
|
|
"}" .
|
|
|
- (* Typed set constructor: TypeName{ elems } — e.g. BITSET{0},
|
|
|
- BITSET{}. The declared type (not SET OF [0..255]) sets the
|
|
|
- width and element span. *)
|
|
|
- TypedSetLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ declared type sets the width (set) or element type (array). *)
|
|
|
+ TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
(. VAR nw: CARDINAL; .)
|
|
|
- = "{" (. IF SymTab.ClassOf(vt) #
|
|
|
- SymTab.ClSet THEN
|
|
|
- SemError(230); nw := 8
|
|
|
- ELSE nw := SymTab.SetWords(vt);
|
|
|
- IF nw = 0 THEN nw := 8 END
|
|
|
+ = "{" (. IF vt = SymTab.InvalidType THEN
|
|
|
+ braceCls := -1
|
|
|
+ ELSE braceCls :=
|
|
|
+ SymTab.ClassOf(vt)
|
|
|
END;
|
|
|
- QbeGen.NewSetTemp(nw, q);
|
|
|
- QbeGen.SetZero(q, nw); .)
|
|
|
- [ SetElem<vt, q> { "," SetElem<vt, q> } ]
|
|
|
- "}" .
|
|
|
+ IF braceCls = SymTab.ClSet THEN
|
|
|
+ IF vt = SymTab.InvalidType THEN
|
|
|
+ nw := 8
|
|
|
+ ELSE nw := SymTab.SetWords(vt);
|
|
|
+ IF nw = 0 THEN nw := 8 END
|
|
|
+ END;
|
|
|
+ QbeGen.NewSetTemp(nw, q);
|
|
|
+ QbeGen.SetZero(q, nw)
|
|
|
+ ELSIF braceCls = SymTab.ClArray THEN
|
|
|
+ QbeGen.CtorBegin(vt)
|
|
|
+ ELSE
|
|
|
+ IF vt # SymTab.InvalidType THEN
|
|
|
+ SemError(230) END;
|
|
|
+ braceCls := -1
|
|
|
+ END; .)
|
|
|
+ [ BraceElem<vt, q> { "," BraceElem<vt, q> } ]
|
|
|
+ "}" (. IF braceCls = SymTab.ClArray THEN
|
|
|
+ QbeGen.CtorEnd(q)
|
|
|
+ ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ QbeGen.CopyOp("0", q)
|
|
|
+ END; .) .
|
|
|
+ BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal>
|
|
|
+ (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ qe, q2: QbeGen.QVal;
|
|
|
+ v, v2, reps, k: INTEGER;
|
|
|
+ elem: SymTab.TypeIndex;
|
|
|
+ lo: INTEGER;
|
|
|
+ span: CARDINAL;
|
|
|
+ cl, cl2: INTEGER;
|
|
|
+ hasR, hasB: BOOLEAN; .)
|
|
|
+ = (. hasR := FALSE; hasB := FALSE; .)
|
|
|
+ Expr<et, qe>
|
|
|
+ [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
+ [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ IF hasB THEN SemError(230) END;
|
|
|
+ lo := SymTab.SetBaseLo(vt);
|
|
|
+ span := SymTab.SetCount(vt);
|
|
|
+ IF (et = SymTab.InvalidType)
|
|
|
+ OR (hasR AND (et2 =
|
|
|
+ SymTab.InvalidType)) THEN
|
|
|
+ ELSE cl :=
|
|
|
+ SymTab.ClassOf(et);
|
|
|
+ IF hasR THEN
|
|
|
+ cl2 :=
|
|
|
+ SymTab.ClassOf(et2)
|
|
|
+ ELSE cl2 := SymTab.ClInt
|
|
|
+ END;
|
|
|
+ IF ((cl # SymTab.ClInt)
|
|
|
+ AND (cl # SymTab.ClChar)
|
|
|
+ AND (cl # SymTab.ClBool))
|
|
|
+ OR (hasR AND
|
|
|
+ ((cl2
|
|
|
+ # SymTab.ClInt)
|
|
|
+ AND (cl2
|
|
|
+ # SymTab.ClChar)
|
|
|
+ AND (cl2
|
|
|
+ # SymTab.ClBool))) THEN
|
|
|
+ SemError(222)
|
|
|
+ ELSIF hasR
|
|
|
+ AND SymTab.ConstInt(qe, v)
|
|
|
+ AND SymTab.ConstInt(q2,
|
|
|
+ v2)
|
|
|
+ AND ((v < lo)
|
|
|
+ OR (v2 < lo)
|
|
|
+ OR (v >= lo +
|
|
|
+ VAL(INTEGER, span))
|
|
|
+ OR (v2 >= lo +
|
|
|
+ VAL(INTEGER, span))
|
|
|
+ OR (v > v2)) THEN
|
|
|
+ SemError(222)
|
|
|
+ ELSIF hasR THEN
|
|
|
+ QbeGen.SetRange(sq, qe, q2,
|
|
|
+ lo, span)
|
|
|
+ ELSIF SymTab.ConstInt(qe,
|
|
|
+ v)
|
|
|
+ AND ((v < lo)
|
|
|
+ OR (v >= lo +
|
|
|
+ VAL(INTEGER,
|
|
|
+ span))) THEN
|
|
|
+ SemError(222)
|
|
|
+ ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ lo, span)
|
|
|
+ END
|
|
|
+ END
|
|
|
+ ELSIF braceCls = SymTab.ClArray THEN
|
|
|
+ IF hasR THEN SemError(230) END;
|
|
|
+ reps := 1;
|
|
|
+ IF hasB THEN
|
|
|
+ IF SymTab.ConstInt(q2, v2)
|
|
|
+ AND (v2 >= 1) THEN
|
|
|
+ reps := v2
|
|
|
+ ELSE SemError(230)
|
|
|
+ END
|
|
|
+ END;
|
|
|
+ elem := SymTab.ArrayElem(vt);
|
|
|
+ IF (SymTab.ClassOf(elem) =
|
|
|
+ SymTab.ClArray)
|
|
|
+ AND (SymTab.ClassOf(et) =
|
|
|
+ SymTab.ClStr) THEN
|
|
|
+ QbeGen.CtorElemStr(qe, elem)
|
|
|
+ ELSE
|
|
|
+ k := 0;
|
|
|
+ WHILE k < reps DO
|
|
|
+ QbeGen.CtorElem(qe, elem);
|
|
|
+ INC(k)
|
|
|
+ END
|
|
|
+ END
|
|
|
+ END; .) .
|
|
|
SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
qe, q2: QbeGen.QVal;
|
|
|
v, v2: INTEGER;
|