|
@@ -70,3655 +70,3639 @@ Listing:
|
|
|
51 init; DISPOSE shallow and nils, deviating from Wirth-undefined);
|
|
51 init; DISPOSE shallow and nils, deviating from Wirth-undefined);
|
|
|
52 nil-deref is raw (no check). *)
|
|
52 nil-deref is raw (no check). *)
|
|
|
53
|
|
53
|
|
|
- 54 IMPORT SymTab, QbeGen, AST, Lower, Check;
|
|
|
|
|
|
|
+ 54 IMPORT SymTab, QbeGen, AST, Lower;
|
|
|
55
|
|
55
|
|
|
56 VAR
|
|
56 VAR
|
|
|
- 57 (* Two-phase frontend (docs/plan-two-phase.md). When TRUE the
|
|
|
|
|
- 58 productions ALSO build AST nodes alongside the legacy emit path.
|
|
|
|
|
- 59 Slice 1: the nodes are inert scaffolding — nothing reads them, so
|
|
|
|
|
- 60 the emitted output is unchanged. *)
|
|
|
|
|
- 61 twoPhase: BOOLEAN;
|
|
|
|
|
- 62
|
|
|
|
|
- 63 (* Two-phase parse (docs/plan-two-phase-parse.md), milestone 1. When
|
|
|
|
|
- 64 TRUE each outermost procedure/method body is shadow-skipped at the
|
|
|
|
|
- 65 token level and the skip verified before the body parses normally.
|
|
|
|
|
- 66 Set by the driver (-twophase); default off. `procNest` counts the
|
|
|
|
|
- 67 Blocks being parsed so only outermost bodies probe. *)
|
|
|
|
|
- 68 twoPhaseParse: BOOLEAN;
|
|
|
|
|
- 69 procNest: CARDINAL;
|
|
|
|
|
- 70
|
|
|
|
|
- 71 (* Two-phase parse spans (milestone 2a): one entry per outermost body
|
|
|
|
|
- 72 shadow-skipped while twoPhaseParse is on — procedure name and the
|
|
|
|
|
- 73 buffer offset its body starts at (the lookahead token's nextPos).
|
|
|
|
|
- 74 Per-parse; nothing consumes the table yet. *)
|
|
|
|
|
- 75 nSpans: CARDINAL;
|
|
|
|
|
- 76 spanName: ARRAY [0 .. 1023] OF SymTab.Name;
|
|
|
|
|
- 77 spanStart: ARRAY [0 .. 1023] OF M2S.INT32;
|
|
|
|
|
- 78 spanIdx: ARRAY [0 .. 1023] OF CARDINAL;
|
|
|
|
|
- 79 spanTy: ARRAY [0 .. 1023] OF INTEGER;
|
|
|
|
|
- 80 spanNode: ARRAY [0 .. 1023] OF AST.Node;
|
|
|
|
|
- 81
|
|
|
|
|
- 82 (* Two-phase parse (milestone 2c): phase-1 skips a module-level proc
|
|
|
|
|
- 83 body (DeferSkip) and phase 2 re-parses it at unit end (RepassAll).
|
|
|
|
|
- 84 `deferredBody` reports the skip to ProcDecl's close choice;
|
|
|
|
|
- 85 `repassing` disables deferral during phase 2; `allowDefer` limits
|
|
|
|
|
- 86 deferral to plain ProcDecls (methods stay inline); `curProcNode` is
|
|
|
|
|
- 87 the NkProcDecl whose body is about to be parsed. *)
|
|
|
|
|
- 88 deferredBody: BOOLEAN;
|
|
|
|
|
- 89 repassing: BOOLEAN;
|
|
|
|
|
- 90 allowDefer: BOOLEAN;
|
|
|
|
|
- 91 curProcNode: AST.Node;
|
|
|
|
|
|
|
+ 57 (* Two-phase parse (docs/plan-two-phase-parse.md), milestone 1. When
|
|
|
|
|
+ 58 TRUE each outermost procedure/method body is shadow-skipped at the
|
|
|
|
|
+ 59 token level and the skip verified before the body parses normally.
|
|
|
|
|
+ 60 Set by the driver (-notwophase turns it off); default on.
|
|
|
|
|
+ 61 Blocks being parsed so only outermost bodies probe. *)
|
|
|
|
|
+ 62 twoPhaseParse: BOOLEAN;
|
|
|
|
|
+ 63
|
|
|
|
|
+ 64 (* Two-phase parse spans (milestone 2a): one entry per outermost body
|
|
|
|
|
+ 65 shadow-skipped while twoPhaseParse is on — procedure name and the
|
|
|
|
|
+ 66 buffer offset its body starts at (the lookahead token's nextPos).
|
|
|
|
|
+ 67 Per-parse; nothing consumes the table yet. *)
|
|
|
|
|
+ 68 nSpans: CARDINAL;
|
|
|
|
|
+ 69 spanName: ARRAY [0 .. 1023] OF SymTab.Name;
|
|
|
|
|
+ 70 spanStart: ARRAY [0 .. 1023] OF M2S.INT32;
|
|
|
|
|
+ 71 spanIdx: ARRAY [0 .. 1023] OF CARDINAL;
|
|
|
|
|
+ 72 spanTy: ARRAY [0 .. 1023] OF INTEGER;
|
|
|
|
|
+ 73 spanNode: ARRAY [0 .. 1023] OF AST.Node;
|
|
|
|
|
+ 74
|
|
|
|
|
+ 75 (* Two-phase parse (milestone 2c): phase-1 skips a module-level proc
|
|
|
|
|
+ 76 body (DeferSkip) and phase 2 re-parses it at unit end (RepassAll).
|
|
|
|
|
+ 77 `deferredBody` reports the skip to ProcDecl's close choice;
|
|
|
|
|
+ 78 `repassing` disables deferral during phase 2; `allowDefer` limits
|
|
|
|
|
+ 79 deferral to plain ProcDecls (methods stay inline); `curProcNode` is
|
|
|
|
|
+ 80 the NkProcDecl whose body is about to be parsed. *)
|
|
|
|
|
+ 81 deferredBody: BOOLEAN;
|
|
|
|
|
+ 82 repassing: BOOLEAN;
|
|
|
|
|
+ 83 allowDefer: BOOLEAN;
|
|
|
|
|
+ 84 curProcNode: AST.Node;
|
|
|
|
|
+ 85
|
|
|
|
|
+ 86 (* Result slot for the expression-AST builder (slice 2). Every
|
|
|
|
|
+ 87 Expr/SimExpr/Term/Fact leaves its node here; the combination
|
|
|
|
|
+ 88 productions save it into locals before parsing the next operand.
|
|
|
|
|
+ 89 `astIsLit` in Fact is per-invocation, so a nested Fact cannot make
|
|
|
|
|
+ 90 an outer non-literal Fact look literal. *)
|
|
|
|
|
+ 91 astCur: AST.Node;
|
|
|
92
|
|
92
|
|
|
- 93 (* Result slot for the expression-AST builder (slice 2). Every
|
|
|
|
|
- 94 Expr/SimExpr/Term/Fact leaves its node here; the combination
|
|
|
|
|
- 95 productions save it into locals before parsing the next operand.
|
|
|
|
|
- 96 `astIsLit` in Fact is per-invocation, so a nested Fact cannot make
|
|
|
|
|
- 97 an outer non-literal Fact look literal. *)
|
|
|
|
|
- 98 astCur: AST.Node;
|
|
|
|
|
- 99
|
|
|
|
|
- 100 (* Actual-argument nodes collected by ActParam for the call being
|
|
|
|
|
- 101 parsed by ArgList (slice 4). Fact resets the count before the
|
|
|
|
|
- 102 optional ArgList and then folds the nodes into an NkCall. *)
|
|
|
|
|
- 103 astNArgs: CARDINAL;
|
|
|
|
|
- 104 astArgs: ARRAY [0 .. 31] OF AST.Node;
|
|
|
|
|
- 105
|
|
|
|
|
- 106 (* Statement-AST result slot (slice 5): the most recently parsed
|
|
|
|
|
- 107 statement. StatSeq folds these into an NkBlock. *)
|
|
|
|
|
- 108 astStmt: AST.Node;
|
|
|
|
|
- 109
|
|
|
|
|
- 110 (* Declaration-AST result slot (slice 6): the most recently built
|
|
|
|
|
- 111 declaration; DeclSeq folds these into an NkDeclSeq. *)
|
|
|
|
|
- 112 astDecl: AST.Node;
|
|
|
|
|
|
|
+ 93 (* Actual-argument nodes collected by ActParam for the call being
|
|
|
|
|
+ 94 parsed by ArgList (slice 4). Fact resets the count before the
|
|
|
|
|
+ 95 optional ArgList and then folds the nodes into an NkCall. *)
|
|
|
|
|
+ 96 astNArgs: CARDINAL;
|
|
|
|
|
+ 97 astArgs: ARRAY [0 .. 31] OF AST.Node;
|
|
|
|
|
+ 98
|
|
|
|
|
+ 99 (* Statement-AST result slot (slice 5): the most recently parsed
|
|
|
|
|
+ 100 statement. StatSeq folds these into an NkBlock. *)
|
|
|
|
|
+ 101 astStmt: AST.Node;
|
|
|
|
|
+ 102
|
|
|
|
|
+ 103 (* Declaration-AST result slot (slice 6): the most recently built
|
|
|
|
|
+ 104 declaration; DeclSeq folds these into an NkDeclSeq. *)
|
|
|
|
|
+ 105 astDecl: AST.Node;
|
|
|
|
|
+ 106
|
|
|
|
|
+ 107 (* The local declarations of the most recent Block (a procedure body);
|
|
|
|
|
+ 108 ProcDecl stores them as the proc node's child 2. *)
|
|
|
|
|
+ 109 astBlkDecls: AST.Node;
|
|
|
|
|
+ 110
|
|
|
|
|
+ 111 (* Unit-AST root (slice 7): NkUnit(name, decls, body). *)
|
|
|
|
|
+ 112 astUnit: AST.Node;
|
|
|
113
|
|
113
|
|
|
- 114 (* The local declarations of the most recent Block (a procedure body);
|
|
|
|
|
- 115 ProcDecl stores them as the proc node's child 2. *)
|
|
|
|
|
- 116 astBlkDecls: AST.Node;
|
|
|
|
|
|
|
+ 114 (* Import accumulator (slice 11): `{ Import }` appends NkImport
|
|
|
|
|
+ 115 nodes here; each unit stores them as NkUnit child[3]. *)
|
|
|
|
|
+ 116 astImp, astImpTail: AST.Node;
|
|
|
117
|
|
117
|
|
|
- 118 (* Unit-AST root (slice 7): NkUnit(name, decls, body). *)
|
|
|
|
|
- 119 astUnit: AST.Node;
|
|
|
|
|
- 120
|
|
|
|
|
- 121 (* Import accumulator (slice 11): `{ Import }` appends NkImport
|
|
|
|
|
- 122 nodes here; each unit stores them as NkUnit child[3]. *)
|
|
|
|
|
- 123 astImp, astImpTail: AST.Node;
|
|
|
|
|
- 124
|
|
|
|
|
- 125 (* Class-AST accumulators (slice 13): the class node currently being
|
|
|
|
|
- 126 parsed and its parent/field/method lists. Classes are not nested
|
|
|
|
|
- 127 inside one another, so module-level state is safe. *)
|
|
|
|
|
- 128 astCls, astClsP, astClsPTail, astClsF, astClsFTail,
|
|
|
|
|
- 129 astClsM, astClsMTail, astMethod: AST.Node;
|
|
|
|
|
- 130
|
|
|
|
|
- 131 (* Class of the method named by the last `obj.Method` designator
|
|
|
|
|
- 132 (InvalidType when the callee is an ordinary procedure). Set by
|
|
|
|
|
- 133 Design, consumed by the following ArgList. *)
|
|
|
|
|
- 134 methCls: SymTab.TypeIndex;
|
|
|
|
|
- 135 (* Class of the type of the innermost `TypeName{...}` brace
|
|
|
|
|
- 136 constructor (ClSet or ClArray); dispatches BraceElem. *)
|
|
|
|
|
- 137 braceCls: INTEGER;
|
|
|
|
|
- 138 (* Module-level VAR declarations whose type was still an unresolved
|
|
|
|
|
- 139 forward alias at declaration time; emitted once the TYPE block
|
|
|
|
|
- 140 completes (module scope only). *)
|
|
|
|
|
- 141 nPendVar: CARDINAL;
|
|
|
|
|
- 142 pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
|
|
- 143 pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
|
|
|
|
|
- 144 (* Forward module-level variables referenced from a procedure body. *)
|
|
|
|
|
- 145 (* GOTO/labels: the label and goto names of the procedure being parsed,
|
|
|
|
|
- 146 reset per procedure and checked at its END. *)
|
|
|
|
|
- 147 nLab, nGot: CARDINAL;
|
|
|
|
|
- 148 labNm, gotNm: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
|
|
|
|
+ 118 (* Class-AST accumulators (slice 13): the class node currently being
|
|
|
|
|
+ 119 parsed and its parent/field/method lists. Classes are not nested
|
|
|
|
|
+ 120 inside one another, so module-level state is safe. *)
|
|
|
|
|
+ 121 astCls, astClsP, astClsPTail, astClsF, astClsFTail,
|
|
|
|
|
+ 122 astClsM, astClsMTail, astMethod: AST.Node;
|
|
|
|
|
+ 123
|
|
|
|
|
+ 124 (* Class of the method named by the last `obj.Method` designator
|
|
|
|
|
+ 125 (InvalidType when the callee is an ordinary procedure). Set by
|
|
|
|
|
+ 126 Design, consumed by the following ArgList. *)
|
|
|
|
|
+ 127 methCls: SymTab.TypeIndex;
|
|
|
|
|
+ 128 (* Class of the type of the innermost `TypeName{...}` brace
|
|
|
|
|
+ 129 constructor (ClSet or ClArray); dispatches BraceElem. *)
|
|
|
|
|
+ 130 braceCls: INTEGER;
|
|
|
|
|
+ 131 (* Module-level VAR declarations whose type was still an unresolved
|
|
|
|
|
+ 132 forward alias at declaration time; emitted once the TYPE block
|
|
|
|
|
+ 133 completes (module scope only). *)
|
|
|
|
|
+ 134 nPendVar: CARDINAL;
|
|
|
|
|
+ 135 pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
|
|
+ 136 pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
|
|
|
|
|
+ 137 (* Forward module-level variables referenced from a procedure body. *)
|
|
|
|
|
+ 138 (* GOTO/labels: the label and goto names of the procedure being parsed,
|
|
|
|
|
+ 139 reset per procedure and checked at its END. *)
|
|
|
|
|
+ 140 nLab, nGot: CARDINAL;
|
|
|
|
|
+ 141 labNm, gotNm: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
|
|
+ 142
|
|
|
|
|
+ 143 (* Generics (Increment 1): the last refining module seen — instance
|
|
|
|
|
+ 144 name, generic name, and the actual type parameters. *)
|
|
|
|
|
+ 145 refInst, refGen: SymTab.Name;
|
|
|
|
|
+ 146 refN: CARDINAL;
|
|
|
|
|
+ 147 refActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
|
|
+ 148 isGen: BOOLEAN;
|
|
|
149
|
|
149
|
|
|
- 150 (* Generics (Increment 1): the last refining module seen — instance
|
|
|
|
|
- 151 name, generic name, and the actual type parameters. *)
|
|
|
|
|
- 152 refInst, refGen: SymTab.Name;
|
|
|
|
|
- 153 refN: CARDINAL;
|
|
|
|
|
- 154 refActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
|
|
- 155 isGen: BOOLEAN;
|
|
|
|
|
- 156
|
|
|
|
|
- 157 (* Generics (Increment 2): instantiation re-parse context. When the
|
|
|
|
|
- 158 driver re-parses a generic's source to instantiate it as `instName`,
|
|
|
|
|
- 159 instActive is TRUE, the module is renamed, and each type formal is
|
|
|
|
|
- 160 bound to the corresponding instActual entry. *)
|
|
|
|
|
- 161 instActive: BOOLEAN;
|
|
|
|
|
- 162 instName: SymTab.Name;
|
|
|
|
|
- 163 instActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
|
|
- 164 instN: CARDINAL;
|
|
|
|
|
- 165 instFk: CARDINAL; (* formal cursor while binding during re-parse *)
|
|
|
|
|
- 166
|
|
|
|
|
- 167 (* Identity of the last-parsed unit and refinement, for the driver's
|
|
|
|
|
- 168 generic registry and its re-parse decision. *)
|
|
|
|
|
- 169 unitName: SymTab.Name;
|
|
|
|
|
- 170 unitWasGen: BOOLEAN;
|
|
|
|
|
- 171 unitWasDef: BOOLEAN;
|
|
|
|
|
- 172 refSeen: BOOLEAN;
|
|
|
|
|
- 173 refIsDef: BOOLEAN;
|
|
|
|
|
- 174
|
|
|
|
|
- 175
|
|
|
|
|
- 176 PROCEDURE CopyNm (src: ARRAY OF CHAR; VAR dst: SymTab.Name);
|
|
|
|
|
- 177 VAR i: CARDINAL;
|
|
|
|
|
- 178 BEGIN
|
|
|
|
|
- 179 i := 0;
|
|
|
|
|
- 180 WHILE (i <= HIGH(dst)) AND (i <= HIGH(src)) AND (src[i] # CHR(0)) DO
|
|
|
|
|
- 181 dst[i] := src[i]; INC(i)
|
|
|
|
|
- 182 END;
|
|
|
|
|
- 183 IF i <= HIGH(dst) THEN dst[i] := CHR(0) END
|
|
|
|
|
- 184 END CopyNm;
|
|
|
|
|
- 185
|
|
|
|
|
- 186 PROCEDURE InInst () : BOOLEAN;
|
|
|
|
|
- 187 BEGIN RETURN instActive END InInst;
|
|
|
|
|
- 188
|
|
|
|
|
- 189 PROCEDURE InstNameGet (VAR nm: SymTab.Name);
|
|
|
|
|
- 190 BEGIN CopyNm(instName, nm) END InstNameGet;
|
|
|
|
|
- 191
|
|
|
|
|
- 192 PROCEDURE InstActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
|
|
- 193 BEGIN
|
|
|
|
|
- 194 IF i >= instN THEN RETURN SymTab.InvalidType END;
|
|
|
|
|
- 195 RETURN instActual[i]
|
|
|
|
|
- 196 END InstActualGet;
|
|
|
|
|
- 197
|
|
|
|
|
- 198 PROCEDURE InstBegin (name: ARRAY OF CHAR);
|
|
|
|
|
- 199 BEGIN instActive := TRUE; CopyNm(name, instName); instN := 0;
|
|
|
|
|
- 200 instFk := 0 END InstBegin;
|
|
|
|
|
- 201
|
|
|
|
|
- 202 PROCEDURE InstAddActual (t: SymTab.TypeIndex);
|
|
|
|
|
- 203 BEGIN
|
|
|
|
|
- 204 IF instN <= HIGH(instActual) THEN instActual[instN] := t; INC(instN) END
|
|
|
|
|
- 205 END InstAddActual;
|
|
|
|
|
- 206
|
|
|
|
|
- 207 PROCEDURE InstEnd;
|
|
|
|
|
- 208 BEGIN instActive := FALSE; instN := 0 END InstEnd;
|
|
|
|
|
- 209
|
|
|
|
|
- 210 PROCEDURE UnitNameGet (VAR nm: SymTab.Name);
|
|
|
|
|
- 211 BEGIN CopyNm(unitName, nm) END UnitNameGet;
|
|
|
|
|
- 212
|
|
|
|
|
- 213 PROCEDURE UnitIsGeneric () : BOOLEAN;
|
|
|
|
|
- 214 BEGIN RETURN unitWasGen END UnitIsGeneric;
|
|
|
|
|
- 215
|
|
|
|
|
- 216 PROCEDURE UnitIsDefModule () : BOOLEAN;
|
|
|
|
|
- 217 BEGIN RETURN unitWasDef END UnitIsDefModule;
|
|
|
|
|
- 218
|
|
|
|
|
- 219 PROCEDURE RefineSeen () : BOOLEAN;
|
|
|
|
|
- 220 BEGIN RETURN refSeen END RefineSeen;
|
|
|
|
|
- 221
|
|
|
|
|
- 222 PROCEDURE RefineIsDef () : BOOLEAN;
|
|
|
|
|
- 223 BEGIN RETURN refIsDef END RefineIsDef;
|
|
|
|
|
- 224
|
|
|
|
|
- 225 PROCEDURE RefineInst (VAR nm: SymTab.Name);
|
|
|
|
|
- 226 BEGIN CopyNm(refInst, nm) END RefineInst;
|
|
|
|
|
- 227
|
|
|
|
|
- 228 PROCEDURE RefineGen (VAR nm: SymTab.Name);
|
|
|
|
|
- 229 BEGIN CopyNm(refGen, nm) END RefineGen;
|
|
|
|
|
- 230
|
|
|
|
|
- 231 PROCEDURE RefineActualCount () : CARDINAL;
|
|
|
|
|
- 232 BEGIN RETURN refN END RefineActualCount;
|
|
|
|
|
- 233
|
|
|
|
|
- 234 PROCEDURE RefineActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
|
|
- 235 BEGIN
|
|
|
|
|
- 236 IF i >= refN THEN RETURN SymTab.InvalidType END;
|
|
|
|
|
- 237 RETURN refActual[i]
|
|
|
|
|
- 238 END RefineActualGet;
|
|
|
|
|
- 239
|
|
|
|
|
- 240 PROCEDURE NoteLabel (nm: ARRAY OF CHAR);
|
|
|
|
|
- 241 (* Record a statement label; duplicate is 200. *)
|
|
|
|
|
- 242 VAR i: CARDINAL;
|
|
|
|
|
- 243 BEGIN
|
|
|
|
|
- 244 i := 0;
|
|
|
|
|
- 245 WHILE i < nLab DO
|
|
|
|
|
- 246 IF SymTab.Equal(labNm[i], nm) THEN SemError(200); RETURN END;
|
|
|
|
|
- 247 INC(i)
|
|
|
|
|
- 248 END;
|
|
|
|
|
- 249 IF nLab <= HIGH(labNm) THEN
|
|
|
|
|
- 250 CopyNm(nm, labNm[nLab]); INC(nLab)
|
|
|
|
|
- 251 END
|
|
|
|
|
- 252 END NoteLabel;
|
|
|
|
|
- 253
|
|
|
|
|
- 254 PROCEDURE NoteGoto (nm: ARRAY OF CHAR);
|
|
|
|
|
- 255 VAR i: CARDINAL;
|
|
|
|
|
- 256 BEGIN
|
|
|
|
|
- 257 i := 0;
|
|
|
|
|
- 258 WHILE i < nGot DO
|
|
|
|
|
- 259 IF SymTab.Equal(gotNm[i], nm) THEN RETURN END;
|
|
|
|
|
- 260 INC(i)
|
|
|
|
|
- 261 END;
|
|
|
|
|
- 262 IF nGot <= HIGH(gotNm) THEN
|
|
|
|
|
- 263 CopyNm(nm, gotNm[nGot]); INC(nGot)
|
|
|
|
|
- 264 END
|
|
|
|
|
- 265 END NoteGoto;
|
|
|
|
|
- 266
|
|
|
|
|
- 267 PROCEDURE CheckGotos;
|
|
|
|
|
- 268 (* At a procedure's END: every GOTO must name a label in that procedure. *)
|
|
|
|
|
- 269 VAR i, j: CARDINAL; found: BOOLEAN;
|
|
|
|
|
- 270 BEGIN
|
|
|
|
|
- 271 i := 0;
|
|
|
|
|
- 272 WHILE i < nGot DO
|
|
|
|
|
- 273 found := FALSE; j := 0;
|
|
|
|
|
- 274 WHILE (j < nLab) AND NOT found DO
|
|
|
|
|
- 275 IF SymTab.Equal(labNm[j], gotNm[i]) THEN found := TRUE END;
|
|
|
|
|
- 276 INC(j)
|
|
|
|
|
- 277 END;
|
|
|
|
|
- 278 IF NOT found THEN SemError(201) END;
|
|
|
|
|
- 279 INC(i)
|
|
|
|
|
- 280 END
|
|
|
|
|
- 281 END CheckGotos;
|
|
|
|
|
- 282
|
|
|
|
|
- 283 PROCEDURE FlushPend;
|
|
|
|
|
- 284 (* Emit module-level globals whose forward type is now resolved. *)
|
|
|
|
|
- 285 VAR k: CARDINAL;
|
|
|
|
|
- 286 BEGIN
|
|
|
|
|
- 287 k := 0;
|
|
|
|
|
- 288 WHILE k < nPendVar DO
|
|
|
|
|
- 289 INC(k)
|
|
|
|
|
- 290 END;
|
|
|
|
|
- 291 nPendVar := 0
|
|
|
|
|
- 292 END FlushPend;
|
|
|
|
|
- 293
|
|
|
|
|
- 294 PROCEDURE AstAppend (kind: INTEGER; VAR head, tail: AST.Node;
|
|
|
|
|
- 295 item: AST.Node);
|
|
|
|
|
- 296 (* Appends `item` to a chunked sequence: each node holds up to
|
|
|
|
|
- 297 AST.MaxChild-1 items; child[MaxChild-1] continues into the next
|
|
|
|
|
- 298 chunk. Unbounded, so blocks/decl sequences are not capped at 8. *)
|
|
|
|
|
- 299 VAR n: AST.Node;
|
|
|
|
|
- 300 BEGIN
|
|
|
|
|
- 301 IF item = AST.NoNode THEN RETURN END;
|
|
|
|
|
- 302 IF head = AST.NoNode THEN
|
|
|
|
|
- 303 head := AST.MakeNode(kind); tail := head
|
|
|
|
|
- 304 END;
|
|
|
|
|
- 305 IF AST.NChild(tail) >= AST.MaxChild - 1 THEN
|
|
|
|
|
- 306 n := AST.MakeNode(kind);
|
|
|
|
|
- 307 AST.SetChild(tail, AST.MaxChild - 1, n);
|
|
|
|
|
- 308 tail := n
|
|
|
|
|
- 309 END;
|
|
|
|
|
- 310 AST.SetChild(tail, AST.NChild(tail), item)
|
|
|
|
|
- 311 END AstAppend;
|
|
|
|
|
- 312
|
|
|
|
|
- 313 PROCEDURE AstCallNode (callee: AST.Node) : AST.Node;
|
|
|
|
|
- 314 (* Builds NkCall(callee, actuals...) from astArgs/astNArgs. The actuals
|
|
|
|
|
- 315 are a chunked sequence (AstAppend): a call can have more than
|
|
|
|
|
- 316 MaxChild-1 arguments (the generic ArgList has 9), and SetChild would
|
|
|
|
|
- 317 silently drop the tail. NkBlock marks the continuation chunks. *)
|
|
|
|
|
- 318 VAR n, tail: AST.Node; j: CARDINAL;
|
|
|
|
|
- 319 BEGIN
|
|
|
|
|
- 320 n := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 321 AST.SetChild(n, 0, callee);
|
|
|
|
|
- 322 tail := n;
|
|
|
|
|
- 323 j := 0;
|
|
|
|
|
- 324 WHILE j < astNArgs DO
|
|
|
|
|
- 325 AstAppend(AST.NkBlock, n, tail, astArgs[j]);
|
|
|
|
|
- 326 INC(j)
|
|
|
|
|
- 327 END;
|
|
|
|
|
- 328 RETURN n
|
|
|
|
|
- 329 END AstCallNode;
|
|
|
|
|
- 330
|
|
|
|
|
|
|
+ 150 (* Generics (Increment 2): instantiation re-parse context. When the
|
|
|
|
|
+ 151 driver re-parses a generic's source to instantiate it as `instName`,
|
|
|
|
|
+ 152 instActive is TRUE, the module is renamed, and each type formal is
|
|
|
|
|
+ 153 bound to the corresponding instActual entry. *)
|
|
|
|
|
+ 154 instActive: BOOLEAN;
|
|
|
|
|
+ 155 instName: SymTab.Name;
|
|
|
|
|
+ 156 instActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
|
|
+ 157 instN: CARDINAL;
|
|
|
|
|
+ 158 instFk: CARDINAL; (* formal cursor while binding during re-parse *)
|
|
|
|
|
+ 159
|
|
|
|
|
+ 160 (* Identity of the last-parsed unit and refinement, for the driver's
|
|
|
|
|
+ 161 generic registry and its re-parse decision. *)
|
|
|
|
|
+ 162 unitName: SymTab.Name;
|
|
|
|
|
+ 163 unitWasGen: BOOLEAN;
|
|
|
|
|
+ 164 unitWasDef: BOOLEAN;
|
|
|
|
|
+ 165 refSeen: BOOLEAN;
|
|
|
|
|
+ 166 refIsDef: BOOLEAN;
|
|
|
|
|
+ 167
|
|
|
|
|
+ 168
|
|
|
|
|
+ 169 PROCEDURE CopyNm (src: ARRAY OF CHAR; VAR dst: SymTab.Name);
|
|
|
|
|
+ 170 VAR i: CARDINAL;
|
|
|
|
|
+ 171 BEGIN
|
|
|
|
|
+ 172 i := 0;
|
|
|
|
|
+ 173 WHILE (i <= HIGH(dst)) AND (i <= HIGH(src)) AND (src[i] # CHR(0)) DO
|
|
|
|
|
+ 174 dst[i] := src[i]; INC(i)
|
|
|
|
|
+ 175 END;
|
|
|
|
|
+ 176 IF i <= HIGH(dst) THEN dst[i] := CHR(0) END
|
|
|
|
|
+ 177 END CopyNm;
|
|
|
|
|
+ 178
|
|
|
|
|
+ 179 PROCEDURE InInst () : BOOLEAN;
|
|
|
|
|
+ 180 BEGIN RETURN instActive END InInst;
|
|
|
|
|
+ 181
|
|
|
|
|
+ 182 PROCEDURE InstNameGet (VAR nm: SymTab.Name);
|
|
|
|
|
+ 183 BEGIN CopyNm(instName, nm) END InstNameGet;
|
|
|
|
|
+ 184
|
|
|
|
|
+ 185 PROCEDURE InstActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
|
|
+ 186 BEGIN
|
|
|
|
|
+ 187 IF i >= instN THEN RETURN SymTab.InvalidType END;
|
|
|
|
|
+ 188 RETURN instActual[i]
|
|
|
|
|
+ 189 END InstActualGet;
|
|
|
|
|
+ 190
|
|
|
|
|
+ 191 PROCEDURE InstBegin (name: ARRAY OF CHAR);
|
|
|
|
|
+ 192 BEGIN instActive := TRUE; CopyNm(name, instName); instN := 0;
|
|
|
|
|
+ 193 instFk := 0 END InstBegin;
|
|
|
|
|
+ 194
|
|
|
|
|
+ 195 PROCEDURE InstAddActual (t: SymTab.TypeIndex);
|
|
|
|
|
+ 196 BEGIN
|
|
|
|
|
+ 197 IF instN <= HIGH(instActual) THEN instActual[instN] := t; INC(instN) END
|
|
|
|
|
+ 198 END InstAddActual;
|
|
|
|
|
+ 199
|
|
|
|
|
+ 200 PROCEDURE InstEnd;
|
|
|
|
|
+ 201 BEGIN instActive := FALSE; instN := 0 END InstEnd;
|
|
|
|
|
+ 202
|
|
|
|
|
+ 203 PROCEDURE UnitNameGet (VAR nm: SymTab.Name);
|
|
|
|
|
+ 204 BEGIN CopyNm(unitName, nm) END UnitNameGet;
|
|
|
|
|
+ 205
|
|
|
|
|
+ 206 PROCEDURE UnitIsGeneric () : BOOLEAN;
|
|
|
|
|
+ 207 BEGIN RETURN unitWasGen END UnitIsGeneric;
|
|
|
|
|
+ 208
|
|
|
|
|
+ 209 PROCEDURE UnitIsDefModule () : BOOLEAN;
|
|
|
|
|
+ 210 BEGIN RETURN unitWasDef END UnitIsDefModule;
|
|
|
|
|
+ 211
|
|
|
|
|
+ 212 PROCEDURE RefineSeen () : BOOLEAN;
|
|
|
|
|
+ 213 BEGIN RETURN refSeen END RefineSeen;
|
|
|
|
|
+ 214
|
|
|
|
|
+ 215 PROCEDURE RefineIsDef () : BOOLEAN;
|
|
|
|
|
+ 216 BEGIN RETURN refIsDef END RefineIsDef;
|
|
|
|
|
+ 217
|
|
|
|
|
+ 218 PROCEDURE RefineInst (VAR nm: SymTab.Name);
|
|
|
|
|
+ 219 BEGIN CopyNm(refInst, nm) END RefineInst;
|
|
|
|
|
+ 220
|
|
|
|
|
+ 221 PROCEDURE RefineGen (VAR nm: SymTab.Name);
|
|
|
|
|
+ 222 BEGIN CopyNm(refGen, nm) END RefineGen;
|
|
|
|
|
+ 223
|
|
|
|
|
+ 224 PROCEDURE RefineActualCount () : CARDINAL;
|
|
|
|
|
+ 225 BEGIN RETURN refN END RefineActualCount;
|
|
|
|
|
+ 226
|
|
|
|
|
+ 227 PROCEDURE RefineActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
|
|
+ 228 BEGIN
|
|
|
|
|
+ 229 IF i >= refN THEN RETURN SymTab.InvalidType END;
|
|
|
|
|
+ 230 RETURN refActual[i]
|
|
|
|
|
+ 231 END RefineActualGet;
|
|
|
|
|
+ 232
|
|
|
|
|
+ 233 PROCEDURE NoteLabel (nm: ARRAY OF CHAR);
|
|
|
|
|
+ 234 (* Record a statement label; duplicate is 200. *)
|
|
|
|
|
+ 235 VAR i: CARDINAL;
|
|
|
|
|
+ 236 BEGIN
|
|
|
|
|
+ 237 i := 0;
|
|
|
|
|
+ 238 WHILE i < nLab DO
|
|
|
|
|
+ 239 IF SymTab.Equal(labNm[i], nm) THEN SemError(200); RETURN END;
|
|
|
|
|
+ 240 INC(i)
|
|
|
|
|
+ 241 END;
|
|
|
|
|
+ 242 IF nLab <= HIGH(labNm) THEN
|
|
|
|
|
+ 243 CopyNm(nm, labNm[nLab]); INC(nLab)
|
|
|
|
|
+ 244 END
|
|
|
|
|
+ 245 END NoteLabel;
|
|
|
|
|
+ 246
|
|
|
|
|
+ 247 PROCEDURE NoteGoto (nm: ARRAY OF CHAR);
|
|
|
|
|
+ 248 VAR i: CARDINAL;
|
|
|
|
|
+ 249 BEGIN
|
|
|
|
|
+ 250 i := 0;
|
|
|
|
|
+ 251 WHILE i < nGot DO
|
|
|
|
|
+ 252 IF SymTab.Equal(gotNm[i], nm) THEN RETURN END;
|
|
|
|
|
+ 253 INC(i)
|
|
|
|
|
+ 254 END;
|
|
|
|
|
+ 255 IF nGot <= HIGH(gotNm) THEN
|
|
|
|
|
+ 256 CopyNm(nm, gotNm[nGot]); INC(nGot)
|
|
|
|
|
+ 257 END
|
|
|
|
|
+ 258 END NoteGoto;
|
|
|
|
|
+ 259
|
|
|
|
|
+ 260 PROCEDURE CheckGotos;
|
|
|
|
|
+ 261 (* At a procedure's END: every GOTO must name a label in that procedure. *)
|
|
|
|
|
+ 262 VAR i, j: CARDINAL; found: BOOLEAN;
|
|
|
|
|
+ 263 BEGIN
|
|
|
|
|
+ 264 i := 0;
|
|
|
|
|
+ 265 WHILE i < nGot DO
|
|
|
|
|
+ 266 found := FALSE; j := 0;
|
|
|
|
|
+ 267 WHILE (j < nLab) AND NOT found DO
|
|
|
|
|
+ 268 IF SymTab.Equal(labNm[j], gotNm[i]) THEN found := TRUE END;
|
|
|
|
|
+ 269 INC(j)
|
|
|
|
|
+ 270 END;
|
|
|
|
|
+ 271 IF NOT found THEN SemError(201) END;
|
|
|
|
|
+ 272 INC(i)
|
|
|
|
|
+ 273 END
|
|
|
|
|
+ 274 END CheckGotos;
|
|
|
|
|
+ 275
|
|
|
|
|
+ 276 PROCEDURE FlushPend;
|
|
|
|
|
+ 277 (* Emit module-level globals whose forward type is now resolved. *)
|
|
|
|
|
+ 278 VAR k: CARDINAL;
|
|
|
|
|
+ 279 BEGIN
|
|
|
|
|
+ 280 k := 0;
|
|
|
|
|
+ 281 WHILE k < nPendVar DO
|
|
|
|
|
+ 282 INC(k)
|
|
|
|
|
+ 283 END;
|
|
|
|
|
+ 284 nPendVar := 0
|
|
|
|
|
+ 285 END FlushPend;
|
|
|
|
|
+ 286
|
|
|
|
|
+ 287 PROCEDURE AstAppend (kind: INTEGER; VAR head, tail: AST.Node;
|
|
|
|
|
+ 288 item: AST.Node);
|
|
|
|
|
+ 289 (* Appends `item` to a chunked sequence: each node holds up to
|
|
|
|
|
+ 290 AST.MaxChild-1 items; child[MaxChild-1] continues into the next
|
|
|
|
|
+ 291 chunk. Unbounded, so blocks/decl sequences are not capped at 8. *)
|
|
|
|
|
+ 292 VAR n: AST.Node;
|
|
|
|
|
+ 293 BEGIN
|
|
|
|
|
+ 294 IF item = AST.NoNode THEN RETURN END;
|
|
|
|
|
+ 295 IF head = AST.NoNode THEN
|
|
|
|
|
+ 296 head := AST.MakeNode(kind); tail := head
|
|
|
|
|
+ 297 END;
|
|
|
|
|
+ 298 IF AST.NChild(tail) >= AST.MaxChild - 1 THEN
|
|
|
|
|
+ 299 n := AST.MakeNode(kind);
|
|
|
|
|
+ 300 AST.SetChild(tail, AST.MaxChild - 1, n);
|
|
|
|
|
+ 301 tail := n
|
|
|
|
|
+ 302 END;
|
|
|
|
|
+ 303 AST.SetChild(tail, AST.NChild(tail), item)
|
|
|
|
|
+ 304 END AstAppend;
|
|
|
|
|
+ 305
|
|
|
|
|
+ 306 PROCEDURE AstCallNode (callee: AST.Node) : AST.Node;
|
|
|
|
|
+ 307 (* Builds NkCall(callee, actuals...) from astArgs/astNArgs. The actuals
|
|
|
|
|
+ 308 are a chunked sequence (AstAppend): a call can have more than
|
|
|
|
|
+ 309 MaxChild-1 arguments (the generic ArgList has 9), and SetChild would
|
|
|
|
|
+ 310 silently drop the tail. NkBlock marks the continuation chunks. *)
|
|
|
|
|
+ 311 VAR n, tail: AST.Node; j: CARDINAL;
|
|
|
|
|
+ 312 BEGIN
|
|
|
|
|
+ 313 n := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 314 AST.SetChild(n, 0, callee);
|
|
|
|
|
+ 315 tail := n;
|
|
|
|
|
+ 316 j := 0;
|
|
|
|
|
+ 317 WHILE j < astNArgs DO
|
|
|
|
|
+ 318 AstAppend(AST.NkBlock, n, tail, astArgs[j]);
|
|
|
|
|
+ 319 INC(j)
|
|
|
|
|
+ 320 END;
|
|
|
|
|
+ 321 RETURN n
|
|
|
|
|
+ 322 END AstCallNode;
|
|
|
|
|
+ 323
|
|
|
|
|
+ 324
|
|
|
|
|
+ 325
|
|
|
|
|
+ 326 PROCEDURE GetUnit (): AST.Node;
|
|
|
|
|
+ 327 (* The most recently parsed unit's AST root (for the Lower comparison). *)
|
|
|
|
|
+ 328 BEGIN
|
|
|
|
|
+ 329 RETURN astUnit
|
|
|
|
|
+ 330 END GetUnit;
|
|
|
331
|
|
331
|
|
|
- 332
|
|
|
|
|
- 333 PROCEDURE GetUnit (): AST.Node;
|
|
|
|
|
- 334 (* The most recently parsed unit's AST root (for the Lower comparison). *)
|
|
|
|
|
- 335 BEGIN
|
|
|
|
|
- 336 RETURN astUnit
|
|
|
|
|
- 337 END GetUnit;
|
|
|
|
|
- 338
|
|
|
|
|
- 339 PROCEDURE SetTwoPhase (b: BOOLEAN);
|
|
|
|
|
- 340 (* Driver switch for the two-phase parse probe (milestone 1). *)
|
|
|
|
|
- 341 BEGIN
|
|
|
|
|
- 342 twoPhaseParse := b
|
|
|
|
|
- 343 END SetTwoPhase;
|
|
|
|
|
- 344
|
|
|
|
|
- 345 PROCEDURE TokIs (kw: ARRAY OF CHAR): BOOLEAN;
|
|
|
|
|
- 346 (* The current lookahead token's source text equals kw. Compares text,
|
|
|
|
|
- 347 not token codes, so grammar renumbering cannot desync the skipper. *)
|
|
|
|
|
- 348 VAR tok: ARRAY [0 .. 63] OF CHAR;
|
|
|
|
|
- 349 BEGIN
|
|
|
|
|
- 350 M2S.GetName(M2S.nextPos, M2S.nextLen, tok);
|
|
|
|
|
- 351 RETURN SymTab.Equal(tok, kw)
|
|
|
|
|
- 352 END TokIs;
|
|
|
|
|
- 353
|
|
|
|
|
- 354 PROCEDURE Adv;
|
|
|
|
|
- 355 (* Advance one token: exactly the parser frame's Get for a grammar
|
|
|
|
|
- 356 without pragmas (its pragma branch is empty and the scanner never
|
|
|
|
|
- 357 returns a token above maxT, so the repeat loop runs once). A
|
|
|
|
|
- 358 separate name because the frame's Get is declared later in this
|
|
|
|
|
- 359 module: a bare Get here would bind the imported M2S.Get (which takes
|
|
|
|
|
- 360 a parameter) under single-pass compilers. *)
|
|
|
|
|
- 361 BEGIN
|
|
|
|
|
- 362 M2S.Get(sym);
|
|
|
|
|
- 363 INC(errDist)
|
|
|
|
|
- 364 END Adv;
|
|
|
|
|
- 365
|
|
|
|
|
- 366 PROCEDURE NoteSpan (pn: SymTab.Name; start: M2S.INT32);
|
|
|
|
|
- 367 (* Records an outermost body span for the re-parse pass (milestone 2).
|
|
|
|
|
- 368 Diagnostic only for now: nothing consumes the table yet. Declared
|
|
|
|
|
- 369 before its caller: V3 resolves single-pass (declaration before use),
|
|
|
|
|
- 370 with no forward tolerance for procedure calls. *)
|
|
|
|
|
- 371 BEGIN
|
|
|
|
|
- 372 IF nSpans > HIGH(spanName) THEN RETURN END;
|
|
|
|
|
- 373 CopyNm(pn, spanName[nSpans]);
|
|
|
|
|
- 374 spanStart[nSpans] := start;
|
|
|
|
|
- 375 spanIdx[nSpans] := SymTab.DeferBody();
|
|
|
|
|
- 376 INC(nSpans)
|
|
|
|
|
- 377 END NoteSpan;
|
|
|
|
|
- 378
|
|
|
|
|
- 379 PROCEDURE Openers (): BOOLEAN;
|
|
|
|
|
- 380 (* TRUE when the current token opens a block that must be closed by an
|
|
|
|
|
- 381 END (BEGIN is excluded: a block's BEGIN shares the declaration END;
|
|
|
|
|
- 382 REPEAT..UNTIL and EXIT/RETURN need no END). *)
|
|
|
|
|
- 383 BEGIN
|
|
|
|
|
- 384 RETURN TokIs("MODULE") OR TokIs("PROCEDURE") OR TokIs("CLASS")
|
|
|
|
|
- 385 OR TokIs("RECORD") OR TokIs("IF") OR TokIs("CASE")
|
|
|
|
|
- 386 OR TokIs("WHILE") OR TokIs("FOR") OR TokIs("LOOP")
|
|
|
|
|
- 387 OR TokIs("WITH")
|
|
|
|
|
- 388 END Openers;
|
|
|
|
|
- 389
|
|
|
|
|
- 390 PROCEDURE DeferSkip (pn: SymTab.Name): BOOLEAN;
|
|
|
|
|
- 391 (* Phase 1 of the deferral: skip the body starting at the current token
|
|
|
|
|
- 392 (the first token after the heading's ';') up to the matching END,
|
|
|
|
|
- 393 verify the END's name, and LEAVE the scanner positioned exactly at
|
|
|
|
|
- 394 that END (so Block's trailing "END" ident consumes it for real), with
|
|
|
|
|
- 395 the span recorded for the re-parse pass. On any inconsistency,
|
|
|
|
|
- 396 restore the scanner and return FALSE so the caller parses normally. *)
|
|
|
|
|
- 397 VAR depth, guard: CARDINAL;
|
|
|
|
|
- 398 nm: SymTab.Name;
|
|
|
|
|
- 399 ok: BOOLEAN;
|
|
|
|
|
- 400 start, endPos: M2S.INT32;
|
|
|
|
|
- 401 BEGIN
|
|
|
|
|
- 402 deferredBody := FALSE;
|
|
|
|
|
- 403 start := M2S.nextPos;
|
|
|
|
|
- 404 M2S.PushPos;
|
|
|
|
|
- 405 depth := 0; guard := 0; ok := TRUE;
|
|
|
|
|
- 406 LOOP
|
|
|
|
|
- 407 IF sym = 0 THEN ok := FALSE; EXIT END;
|
|
|
|
|
- 408 IF TokIs("END") THEN
|
|
|
|
|
- 409 IF depth = 0 THEN EXIT END;
|
|
|
|
|
- 410 DEC(depth)
|
|
|
|
|
- 411 ELSIF Openers() THEN
|
|
|
|
|
- 412 INC(depth)
|
|
|
|
|
- 413 END;
|
|
|
|
|
- 414 Adv;
|
|
|
|
|
- 415 INC(guard);
|
|
|
|
|
- 416 IF guard > 1000000 THEN ok := FALSE; EXIT END
|
|
|
|
|
- 417 END;
|
|
|
|
|
- 418 IF ok THEN
|
|
|
|
|
- 419 (* sym is the matching END; check the name after it, then seek back
|
|
|
|
|
- 420 so Block sees END (its "END" ident then consumes it for real). *)
|
|
|
|
|
- 421 endPos := M2S.nextPos;
|
|
|
|
|
- 422 Adv;
|
|
|
|
|
- 423 M2S.GetName(M2S.nextPos, M2S.nextLen, nm);
|
|
|
|
|
- 424 IF (sym = 0) OR NOT SymTab.Equal(nm, pn) THEN ok := FALSE END;
|
|
|
|
|
- 425 IF ok THEN
|
|
|
|
|
- 426 M2S.SeekTo(endPos); Adv
|
|
|
|
|
- 427 END
|
|
|
|
|
- 428 END;
|
|
|
|
|
- 429 IF ok THEN
|
|
|
|
|
- 430 NoteSpan(pn, start);
|
|
|
|
|
- 431 spanTy[nSpans - 1] := Lower.CurScopeProc();
|
|
|
|
|
- 432 spanNode[nSpans - 1] := curProcNode;
|
|
|
|
|
- 433 M2S.DropPos; (* keep the scanner at END; discard the snapshot *)
|
|
|
|
|
- 434 deferredBody := TRUE;
|
|
|
|
|
- 435 RETURN TRUE
|
|
|
|
|
- 436 ELSE
|
|
|
|
|
- 437 M2S.PopPos;
|
|
|
|
|
- 438 FileIO.WriteString(FileIO.StdOut, "twophase defer mismatch in ");
|
|
|
|
|
- 439 FileIO.WriteString(FileIO.StdOut, pn);
|
|
|
|
|
- 440 FileIO.WriteLn(FileIO.StdOut);
|
|
|
|
|
- 441 RETURN FALSE
|
|
|
|
|
- 442 END
|
|
|
|
|
- 443 END DeferSkip;
|
|
|
|
|
- 444
|
|
|
|
|
- 445 CHARACTERS
|
|
|
|
|
- 446 eol = CHR(13) .
|
|
|
|
|
- 447 lf = CHR(10) .
|
|
|
|
|
- 448 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
|
|
- 449 digit = "0123456789" .
|
|
|
|
|
- 450 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
|
|
- 451 noQuote1 = ANY - "'" - eol .
|
|
|
|
|
- 452 noQuote2 = ANY - '"' - eol .
|
|
|
|
|
- 453
|
|
|
|
|
- 454 IGNORE CHR(9) .. CHR(13)
|
|
|
|
|
- 455
|
|
|
|
|
- 456 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
|
|
- 457 COMMENTS FROM "//" TO lf
|
|
|
|
|
- 458
|
|
|
|
|
- 459 TOKENS
|
|
|
|
|
- 460 ident = letter { letter | digit | "_" } .
|
|
|
|
|
- 461 integer = digit { digit }
|
|
|
|
|
- 462 | digit { digit } CONTEXT("..")
|
|
|
|
|
- 463 | "0x" hexDigit { hexDigit }
|
|
|
|
|
- 464 | "0X" hexDigit { hexDigit } .
|
|
|
|
|
- 465 real = digit { digit } "." { digit }
|
|
|
|
|
- 466 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
|
|
- 467 string = "'" { noQuote1 } "'"
|
|
|
|
|
- 468 | '"' { noQuote2 } '"' .
|
|
|
|
|
- 469 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
|
|
- 470 ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
|
|
|
|
|
- 471
|
|
|
|
|
- 472 PRODUCTIONS
|
|
|
|
|
- 473 M2
|
|
|
|
|
- 474 = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
|
|
|
|
|
- 475 astImp := AST.NoNode;
|
|
|
|
|
- 476 astImpTail := AST.NoNode;
|
|
|
|
|
- 477 procNest := 0; nSpans := 0;
|
|
|
|
|
- 478 SymTab.DeferReset; .)
|
|
|
|
|
- 479 Unit "." .
|
|
|
|
|
- 480 (* Units: program modules compile fully; DEFINITION and
|
|
|
|
|
- 481 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
|
|
- 482 (each ends with one 230); same for nested local modules. *)
|
|
|
|
|
- 483 (* Generics (Increment 1): formal and actual parameters. Formals are
|
|
|
|
|
- 484 TYPE parameters only; actuals are type identifiers. *)
|
|
|
|
|
- 485 GenericFormals
|
|
|
|
|
- 486 = "(" GenericFormal { ";" GenericFormal } ")" .
|
|
|
|
|
- 487 GenericFormal (. VAR nm: SymTab.Name; .)
|
|
|
|
|
- 488 = GetIdent<nm> (. IF instActive THEN
|
|
|
|
|
|
|
+ 332 PROCEDURE SetTwoPhase (b: BOOLEAN);
|
|
|
|
|
+ 333 (* Driver switch for the two-phase parse probe (milestone 1). *)
|
|
|
|
|
+ 334 BEGIN
|
|
|
|
|
+ 335 twoPhaseParse := b
|
|
|
|
|
+ 336 END SetTwoPhase;
|
|
|
|
|
+ 337
|
|
|
|
|
+ 338 PROCEDURE TokIs (kw: ARRAY OF CHAR): BOOLEAN;
|
|
|
|
|
+ 339 (* The current lookahead token's source text equals kw. Compares text,
|
|
|
|
|
+ 340 not token codes, so grammar renumbering cannot desync the skipper. *)
|
|
|
|
|
+ 341 VAR tok: ARRAY [0 .. 63] OF CHAR;
|
|
|
|
|
+ 342 BEGIN
|
|
|
|
|
+ 343 M2S.GetName(M2S.nextPos, M2S.nextLen, tok);
|
|
|
|
|
+ 344 RETURN SymTab.Equal(tok, kw)
|
|
|
|
|
+ 345 END TokIs;
|
|
|
|
|
+ 346
|
|
|
|
|
+ 347 PROCEDURE Adv;
|
|
|
|
|
+ 348 (* Advance one token: exactly the parser frame's Get for a grammar
|
|
|
|
|
+ 349 without pragmas (its pragma branch is empty and the scanner never
|
|
|
|
|
+ 350 returns a token above maxT, so the repeat loop runs once). A
|
|
|
|
|
+ 351 separate name because the frame's Get is declared later in this
|
|
|
|
|
+ 352 module: a bare Get here would bind the imported M2S.Get (which takes
|
|
|
|
|
+ 353 a parameter) under single-pass compilers. *)
|
|
|
|
|
+ 354 BEGIN
|
|
|
|
|
+ 355 M2S.Get(sym);
|
|
|
|
|
+ 356 INC(errDist)
|
|
|
|
|
+ 357 END Adv;
|
|
|
|
|
+ 358
|
|
|
|
|
+ 359 PROCEDURE NoteSpan (pn: SymTab.Name; start: M2S.INT32);
|
|
|
|
|
+ 360 (* Records an outermost body span for the re-parse pass (milestone 2).
|
|
|
|
|
+ 361 Diagnostic only for now: nothing consumes the table yet. Declared
|
|
|
|
|
+ 362 before its caller: V3 resolves single-pass (declaration before use),
|
|
|
|
|
+ 363 with no forward tolerance for procedure calls. *)
|
|
|
|
|
+ 364 BEGIN
|
|
|
|
|
+ 365 IF nSpans > HIGH(spanName) THEN RETURN END;
|
|
|
|
|
+ 366 CopyNm(pn, spanName[nSpans]);
|
|
|
|
|
+ 367 spanStart[nSpans] := start;
|
|
|
|
|
+ 368 spanIdx[nSpans] := SymTab.DeferBody();
|
|
|
|
|
+ 369 INC(nSpans)
|
|
|
|
|
+ 370 END NoteSpan;
|
|
|
|
|
+ 371
|
|
|
|
|
+ 372 PROCEDURE Openers (): BOOLEAN;
|
|
|
|
|
+ 373 (* TRUE when the current token opens a block that must be closed by an
|
|
|
|
|
+ 374 END (BEGIN is excluded: a block's BEGIN shares the declaration END;
|
|
|
|
|
+ 375 REPEAT..UNTIL and EXIT/RETURN need no END). *)
|
|
|
|
|
+ 376 BEGIN
|
|
|
|
|
+ 377 RETURN TokIs("MODULE") OR TokIs("PROCEDURE") OR TokIs("CLASS")
|
|
|
|
|
+ 378 OR TokIs("RECORD") OR TokIs("IF") OR TokIs("CASE")
|
|
|
|
|
+ 379 OR TokIs("WHILE") OR TokIs("FOR") OR TokIs("LOOP")
|
|
|
|
|
+ 380 OR TokIs("WITH")
|
|
|
|
|
+ 381 END Openers;
|
|
|
|
|
+ 382
|
|
|
|
|
+ 383 PROCEDURE DeferSkip (pn: SymTab.Name): BOOLEAN;
|
|
|
|
|
+ 384 (* Phase 1 of the deferral: skip the body starting at the current token
|
|
|
|
|
+ 385 (the first token after the heading's ';') up to the matching END,
|
|
|
|
|
+ 386 verify the END's name, and LEAVE the scanner positioned exactly at
|
|
|
|
|
+ 387 that END (so Block's trailing "END" ident consumes it for real), with
|
|
|
|
|
+ 388 the span recorded for the re-parse pass. On any inconsistency,
|
|
|
|
|
+ 389 restore the scanner and return FALSE so the caller parses normally. *)
|
|
|
|
|
+ 390 VAR depth, guard: CARDINAL;
|
|
|
|
|
+ 391 nm: SymTab.Name;
|
|
|
|
|
+ 392 ok: BOOLEAN;
|
|
|
|
|
+ 393 start, endPos: M2S.INT32;
|
|
|
|
|
+ 394 BEGIN
|
|
|
|
|
+ 395 deferredBody := FALSE;
|
|
|
|
|
+ 396 start := M2S.nextPos;
|
|
|
|
|
+ 397 M2S.PushPos;
|
|
|
|
|
+ 398 depth := 0; guard := 0; ok := TRUE;
|
|
|
|
|
+ 399 LOOP
|
|
|
|
|
+ 400 IF sym = 0 THEN ok := FALSE; EXIT END;
|
|
|
|
|
+ 401 IF TokIs("END") THEN
|
|
|
|
|
+ 402 IF depth = 0 THEN EXIT END;
|
|
|
|
|
+ 403 DEC(depth)
|
|
|
|
|
+ 404 ELSIF Openers() THEN
|
|
|
|
|
+ 405 INC(depth)
|
|
|
|
|
+ 406 END;
|
|
|
|
|
+ 407 Adv;
|
|
|
|
|
+ 408 INC(guard);
|
|
|
|
|
+ 409 IF guard > 1000000 THEN ok := FALSE; EXIT END
|
|
|
|
|
+ 410 END;
|
|
|
|
|
+ 411 IF ok THEN
|
|
|
|
|
+ 412 (* sym is the matching END; check the name after it, then seek back
|
|
|
|
|
+ 413 so Block sees END (its "END" ident then consumes it for real). *)
|
|
|
|
|
+ 414 endPos := M2S.nextPos;
|
|
|
|
|
+ 415 Adv;
|
|
|
|
|
+ 416 M2S.GetName(M2S.nextPos, M2S.nextLen, nm);
|
|
|
|
|
+ 417 IF (sym = 0) OR NOT SymTab.Equal(nm, pn) THEN ok := FALSE END;
|
|
|
|
|
+ 418 IF ok THEN
|
|
|
|
|
+ 419 M2S.SeekTo(endPos); Adv
|
|
|
|
|
+ 420 END
|
|
|
|
|
+ 421 END;
|
|
|
|
|
+ 422 IF ok THEN
|
|
|
|
|
+ 423 NoteSpan(pn, start);
|
|
|
|
|
+ 424 spanTy[nSpans - 1] := Lower.CurScopeProc();
|
|
|
|
|
+ 425 spanNode[nSpans - 1] := curProcNode;
|
|
|
|
|
+ 426 M2S.DropPos; (* keep the scanner at END; discard the snapshot *)
|
|
|
|
|
+ 427 deferredBody := TRUE;
|
|
|
|
|
+ 428 RETURN TRUE
|
|
|
|
|
+ 429 ELSE
|
|
|
|
|
+ 430 M2S.PopPos;
|
|
|
|
|
+ 431 FileIO.WriteString(FileIO.StdOut, "twophase defer mismatch in ");
|
|
|
|
|
+ 432 FileIO.WriteString(FileIO.StdOut, pn);
|
|
|
|
|
+ 433 FileIO.WriteLn(FileIO.StdOut);
|
|
|
|
|
+ 434 RETURN FALSE
|
|
|
|
|
+ 435 END
|
|
|
|
|
+ 436 END DeferSkip;
|
|
|
|
|
+ 437
|
|
|
|
|
+ 438 CHARACTERS
|
|
|
|
|
+ 439 eol = CHR(13) .
|
|
|
|
|
+ 440 lf = CHR(10) .
|
|
|
|
|
+ 441 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
|
|
+ 442 digit = "0123456789" .
|
|
|
|
|
+ 443 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
|
|
+ 444 noQuote1 = ANY - "'" - eol .
|
|
|
|
|
+ 445 noQuote2 = ANY - '"' - eol .
|
|
|
|
|
+ 446
|
|
|
|
|
+ 447 IGNORE CHR(9) .. CHR(13)
|
|
|
|
|
+ 448
|
|
|
|
|
+ 449 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
|
|
+ 450 COMMENTS FROM "//" TO lf
|
|
|
|
|
+ 451
|
|
|
|
|
+ 452 TOKENS
|
|
|
|
|
+ 453 ident = letter { letter | digit | "_" } .
|
|
|
|
|
+ 454 integer = digit { digit }
|
|
|
|
|
+ 455 | digit { digit } CONTEXT("..")
|
|
|
|
|
+ 456 | "0x" hexDigit { hexDigit }
|
|
|
|
|
+ 457 | "0X" hexDigit { hexDigit } .
|
|
|
|
|
+ 458 real = digit { digit } "." { digit }
|
|
|
|
|
+ 459 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
|
|
+ 460 string = "'" { noQuote1 } "'"
|
|
|
|
|
+ 461 | '"' { noQuote2 } '"' .
|
|
|
|
|
+ 462 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
|
|
+ 463 ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
|
|
|
|
|
+ 464
|
|
|
|
|
+ 465 PRODUCTIONS
|
|
|
|
|
+ 466 M2
|
|
|
|
|
+ 467 = (. astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
|
|
|
|
|
+ 468 astImp := AST.NoNode;
|
|
|
|
|
+ 469 astImpTail := AST.NoNode;
|
|
|
|
|
+ 470 nSpans := 0;
|
|
|
|
|
+ 471 SymTab.DeferReset; .)
|
|
|
|
|
+ 472 Unit "." .
|
|
|
|
|
+ 473 (* Units: program modules compile fully; DEFINITION and
|
|
|
|
|
+ 474 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
|
|
+ 475 (each ends with one 230); same for nested local modules. *)
|
|
|
|
|
+ 476 (* Generics (Increment 1): formal and actual parameters. Formals are
|
|
|
|
|
+ 477 TYPE parameters only; actuals are type identifiers. *)
|
|
|
|
|
+ 478 GenericFormals
|
|
|
|
|
+ 479 = "(" GenericFormal { ";" GenericFormal } ")" .
|
|
|
|
|
+ 480 GenericFormal (. VAR nm: SymTab.Name; .)
|
|
|
|
|
+ 481 = GetIdent<nm> (. IF instActive THEN
|
|
|
|
|
+ 482 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
|
|
+ 483 InstActualGet(instFk)) THEN
|
|
|
|
|
+ 484 SemError(200) END
|
|
|
|
|
+ 485 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
|
|
+ 486 SemError(200) END;
|
|
|
|
|
+ 487 INC(instFk); .)
|
|
|
|
|
+ 488 { "," GetIdent<nm> (. IF instActive THEN
|
|
|
489 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
489 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
490 InstActualGet(instFk)) THEN
|
|
490 InstActualGet(instFk)) THEN
|
|
|
491 SemError(200) END
|
|
491 SemError(200) END
|
|
|
492 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
492 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
493 SemError(200) END;
|
|
493 SemError(200) END;
|
|
|
- 494 INC(instFk); .)
|
|
|
|
|
- 495 { "," GetIdent<nm> (. IF instActive THEN
|
|
|
|
|
- 496 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
|
|
- 497 InstActualGet(instFk)) THEN
|
|
|
|
|
- 498 SemError(200) END
|
|
|
|
|
- 499 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
|
|
- 500 SemError(200) END;
|
|
|
|
|
- 501 INC(instFk); .) }
|
|
|
|
|
- 502 ":" "TYPE" .
|
|
|
|
|
- 503 Actuals
|
|
|
|
|
- 504 = Actual { "," Actual } .
|
|
|
|
|
- 505 Actual (. VAR at: SymTab.TypeIndex; .)
|
|
|
|
|
- 506 = TypeIdent<at> (. IF refN <= HIGH(refActual) THEN
|
|
|
|
|
- 507 refActual[refN] := at; INC(refN)
|
|
|
|
|
- 508 END; .) .
|
|
|
|
|
- 509 Unit
|
|
|
|
|
- 510 = (. isGen := FALSE;
|
|
|
|
|
- 511 allowDefer := FALSE;
|
|
|
|
|
- 512 repassing := FALSE; .)
|
|
|
|
|
- 513 [ "GENERIC" (. isGen := TRUE; .) ]
|
|
|
|
|
- 514 ( DefUnit | ImplUnit | ProgModule ) .
|
|
|
|
|
- 515 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
|
|
- 516 and one program (last) into one image. Units share the symbol
|
|
|
|
|
- 517 table; imports materialize exported names. *)
|
|
|
|
|
- 518 DefUnit (. VAR m1, m2, pn: SymTab.Name;
|
|
|
|
|
- 519 g: SymTab.Name;
|
|
|
|
|
- 520 astSeq, astTail, astProc: AST.Node; .)
|
|
|
|
|
- 521 = (. refN := 0; refSeen := FALSE; .)
|
|
|
|
|
- 522 "DEFINITION" "MODULE"
|
|
|
|
|
- 523 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
|
|
- 524 IF instActive THEN
|
|
|
|
|
- 525 IF NOT SymTab.Reenter(m1,
|
|
|
|
|
- 526 SymTab.UnitDef) THEN
|
|
|
|
|
- 527 SemError(200) END
|
|
|
|
|
- 528 ELSIF NOT SymTab.BeginDef(m1) THEN
|
|
|
|
|
- 529 SemError(200) END;
|
|
|
|
|
- 530 QbeGen.SetModule(m1);
|
|
|
|
|
- 531 CopyNm(m1, unitName);
|
|
|
|
|
- 532 unitWasGen := isGen
|
|
|
|
|
- 533 AND NOT instActive;
|
|
|
|
|
- 534 unitWasDef := TRUE; .)
|
|
|
|
|
- 535 [ GenericFormals ]
|
|
|
|
|
- 536 ( ";"
|
|
|
|
|
- 537 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 538 astImp, astImpTail, astDecl); .) }
|
|
|
|
|
- 539 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
|
|
- 540 list: parsed, and the
|
|
|
|
|
- 541 names are already exported
|
|
|
|
|
- 542 by the module scope *) .)
|
|
|
|
|
- 543 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
|
|
- 544 (. astSeq := AST.NoNode;
|
|
|
|
|
- 545 astTail := AST.NoNode; .)
|
|
|
|
|
- 546 { ConstBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 547 astSeq, astTail, astDecl); .)
|
|
|
|
|
- 548 | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 549 astSeq, astTail, astDecl); .)
|
|
|
|
|
- 550 | VarBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 551 astSeq, astTail, astDecl); .)
|
|
|
|
|
- 552 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
- 553 (. (* a heading only: record it so
|
|
|
|
|
- 554 Lower can replay it *)
|
|
|
|
|
- 555 astProc := AST.MakeNode(AST.NkProcDecl);
|
|
|
|
|
- 556 AST.SetOp(astProc, 0);
|
|
|
|
|
- 557 AST.SetChild(astProc, 0,
|
|
|
|
|
- 558 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
|
|
- 559 AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 560 astSeq, astTail, astProc);
|
|
|
|
|
- 561 Lower.NoteProcNode(astProc);
|
|
|
|
|
- 562 Lower.ScopeLeave;
|
|
|
|
|
- 563 SymTab.CloseProc;
|
|
|
|
|
- 564 QbeGen.AbortFunc; .) }
|
|
|
|
|
- 565 (. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
- 566 AST.SetChild(astUnit, 0,
|
|
|
|
|
- 567 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
- 568 AST.SetChild(astUnit, 1, astSeq);
|
|
|
|
|
- 569 AST.SetChild(astUnit, 3, astImp);
|
|
|
|
|
- 570 astDecl := AST.NoNode;
|
|
|
|
|
- 571 astStmt := AST.NoNode; .)
|
|
|
|
|
- 572 "END"
|
|
|
|
|
- 573 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
|
|
- 574 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 575 SemError(202) END;
|
|
|
|
|
- 576 SymTab.EndUnit; .)
|
|
|
|
|
- 577 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
|
|
- 578 (. CopyNm(m1, refInst);
|
|
|
|
|
- 579 CopyNm(g, refGen);
|
|
|
|
|
- 580 refSeen := TRUE; refIsDef := TRUE;
|
|
|
|
|
- 581 astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
- 582 AST.SetChild(astUnit, 0,
|
|
|
|
|
- 583 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
- 584 astDecl := AST.NoNode;
|
|
|
|
|
- 585 astStmt := AST.NoNode; .)
|
|
|
|
|
- 586 "END"
|
|
|
|
|
- 587 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 588 SemError(202) END;
|
|
|
|
|
- 589 SymTab.EndUnit; .) ) .
|
|
|
|
|
- 590 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
- 591 g: SymTab.Name;
|
|
|
|
|
- 592 k: CARDINAL;
|
|
|
|
|
- 593 rp: CARDINAL;
|
|
|
|
|
- 594 rpOk: BOOLEAN;
|
|
|
|
|
- 595 rErrs: INTEGER;
|
|
|
|
|
- 596 rDecl, rStmt: AST.Node;
|
|
|
|
|
- 597 rnm: SymTab.Name;
|
|
|
|
|
- 598 rSym, rErr: CARDINAL;
|
|
|
|
|
- 599 fname: SymTab.Name;
|
|
|
|
|
- 600 unres: BOOLEAN;
|
|
|
|
|
- 601 astNode: AST.Node; .)
|
|
|
|
|
- 602 = (. refN := 0; refSeen := FALSE; .)
|
|
|
|
|
- 603 "IMPLEMENTATION" "MODULE"
|
|
|
|
|
- 604 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
|
|
- 605 IF instActive THEN
|
|
|
|
|
- 606 IF NOT SymTab.Reenter(m1,
|
|
|
|
|
- 607 SymTab.UnitImpl) THEN
|
|
|
|
|
- 608 SemError(201) END
|
|
|
|
|
- 609 ELSIF NOT SymTab.BeginImpl(m1) THEN
|
|
|
|
|
- 610 SemError(201) END;
|
|
|
|
|
- 611 astStmt := AST.NoNode;
|
|
|
|
|
- 612 astDecl := AST.NoNode;
|
|
|
|
|
- 613 astImp := AST.NoNode;
|
|
|
|
|
- 614 astImpTail := AST.NoNode;
|
|
|
|
|
- 615 nPendVar := 0;
|
|
|
|
|
- 616 CopyNm(m1, unitName);
|
|
|
|
|
- 617 unitWasGen := isGen AND NOT instActive;
|
|
|
|
|
- 618 unitWasDef := FALSE;
|
|
|
|
|
- 619 QbeGen.SetModule(m1); .)
|
|
|
|
|
- 620 [ GenericFormals ]
|
|
|
|
|
- 621 ( ";"
|
|
|
|
|
- 622 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 623 astImp, astImpTail, astDecl); .) }
|
|
|
|
|
- 624 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 625 [ "BEGIN" (. FlushPend;
|
|
|
|
|
- 626 k := 0;
|
|
|
|
|
- 627 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 628 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 629 IF unres THEN SemError(201) END;
|
|
|
|
|
- 630 INC(k)
|
|
|
|
|
- 631 END;
|
|
|
|
|
- 632 SymTab.FwdClear;
|
|
|
|
|
- 633
|
|
|
|
|
- 634 nLab := 0; nGot := 0; .)
|
|
|
|
|
- 635 [ StatSeq ] ]
|
|
|
|
|
- 636 (. IF twoPhaseParse THEN
|
|
|
|
|
- 637 rSym := sym; rErr := errDist;
|
|
|
|
|
- 638 rDecl := astDecl; rStmt := astStmt;
|
|
|
|
|
- 639 M2S.PushPos;
|
|
|
|
|
- 640 repassing := TRUE;
|
|
|
|
|
- 641 rp := 0;
|
|
|
|
|
- 642 WHILE rp < nSpans DO
|
|
|
|
|
- 643 k := 0;
|
|
|
|
|
- 644 WHILE (k <= HIGH(rnm))
|
|
|
|
|
- 645 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
|
|
- 646 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
|
|
- 647 END;
|
|
|
|
|
- 648 rnm[k] := CHR(0);
|
|
|
|
|
- 649 M2S.SeekTo(spanStart[rp]);
|
|
|
|
|
- 650 Adv;
|
|
|
|
|
- 651 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
|
|
- 652 IF NOT rpOk THEN
|
|
|
|
|
- 653 FileIO.WriteString(FileIO.StdOut,
|
|
|
|
|
- 654 "twophase reenter failed");
|
|
|
|
|
- 655 FileIO.WriteLn(FileIO.StdOut)
|
|
|
|
|
- 656 END;
|
|
|
|
|
- 657 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
|
|
- 658 QbeGen.BeginFunc("");
|
|
|
|
|
- 659 Block(rnm);
|
|
|
|
|
- 660 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
|
|
- 661 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
|
|
- 662 Lower.ScopeLeave;
|
|
|
|
|
- 663 SymTab.CloseProc;
|
|
|
|
|
- 664 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
|
|
- 665 INC(rp)
|
|
|
|
|
- 666 END;
|
|
|
|
|
- 667 rErrs := M2S.errors;
|
|
|
|
|
- 668 repassing := FALSE;
|
|
|
|
|
- 669 M2S.PopPos;
|
|
|
|
|
- 670 sym := rSym; errDist := rErr;
|
|
|
|
|
- 671 M2S.errors := rErrs;
|
|
|
|
|
- 672
|
|
|
|
|
- 673 astDecl := rDecl; astStmt := rStmt
|
|
|
|
|
- 674 END; .)
|
|
|
|
|
- 675 "END"
|
|
|
|
|
- 676 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
|
|
- 677 FlushPend;
|
|
|
|
|
- 678 k := 0;
|
|
|
|
|
- 679 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 680 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 681 IF unres THEN SemError(201) END;
|
|
|
|
|
- 682 INC(k)
|
|
|
|
|
- 683 END;
|
|
|
|
|
- 684 SymTab.FwdClear;
|
|
|
|
|
- 685
|
|
|
|
|
- 686 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
- 687 AST.SetChild(astNode, 0,
|
|
|
|
|
- 688 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
- 689 AST.SetChild(astNode, 1, astDecl);
|
|
|
|
|
- 690 AST.SetChild(astNode, 2, astStmt);
|
|
|
|
|
- 691 AST.SetChild(astNode, 3, astImp);
|
|
|
|
|
- 692 astUnit := astNode;
|
|
|
|
|
- 693 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 694 SemError(202) END;
|
|
|
|
|
- 695 CheckGotos;
|
|
|
|
|
- 696 SymTab.EndUnit; .)
|
|
|
|
|
- 697 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
|
|
- 698 (. CopyNm(m1, refInst);
|
|
|
|
|
- 699 CopyNm(g, refGen);
|
|
|
|
|
- 700 refSeen := TRUE; refIsDef := FALSE;
|
|
|
|
|
- 701 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
- 702 AST.SetChild(astNode, 0,
|
|
|
|
|
- 703 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
- 704 astDecl := AST.NoNode;
|
|
|
|
|
- 705 astStmt := AST.NoNode; .)
|
|
|
|
|
- 706 "END"
|
|
|
|
|
- 707 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 708 SemError(202) END;
|
|
|
|
|
- 709 SymTab.EndUnit; .) ) .
|
|
|
|
|
- 710 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
- 711 k: CARDINAL;
|
|
|
|
|
- 712 rp: CARDINAL;
|
|
|
|
|
- 713 rpOk: BOOLEAN;
|
|
|
|
|
- 714 rErrs: INTEGER;
|
|
|
|
|
- 715 rDecl, rStmt: AST.Node;
|
|
|
|
|
- 716 rnm: SymTab.Name;
|
|
|
|
|
- 717 rSym, rErr: CARDINAL;
|
|
|
|
|
- 718 fname: SymTab.Name;
|
|
|
|
|
- 719 unres: BOOLEAN;
|
|
|
|
|
- 720 astNode: AST.Node; .)
|
|
|
|
|
- 721 = "MODULE"
|
|
|
|
|
- 722 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
|
|
- 723 SemError(200) END;
|
|
|
|
|
- 724 astStmt := AST.NoNode;
|
|
|
|
|
- 725 astDecl := AST.NoNode;
|
|
|
|
|
- 726 astImp := AST.NoNode;
|
|
|
|
|
- 727 astImpTail := AST.NoNode;
|
|
|
|
|
- 728 nPendVar := 0;
|
|
|
|
|
- 729 QbeGen.SetModule(m1); .)
|
|
|
|
|
- 730 [ Priority ]
|
|
|
|
|
- 731 ";"
|
|
|
|
|
- 732 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 733 astImp, astImpTail, astDecl); .) }
|
|
|
|
|
- 734 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 735 [ "BEGIN" (. FlushPend;
|
|
|
|
|
- 736 k := 0;
|
|
|
|
|
- 737 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 738 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 739 IF unres THEN SemError(201) END;
|
|
|
|
|
- 740 INC(k)
|
|
|
|
|
- 741 END;
|
|
|
|
|
- 742 SymTab.FwdClear;
|
|
|
|
|
- 743
|
|
|
|
|
- 744 nLab := 0; nGot := 0; .)
|
|
|
|
|
- 745 [ StatSeq ] ]
|
|
|
|
|
- 746 (. IF twoPhaseParse THEN
|
|
|
|
|
- 747 rSym := sym; rErr := errDist;
|
|
|
|
|
- 748 rDecl := astDecl; rStmt := astStmt;
|
|
|
|
|
- 749 M2S.PushPos;
|
|
|
|
|
- 750 repassing := TRUE;
|
|
|
|
|
- 751 rp := 0;
|
|
|
|
|
- 752 WHILE rp < nSpans DO
|
|
|
|
|
- 753 k := 0;
|
|
|
|
|
- 754 WHILE (k <= HIGH(rnm))
|
|
|
|
|
- 755 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
|
|
- 756 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
|
|
- 757 END;
|
|
|
|
|
- 758 rnm[k] := CHR(0);
|
|
|
|
|
- 759 M2S.SeekTo(spanStart[rp]);
|
|
|
|
|
- 760 Adv;
|
|
|
|
|
- 761 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
|
|
- 762 IF NOT rpOk THEN
|
|
|
|
|
- 763 FileIO.WriteString(FileIO.StdOut,
|
|
|
|
|
- 764 "twophase reenter failed");
|
|
|
|
|
- 765 FileIO.WriteLn(FileIO.StdOut)
|
|
|
|
|
- 766 END;
|
|
|
|
|
- 767 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
|
|
- 768 QbeGen.BeginFunc("");
|
|
|
|
|
- 769 Block(rnm);
|
|
|
|
|
- 770 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
|
|
- 771 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
|
|
- 772 Lower.ScopeLeave;
|
|
|
|
|
- 773 SymTab.CloseProc;
|
|
|
|
|
- 774 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
|
|
- 775 INC(rp)
|
|
|
|
|
- 776 END;
|
|
|
|
|
- 777 rErrs := M2S.errors;
|
|
|
|
|
- 778 repassing := FALSE;
|
|
|
|
|
- 779 M2S.PopPos;
|
|
|
|
|
- 780 sym := rSym; errDist := rErr;
|
|
|
|
|
- 781 M2S.errors := rErrs;
|
|
|
|
|
- 782
|
|
|
|
|
- 783 astDecl := rDecl; astStmt := rStmt
|
|
|
|
|
- 784 END; .)
|
|
|
|
|
- 785 "END"
|
|
|
|
|
- 786 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
|
|
- 787 FlushPend;
|
|
|
|
|
- 788 k := 0;
|
|
|
|
|
- 789 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
- 790 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
- 791 IF unres THEN SemError(201) END;
|
|
|
|
|
- 792 INC(k)
|
|
|
|
|
- 793 END;
|
|
|
|
|
- 794 SymTab.FwdClear;
|
|
|
|
|
- 795
|
|
|
|
|
- 796 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 797 SemError(202) END;
|
|
|
|
|
- 798 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
- 799 AST.SetChild(astNode, 0,
|
|
|
|
|
- 800 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
- 801 AST.SetChild(astNode, 1, astDecl);
|
|
|
|
|
- 802 AST.SetChild(astNode, 2, astStmt);
|
|
|
|
|
- 803 AST.SetChild(astNode, 3, astImp);
|
|
|
|
|
- 804 astUnit := astNode;
|
|
|
|
|
- 805 CheckGotos;
|
|
|
|
|
- 806 SymTab.EndUnit; .) .
|
|
|
|
|
- 807 DeclSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
- 808 = (. astSeq := AST.NoNode;
|
|
|
|
|
- 809 astTail := AST.NoNode; .)
|
|
|
|
|
- 810 { (. astDecl := AST.NoNode; .)
|
|
|
|
|
- 811 ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
|
|
- 812 | NestedModule ";" | ClassItem ";" )
|
|
|
|
|
- 813 (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 814 astSeq, astTail, astDecl); .) }
|
|
|
|
|
- 815 (. astDecl := astSeq; .) .
|
|
|
|
|
- 816 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
|
|
- 817 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
|
|
- 818 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
|
|
- 819 scope at END. *)
|
|
|
|
|
- 820 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
- 821 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
|
|
- 822 expCount, k: CARDINAL;
|
|
|
|
|
- 823 astNode, nImp, nImpTail:
|
|
|
|
|
- 824 AST.Node; .)
|
|
|
|
|
- 825 = "MODULE"
|
|
|
|
|
- 826 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
|
|
- 827 SymTab.KindModule) THEN
|
|
|
|
|
- 828 SemError(200) END;
|
|
|
|
|
- 829 SymTab.PushScope;
|
|
|
|
|
- 830 expCount := 0;
|
|
|
|
|
- 831 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
- 832 AST.SetChild(astNode, 0,
|
|
|
|
|
- 833 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
- 834 astStmt := AST.NoNode;
|
|
|
|
|
- 835 astDecl := AST.NoNode;
|
|
|
|
|
- 836 nImp := AST.NoNode;
|
|
|
|
|
- 837 nImpTail := AST.NoNode; .)
|
|
|
|
|
- 838 [ Priority ]
|
|
|
|
|
- 839 ";"
|
|
|
|
|
- 840 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 841 nImp, nImpTail, astDecl); .) }
|
|
|
|
|
- 842 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
|
|
- 843 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
|
|
- 844 { "," GetIdent<expNames[expCount]>
|
|
|
|
|
- 845 (. INC(expCount); .) }
|
|
|
|
|
- 846 ";" ]
|
|
|
|
|
- 847 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 848 [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
|
|
- 849 .)
|
|
|
|
|
- 850 [ StatSeq ] ]
|
|
|
|
|
- 851 "END"
|
|
|
|
|
- 852 GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
|
|
|
|
|
- 853 AST.SetChild(astNode, 2, astStmt);
|
|
|
|
|
- 854 AST.SetChild(astNode, 3, nImp);
|
|
|
|
|
- 855 astDecl := astNode;
|
|
|
|
|
- 856 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
- 857 SemError(202) END;
|
|
|
|
|
- 858 k := 0;
|
|
|
|
|
- 859 WHILE k < expCount DO
|
|
|
|
|
- 860 SymTab.ExportUp(expNames[k]);
|
|
|
|
|
- 861 INC(k)
|
|
|
|
|
- 862 END;
|
|
|
|
|
- 863 SymTab.PopScope; .) .
|
|
|
|
|
- 864 Priority
|
|
|
|
|
- 865 = "[" integer "]" (. SemError(230); .) .
|
|
|
|
|
- 866 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
|
|
- 867 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
|
|
- 868 materializes on first use (Design). *)
|
|
|
|
|
- 869 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
|
|
- 870 import lines don't fail); a known module's missing export is
|
|
|
|
|
- 871 201. *)
|
|
|
|
|
- 872 Import (. VAR n: SymTab.Name;
|
|
|
|
|
- 873 astImport: AST.Node; .)
|
|
|
|
|
- 874 = "FROM"
|
|
|
|
|
- 875 GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
|
|
- 876 AST.SetChild(astImport, 0,
|
|
|
|
|
- 877 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
- 878 "IMPORT"
|
|
|
|
|
- 879 ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
|
|
- 880 | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
|
|
- 881 ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
|
|
- 882 ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
|
|
- 883 (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 884 = ImpName<mod, node>
|
|
|
|
|
- 885 { "," ImpName<mod, node> } .
|
|
|
|
|
- 886 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
|
|
- 887 accepted and ignored: the built-in applies regardless. *)
|
|
|
|
|
- 888 ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
|
|
- 889 (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 890 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
- 891 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
- 892 IF SymTab.Equal(mod, "libc") THEN
|
|
|
|
|
- 893 (* intrinsic C library:
|
|
|
|
|
- 894 permissive external *)
|
|
|
|
|
- 895 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
|
|
- 896 SemError(201) END;
|
|
|
|
|
- 897 Lower.NoteCProc(n)
|
|
|
|
|
- 898 ELSIF SymTab.ModKnown(mod) THEN
|
|
|
|
|
- 899 IF NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
|
|
- 900 SemError(201)
|
|
|
|
|
- 901 ELSE Lower.NoteImportedProc(n)
|
|
|
|
|
- 902 END
|
|
|
|
|
- 903 END; .)
|
|
|
|
|
- 904 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
|
|
- 905 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
|
|
- 906 | "UCHR" | "CHR8" | "UORD"
|
|
|
|
|
- 907 | "INC" | "DEC" ) .
|
|
|
|
|
- 908 ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 909 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
- 910 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
- 911 { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
- 912 AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
|
|
- 913 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
|
|
- 914 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
|
|
- 915 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
|
|
- 916 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
|
|
- 917 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
|
|
- 918 TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
- 919 = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
|
|
- 920 astSeq := AST.NoNode;
|
|
|
|
|
- 921 astTail := AST.NoNode; .)
|
|
|
|
|
- 922 { (. astDecl := AST.NoNode; .)
|
|
|
|
|
- 923 ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
|
|
- 924 (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 925 astSeq, astTail, astDecl); .) }
|
|
|
|
|
- 926 (. SymTab.EndTypeBlock;
|
|
|
|
|
- 927 astDecl := astSeq; .) .
|
|
|
|
|
- 928 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
|
|
- 929 t, op: SymTab.TypeIndex;
|
|
|
|
|
- 930 astNode: AST.Node; .)
|
|
|
|
|
- 931 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
|
|
- 932 IF op = SymTab.InvalidType THEN
|
|
|
|
|
- 933 IF NOT SymTab.Enter(n,
|
|
|
|
|
- 934 SymTab.KindType) THEN
|
|
|
|
|
- 935 SemError(200) END
|
|
|
|
|
- 936 END; .)
|
|
|
|
|
- 937 ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
|
|
|
|
|
- 938 AST.SetChild(astNode, 0,
|
|
|
|
|
- 939 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
- 940 AST.SetTy(astNode, t);
|
|
|
|
|
- 941 astDecl := astNode;
|
|
|
|
|
- 942 IF op # SymTab.InvalidType THEN
|
|
|
|
|
- 943 SymTab.SetTarget(op, t)
|
|
|
|
|
- 944 ELSE SymTab.SetSymType(n, t)
|
|
|
|
|
- 945 END; .)
|
|
|
|
|
- 946 | (. IF op # SymTab.InvalidType THEN
|
|
|
|
|
- 947 (* stays opaque *)
|
|
|
|
|
- 948 ELSIF NOT isDef THEN
|
|
|
|
|
- 949 SemError(231)
|
|
|
|
|
- 950 ELSE SymTab.SetSymType(n,
|
|
|
|
|
- 951 SymTab.NewAlias()) END; .) ) .
|
|
|
|
|
- 952 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
- 953 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
|
|
- 954 | Subrange<t>
|
|
|
|
|
- 955 | Enum<t>
|
|
|
|
|
- 956 | ArrayType<t, allowOpen>
|
|
|
|
|
- 957 | SetType<t>
|
|
|
|
|
- 958 | RecordType<t>
|
|
|
|
|
- 959 | PointerType<t>
|
|
|
|
|
- 960 | ProcType<t> .
|
|
|
|
|
- 961 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
|
|
- 962 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
|
|
- 963 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
|
|
- 964 are code pointers; params are collected into the descriptor. *)
|
|
|
|
|
- 965 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
|
|
- 966 isV: BOOLEAN; .)
|
|
|
|
|
- 967 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
|
|
- 968 t := SymTab.NewProcType(res); .)
|
|
|
|
|
- 969 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
|
|
- 970 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
|
|
- 971 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
|
|
- 972 isV: BOOLEAN;
|
|
|
|
|
- 973 cnt, k: CARDINAL;
|
|
|
|
|
- 974 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
|
|
- 975 = (. isV := FALSE; cnt := 0; .)
|
|
|
|
|
- 976 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
- 977 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
|
|
- 978 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
|
|
- 979 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
|
|
- 980 WHILE k < cnt DO
|
|
|
|
|
- 981 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
- 982 INC(k)
|
|
|
|
|
- 983 END; .)
|
|
|
|
|
- 984 | (. (* type-only parameter list:
|
|
|
|
|
- 985 each name is a type (GNU
|
|
|
|
|
- 986 shorthand used by the
|
|
|
|
|
- 987 Coco/R scanner frame) *)
|
|
|
|
|
- 988 k := 0;
|
|
|
|
|
- 989 WHILE k < cnt DO
|
|
|
|
|
- 990 IF SymTab.Lookup(names[k])
|
|
|
|
|
- 991 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
|
|
- 992 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
|
|
- 993 pt := SymTab.SymType(names[k])
|
|
|
|
|
- 994 ELSE SemError(201);
|
|
|
|
|
- 995 pt := SymTab.InvalidType
|
|
|
|
|
- 996 END;
|
|
|
|
|
- 997 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
- 998 INC(k)
|
|
|
|
|
- 999 END; .) )
|
|
|
|
|
- 1000 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
|
|
- 1001 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
|
|
- 1002 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
|
|
- 1003 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
|
|
- 1004 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
|
|
- 1005 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
|
|
- 1006 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
|
|
- 1007 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
- 1008 (. VAR elem: SymTab.TypeIndex;
|
|
|
|
|
- 1009 ok: BOOLEAN;
|
|
|
|
|
- 1010 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
|
|
- 1011 nb, k: CARDINAL;
|
|
|
|
|
- 1012 idx: SymTab.TypeIndex;
|
|
|
|
|
- 1013 ilo, ihi: INTEGER; .)
|
|
|
|
|
- 1014 = "ARRAY"
|
|
|
|
|
- 1015 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
|
|
- 1016 SemError(230) END;
|
|
|
|
|
- 1017 t := SymTab.NewOpenArray(elem); .)
|
|
|
|
|
- 1018 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
|
|
- 1019 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
|
|
- 1020 type's ordinal bounds give the
|
|
|
|
|
- 1021 [lo..hi] pair *)
|
|
|
|
|
- 1022 IF SymTab.TypeBounds(idx, ilo,
|
|
|
|
|
- 1023 ihi)
|
|
|
|
|
- 1024 THEN t := SymTab.NewArrayB(elem,
|
|
|
|
|
- 1025 ilo, ihi)
|
|
|
|
|
- 1026 ELSE SemError(230);
|
|
|
|
|
- 1027 t := SymTab.InvalidType
|
|
|
|
|
- 1028 END; .)
|
|
|
|
|
- 1029 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
|
|
- 1030 BoundPair<ok>
|
|
|
|
|
- 1031 { "," BoundPair<ok> }
|
|
|
|
|
- 1032 "]" (. (* snapshot before the element
|
|
|
|
|
- 1033 type, which reuses the bound
|
|
|
|
|
- 1034 buffer for a nested ARRAY *)
|
|
|
|
|
- 1035 nb := SymTab.BoundCount();
|
|
|
|
|
- 1036 k := 0;
|
|
|
|
|
- 1037 WHILE k < nb DO
|
|
|
|
|
- 1038 bnds[k] := SymTab.BoundLo(k);
|
|
|
|
|
- 1039 bndh[k] := SymTab.BoundHi(k);
|
|
|
|
|
- 1040 INC(k)
|
|
|
|
|
- 1041 END; .)
|
|
|
|
|
- 1042 "OF" Type<elem, FALSE>
|
|
|
|
|
- 1043 (. IF ok THEN
|
|
|
|
|
- 1044 k := nb;
|
|
|
|
|
- 1045 WHILE k > 0 DO
|
|
|
|
|
- 1046 DEC(k);
|
|
|
|
|
- 1047 elem := SymTab.NewArrayB(
|
|
|
|
|
- 1048 elem, bnds[k], bndh[k])
|
|
|
|
|
- 1049 END;
|
|
|
|
|
- 1050 t := elem
|
|
|
|
|
- 1051 ELSE t := SymTab.InvalidType
|
|
|
|
|
- 1052 END; .) ) .
|
|
|
|
|
- 1053 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
- 1054 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
- 1055 lo, hi: INTEGER;
|
|
|
|
|
- 1056 cl, cl2: INTEGER; .)
|
|
|
|
|
- 1057 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
- 1058 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
- 1059 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
- 1060 ok := FALSE
|
|
|
|
|
- 1061 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
|
|
- 1062 cl2 := SymTab.ClassOf(thi);
|
|
|
|
|
- 1063 IF ((cl # SymTab.ClInt)
|
|
|
|
|
- 1064 AND (cl # SymTab.ClChar))
|
|
|
|
|
- 1065 OR ((cl2 # SymTab.ClInt)
|
|
|
|
|
- 1066 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
|
|
- 1067 SemError(230); ok := FALSE
|
|
|
|
|
- 1068 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
- 1069 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
- 1070 OR (lo > hi) THEN
|
|
|
|
|
- 1071 SemError(230); ok := FALSE
|
|
|
|
|
- 1072 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
|
|
- 1073 SemError(230); ok := FALSE
|
|
|
|
|
- 1074 END;
|
|
|
|
|
- 1075 END; .) .
|
|
|
|
|
- 1076 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
|
|
- 1077 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
|
|
- 1078 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
|
|
- 1079 comparison across suitable bases are lenient (masks over min
|
|
|
|
|
- 1080 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
|
|
- 1081 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
|
|
- 1082 blo, bhi, bspan: INTEGER;
|
|
|
|
|
- 1083 bcls: INTEGER; .)
|
|
|
|
|
- 1084 = "SET" "OF" Type<base, FALSE>
|
|
|
|
|
- 1085 (. IF base = SymTab.InvalidType THEN
|
|
|
|
|
- 1086 t := SymTab.InvalidType
|
|
|
|
|
- 1087 ELSE bcls :=
|
|
|
|
|
- 1088 SymTab.ClassOf(base);
|
|
|
|
|
- 1089 IF bcls = SymTab.ClBool THEN
|
|
|
|
|
- 1090 blo := 0; bspan := 2
|
|
|
|
|
- 1091 ELSIF bcls = SymTab.ClChar THEN
|
|
|
|
|
- 1092 blo := 0; bspan := 256
|
|
|
|
|
- 1093 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
|
|
- 1094 blo := 0;
|
|
|
|
|
- 1095 bspan := VAL(INTEGER,
|
|
|
|
|
- 1096 SymTab.EnumCount(base))
|
|
|
|
|
- 1097 ELSIF SymTab.SubBounds(base,
|
|
|
|
|
- 1098 blo, bhi) THEN
|
|
|
|
|
- 1099 bspan := bhi - blo + 1
|
|
|
|
|
- 1100 ELSE bspan := 0 END;
|
|
|
|
|
- 1101 IF (bspan <= 0)
|
|
|
|
|
- 1102 OR (bspan > 65536) THEN
|
|
|
|
|
- 1103 SemError(230);
|
|
|
|
|
- 1104 t := SymTab.InvalidType
|
|
|
|
|
- 1105 ELSE t := SymTab.NewSet(base)
|
|
|
|
|
- 1106 END
|
|
|
|
|
- 1107 END; .) .
|
|
|
|
|
- 1108 (* Records: flat blobs; array fields are pointers to static
|
|
|
|
|
- 1109 descriptors (locked amendment), nested records inline. Field
|
|
|
|
|
- 1110 offsets static and declaration-ordered. *)
|
|
|
|
|
- 1111 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
|
|
- 1112 variant part is a `CASE ... END` item; because it starts with the
|
|
|
|
|
- 1113 CASE keyword it is unambiguously distinguishable from a field
|
|
|
|
|
- 1114 (which starts with an identifier). *)
|
|
|
|
|
- 1115 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
- 1116 tagOk: BOOLEAN; .)
|
|
|
|
|
- 1117 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
|
|
- 1118 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
|
|
- 1119 "END" (. SymTab.LayoutRecord(t); .) .
|
|
|
|
|
- 1120 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
|
|
- 1121 = RecField<rec>
|
|
|
|
|
- 1122 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
|
|
- 1123 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
|
|
- 1124 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
|
|
- 1125 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
|
|
- 1126 tagN: SymTab.Name; .)
|
|
|
|
|
- 1127 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
- 1128 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
- 1129 tagN) THEN
|
|
|
|
|
- 1130 SemError(200) END; .)
|
|
|
|
|
- 1131 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
|
|
- 1132 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
|
|
- 1133 SemError(224)
|
|
|
|
|
- 1134 END;
|
|
|
|
|
- 1135 SymTab.FixPendingF(rec, tagT);
|
|
|
|
|
- 1136 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
|
|
- 1137 "OF"
|
|
|
|
|
- 1138 RecFieldList<rec>
|
|
|
|
|
- 1139 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
- 1140 RecFieldList<rec> }
|
|
|
|
|
- 1141 "END" .
|
|
|
|
|
- 1142 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
|
|
- 1143 lv1, lv2: QbeGen.QVal; .)
|
|
|
|
|
- 1144 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
|
|
- 1145 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
|
|
- 1146 (* Variant case label: a constant (or a constant range). Values are
|
|
|
|
|
- 1147 not interpreted (the layout overlays regardless). *)
|
|
|
|
|
- 1148 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 1149 (. VAR lname: SymTab.Name; .)
|
|
|
|
|
- 1150 = ( ident (. LexName(lname);
|
|
|
|
|
- 1151 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 1152 t := SymTab.IntType(); .)
|
|
|
|
|
- 1153 | integer (. LexString(lname);
|
|
|
|
|
- 1154 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 1155 t := SymTab.IntType(); .)
|
|
|
|
|
- 1156 | charConst (. LexString(lname);
|
|
|
|
|
- 1157 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 1158 t := SymTab.CharType(); .) ) .
|
|
|
|
|
- 1159 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
- 1160 t2: SymTab.TypeIndex; .)
|
|
|
|
|
- 1161 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
|
|
- 1162 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 1163 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
- 1164 n) THEN
|
|
|
|
|
- 1165 SemError(200) END; .)
|
|
|
|
|
- 1166 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
- 1167 n) THEN
|
|
|
|
|
- 1168 SemError(200) END; .) } .
|
|
|
|
|
- 1169 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
|
|
- 1170 k: INTEGER;
|
|
|
|
|
- 1171 dotted: BOOLEAN; .)
|
|
|
|
|
- 1172 = GetIdent<n> (. dotted := FALSE;
|
|
|
|
|
- 1173 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
- 1174 k := -1;
|
|
|
|
|
- 1175 t := SymTab.ForwardType(n);
|
|
|
|
|
- 1176 IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 1177 SemError(201)
|
|
|
|
|
- 1178 END
|
|
|
|
|
- 1179 ELSE k := SymTab.SymKind(n);
|
|
|
|
|
- 1180 IF (k = SymTab.KindType)
|
|
|
|
|
- 1181 OR (k = SymTab.KindPredef) THEN
|
|
|
|
|
- 1182 t := SymTab.SymType(n)
|
|
|
|
|
- 1183 ELSE t := SymTab.InvalidType
|
|
|
|
|
|
|
+ 494 INC(instFk); .) }
|
|
|
|
|
+ 495 ":" "TYPE" .
|
|
|
|
|
+ 496 Actuals
|
|
|
|
|
+ 497 = Actual { "," Actual } .
|
|
|
|
|
+ 498 Actual (. VAR at: SymTab.TypeIndex; .)
|
|
|
|
|
+ 499 = TypeIdent<at> (. IF refN <= HIGH(refActual) THEN
|
|
|
|
|
+ 500 refActual[refN] := at; INC(refN)
|
|
|
|
|
+ 501 END; .) .
|
|
|
|
|
+ 502 Unit
|
|
|
|
|
+ 503 = (. isGen := FALSE;
|
|
|
|
|
+ 504 allowDefer := FALSE;
|
|
|
|
|
+ 505 repassing := FALSE; .)
|
|
|
|
|
+ 506 [ "GENERIC" (. isGen := TRUE; .) ]
|
|
|
|
|
+ 507 ( DefUnit | ImplUnit | ProgModule ) .
|
|
|
|
|
+ 508 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
|
|
+ 509 and one program (last) into one image. Units share the symbol
|
|
|
|
|
+ 510 table; imports materialize exported names. *)
|
|
|
|
|
+ 511 DefUnit (. VAR m1, m2, pn: SymTab.Name;
|
|
|
|
|
+ 512 g: SymTab.Name;
|
|
|
|
|
+ 513 astSeq, astTail, astProc: AST.Node; .)
|
|
|
|
|
+ 514 = (. refN := 0; refSeen := FALSE; .)
|
|
|
|
|
+ 515 "DEFINITION" "MODULE"
|
|
|
|
|
+ 516 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
|
|
+ 517 IF instActive THEN
|
|
|
|
|
+ 518 IF NOT SymTab.Reenter(m1,
|
|
|
|
|
+ 519 SymTab.UnitDef) THEN
|
|
|
|
|
+ 520 SemError(200) END
|
|
|
|
|
+ 521 ELSIF NOT SymTab.BeginDef(m1) THEN
|
|
|
|
|
+ 522 SemError(200) END;
|
|
|
|
|
+ 523 QbeGen.SetModule(m1);
|
|
|
|
|
+ 524 CopyNm(m1, unitName);
|
|
|
|
|
+ 525 unitWasGen := isGen
|
|
|
|
|
+ 526 AND NOT instActive;
|
|
|
|
|
+ 527 unitWasDef := TRUE; .)
|
|
|
|
|
+ 528 [ GenericFormals ]
|
|
|
|
|
+ 529 ( ";"
|
|
|
|
|
+ 530 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 531 astImp, astImpTail, astDecl); .) }
|
|
|
|
|
+ 532 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
|
|
+ 533 list: parsed, and the
|
|
|
|
|
+ 534 names are already exported
|
|
|
|
|
+ 535 by the module scope *) .)
|
|
|
|
|
+ 536 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
|
|
+ 537 (. astSeq := AST.NoNode;
|
|
|
|
|
+ 538 astTail := AST.NoNode; .)
|
|
|
|
|
+ 539 { ConstBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 540 astSeq, astTail, astDecl); .)
|
|
|
|
|
+ 541 | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 542 astSeq, astTail, astDecl); .)
|
|
|
|
|
+ 543 | VarBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 544 astSeq, astTail, astDecl); .)
|
|
|
|
|
+ 545 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
+ 546 (. (* a heading only: record it so
|
|
|
|
|
+ 547 Lower can replay it *)
|
|
|
|
|
+ 548 astProc := AST.MakeNode(AST.NkProcDecl);
|
|
|
|
|
+ 549 AST.SetOp(astProc, 0);
|
|
|
|
|
+ 550 AST.SetChild(astProc, 0,
|
|
|
|
|
+ 551 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
|
|
+ 552 AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 553 astSeq, astTail, astProc);
|
|
|
|
|
+ 554 Lower.NoteProcNode(astProc);
|
|
|
|
|
+ 555 Lower.ScopeLeave;
|
|
|
|
|
+ 556 SymTab.CloseProc;
|
|
|
|
|
+ 557 QbeGen.AbortFunc; .) }
|
|
|
|
|
+ 558 (. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
+ 559 AST.SetChild(astUnit, 0,
|
|
|
|
|
+ 560 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
+ 561 AST.SetChild(astUnit, 1, astSeq);
|
|
|
|
|
+ 562 AST.SetChild(astUnit, 3, astImp);
|
|
|
|
|
+ 563 astDecl := AST.NoNode;
|
|
|
|
|
+ 564 astStmt := AST.NoNode; .)
|
|
|
|
|
+ 565 "END"
|
|
|
|
|
+ 566 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
|
|
+ 567 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 568 SemError(202) END;
|
|
|
|
|
+ 569 SymTab.EndUnit; .)
|
|
|
|
|
+ 570 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
|
|
+ 571 (. CopyNm(m1, refInst);
|
|
|
|
|
+ 572 CopyNm(g, refGen);
|
|
|
|
|
+ 573 refSeen := TRUE; refIsDef := TRUE;
|
|
|
|
|
+ 574 astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
+ 575 AST.SetChild(astUnit, 0,
|
|
|
|
|
+ 576 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
+ 577 astDecl := AST.NoNode;
|
|
|
|
|
+ 578 astStmt := AST.NoNode; .)
|
|
|
|
|
+ 579 "END"
|
|
|
|
|
+ 580 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 581 SemError(202) END;
|
|
|
|
|
+ 582 SymTab.EndUnit; .) ) .
|
|
|
|
|
+ 583 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
+ 584 g: SymTab.Name;
|
|
|
|
|
+ 585 k: CARDINAL;
|
|
|
|
|
+ 586 rp: CARDINAL;
|
|
|
|
|
+ 587 rpOk: BOOLEAN;
|
|
|
|
|
+ 588 rErrs: INTEGER;
|
|
|
|
|
+ 589 rDecl, rStmt: AST.Node;
|
|
|
|
|
+ 590 rnm: SymTab.Name;
|
|
|
|
|
+ 591 rSym, rErr: CARDINAL;
|
|
|
|
|
+ 592 fname: SymTab.Name;
|
|
|
|
|
+ 593 unres: BOOLEAN;
|
|
|
|
|
+ 594 astNode: AST.Node; .)
|
|
|
|
|
+ 595 = (. refN := 0; refSeen := FALSE; .)
|
|
|
|
|
+ 596 "IMPLEMENTATION" "MODULE"
|
|
|
|
|
+ 597 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
|
|
+ 598 IF instActive THEN
|
|
|
|
|
+ 599 IF NOT SymTab.Reenter(m1,
|
|
|
|
|
+ 600 SymTab.UnitImpl) THEN
|
|
|
|
|
+ 601 SemError(201) END
|
|
|
|
|
+ 602 ELSIF NOT SymTab.BeginImpl(m1) THEN
|
|
|
|
|
+ 603 SemError(201) END;
|
|
|
|
|
+ 604 astStmt := AST.NoNode;
|
|
|
|
|
+ 605 astDecl := AST.NoNode;
|
|
|
|
|
+ 606 astImp := AST.NoNode;
|
|
|
|
|
+ 607 astImpTail := AST.NoNode;
|
|
|
|
|
+ 608 nPendVar := 0;
|
|
|
|
|
+ 609 CopyNm(m1, unitName);
|
|
|
|
|
+ 610 unitWasGen := isGen AND NOT instActive;
|
|
|
|
|
+ 611 unitWasDef := FALSE;
|
|
|
|
|
+ 612 QbeGen.SetModule(m1); .)
|
|
|
|
|
+ 613 [ GenericFormals ]
|
|
|
|
|
+ 614 ( ";"
|
|
|
|
|
+ 615 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 616 astImp, astImpTail, astDecl); .) }
|
|
|
|
|
+ 617 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 618 [ "BEGIN" (. FlushPend;
|
|
|
|
|
+ 619 k := 0;
|
|
|
|
|
+ 620 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 621 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 622 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 623 INC(k)
|
|
|
|
|
+ 624 END;
|
|
|
|
|
+ 625 SymTab.FwdClear;
|
|
|
|
|
+ 626
|
|
|
|
|
+ 627 nLab := 0; nGot := 0; .)
|
|
|
|
|
+ 628 [ StatSeq ] ]
|
|
|
|
|
+ 629 (. IF twoPhaseParse THEN
|
|
|
|
|
+ 630 rSym := sym; rErr := errDist;
|
|
|
|
|
+ 631 rDecl := astDecl; rStmt := astStmt;
|
|
|
|
|
+ 632 M2S.PushPos;
|
|
|
|
|
+ 633 repassing := TRUE;
|
|
|
|
|
+ 634 rp := 0;
|
|
|
|
|
+ 635 WHILE rp < nSpans DO
|
|
|
|
|
+ 636 k := 0;
|
|
|
|
|
+ 637 WHILE (k <= HIGH(rnm))
|
|
|
|
|
+ 638 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
|
|
+ 639 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
|
|
+ 640 END;
|
|
|
|
|
+ 641 rnm[k] := CHR(0);
|
|
|
|
|
+ 642 M2S.SeekTo(spanStart[rp]);
|
|
|
|
|
+ 643 Adv;
|
|
|
|
|
+ 644 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
|
|
+ 645 IF NOT rpOk THEN
|
|
|
|
|
+ 646 FileIO.WriteString(FileIO.StdOut,
|
|
|
|
|
+ 647 "twophase reenter failed");
|
|
|
|
|
+ 648 FileIO.WriteLn(FileIO.StdOut)
|
|
|
|
|
+ 649 END;
|
|
|
|
|
+ 650 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
|
|
+ 651 QbeGen.BeginFunc("");
|
|
|
|
|
+ 652 Block(rnm);
|
|
|
|
|
+ 653 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
|
|
+ 654 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
|
|
+ 655 Lower.ScopeLeave;
|
|
|
|
|
+ 656 SymTab.CloseProc;
|
|
|
|
|
+ 657 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
|
|
+ 658 INC(rp)
|
|
|
|
|
+ 659 END;
|
|
|
|
|
+ 660 rErrs := M2S.errors;
|
|
|
|
|
+ 661 repassing := FALSE;
|
|
|
|
|
+ 662 M2S.PopPos;
|
|
|
|
|
+ 663 sym := rSym; errDist := rErr;
|
|
|
|
|
+ 664 M2S.errors := rErrs;
|
|
|
|
|
+ 665
|
|
|
|
|
+ 666 astDecl := rDecl; astStmt := rStmt
|
|
|
|
|
+ 667 END; .)
|
|
|
|
|
+ 668 "END"
|
|
|
|
|
+ 669 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
|
|
+ 670 FlushPend;
|
|
|
|
|
+ 671 k := 0;
|
|
|
|
|
+ 672 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 673 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 674 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 675 INC(k)
|
|
|
|
|
+ 676 END;
|
|
|
|
|
+ 677 SymTab.FwdClear;
|
|
|
|
|
+ 678
|
|
|
|
|
+ 679 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
+ 680 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 681 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
+ 682 AST.SetChild(astNode, 1, astDecl);
|
|
|
|
|
+ 683 AST.SetChild(astNode, 2, astStmt);
|
|
|
|
|
+ 684 AST.SetChild(astNode, 3, astImp);
|
|
|
|
|
+ 685 astUnit := astNode;
|
|
|
|
|
+ 686 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 687 SemError(202) END;
|
|
|
|
|
+ 688 CheckGotos;
|
|
|
|
|
+ 689 SymTab.EndUnit; .)
|
|
|
|
|
+ 690 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
|
|
+ 691 (. CopyNm(m1, refInst);
|
|
|
|
|
+ 692 CopyNm(g, refGen);
|
|
|
|
|
+ 693 refSeen := TRUE; refIsDef := FALSE;
|
|
|
|
|
+ 694 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
+ 695 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 696 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
+ 697 astDecl := AST.NoNode;
|
|
|
|
|
+ 698 astStmt := AST.NoNode; .)
|
|
|
|
|
+ 699 "END"
|
|
|
|
|
+ 700 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 701 SemError(202) END;
|
|
|
|
|
+ 702 SymTab.EndUnit; .) ) .
|
|
|
|
|
+ 703 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
+ 704 k: CARDINAL;
|
|
|
|
|
+ 705 rp: CARDINAL;
|
|
|
|
|
+ 706 rpOk: BOOLEAN;
|
|
|
|
|
+ 707 rErrs: INTEGER;
|
|
|
|
|
+ 708 rDecl, rStmt: AST.Node;
|
|
|
|
|
+ 709 rnm: SymTab.Name;
|
|
|
|
|
+ 710 rSym, rErr: CARDINAL;
|
|
|
|
|
+ 711 fname: SymTab.Name;
|
|
|
|
|
+ 712 unres: BOOLEAN;
|
|
|
|
|
+ 713 astNode: AST.Node; .)
|
|
|
|
|
+ 714 = "MODULE"
|
|
|
|
|
+ 715 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
|
|
+ 716 SemError(200) END;
|
|
|
|
|
+ 717 astStmt := AST.NoNode;
|
|
|
|
|
+ 718 astDecl := AST.NoNode;
|
|
|
|
|
+ 719 astImp := AST.NoNode;
|
|
|
|
|
+ 720 astImpTail := AST.NoNode;
|
|
|
|
|
+ 721 nPendVar := 0;
|
|
|
|
|
+ 722 QbeGen.SetModule(m1); .)
|
|
|
|
|
+ 723 [ Priority ]
|
|
|
|
|
+ 724 ";"
|
|
|
|
|
+ 725 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 726 astImp, astImpTail, astDecl); .) }
|
|
|
|
|
+ 727 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 728 [ "BEGIN" (. FlushPend;
|
|
|
|
|
+ 729 k := 0;
|
|
|
|
|
+ 730 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 731 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 732 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 733 INC(k)
|
|
|
|
|
+ 734 END;
|
|
|
|
|
+ 735 SymTab.FwdClear;
|
|
|
|
|
+ 736
|
|
|
|
|
+ 737 nLab := 0; nGot := 0; .)
|
|
|
|
|
+ 738 [ StatSeq ] ]
|
|
|
|
|
+ 739 (. IF twoPhaseParse THEN
|
|
|
|
|
+ 740 rSym := sym; rErr := errDist;
|
|
|
|
|
+ 741 rDecl := astDecl; rStmt := astStmt;
|
|
|
|
|
+ 742 M2S.PushPos;
|
|
|
|
|
+ 743 repassing := TRUE;
|
|
|
|
|
+ 744 rp := 0;
|
|
|
|
|
+ 745 WHILE rp < nSpans DO
|
|
|
|
|
+ 746 k := 0;
|
|
|
|
|
+ 747 WHILE (k <= HIGH(rnm))
|
|
|
|
|
+ 748 AND (spanName[rp][k] # CHR(0)) DO
|
|
|
|
|
+ 749 rnm[k] := spanName[rp][k]; INC(k)
|
|
|
|
|
+ 750 END;
|
|
|
|
|
+ 751 rnm[k] := CHR(0);
|
|
|
|
|
+ 752 M2S.SeekTo(spanStart[rp]);
|
|
|
|
|
+ 753 Adv;
|
|
|
|
|
+ 754 rpOk := SymTab.ReenterDeferred(spanIdx[rp]);
|
|
|
|
|
+ 755 IF NOT rpOk THEN
|
|
|
|
|
+ 756 FileIO.WriteString(FileIO.StdOut,
|
|
|
|
|
+ 757 "twophase reenter failed");
|
|
|
|
|
+ 758 FileIO.WriteLn(FileIO.StdOut)
|
|
|
|
|
+ 759 END;
|
|
|
|
|
+ 760 Lower.ReenterScopeProc(spanTy[rp]);
|
|
|
|
|
+ 761 QbeGen.BeginFunc("");
|
|
|
|
|
+ 762 Block(rnm);
|
|
|
|
|
+ 763 AST.SetChild(spanNode[rp], 1, astStmt);
|
|
|
|
|
+ 764 AST.SetChild(spanNode[rp], 2, astBlkDecls);
|
|
|
|
|
+ 765 Lower.ScopeLeave;
|
|
|
|
|
+ 766 SymTab.CloseProc;
|
|
|
|
|
+ 767 QbeGen.EndFunc(SymTab.ProcRes(rnm));
|
|
|
|
|
+ 768 INC(rp)
|
|
|
|
|
+ 769 END;
|
|
|
|
|
+ 770 rErrs := M2S.errors;
|
|
|
|
|
+ 771 repassing := FALSE;
|
|
|
|
|
+ 772 M2S.PopPos;
|
|
|
|
|
+ 773 sym := rSym; errDist := rErr;
|
|
|
|
|
+ 774 M2S.errors := rErrs;
|
|
|
|
|
+ 775
|
|
|
|
|
+ 776 astDecl := rDecl; astStmt := rStmt
|
|
|
|
|
+ 777 END; .)
|
|
|
|
|
+ 778 "END"
|
|
|
|
|
+ 779 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
|
|
+ 780 FlushPend;
|
|
|
|
|
+ 781 k := 0;
|
|
|
|
|
+ 782 WHILE k < SymTab.FwdPending() DO
|
|
|
|
|
+ 783 SymTab.FwdInfo(k, fname, unres);
|
|
|
|
|
+ 784 IF unres THEN SemError(201) END;
|
|
|
|
|
+ 785 INC(k)
|
|
|
|
|
+ 786 END;
|
|
|
|
|
+ 787 SymTab.FwdClear;
|
|
|
|
|
+ 788
|
|
|
|
|
+ 789 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 790 SemError(202) END;
|
|
|
|
|
+ 791 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
+ 792 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 793 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
+ 794 AST.SetChild(astNode, 1, astDecl);
|
|
|
|
|
+ 795 AST.SetChild(astNode, 2, astStmt);
|
|
|
|
|
+ 796 AST.SetChild(astNode, 3, astImp);
|
|
|
|
|
+ 797 astUnit := astNode;
|
|
|
|
|
+ 798 CheckGotos;
|
|
|
|
|
+ 799 SymTab.EndUnit; .) .
|
|
|
|
|
+ 800 DeclSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
+ 801 = (. astSeq := AST.NoNode;
|
|
|
|
|
+ 802 astTail := AST.NoNode; .)
|
|
|
|
|
+ 803 { (. astDecl := AST.NoNode; .)
|
|
|
|
|
+ 804 ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
|
|
+ 805 | NestedModule ";" | ClassItem ";" )
|
|
|
|
|
+ 806 (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 807 astSeq, astTail, astDecl); .) }
|
|
|
|
|
+ 808 (. astDecl := astSeq; .) .
|
|
|
|
|
+ 809 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
|
|
+ 810 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
|
|
+ 811 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
|
|
+ 812 scope at END. *)
|
|
|
|
|
+ 813 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
|
|
+ 814 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
|
|
+ 815 expCount, k: CARDINAL;
|
|
|
|
|
+ 816 astNode, nImp, nImpTail:
|
|
|
|
|
+ 817 AST.Node; .)
|
|
|
|
|
+ 818 = "MODULE"
|
|
|
|
|
+ 819 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
|
|
+ 820 SymTab.KindModule) THEN
|
|
|
|
|
+ 821 SemError(200) END;
|
|
|
|
|
+ 822 SymTab.PushScope;
|
|
|
|
|
+ 823 expCount := 0;
|
|
|
|
|
+ 824 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
|
|
+ 825 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 826 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
|
|
+ 827 astStmt := AST.NoNode;
|
|
|
|
|
+ 828 astDecl := AST.NoNode;
|
|
|
|
|
+ 829 nImp := AST.NoNode;
|
|
|
|
|
+ 830 nImpTail := AST.NoNode; .)
|
|
|
|
|
+ 831 [ Priority ]
|
|
|
|
|
+ 832 ";"
|
|
|
|
|
+ 833 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 834 nImp, nImpTail, astDecl); .) }
|
|
|
|
|
+ 835 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
|
|
+ 836 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
|
|
+ 837 { "," GetIdent<expNames[expCount]>
|
|
|
|
|
+ 838 (. INC(expCount); .) }
|
|
|
|
|
+ 839 ";" ]
|
|
|
|
|
+ 840 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 841 [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
|
|
+ 842 .)
|
|
|
|
|
+ 843 [ StatSeq ] ]
|
|
|
|
|
+ 844 "END"
|
|
|
|
|
+ 845 GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
|
|
|
|
|
+ 846 AST.SetChild(astNode, 2, astStmt);
|
|
|
|
|
+ 847 AST.SetChild(astNode, 3, nImp);
|
|
|
|
|
+ 848 astDecl := astNode;
|
|
|
|
|
+ 849 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
|
|
+ 850 SemError(202) END;
|
|
|
|
|
+ 851 k := 0;
|
|
|
|
|
+ 852 WHILE k < expCount DO
|
|
|
|
|
+ 853 SymTab.ExportUp(expNames[k]);
|
|
|
|
|
+ 854 INC(k)
|
|
|
|
|
+ 855 END;
|
|
|
|
|
+ 856 SymTab.PopScope; .) .
|
|
|
|
|
+ 857 Priority
|
|
|
|
|
+ 858 = "[" integer "]" (. SemError(230); .) .
|
|
|
|
|
+ 859 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
|
|
+ 860 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
|
|
+ 861 materializes on first use (Design). *)
|
|
|
|
|
+ 862 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
|
|
+ 863 import lines don't fail); a known module's missing export is
|
|
|
|
|
+ 864 201. *)
|
|
|
|
|
+ 865 Import (. VAR n: SymTab.Name;
|
|
|
|
|
+ 866 astImport: AST.Node; .)
|
|
|
|
|
+ 867 = "FROM"
|
|
|
|
|
+ 868 GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
|
|
+ 869 AST.SetChild(astImport, 0,
|
|
|
|
|
+ 870 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
+ 871 "IMPORT"
|
|
|
|
|
+ 872 ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
|
|
+ 873 | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
|
|
+ 874 ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
|
|
+ 875 ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
|
|
+ 876 (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 877 = ImpName<mod, node>
|
|
|
|
|
+ 878 { "," ImpName<mod, node> } .
|
|
|
|
|
+ 879 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
|
|
+ 880 accepted and ignored: the built-in applies regardless. *)
|
|
|
|
|
+ 881 ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
|
|
+ 882 (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 883 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
+ 884 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
+ 885 IF SymTab.Equal(mod, "libc") THEN
|
|
|
|
|
+ 886 (* intrinsic C library:
|
|
|
|
|
+ 887 permissive external *)
|
|
|
|
|
+ 888 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
|
|
+ 889 SemError(201) END;
|
|
|
|
|
+ 890 Lower.NoteCProc(n)
|
|
|
|
|
+ 891 ELSIF SymTab.ModKnown(mod) THEN
|
|
|
|
|
+ 892 IF NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
|
|
+ 893 SemError(201)
|
|
|
|
|
+ 894 ELSE Lower.NoteImportedProc(n)
|
|
|
|
|
+ 895 END
|
|
|
|
|
+ 896 END; .)
|
|
|
|
|
+ 897 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
|
|
+ 898 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
|
|
+ 899 | "UCHR" | "CHR8" | "UORD"
|
|
|
|
|
+ 900 | "INC" | "DEC" ) .
|
|
|
|
|
+ 901 ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 902 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
+ 903 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
+ 904 { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
+ 905 AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
|
|
+ 906 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
|
|
+ 907 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
|
|
+ 908 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
|
|
+ 909 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
|
|
+ 910 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
|
|
+ 911 TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
+ 912 = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
|
|
+ 913 astSeq := AST.NoNode;
|
|
|
|
|
+ 914 astTail := AST.NoNode; .)
|
|
|
|
|
+ 915 { (. astDecl := AST.NoNode; .)
|
|
|
|
|
+ 916 ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
|
|
+ 917 (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 918 astSeq, astTail, astDecl); .) }
|
|
|
|
|
+ 919 (. SymTab.EndTypeBlock;
|
|
|
|
|
+ 920 astDecl := astSeq; .) .
|
|
|
|
|
+ 921 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 922 t, op: SymTab.TypeIndex;
|
|
|
|
|
+ 923 astNode: AST.Node; .)
|
|
|
|
|
+ 924 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
|
|
+ 925 IF op = SymTab.InvalidType THEN
|
|
|
|
|
+ 926 IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 927 SymTab.KindType) THEN
|
|
|
|
|
+ 928 SemError(200) END
|
|
|
|
|
+ 929 END; .)
|
|
|
|
|
+ 930 ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
|
|
|
|
|
+ 931 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 932 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
+ 933 AST.SetTy(astNode, t);
|
|
|
|
|
+ 934 astDecl := astNode;
|
|
|
|
|
+ 935 IF op # SymTab.InvalidType THEN
|
|
|
|
|
+ 936 SymTab.SetTarget(op, t)
|
|
|
|
|
+ 937 ELSE SymTab.SetSymType(n, t)
|
|
|
|
|
+ 938 END; .)
|
|
|
|
|
+ 939 | (. IF op # SymTab.InvalidType THEN
|
|
|
|
|
+ 940 (* stays opaque *)
|
|
|
|
|
+ 941 ELSIF NOT isDef THEN
|
|
|
|
|
+ 942 SemError(231)
|
|
|
|
|
+ 943 ELSE SymTab.SetSymType(n,
|
|
|
|
|
+ 944 SymTab.NewAlias()) END; .) ) .
|
|
|
|
|
+ 945 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
+ 946 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
|
|
+ 947 | Subrange<t>
|
|
|
|
|
+ 948 | Enum<t>
|
|
|
|
|
+ 949 | ArrayType<t, allowOpen>
|
|
|
|
|
+ 950 | SetType<t>
|
|
|
|
|
+ 951 | RecordType<t>
|
|
|
|
|
+ 952 | PointerType<t>
|
|
|
|
|
+ 953 | ProcType<t> .
|
|
|
|
|
+ 954 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
|
|
+ 955 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
|
|
+ 956 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
|
|
+ 957 are code pointers; params are collected into the descriptor. *)
|
|
|
|
|
+ 958 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
|
|
+ 959 isV: BOOLEAN; .)
|
|
|
|
|
+ 960 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
|
|
+ 961 t := SymTab.NewProcType(res); .)
|
|
|
|
|
+ 962 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
|
|
+ 963 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
|
|
+ 964 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
|
|
+ 965 isV: BOOLEAN;
|
|
|
|
|
+ 966 cnt, k: CARDINAL;
|
|
|
|
|
+ 967 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
|
|
+ 968 = (. isV := FALSE; cnt := 0; .)
|
|
|
|
|
+ 969 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
+ 970 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
|
|
+ 971 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
|
|
+ 972 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
|
|
+ 973 WHILE k < cnt DO
|
|
|
|
|
+ 974 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
+ 975 INC(k)
|
|
|
|
|
+ 976 END; .)
|
|
|
|
|
+ 977 | (. (* type-only parameter list:
|
|
|
|
|
+ 978 each name is a type (GNU
|
|
|
|
|
+ 979 shorthand used by the
|
|
|
|
|
+ 980 Coco/R scanner frame) *)
|
|
|
|
|
+ 981 k := 0;
|
|
|
|
|
+ 982 WHILE k < cnt DO
|
|
|
|
|
+ 983 IF SymTab.Lookup(names[k])
|
|
|
|
|
+ 984 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
|
|
+ 985 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
|
|
+ 986 pt := SymTab.SymType(names[k])
|
|
|
|
|
+ 987 ELSE SemError(201);
|
|
|
|
|
+ 988 pt := SymTab.InvalidType
|
|
|
|
|
+ 989 END;
|
|
|
|
|
+ 990 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
|
|
+ 991 INC(k)
|
|
|
|
|
+ 992 END; .) )
|
|
|
|
|
+ 993 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
|
|
+ 994 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
|
|
+ 995 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
|
|
+ 996 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
|
|
+ 997 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
|
|
+ 998 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
|
|
+ 999 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
|
|
+ 1000 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
|
|
+ 1001 (. VAR elem: SymTab.TypeIndex;
|
|
|
|
|
+ 1002 ok: BOOLEAN;
|
|
|
|
|
+ 1003 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
|
|
+ 1004 nb, k: CARDINAL;
|
|
|
|
|
+ 1005 idx: SymTab.TypeIndex;
|
|
|
|
|
+ 1006 ilo, ihi: INTEGER; .)
|
|
|
|
|
+ 1007 = "ARRAY"
|
|
|
|
|
+ 1008 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
|
|
+ 1009 SemError(230) END;
|
|
|
|
|
+ 1010 t := SymTab.NewOpenArray(elem); .)
|
|
|
|
|
+ 1011 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
|
|
+ 1012 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
|
|
+ 1013 type's ordinal bounds give the
|
|
|
|
|
+ 1014 [lo..hi] pair *)
|
|
|
|
|
+ 1015 IF SymTab.TypeBounds(idx, ilo,
|
|
|
|
|
+ 1016 ihi)
|
|
|
|
|
+ 1017 THEN t := SymTab.NewArrayB(elem,
|
|
|
|
|
+ 1018 ilo, ihi)
|
|
|
|
|
+ 1019 ELSE SemError(230);
|
|
|
|
|
+ 1020 t := SymTab.InvalidType
|
|
|
|
|
+ 1021 END; .)
|
|
|
|
|
+ 1022 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
|
|
+ 1023 BoundPair<ok>
|
|
|
|
|
+ 1024 { "," BoundPair<ok> }
|
|
|
|
|
+ 1025 "]" (. (* snapshot before the element
|
|
|
|
|
+ 1026 type, which reuses the bound
|
|
|
|
|
+ 1027 buffer for a nested ARRAY *)
|
|
|
|
|
+ 1028 nb := SymTab.BoundCount();
|
|
|
|
|
+ 1029 k := 0;
|
|
|
|
|
+ 1030 WHILE k < nb DO
|
|
|
|
|
+ 1031 bnds[k] := SymTab.BoundLo(k);
|
|
|
|
|
+ 1032 bndh[k] := SymTab.BoundHi(k);
|
|
|
|
|
+ 1033 INC(k)
|
|
|
|
|
+ 1034 END; .)
|
|
|
|
|
+ 1035 "OF" Type<elem, FALSE>
|
|
|
|
|
+ 1036 (. IF ok THEN
|
|
|
|
|
+ 1037 k := nb;
|
|
|
|
|
+ 1038 WHILE k > 0 DO
|
|
|
|
|
+ 1039 DEC(k);
|
|
|
|
|
+ 1040 elem := SymTab.NewArrayB(
|
|
|
|
|
+ 1041 elem, bnds[k], bndh[k])
|
|
|
|
|
+ 1042 END;
|
|
|
|
|
+ 1043 t := elem
|
|
|
|
|
+ 1044 ELSE t := SymTab.InvalidType
|
|
|
|
|
+ 1045 END; .) ) .
|
|
|
|
|
+ 1046 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
+ 1047 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
+ 1048 lo, hi: INTEGER;
|
|
|
|
|
+ 1049 cl, cl2: INTEGER; .)
|
|
|
|
|
+ 1050 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
+ 1051 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
+ 1052 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
+ 1053 ok := FALSE
|
|
|
|
|
+ 1054 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
|
|
+ 1055 cl2 := SymTab.ClassOf(thi);
|
|
|
|
|
+ 1056 IF ((cl # SymTab.ClInt)
|
|
|
|
|
+ 1057 AND (cl # SymTab.ClChar))
|
|
|
|
|
+ 1058 OR ((cl2 # SymTab.ClInt)
|
|
|
|
|
+ 1059 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
|
|
+ 1060 SemError(230); ok := FALSE
|
|
|
|
|
+ 1061 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
+ 1062 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
+ 1063 OR (lo > hi) THEN
|
|
|
|
|
+ 1064 SemError(230); ok := FALSE
|
|
|
|
|
+ 1065 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
|
|
+ 1066 SemError(230); ok := FALSE
|
|
|
|
|
+ 1067 END;
|
|
|
|
|
+ 1068 END; .) .
|
|
|
|
|
+ 1069 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
|
|
+ 1070 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
|
|
+ 1071 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
|
|
+ 1072 comparison across suitable bases are lenient (masks over min
|
|
|
|
|
+ 1073 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
|
|
+ 1074 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
|
|
+ 1075 blo, bhi, bspan: INTEGER;
|
|
|
|
|
+ 1076 bcls: INTEGER; .)
|
|
|
|
|
+ 1077 = "SET" "OF" Type<base, FALSE>
|
|
|
|
|
+ 1078 (. IF base = SymTab.InvalidType THEN
|
|
|
|
|
+ 1079 t := SymTab.InvalidType
|
|
|
|
|
+ 1080 ELSE bcls :=
|
|
|
|
|
+ 1081 SymTab.ClassOf(base);
|
|
|
|
|
+ 1082 IF bcls = SymTab.ClBool THEN
|
|
|
|
|
+ 1083 blo := 0; bspan := 2
|
|
|
|
|
+ 1084 ELSIF bcls = SymTab.ClChar THEN
|
|
|
|
|
+ 1085 blo := 0; bspan := 256
|
|
|
|
|
+ 1086 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
|
|
+ 1087 blo := 0;
|
|
|
|
|
+ 1088 bspan := VAL(INTEGER,
|
|
|
|
|
+ 1089 SymTab.EnumCount(base))
|
|
|
|
|
+ 1090 ELSIF SymTab.SubBounds(base,
|
|
|
|
|
+ 1091 blo, bhi) THEN
|
|
|
|
|
+ 1092 bspan := bhi - blo + 1
|
|
|
|
|
+ 1093 ELSE bspan := 0 END;
|
|
|
|
|
+ 1094 IF (bspan <= 0)
|
|
|
|
|
+ 1095 OR (bspan > 65536) THEN
|
|
|
|
|
+ 1096 SemError(230);
|
|
|
|
|
+ 1097 t := SymTab.InvalidType
|
|
|
|
|
+ 1098 ELSE t := SymTab.NewSet(base)
|
|
|
|
|
+ 1099 END
|
|
|
|
|
+ 1100 END; .) .
|
|
|
|
|
+ 1101 (* Records: flat blobs; array fields are pointers to static
|
|
|
|
|
+ 1102 descriptors (locked amendment), nested records inline. Field
|
|
|
|
|
+ 1103 offsets static and declaration-ordered. *)
|
|
|
|
|
+ 1104 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
|
|
+ 1105 variant part is a `CASE ... END` item; because it starts with the
|
|
|
|
|
+ 1106 CASE keyword it is unambiguously distinguishable from a field
|
|
|
|
|
+ 1107 (which starts with an identifier). *)
|
|
|
|
|
+ 1108 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
+ 1109 tagOk: BOOLEAN; .)
|
|
|
|
|
+ 1110 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
|
|
+ 1111 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
|
|
+ 1112 "END" (. SymTab.LayoutRecord(t); .) .
|
|
|
|
|
+ 1113 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1114 = RecField<rec>
|
|
|
|
|
+ 1115 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
|
|
+ 1116 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
|
|
+ 1117 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
|
|
+ 1118 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
|
|
+ 1119 tagN: SymTab.Name; .)
|
|
|
|
|
+ 1120 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
+ 1121 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
+ 1122 tagN) THEN
|
|
|
|
|
+ 1123 SemError(200) END; .)
|
|
|
|
|
+ 1124 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
|
|
+ 1125 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
|
|
+ 1126 SemError(224)
|
|
|
|
|
+ 1127 END;
|
|
|
|
|
+ 1128 SymTab.FixPendingF(rec, tagT);
|
|
|
|
|
+ 1129 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
|
|
+ 1130 "OF"
|
|
|
|
|
+ 1131 RecFieldList<rec>
|
|
|
|
|
+ 1132 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
|
|
+ 1133 RecFieldList<rec> }
|
|
|
|
|
+ 1134 "END" .
|
|
|
|
|
+ 1135 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
|
|
+ 1136 lv1, lv2: QbeGen.QVal; .)
|
|
|
|
|
+ 1137 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
|
|
+ 1138 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
|
|
+ 1139 (* Variant case label: a constant (or a constant range). Values are
|
|
|
|
|
+ 1140 not interpreted (the layout overlays regardless). *)
|
|
|
|
|
+ 1141 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 1142 (. VAR lname: SymTab.Name; .)
|
|
|
|
|
+ 1143 = ( ident (. LexName(lname);
|
|
|
|
|
+ 1144 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 1145 t := SymTab.IntType(); .)
|
|
|
|
|
+ 1146 | integer (. LexString(lname);
|
|
|
|
|
+ 1147 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 1148 t := SymTab.IntType(); .)
|
|
|
|
|
+ 1149 | charConst (. LexString(lname);
|
|
|
|
|
+ 1150 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 1151 t := SymTab.CharType(); .) ) .
|
|
|
|
|
+ 1152 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 1153 t2: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1154 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
|
|
+ 1155 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 1156 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
+ 1157 n) THEN
|
|
|
|
|
+ 1158 SemError(200) END; .)
|
|
|
|
|
+ 1159 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
|
|
+ 1160 n) THEN
|
|
|
|
|
+ 1161 SemError(200) END; .) } .
|
|
|
|
|
+ 1162 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
|
|
+ 1163 k: INTEGER;
|
|
|
|
|
+ 1164 dotted: BOOLEAN; .)
|
|
|
|
|
+ 1165 = GetIdent<n> (. dotted := FALSE;
|
|
|
|
|
+ 1166 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
+ 1167 k := -1;
|
|
|
|
|
+ 1168 t := SymTab.ForwardType(n);
|
|
|
|
|
+ 1169 IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 1170 SemError(201)
|
|
|
|
|
+ 1171 END
|
|
|
|
|
+ 1172 ELSE k := SymTab.SymKind(n);
|
|
|
|
|
+ 1173 IF (k = SymTab.KindType)
|
|
|
|
|
+ 1174 OR (k = SymTab.KindPredef) THEN
|
|
|
|
|
+ 1175 t := SymTab.SymType(n)
|
|
|
|
|
+ 1176 ELSE t := SymTab.InvalidType
|
|
|
|
|
+ 1177 END
|
|
|
|
|
+ 1178 END; .)
|
|
|
|
|
+ 1179 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
|
|
+ 1180 IF k = SymTab.KindModule THEN
|
|
|
|
|
+ 1181 t := SymTab.QualType(n, qid);
|
|
|
|
|
+ 1182 IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 1183 SemError(201)
|
|
|
1184 END
|
|
1184 END
|
|
|
- 1185 END; .)
|
|
|
|
|
- 1186 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
|
|
- 1187 IF k = SymTab.KindModule THEN
|
|
|
|
|
- 1188 t := SymTab.QualType(n, qid);
|
|
|
|
|
- 1189 IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 1190 SemError(201)
|
|
|
|
|
- 1191 END
|
|
|
|
|
- 1192 ELSE SemError(221);
|
|
|
|
|
- 1193 t := SymTab.InvalidType
|
|
|
|
|
- 1194 END; .) ]
|
|
|
|
|
- 1195 (. IF NOT dotted THEN
|
|
|
|
|
- 1196 IF (k = SymTab.KindModule)
|
|
|
|
|
- 1197 OR ((k # SymTab.KindType)
|
|
|
|
|
- 1198 AND (k # SymTab.KindPredef)
|
|
|
|
|
- 1199 AND (k # SymTab.KindImport)
|
|
|
|
|
- 1200 AND (k # -1)) THEN
|
|
|
|
|
- 1201 SemError(221)
|
|
|
|
|
- 1202 END
|
|
|
|
|
- 1203 END; .) .
|
|
|
|
|
- 1204 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
- 1205 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
- 1206 lo, hi: INTEGER; .)
|
|
|
|
|
- 1207 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
- 1208 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
- 1209 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
- 1210 t := SymTab.InvalidType
|
|
|
|
|
- 1211 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
|
|
- 1212 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
|
|
- 1213 SemError(230);
|
|
|
|
|
- 1214 t := SymTab.InvalidType
|
|
|
|
|
- 1215 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
- 1216 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
- 1217 OR (lo > hi) THEN
|
|
|
|
|
- 1218 SemError(230);
|
|
|
|
|
- 1219 t := SymTab.InvalidType
|
|
|
|
|
- 1220 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
|
|
- 1221 END; .)
|
|
|
|
|
- 1222 "]" .
|
|
|
|
|
- 1223 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
- 1224 ord: INTEGER;
|
|
|
|
|
- 1225 qv: QbeGen.QVal; .)
|
|
|
|
|
- 1226 = "(" (. t := SymTab.NewEnum();
|
|
|
|
|
- 1227 ord := 0; .)
|
|
|
|
|
- 1228 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 1229 SymTab.KindConst) THEN
|
|
|
|
|
- 1230 SemError(200) END;
|
|
|
|
|
- 1231 SymTab.SetSymType(n, t);
|
|
|
|
|
- 1232 QbeGen.IntStr(ord, qv);
|
|
|
|
|
- 1233 SymTab.SetSymVal(n, qv);
|
|
|
|
|
- 1234 Lower.NoteVar(n,
|
|
|
|
|
- 1235 SymTab.KindConst, t);
|
|
|
|
|
- 1236 Lower.NoteConstVal(qv);
|
|
|
|
|
- 1237 INC(ord); .)
|
|
|
|
|
- 1238 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 1239 SymTab.KindConst) THEN
|
|
|
|
|
- 1240 SemError(200) END;
|
|
|
|
|
- 1241 SymTab.SetSymType(n, t);
|
|
|
|
|
- 1242 QbeGen.IntStr(ord, qv);
|
|
|
|
|
- 1243 SymTab.SetSymVal(n, qv);
|
|
|
|
|
- 1244 Lower.NoteVar(n,
|
|
|
|
|
- 1245 SymTab.KindConst, t);
|
|
|
|
|
- 1246 Lower.NoteConstVal(qv);
|
|
|
|
|
- 1247 INC(ord); .) }
|
|
|
|
|
- 1248 ")" (. SymTab.SetEnumCount(t,
|
|
|
|
|
- 1249 VAL(CARDINAL, ord)); .) .
|
|
|
|
|
- 1250 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
|
|
- 1251 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
|
|
- 1252 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
|
|
- 1253 class/impl block. Methods end with ";" per the Table example
|
|
|
|
|
- 1254 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
|
|
- 1255 (* Single CLASS item in both loops: separating declaration from
|
|
|
|
|
- 1256 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
|
|
- 1257 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
|
|
- 1258 The second token decides after CLASS is consumed. A misplaced
|
|
|
|
|
- 1259 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
|
|
- 1260 whole unit ends 230 until lowering). *)
|
|
|
|
|
- 1261 ClassItem
|
|
|
|
|
- 1262 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
|
|
- 1263 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
|
|
- 1264 ct: SymTab.TypeIndex; .)
|
|
|
|
|
- 1265 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
|
|
- 1266 SymTab.KindType) THEN
|
|
|
|
|
- 1267 SemError(200) END;
|
|
|
|
|
- 1268 ct := SymTab.NewClass();
|
|
|
|
|
- 1269 SymTab.SetSymType(cn, ct);
|
|
|
|
|
- 1270 SymTab.PushClassScope(ct);
|
|
|
|
|
- 1271 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
|
|
- 1272 AST.SetChild(astCls, 0,
|
|
|
|
|
- 1273 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
|
|
- 1274 astClsP := AST.NoNode;
|
|
|
|
|
- 1275 astClsPTail := AST.NoNode;
|
|
|
|
|
- 1276 astClsF := AST.NoNode;
|
|
|
|
|
- 1277 astClsFTail := AST.NoNode;
|
|
|
|
|
- 1278 astClsM := AST.NoNode;
|
|
|
|
|
- 1279 astClsMTail := AST.NoNode; .)
|
|
|
|
|
- 1280 [ Parents<ct> ]
|
|
|
|
|
- 1281 ";"
|
|
|
|
|
- 1282 { ClassField<ct> ";" }
|
|
|
|
|
- 1283 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
- 1284 (. Lower.ScopeLeave;
|
|
|
|
|
- 1285 SymTab.CloseProc;
|
|
|
|
|
- 1286 QbeGen.AbortFunc; .) }
|
|
|
|
|
- 1287 "END"
|
|
|
|
|
- 1288 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
- 1289 SemError(202) END;
|
|
|
|
|
- 1290 SymTab.LayoutClass(ct);
|
|
|
|
|
- 1291 SymTab.PopScope;
|
|
|
|
|
- 1292 AST.SetChild(astCls, 1, astClsP);
|
|
|
|
|
- 1293 AST.SetChild(astCls, 2, astClsF);
|
|
|
|
|
- 1294 AST.SetChild(astCls, 3, astClsM);
|
|
|
|
|
- 1295 astDecl := astCls; .) .
|
|
|
|
|
- 1296 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
|
|
- 1297 = "(" Parent1<ct>
|
|
|
|
|
- 1298 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
|
|
- 1299 ")" .
|
|
|
|
|
- 1300 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
|
|
- 1301 pt: SymTab.TypeIndex; .)
|
|
|
|
|
- 1302 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
|
|
- 1303 SemError(201)
|
|
|
|
|
- 1304 ELSE pt := SymTab.SymType(p);
|
|
|
|
|
- 1305 IF SymTab.ClassOf(pt) #
|
|
|
|
|
- 1306 SymTab.ClClass THEN
|
|
|
|
|
- 1307 SemError(230)
|
|
|
|
|
- 1308 ELSE SymTab.SetParent(ct, pt)
|
|
|
|
|
- 1309 END
|
|
|
|
|
- 1310 END;
|
|
|
|
|
- 1311 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
- 1312 astClsP, astClsPTail,
|
|
|
|
|
- 1313 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
|
|
- 1314 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
|
|
- 1315 t: SymTab.TypeIndex;
|
|
|
|
|
- 1316 astNode: AST.Node; .)
|
|
|
|
|
- 1317 = GetIdent<n>
|
|
|
|
|
- 1318 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 1319 SymTab.KindConst) THEN
|
|
|
|
|
- 1320 SemError(200) END;
|
|
|
|
|
- 1321 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
|
|
- 1322 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1323 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
- 1324 AST.SetChild(astNode, 1,
|
|
|
|
|
- 1325 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
|
|
- 1326 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
- 1327 astClsF, astClsFTail, astNode);
|
|
|
|
|
- 1328 IF SymTab.Lookup(rhs) THEN
|
|
|
|
|
- 1329 SymTab.SetSymType(n,
|
|
|
|
|
- 1330 SymTab.SymType(rhs))
|
|
|
|
|
- 1331 END; .)
|
|
|
|
|
- 1332 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
- 1333 n) THEN
|
|
|
|
|
- 1334 SemError(200) END;
|
|
|
|
|
- 1335 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
|
|
- 1336 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1337 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
- 1338 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
- 1339 n) THEN
|
|
|
|
|
- 1340 SemError(200) END;
|
|
|
|
|
- 1341 AST.SetChild(astNode,
|
|
|
|
|
- 1342 AST.NChild(astNode),
|
|
|
|
|
- 1343 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
|
|
- 1344 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
|
|
- 1345 AST.SetTy(astNode, t);
|
|
|
|
|
- 1346 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
- 1347 astClsF, astClsFTail, astNode); .) ) .
|
|
|
|
|
- 1348 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
|
|
- 1349 (. VAR wantVirt: BOOLEAN; .)
|
|
|
|
|
- 1350 = (. wantVirt := FALSE; .)
|
|
|
|
|
- 1351 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
|
|
- 1352 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
|
|
- 1353 SymTab.MarkVirtual END;
|
|
|
|
|
- 1354 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
|
|
- 1355 AST.SetChild(astMethod, 0,
|
|
|
|
|
- 1356 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
|
|
- 1357 IF wantVirt THEN
|
|
|
|
|
- 1358 AST.SetOp(astMethod, 3)
|
|
|
|
|
- 1359 ELSE AST.SetOp(astMethod, 0)
|
|
|
|
|
- 1360 END;
|
|
|
|
|
- 1361 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
- 1362 astClsM, astClsMTail, astMethod); .) .
|
|
|
|
|
- 1363 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
|
|
- 1364 ct: SymTab.TypeIndex; .)
|
|
|
|
|
- 1365 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
|
|
- 1366 SemError(201);
|
|
|
|
|
- 1367 ct := SymTab.InvalidType
|
|
|
|
|
- 1368 ELSE ct := SymTab.SymType(cn);
|
|
|
|
|
- 1369 IF SymTab.ClassOf(ct) #
|
|
|
|
|
- 1370 SymTab.ClClass THEN
|
|
|
|
|
- 1371 SemError(230);
|
|
|
|
|
- 1372 ct := SymTab.InvalidType
|
|
|
|
|
- 1373 END
|
|
|
|
|
- 1374 END;
|
|
|
|
|
- 1375 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
|
|
- 1376 AST.SetOp(astCls, 1);
|
|
|
|
|
- 1377 AST.SetChild(astCls, 0,
|
|
|
|
|
- 1378 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
|
|
- 1379 astClsM := AST.NoNode;
|
|
|
|
|
- 1380 astClsMTail := AST.NoNode;
|
|
|
|
|
- 1381 astStmt := AST.NoNode;
|
|
|
|
|
- 1382 IF ct #
|
|
|
|
|
- 1383 SymTab.InvalidType THEN
|
|
|
|
|
- 1384 IF NOT SymTab.PushClassMembers(
|
|
|
|
|
- 1385 ct) THEN
|
|
|
|
|
- 1386 SemError(230) END;
|
|
|
|
|
- 1387 SymTab.PushImplClass(ct)
|
|
|
|
|
- 1388 END; .)
|
|
|
|
|
- 1389 ";" { MethodImpl<ct> ";" }
|
|
|
|
|
- 1390 (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 1391 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
|
|
- 1392 .)
|
|
|
|
|
- 1393 [ StatSeq ] ]
|
|
|
|
|
- 1394 "END"
|
|
|
|
|
- 1395 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
- 1396 SemError(202) END;
|
|
|
|
|
- 1397 SymTab.PopImplClass;
|
|
|
|
|
- 1398 SymTab.PopScope;
|
|
|
|
|
- 1399 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
|
|
- 1400 AST.SetChild(astCls, 2, astStmt);
|
|
|
|
|
- 1401 AST.SetChild(astCls, 3, astClsM);
|
|
|
|
|
- 1402 astDecl := astCls; .) .
|
|
|
|
|
- 1403 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
|
|
- 1404 thisQ: QbeGen.QVal;
|
|
|
|
|
- 1405 methRes: SymTab.TypeIndex; .)
|
|
|
|
|
- 1406 = MethodHeading<pn, ct> ";"
|
|
|
|
|
- 1407 (. IF (ct #
|
|
|
|
|
- 1408 SymTab.InvalidType)
|
|
|
|
|
- 1409 AND NOT SymTab.MethodExists(ct,
|
|
|
|
|
- 1410 pn) THEN
|
|
|
|
|
- 1411 SemError(201) END; .)
|
|
|
|
|
- 1412 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
|
|
- 1413 SymTab.MarkFwd;
|
|
|
|
|
- 1414 QbeGen.AbortFunc;
|
|
|
|
|
- 1415 Lower.ScopeLeave;
|
|
|
|
|
- 1416 SymTab.CloseProc; .)
|
|
|
|
|
- 1417 | (.
|
|
|
|
|
- 1418 (* bind the receiver: bare
|
|
|
|
|
- 1419 field names resolve
|
|
|
|
|
- 1420 against THIS *)
|
|
|
|
|
- 1421 QbeGen.CopyOp("@", thisQ);
|
|
|
|
|
- 1422 QbeGen.PushWith(thisQ); .)
|
|
|
|
|
- 1423 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
|
|
- 1424 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
|
|
- 1425 QbeGen.PopWith;
|
|
|
|
|
- 1426 methRes := SymTab.CurRes();
|
|
|
|
|
- 1427 Lower.ScopeLeave;
|
|
|
|
|
- 1428 SymTab.CloseProc;
|
|
|
|
|
- 1429 QbeGen.EndFunc(methRes); .) ) .
|
|
|
|
|
- 1430 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
- 1431 = "CONST" (. astSeq := AST.NoNode;
|
|
|
|
|
- 1432 astTail := AST.NoNode; .)
|
|
|
|
|
- 1433 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 1434 astSeq, astTail, astDecl); .) }
|
|
|
|
|
- 1435 (. astDecl := astSeq; .) .
|
|
|
|
|
- 1436 ConstDecl (. VAR n: SymTab.Name;
|
|
|
|
|
- 1437 t: SymTab.TypeIndex;
|
|
|
|
|
- 1438 qv: QbeGen.QVal;
|
|
|
|
|
- 1439 cls: INTEGER;
|
|
|
|
|
- 1440 astNode: AST.Node; .)
|
|
|
|
|
- 1441 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
- 1442 SymTab.KindConst) THEN
|
|
|
|
|
- 1443 SemError(200) END; .)
|
|
|
|
|
- 1444 "="
|
|
|
|
|
- 1445 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
|
|
- 1446 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1447 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
- 1448 AST.SetChild(astNode, 1, astCur);
|
|
|
|
|
- 1449 AST.SetTy(astNode, t);
|
|
|
|
|
- 1450 astDecl := astNode;
|
|
|
|
|
- 1451 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
|
|
- 1452 Lower.NoteConstVal(qv);
|
|
|
|
|
- 1453 SymTab.SetSymType(n, t);
|
|
|
|
|
- 1454 cls := SymTab.ClassOf(t);
|
|
|
|
|
- 1455 IF (cls = SymTab.ClArray)
|
|
|
|
|
- 1456 OR (cls = SymTab.ClRecord)
|
|
|
|
|
- 1457 OR (cls = SymTab.ClClass)
|
|
|
|
|
- 1458 OR (cls = SymTab.ClStr)
|
|
|
|
|
- 1459 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
- 1460 (* an aggregate/string
|
|
|
|
|
- 1461 constant: qv is its
|
|
|
|
|
- 1462 descriptor address; no
|
|
|
|
|
- 1463 scalar data *)
|
|
|
|
|
- 1464 SymTab.SetSymVal(n, qv)
|
|
|
|
|
- 1465 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
|
|
- 1466 SemError(230)
|
|
|
|
|
- 1467 ELSE
|
|
|
|
|
- 1468 SymTab.SetSymVal(n, qv);
|
|
|
|
|
- 1469 END; .) .
|
|
|
|
|
- 1470 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
- 1471 = "VAR" (. astSeq := AST.NoNode;
|
|
|
|
|
- 1472 astTail := AST.NoNode; .)
|
|
|
|
|
- 1473 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
- 1474 astSeq, astTail, astDecl); .) }
|
|
|
|
|
- 1475 (. astDecl := astSeq; .) .
|
|
|
|
|
- 1476 VarDecl (. VAR nm: SymTab.Name;
|
|
|
|
|
- 1477 t: SymTab.TypeIndex;
|
|
|
|
|
- 1478 i: CARDINAL;
|
|
|
|
|
- 1479 cls: INTEGER;
|
|
|
|
|
- 1480 astNode, astTail: AST.Node; .)
|
|
|
|
|
- 1481 = VarIdents ":"
|
|
|
|
|
- 1482 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
|
|
- 1483 astTail := astNode;
|
|
|
|
|
- 1484 i := 0;
|
|
|
|
|
- 1485 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 1486 SymTab.PendName(i, nm);
|
|
|
|
|
- 1487 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
|
|
- 1488 (* chunked: a VAR list can
|
|
|
|
|
- 1489 exceed AST.MaxChild *)
|
|
|
|
|
- 1490 AstAppend(AST.NkBlock,
|
|
|
|
|
- 1491 astNode, astTail,
|
|
|
|
|
- 1492 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
|
|
- 1493 INC(i)
|
|
|
|
|
- 1494 END;
|
|
|
|
|
- 1495 AST.SetTy(astNode, t);
|
|
|
|
|
- 1496 astDecl := astNode;
|
|
|
|
|
- 1497 cls := SymTab.ClassOf(t);
|
|
|
|
|
- 1498 IF (t # SymTab.InvalidType)
|
|
|
|
|
- 1499 AND NOT SymTab.IsUnresolved(t)
|
|
|
|
|
- 1500 AND (cls # SymTab.ClInt)
|
|
|
|
|
- 1501 AND (cls # SymTab.ClBool)
|
|
|
|
|
- 1502 AND (cls # SymTab.ClChar)
|
|
|
|
|
- 1503 AND (cls # SymTab.ClReal)
|
|
|
|
|
- 1504 AND (cls # SymTab.ClArray)
|
|
|
|
|
- 1505 AND (cls # SymTab.ClSet)
|
|
|
|
|
- 1506 AND (cls # SymTab.ClRecord)
|
|
|
|
|
- 1507 AND (cls # SymTab.ClPtr)
|
|
|
|
|
- 1508 AND (cls # SymTab.ClLong)
|
|
|
|
|
- 1509 AND (cls # SymTab.ClProc)
|
|
|
|
|
- 1510 AND (cls # SymTab.ClUChar)
|
|
|
|
|
- 1511 AND (cls # SymTab.ClUStr)
|
|
|
|
|
- 1512 AND (cls # SymTab.ClEnum)
|
|
|
|
|
- 1513 AND (cls # SymTab.ClClass) THEN
|
|
|
|
|
- 1514 SemError(230) END;
|
|
|
|
|
- 1515 IF QbeGen.LocFull() THEN
|
|
|
|
|
- 1516 SemError(233) END;
|
|
|
|
|
- 1517 i := 0;
|
|
|
|
|
- 1518 IF SymTab.IsUnresolved(t)
|
|
|
|
|
- 1519 AND NOT SymTab.InProc() THEN
|
|
|
|
|
- 1520 (* a forward-typed global:
|
|
|
|
|
- 1521 defer emission until the
|
|
|
|
|
- 1522 TYPE block completes *)
|
|
|
|
|
- 1523 AST.SetOp(astNode, 1);
|
|
|
|
|
- 1524 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 1525 SymTab.PendName(i, nm);
|
|
|
|
|
- 1526 IF nPendVar <=
|
|
|
|
|
- 1527 HIGH(pendVarName) THEN
|
|
|
|
|
- 1528 pendVarName[nPendVar] := nm;
|
|
|
|
|
- 1529 pendVarT[nPendVar] := t;
|
|
|
|
|
- 1530 INC(nPendVar)
|
|
|
|
|
- 1531 END;
|
|
|
|
|
- 1532 INC(i)
|
|
|
|
|
- 1533 END
|
|
|
|
|
- 1534 ELSE
|
|
|
|
|
- 1535 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 1536 SymTab.PendName(i, nm);
|
|
|
|
|
- 1537 INC(i)
|
|
|
|
|
- 1538 END
|
|
|
|
|
- 1539 END;
|
|
|
|
|
- 1540 (* a plain VAR list, not a
|
|
|
|
|
- 1541 heading: the signature
|
|
|
|
|
- 1542 result is discarded *)
|
|
|
|
|
- 1543 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
- 1544 END; .) .
|
|
|
|
|
- 1545 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 1546 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
- 1547 SymTab.KindVar) THEN
|
|
|
|
|
|
|
+ 1185 ELSE SemError(221);
|
|
|
|
|
+ 1186 t := SymTab.InvalidType
|
|
|
|
|
+ 1187 END; .) ]
|
|
|
|
|
+ 1188 (. IF NOT dotted THEN
|
|
|
|
|
+ 1189 IF (k = SymTab.KindModule)
|
|
|
|
|
+ 1190 OR ((k # SymTab.KindType)
|
|
|
|
|
+ 1191 AND (k # SymTab.KindPredef)
|
|
|
|
|
+ 1192 AND (k # SymTab.KindImport)
|
|
|
|
|
+ 1193 AND (k # -1)) THEN
|
|
|
|
|
+ 1194 SemError(221)
|
|
|
|
|
+ 1195 END
|
|
|
|
|
+ 1196 END; .) .
|
|
|
|
|
+ 1197 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
|
|
+ 1198 qlo, qhi: QbeGen.QVal;
|
|
|
|
|
+ 1199 lo, hi: INTEGER; .)
|
|
|
|
|
+ 1200 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
|
|
+ 1201 (. IF (tlo = SymTab.InvalidType)
|
|
|
|
|
+ 1202 OR (thi = SymTab.InvalidType) THEN
|
|
|
|
|
+ 1203 t := SymTab.InvalidType
|
|
|
|
|
+ 1204 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
|
|
+ 1205 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
|
|
+ 1206 SemError(230);
|
|
|
|
|
+ 1207 t := SymTab.InvalidType
|
|
|
|
|
+ 1208 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
|
|
+ 1209 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
|
|
+ 1210 OR (lo > hi) THEN
|
|
|
|
|
+ 1211 SemError(230);
|
|
|
|
|
+ 1212 t := SymTab.InvalidType
|
|
|
|
|
+ 1213 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
|
|
+ 1214 END; .)
|
|
|
|
|
+ 1215 "]" .
|
|
|
|
|
+ 1216 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
|
|
+ 1217 ord: INTEGER;
|
|
|
|
|
+ 1218 qv: QbeGen.QVal; .)
|
|
|
|
|
+ 1219 = "(" (. t := SymTab.NewEnum();
|
|
|
|
|
+ 1220 ord := 0; .)
|
|
|
|
|
+ 1221 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 1222 SymTab.KindConst) THEN
|
|
|
|
|
+ 1223 SemError(200) END;
|
|
|
|
|
+ 1224 SymTab.SetSymType(n, t);
|
|
|
|
|
+ 1225 QbeGen.IntStr(ord, qv);
|
|
|
|
|
+ 1226 SymTab.SetSymVal(n, qv);
|
|
|
|
|
+ 1227 Lower.NoteVar(n,
|
|
|
|
|
+ 1228 SymTab.KindConst, t);
|
|
|
|
|
+ 1229 Lower.NoteConstVal(qv);
|
|
|
|
|
+ 1230 INC(ord); .)
|
|
|
|
|
+ 1231 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 1232 SymTab.KindConst) THEN
|
|
|
|
|
+ 1233 SemError(200) END;
|
|
|
|
|
+ 1234 SymTab.SetSymType(n, t);
|
|
|
|
|
+ 1235 QbeGen.IntStr(ord, qv);
|
|
|
|
|
+ 1236 SymTab.SetSymVal(n, qv);
|
|
|
|
|
+ 1237 Lower.NoteVar(n,
|
|
|
|
|
+ 1238 SymTab.KindConst, t);
|
|
|
|
|
+ 1239 Lower.NoteConstVal(qv);
|
|
|
|
|
+ 1240 INC(ord); .) }
|
|
|
|
|
+ 1241 ")" (. SymTab.SetEnumCount(t,
|
|
|
|
|
+ 1242 VAL(CARDINAL, ord)); .) .
|
|
|
|
|
+ 1243 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
|
|
+ 1244 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
|
|
+ 1245 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
|
|
+ 1246 class/impl block. Methods end with ";" per the Table example
|
|
|
|
|
+ 1247 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
|
|
+ 1248 (* Single CLASS item in both loops: separating declaration from
|
|
|
|
|
+ 1249 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
|
|
+ 1250 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
|
|
+ 1251 The second token decides after CLASS is consumed. A misplaced
|
|
|
|
|
+ 1252 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
|
|
+ 1253 whole unit ends 230 until lowering). *)
|
|
|
|
|
+ 1254 ClassItem
|
|
|
|
|
+ 1255 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
|
|
+ 1256 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
|
|
+ 1257 ct: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1258 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
|
|
+ 1259 SymTab.KindType) THEN
|
|
|
|
|
+ 1260 SemError(200) END;
|
|
|
|
|
+ 1261 ct := SymTab.NewClass();
|
|
|
|
|
+ 1262 SymTab.SetSymType(cn, ct);
|
|
|
|
|
+ 1263 SymTab.PushClassScope(ct);
|
|
|
|
|
+ 1264 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
|
|
+ 1265 AST.SetChild(astCls, 0,
|
|
|
|
|
+ 1266 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
|
|
+ 1267 astClsP := AST.NoNode;
|
|
|
|
|
+ 1268 astClsPTail := AST.NoNode;
|
|
|
|
|
+ 1269 astClsF := AST.NoNode;
|
|
|
|
|
+ 1270 astClsFTail := AST.NoNode;
|
|
|
|
|
+ 1271 astClsM := AST.NoNode;
|
|
|
|
|
+ 1272 astClsMTail := AST.NoNode; .)
|
|
|
|
|
+ 1273 [ Parents<ct> ]
|
|
|
|
|
+ 1274 ";"
|
|
|
|
|
+ 1275 { ClassField<ct> ";" }
|
|
|
|
|
+ 1276 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
+ 1277 (. Lower.ScopeLeave;
|
|
|
|
|
+ 1278 SymTab.CloseProc;
|
|
|
|
|
+ 1279 QbeGen.AbortFunc; .) }
|
|
|
|
|
+ 1280 "END"
|
|
|
|
|
+ 1281 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
+ 1282 SemError(202) END;
|
|
|
|
|
+ 1283 SymTab.LayoutClass(ct);
|
|
|
|
|
+ 1284 SymTab.PopScope;
|
|
|
|
|
+ 1285 AST.SetChild(astCls, 1, astClsP);
|
|
|
|
|
+ 1286 AST.SetChild(astCls, 2, astClsF);
|
|
|
|
|
+ 1287 AST.SetChild(astCls, 3, astClsM);
|
|
|
|
|
+ 1288 astDecl := astCls; .) .
|
|
|
|
|
+ 1289 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
|
|
+ 1290 = "(" Parent1<ct>
|
|
|
|
|
+ 1291 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
|
|
+ 1292 ")" .
|
|
|
|
|
+ 1293 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
|
|
+ 1294 pt: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1295 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
|
|
+ 1296 SemError(201)
|
|
|
|
|
+ 1297 ELSE pt := SymTab.SymType(p);
|
|
|
|
|
+ 1298 IF SymTab.ClassOf(pt) #
|
|
|
|
|
+ 1299 SymTab.ClClass THEN
|
|
|
|
|
+ 1300 SemError(230)
|
|
|
|
|
+ 1301 ELSE SymTab.SetParent(ct, pt)
|
|
|
|
|
+ 1302 END
|
|
|
|
|
+ 1303 END;
|
|
|
|
|
+ 1304 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
+ 1305 astClsP, astClsPTail,
|
|
|
|
|
+ 1306 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
|
|
+ 1307 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
|
|
+ 1308 t: SymTab.TypeIndex;
|
|
|
|
|
+ 1309 astNode: AST.Node; .)
|
|
|
|
|
+ 1310 = GetIdent<n>
|
|
|
|
|
+ 1311 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 1312 SymTab.KindConst) THEN
|
|
|
|
|
+ 1313 SemError(200) END;
|
|
|
|
|
+ 1314 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
|
|
+ 1315 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1316 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
+ 1317 AST.SetChild(astNode, 1,
|
|
|
|
|
+ 1318 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
|
|
+ 1319 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
+ 1320 astClsF, astClsFTail, astNode);
|
|
|
|
|
+ 1321 IF SymTab.Lookup(rhs) THEN
|
|
|
|
|
+ 1322 SymTab.SetSymType(n,
|
|
|
|
|
+ 1323 SymTab.SymType(rhs))
|
|
|
|
|
+ 1324 END; .)
|
|
|
|
|
+ 1325 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
+ 1326 n) THEN
|
|
|
|
|
+ 1327 SemError(200) END;
|
|
|
|
|
+ 1328 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
|
|
+ 1329 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1330 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
+ 1331 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
|
|
+ 1332 n) THEN
|
|
|
|
|
+ 1333 SemError(200) END;
|
|
|
|
|
+ 1334 AST.SetChild(astNode,
|
|
|
|
|
+ 1335 AST.NChild(astNode),
|
|
|
|
|
+ 1336 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
|
|
+ 1337 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
|
|
+ 1338 AST.SetTy(astNode, t);
|
|
|
|
|
+ 1339 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
+ 1340 astClsF, astClsFTail, astNode); .) ) .
|
|
|
|
|
+ 1341 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
|
|
+ 1342 (. VAR wantVirt: BOOLEAN; .)
|
|
|
|
|
+ 1343 = (. wantVirt := FALSE; .)
|
|
|
|
|
+ 1344 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
|
|
+ 1345 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
|
|
+ 1346 SymTab.MarkVirtual END;
|
|
|
|
|
+ 1347 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
|
|
+ 1348 AST.SetChild(astMethod, 0,
|
|
|
|
|
+ 1349 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
|
|
+ 1350 IF wantVirt THEN
|
|
|
|
|
+ 1351 AST.SetOp(astMethod, 3)
|
|
|
|
|
+ 1352 ELSE AST.SetOp(astMethod, 0)
|
|
|
|
|
+ 1353 END;
|
|
|
|
|
+ 1354 AstAppend(AST.NkFieldDecl,
|
|
|
|
|
+ 1355 astClsM, astClsMTail, astMethod); .) .
|
|
|
|
|
+ 1356 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
|
|
+ 1357 ct: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1358 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
|
|
+ 1359 SemError(201);
|
|
|
|
|
+ 1360 ct := SymTab.InvalidType
|
|
|
|
|
+ 1361 ELSE ct := SymTab.SymType(cn);
|
|
|
|
|
+ 1362 IF SymTab.ClassOf(ct) #
|
|
|
|
|
+ 1363 SymTab.ClClass THEN
|
|
|
|
|
+ 1364 SemError(230);
|
|
|
|
|
+ 1365 ct := SymTab.InvalidType
|
|
|
|
|
+ 1366 END
|
|
|
|
|
+ 1367 END;
|
|
|
|
|
+ 1368 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
|
|
+ 1369 AST.SetOp(astCls, 1);
|
|
|
|
|
+ 1370 AST.SetChild(astCls, 0,
|
|
|
|
|
+ 1371 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
|
|
+ 1372 astClsM := AST.NoNode;
|
|
|
|
|
+ 1373 astClsMTail := AST.NoNode;
|
|
|
|
|
+ 1374 astStmt := AST.NoNode;
|
|
|
|
|
+ 1375 IF ct #
|
|
|
|
|
+ 1376 SymTab.InvalidType THEN
|
|
|
|
|
+ 1377 IF NOT SymTab.PushClassMembers(
|
|
|
|
|
+ 1378 ct) THEN
|
|
|
|
|
+ 1379 SemError(230) END;
|
|
|
|
|
+ 1380 SymTab.PushImplClass(ct)
|
|
|
|
|
+ 1381 END; .)
|
|
|
|
|
+ 1382 ";" { MethodImpl<ct> ";" }
|
|
|
|
|
+ 1383 (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 1384 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
|
|
+ 1385 .)
|
|
|
|
|
+ 1386 [ StatSeq ] ]
|
|
|
|
|
+ 1387 "END"
|
|
|
|
|
+ 1388 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
|
|
+ 1389 SemError(202) END;
|
|
|
|
|
+ 1390 SymTab.PopImplClass;
|
|
|
|
|
+ 1391 SymTab.PopScope;
|
|
|
|
|
+ 1392 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
|
|
+ 1393 AST.SetChild(astCls, 2, astStmt);
|
|
|
|
|
+ 1394 AST.SetChild(astCls, 3, astClsM);
|
|
|
|
|
+ 1395 astDecl := astCls; .) .
|
|
|
|
|
+ 1396 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
|
|
+ 1397 thisQ: QbeGen.QVal;
|
|
|
|
|
+ 1398 methRes: SymTab.TypeIndex; .)
|
|
|
|
|
+ 1399 = MethodHeading<pn, ct> ";"
|
|
|
|
|
+ 1400 (. IF (ct #
|
|
|
|
|
+ 1401 SymTab.InvalidType)
|
|
|
|
|
+ 1402 AND NOT SymTab.MethodExists(ct,
|
|
|
|
|
+ 1403 pn) THEN
|
|
|
|
|
+ 1404 SemError(201) END; .)
|
|
|
|
|
+ 1405 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
|
|
+ 1406 SymTab.MarkFwd;
|
|
|
|
|
+ 1407 QbeGen.AbortFunc;
|
|
|
|
|
+ 1408 Lower.ScopeLeave;
|
|
|
|
|
+ 1409 SymTab.CloseProc; .)
|
|
|
|
|
+ 1410 | (.
|
|
|
|
|
+ 1411 (* bind the receiver: bare
|
|
|
|
|
+ 1412 field names resolve
|
|
|
|
|
+ 1413 against THIS *)
|
|
|
|
|
+ 1414 QbeGen.CopyOp("@", thisQ);
|
|
|
|
|
+ 1415 QbeGen.PushWith(thisQ); .)
|
|
|
|
|
+ 1416 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
|
|
+ 1417 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
|
|
+ 1418 QbeGen.PopWith;
|
|
|
|
|
+ 1419 methRes := SymTab.CurRes();
|
|
|
|
|
+ 1420 Lower.ScopeLeave;
|
|
|
|
|
+ 1421 SymTab.CloseProc;
|
|
|
|
|
+ 1422 QbeGen.EndFunc(methRes); .) ) .
|
|
|
|
|
+ 1423 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
+ 1424 = "CONST" (. astSeq := AST.NoNode;
|
|
|
|
|
+ 1425 astTail := AST.NoNode; .)
|
|
|
|
|
+ 1426 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 1427 astSeq, astTail, astDecl); .) }
|
|
|
|
|
+ 1428 (. astDecl := astSeq; .) .
|
|
|
|
|
+ 1429 ConstDecl (. VAR n: SymTab.Name;
|
|
|
|
|
+ 1430 t: SymTab.TypeIndex;
|
|
|
|
|
+ 1431 qv: QbeGen.QVal;
|
|
|
|
|
+ 1432 cls: INTEGER;
|
|
|
|
|
+ 1433 astNode: AST.Node; .)
|
|
|
|
|
+ 1434 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
|
|
+ 1435 SymTab.KindConst) THEN
|
|
|
|
|
+ 1436 SemError(200) END; .)
|
|
|
|
|
+ 1437 "="
|
|
|
|
|
+ 1438 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
|
|
+ 1439 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1440 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
+ 1441 AST.SetChild(astNode, 1, astCur);
|
|
|
|
|
+ 1442 AST.SetTy(astNode, t);
|
|
|
|
|
+ 1443 astDecl := astNode;
|
|
|
|
|
+ 1444 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
|
|
+ 1445 Lower.NoteConstVal(qv);
|
|
|
|
|
+ 1446 SymTab.SetSymType(n, t);
|
|
|
|
|
+ 1447 cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 1448 IF (cls = SymTab.ClArray)
|
|
|
|
|
+ 1449 OR (cls = SymTab.ClRecord)
|
|
|
|
|
+ 1450 OR (cls = SymTab.ClClass)
|
|
|
|
|
+ 1451 OR (cls = SymTab.ClStr)
|
|
|
|
|
+ 1452 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
+ 1453 (* an aggregate/string
|
|
|
|
|
+ 1454 constant: qv is its
|
|
|
|
|
+ 1455 descriptor address; no
|
|
|
|
|
+ 1456 scalar data *)
|
|
|
|
|
+ 1457 SymTab.SetSymVal(n, qv)
|
|
|
|
|
+ 1458 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
|
|
+ 1459 SemError(230)
|
|
|
|
|
+ 1460 ELSE
|
|
|
|
|
+ 1461 SymTab.SetSymVal(n, qv);
|
|
|
|
|
+ 1462 END; .) .
|
|
|
|
|
+ 1463 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
+ 1464 = "VAR" (. astSeq := AST.NoNode;
|
|
|
|
|
+ 1465 astTail := AST.NoNode; .)
|
|
|
|
|
+ 1466 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
|
|
+ 1467 astSeq, astTail, astDecl); .) }
|
|
|
|
|
+ 1468 (. astDecl := astSeq; .) .
|
|
|
|
|
+ 1469 VarDecl (. VAR nm: SymTab.Name;
|
|
|
|
|
+ 1470 t: SymTab.TypeIndex;
|
|
|
|
|
+ 1471 i: CARDINAL;
|
|
|
|
|
+ 1472 cls: INTEGER;
|
|
|
|
|
+ 1473 astNode, astTail: AST.Node; .)
|
|
|
|
|
+ 1474 = VarIdents ":"
|
|
|
|
|
+ 1475 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
|
|
+ 1476 astTail := astNode;
|
|
|
|
|
+ 1477 i := 0;
|
|
|
|
|
+ 1478 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 1479 SymTab.PendName(i, nm);
|
|
|
|
|
+ 1480 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
|
|
+ 1481 (* chunked: a VAR list can
|
|
|
|
|
+ 1482 exceed AST.MaxChild *)
|
|
|
|
|
+ 1483 AstAppend(AST.NkBlock,
|
|
|
|
|
+ 1484 astNode, astTail,
|
|
|
|
|
+ 1485 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
|
|
+ 1486 INC(i)
|
|
|
|
|
+ 1487 END;
|
|
|
|
|
+ 1488 AST.SetTy(astNode, t);
|
|
|
|
|
+ 1489 astDecl := astNode;
|
|
|
|
|
+ 1490 cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 1491 IF (t # SymTab.InvalidType)
|
|
|
|
|
+ 1492 AND NOT SymTab.IsUnresolved(t)
|
|
|
|
|
+ 1493 AND (cls # SymTab.ClInt)
|
|
|
|
|
+ 1494 AND (cls # SymTab.ClBool)
|
|
|
|
|
+ 1495 AND (cls # SymTab.ClChar)
|
|
|
|
|
+ 1496 AND (cls # SymTab.ClReal)
|
|
|
|
|
+ 1497 AND (cls # SymTab.ClArray)
|
|
|
|
|
+ 1498 AND (cls # SymTab.ClSet)
|
|
|
|
|
+ 1499 AND (cls # SymTab.ClRecord)
|
|
|
|
|
+ 1500 AND (cls # SymTab.ClPtr)
|
|
|
|
|
+ 1501 AND (cls # SymTab.ClLong)
|
|
|
|
|
+ 1502 AND (cls # SymTab.ClProc)
|
|
|
|
|
+ 1503 AND (cls # SymTab.ClUChar)
|
|
|
|
|
+ 1504 AND (cls # SymTab.ClUStr)
|
|
|
|
|
+ 1505 AND (cls # SymTab.ClEnum)
|
|
|
|
|
+ 1506 AND (cls # SymTab.ClClass) THEN
|
|
|
|
|
+ 1507 SemError(230) END;
|
|
|
|
|
+ 1508 IF QbeGen.LocFull() THEN
|
|
|
|
|
+ 1509 SemError(233) END;
|
|
|
|
|
+ 1510 i := 0;
|
|
|
|
|
+ 1511 IF SymTab.IsUnresolved(t)
|
|
|
|
|
+ 1512 AND NOT SymTab.InProc() THEN
|
|
|
|
|
+ 1513 (* a forward-typed global:
|
|
|
|
|
+ 1514 defer emission until the
|
|
|
|
|
+ 1515 TYPE block completes *)
|
|
|
|
|
+ 1516 AST.SetOp(astNode, 1);
|
|
|
|
|
+ 1517 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 1518 SymTab.PendName(i, nm);
|
|
|
|
|
+ 1519 IF nPendVar <=
|
|
|
|
|
+ 1520 HIGH(pendVarName) THEN
|
|
|
|
|
+ 1521 pendVarName[nPendVar] := nm;
|
|
|
|
|
+ 1522 pendVarT[nPendVar] := t;
|
|
|
|
|
+ 1523 INC(nPendVar)
|
|
|
|
|
+ 1524 END;
|
|
|
|
|
+ 1525 INC(i)
|
|
|
|
|
+ 1526 END
|
|
|
|
|
+ 1527 ELSE
|
|
|
|
|
+ 1528 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 1529 SymTab.PendName(i, nm);
|
|
|
|
|
+ 1530 INC(i)
|
|
|
|
|
+ 1531 END
|
|
|
|
|
+ 1532 END;
|
|
|
|
|
+ 1533 (* a plain VAR list, not a
|
|
|
|
|
+ 1534 heading: the signature
|
|
|
|
|
+ 1535 result is discarded *)
|
|
|
|
|
+ 1536 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
+ 1537 END; .) .
|
|
|
|
|
+ 1538 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 1539 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
+ 1540 SymTab.KindVar) THEN
|
|
|
|
|
+ 1541 SemError(200) END; .)
|
|
|
|
|
+ 1542 { ","
|
|
|
|
|
+ 1543 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
+ 1544 SymTab.KindVar) THEN
|
|
|
|
|
+ 1545 SemError(200) END; .) } .
|
|
|
|
|
+ 1546 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 1547 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
1548 SemError(200) END; .)
|
|
1548 SemError(200) END; .)
|
|
|
- 1549 { ","
|
|
|
|
|
- 1550 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
|
|
- 1551 SymTab.KindVar) THEN
|
|
|
|
|
- 1552 SemError(200) END; .) } .
|
|
|
|
|
- 1553 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 1554 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
- 1555 SemError(200) END; .)
|
|
|
|
|
- 1556 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
- 1557 SemError(200) END; .) } .
|
|
|
|
|
- 1558 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
|
|
- 1559 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
|
|
- 1560 FORWARD marks; the body heading re-enters (signature compare
|
|
|
|
|
- 1561 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
|
|
- 1562 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
|
|
- 1563 (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1564 mg: QbeGen.QVal; .)
|
|
|
|
|
- 1565 = "PROCEDURE"
|
|
|
|
|
- 1566 GetIdent<pn> (. IF methCls #
|
|
|
|
|
- 1567 SymTab.InvalidType THEN
|
|
|
|
|
- 1568 (* a method: resume the
|
|
|
|
|
- 1569 declared symbol (reuse
|
|
|
|
|
- 1570 its uid) *)
|
|
|
|
|
- 1571 IF NOT SymTab.ResumeMethod(
|
|
|
|
|
- 1572 methCls, pn) THEN
|
|
|
|
|
- 1573 SemError(200) END
|
|
|
|
|
- 1574 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
|
|
- 1575 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
|
|
- 1576 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
|
|
- 1577 SemError(200) END
|
|
|
|
|
- 1578 END
|
|
|
|
|
- 1579 END;
|
|
|
|
|
- 1580 Lower.ScopeEnter;
|
|
|
|
|
- 1581 Lower.NoteProc(pn,
|
|
|
|
|
- 1582 SymTab.ProcUid(pn),
|
|
|
|
|
- 1583 SymTab.InvalidType,
|
|
|
|
|
- 1584 SymTab.ProcDepthOf(pn),
|
|
|
|
|
- 1585 FALSE);
|
|
|
|
|
- 1586 QbeGen.BeginFunc("");
|
|
|
|
|
- 1587 IF methCls #
|
|
|
|
|
- 1588 SymTab.InvalidType THEN
|
|
|
|
|
- 1589 (* hidden THIS receiver:
|
|
|
|
|
- 1590 a VAR param of the
|
|
|
|
|
- 1591 class type, pushed as
|
|
|
|
|
- 1592 the WITH base *)
|
|
|
|
|
- 1593 IF NOT SymTab.EnterThisParam(
|
|
|
|
|
- 1594 methCls) THEN
|
|
|
|
|
- 1595 SemError(200) END;
|
|
|
|
|
- 1596 IF NOT QbeGen.FuncParam(
|
|
|
|
|
- 1597 "THIS", TRUE,
|
|
|
|
|
- 1598 methCls) THEN
|
|
|
|
|
- 1599 SemError(233) END
|
|
|
|
|
- 1600 END; .)
|
|
|
|
|
- 1601 [ FormalParams ]
|
|
|
|
|
- 1602 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
|
|
- 1603 SemError(235) END;
|
|
|
|
|
- 1604 Lower.SetProcRes(t); .) ] .
|
|
|
|
|
- 1605 FormalParams
|
|
|
|
|
- 1606 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
|
|
- 1607 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 1608 nm: SymTab.Name;
|
|
|
|
|
- 1609 i: CARDINAL;
|
|
|
|
|
- 1610 isV: BOOLEAN; .)
|
|
|
|
|
- 1611 = (. isV := FALSE; .)
|
|
|
|
|
- 1612 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
- 1613 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
|
|
- 1614 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
- 1615 SymTab.PendName(i, nm);
|
|
|
|
|
- 1616 Lower.NoteParam(nm, t, isV);
|
|
|
|
|
- 1617 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
|
|
- 1618 (* value open arrays are
|
|
|
|
|
- 1619 passed as descriptor
|
|
|
|
|
- 1620 addresses (no copy):
|
|
|
|
|
- 1621 same representation as
|
|
|
|
|
- 1622 VAR formals *)
|
|
|
|
|
- 1623 IF NOT QbeGen.FuncParam(nm,
|
|
|
|
|
- 1624 isV
|
|
|
|
|
- 1625 OR SymTab.IsOpenArray(t),
|
|
|
|
|
- 1626 t) THEN
|
|
|
|
|
- 1627 SemError(233) END;
|
|
|
|
|
- 1628 INC(i)
|
|
|
|
|
- 1629 END;
|
|
|
|
|
- 1630 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
- 1631 SemError(235) END; .) .
|
|
|
|
|
- 1632 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
|
|
- 1633 static link gives them their parent's frame. Methods keep
|
|
|
|
|
- 1634 parse-now/230-later. *)
|
|
|
|
|
- 1635 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
|
|
- 1636 astNode: AST.Node; .)
|
|
|
|
|
- 1637 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
- 1638 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
|
|
- 1639 AST.SetOp(astNode, 0);
|
|
|
|
|
- 1640 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1641 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
|
|
- 1642 Lower.NoteProcNode(astNode); .)
|
|
|
|
|
- 1643 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
|
|
- 1644 astDecl := astNode;
|
|
|
|
|
|
|
+ 1549 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
|
|
+ 1550 SemError(200) END; .) } .
|
|
|
|
|
+ 1551 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
|
|
+ 1552 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
|
|
+ 1553 FORWARD marks; the body heading re-enters (signature compare
|
|
|
|
|
+ 1554 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
|
|
+ 1555 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
|
|
+ 1556 (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1557 mg: QbeGen.QVal; .)
|
|
|
|
|
+ 1558 = "PROCEDURE"
|
|
|
|
|
+ 1559 GetIdent<pn> (. IF methCls #
|
|
|
|
|
+ 1560 SymTab.InvalidType THEN
|
|
|
|
|
+ 1561 (* a method: resume the
|
|
|
|
|
+ 1562 declared symbol (reuse
|
|
|
|
|
+ 1563 its uid) *)
|
|
|
|
|
+ 1564 IF NOT SymTab.ResumeMethod(
|
|
|
|
|
+ 1565 methCls, pn) THEN
|
|
|
|
|
+ 1566 SemError(200) END
|
|
|
|
|
+ 1567 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
|
|
+ 1568 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
|
|
+ 1569 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
|
|
+ 1570 SemError(200) END
|
|
|
|
|
+ 1571 END
|
|
|
|
|
+ 1572 END;
|
|
|
|
|
+ 1573 Lower.ScopeEnter;
|
|
|
|
|
+ 1574 Lower.NoteProc(pn,
|
|
|
|
|
+ 1575 SymTab.ProcUid(pn),
|
|
|
|
|
+ 1576 SymTab.InvalidType,
|
|
|
|
|
+ 1577 SymTab.ProcDepthOf(pn),
|
|
|
|
|
+ 1578 FALSE);
|
|
|
|
|
+ 1579 QbeGen.BeginFunc("");
|
|
|
|
|
+ 1580 IF methCls #
|
|
|
|
|
+ 1581 SymTab.InvalidType THEN
|
|
|
|
|
+ 1582 (* hidden THIS receiver:
|
|
|
|
|
+ 1583 a VAR param of the
|
|
|
|
|
+ 1584 class type, pushed as
|
|
|
|
|
+ 1585 the WITH base *)
|
|
|
|
|
+ 1586 IF NOT SymTab.EnterThisParam(
|
|
|
|
|
+ 1587 methCls) THEN
|
|
|
|
|
+ 1588 SemError(200) END;
|
|
|
|
|
+ 1589 IF NOT QbeGen.FuncParam(
|
|
|
|
|
+ 1590 "THIS", TRUE,
|
|
|
|
|
+ 1591 methCls) THEN
|
|
|
|
|
+ 1592 SemError(233) END
|
|
|
|
|
+ 1593 END; .)
|
|
|
|
|
+ 1594 [ FormalParams ]
|
|
|
|
|
+ 1595 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
|
|
+ 1596 SemError(235) END;
|
|
|
|
|
+ 1597 Lower.SetProcRes(t); .) ] .
|
|
|
|
|
+ 1598 FormalParams
|
|
|
|
|
+ 1599 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
|
|
+ 1600 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 1601 nm: SymTab.Name;
|
|
|
|
|
+ 1602 i: CARDINAL;
|
|
|
|
|
+ 1603 isV: BOOLEAN; .)
|
|
|
|
|
+ 1604 = (. isV := FALSE; .)
|
|
|
|
|
+ 1605 [ "VAR" (. isV := TRUE; .) ]
|
|
|
|
|
+ 1606 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
|
|
+ 1607 WHILE i < SymTab.PendCount() DO
|
|
|
|
|
+ 1608 SymTab.PendName(i, nm);
|
|
|
|
|
+ 1609 Lower.NoteParam(nm, t, isV);
|
|
|
|
|
+ 1610 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
|
|
+ 1611 (* value open arrays are
|
|
|
|
|
+ 1612 passed as descriptor
|
|
|
|
|
+ 1613 addresses (no copy):
|
|
|
|
|
+ 1614 same representation as
|
|
|
|
|
+ 1615 VAR formals *)
|
|
|
|
|
+ 1616 IF NOT QbeGen.FuncParam(nm,
|
|
|
|
|
+ 1617 isV
|
|
|
|
|
+ 1618 OR SymTab.IsOpenArray(t),
|
|
|
|
|
+ 1619 t) THEN
|
|
|
|
|
+ 1620 SemError(233) END;
|
|
|
|
|
+ 1621 INC(i)
|
|
|
|
|
+ 1622 END;
|
|
|
|
|
+ 1623 IF NOT SymTab.FixPending(t) THEN
|
|
|
|
|
+ 1624 SemError(235) END; .) .
|
|
|
|
|
+ 1625 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
|
|
+ 1626 static link gives them their parent's frame. Methods keep
|
|
|
|
|
+ 1627 parse-now/230-later. *)
|
|
|
|
|
+ 1628 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
|
|
+ 1629 astNode: AST.Node; .)
|
|
|
|
|
+ 1630 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
|
|
+ 1631 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
|
|
+ 1632 AST.SetOp(astNode, 0);
|
|
|
|
|
+ 1633 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1634 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
|
|
+ 1635 Lower.NoteProcNode(astNode); .)
|
|
|
|
|
+ 1636 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
|
|
+ 1637 astDecl := astNode;
|
|
|
|
|
+ 1638 Lower.ScopeLeave;
|
|
|
|
|
+ 1639 SymTab.MarkFwd;
|
|
|
|
|
+ 1640 SymTab.CloseProc;
|
|
|
|
|
+ 1641 QbeGen.AbortFunc; .)
|
|
|
|
|
+ 1642 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
|
|
+ 1643 astDecl := astNode;
|
|
|
|
|
+ 1644 Lower.MarkProcExternal;
|
|
|
1645 Lower.ScopeLeave;
|
|
1645 Lower.ScopeLeave;
|
|
|
- 1646 SymTab.MarkFwd;
|
|
|
|
|
|
|
+ 1646 SymTab.MarkExternal("");
|
|
|
1647 SymTab.CloseProc;
|
|
1647 SymTab.CloseProc;
|
|
|
1648 QbeGen.AbortFunc; .)
|
|
1648 QbeGen.AbortFunc; .)
|
|
|
- 1649 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
|
|
- 1650 astDecl := astNode;
|
|
|
|
|
- 1651 Lower.MarkProcExternal;
|
|
|
|
|
- 1652 Lower.ScopeLeave;
|
|
|
|
|
- 1653 SymTab.MarkExternal("");
|
|
|
|
|
- 1654 SymTab.CloseProc;
|
|
|
|
|
- 1655 QbeGen.AbortFunc; .)
|
|
|
|
|
- 1656 |
|
|
|
|
|
- 1657 (. allowDefer := TRUE; deferredBody := FALSE;
|
|
|
|
|
- 1658 curProcNode := astNode; .)
|
|
|
|
|
- 1659 Block<pn> (. IF deferredBody THEN
|
|
|
|
|
- 1660 (* body skipped: close like
|
|
|
|
|
- 1661 FORWARD (no body node) *)
|
|
|
|
|
|
|
+ 1649 |
|
|
|
|
|
+ 1650 (. allowDefer := TRUE; deferredBody := FALSE;
|
|
|
|
|
+ 1651 curProcNode := astNode; .)
|
|
|
|
|
+ 1652 Block<pn> (. IF deferredBody THEN
|
|
|
|
|
+ 1653 (* body skipped: close like
|
|
|
|
|
+ 1654 FORWARD (no body node) *)
|
|
|
|
|
+ 1655 astDecl := astNode;
|
|
|
|
|
+ 1656 Lower.ScopeLeave;
|
|
|
|
|
+ 1657 SymTab.CloseProc;
|
|
|
|
|
+ 1658 QbeGen.AbortFunc
|
|
|
|
|
+ 1659 ELSE
|
|
|
|
|
+ 1660 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
+ 1661 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
1662 astDecl := astNode;
|
|
1662 astDecl := astNode;
|
|
|
1663 Lower.ScopeLeave;
|
|
1663 Lower.ScopeLeave;
|
|
|
1664 SymTab.CloseProc;
|
|
1664 SymTab.CloseProc;
|
|
|
- 1665 QbeGen.AbortFunc
|
|
|
|
|
- 1666 ELSE
|
|
|
|
|
- 1667 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
- 1668 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
|
|
- 1669 astDecl := astNode;
|
|
|
|
|
- 1670 Lower.ScopeLeave;
|
|
|
|
|
- 1671 SymTab.CloseProc;
|
|
|
|
|
- 1672 QbeGen.EndFunc(
|
|
|
|
|
- 1673 SymTab.ProcRes(pn))
|
|
|
|
|
- 1674 END; .) ) .
|
|
|
|
|
- 1675 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; dfr: BOOLEAN; .)
|
|
|
|
|
- 1676 = (. dfr := FALSE;
|
|
|
|
|
- 1677 IF allowDefer AND twoPhaseParse
|
|
|
|
|
- 1678 AND NOT repassing THEN
|
|
|
|
|
- 1679 dfr := DeferSkip(pn)
|
|
|
|
|
- 1680 END;
|
|
|
|
|
- 1681 allowDefer := FALSE;
|
|
|
|
|
- 1682 IF NOT dfr THEN INC(procNest) END; .)
|
|
|
|
|
- 1683 DeclSeq (. astBlkDecls := astDecl;
|
|
|
|
|
- 1684 astStmt := AST.NoNode;
|
|
|
|
|
- 1685 nLab := 0; nGot := 0; .)
|
|
|
|
|
- 1686 [ "BEGIN" (. (* an empty body is still a
|
|
|
|
|
- 1687 body: mark it so Lower
|
|
|
|
|
- 1688 does not read it as a
|
|
|
|
|
- 1689 definition heading *)
|
|
|
|
|
- 1690 IF NOT dfr THEN
|
|
|
|
|
- 1691 IF astStmt = AST.NoNode THEN
|
|
|
|
|
- 1692 astStmt :=
|
|
|
|
|
- 1693 AST.MakeNode(AST.NkBlock)
|
|
|
|
|
- 1694 END
|
|
|
|
|
- 1695 END; .)
|
|
|
|
|
- 1696 [ StatSeq ] ]
|
|
|
|
|
- 1697 "END"
|
|
|
|
|
- 1698 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
|
|
- 1699 SemError(202) END;
|
|
|
|
|
- 1700 IF NOT dfr THEN DEC(procNest) END;
|
|
|
|
|
- 1701 CheckGotos; .) .
|
|
|
|
|
- 1702 (* Two-phase, phase 2 (milestone 2c): re-parse every deferred module-
|
|
|
|
|
- 1703 level body once the unit's declarations are complete. Inlined at
|
|
|
|
|
- 1704 both call sites because a stand-alone epsilon production is
|
|
|
|
|
- 1705 "unreachable" to Coco/R (referenced only from actions). *)
|
|
|
|
|
- 1706 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
- 1707 = (. astSeq := AST.NoNode;
|
|
|
|
|
- 1708 astTail := AST.NoNode; .)
|
|
|
|
|
- 1709 Statement (. AstAppend(AST.NkBlock,
|
|
|
|
|
- 1710 astSeq, astTail, astStmt); .)
|
|
|
|
|
- 1711 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
|
|
- 1712 astSeq, astTail, astStmt); .) ] }
|
|
|
|
|
- 1713 (. astStmt := astSeq; .) .
|
|
|
|
|
- 1714 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
|
|
- 1715 are accepted: the statement after ';' is optional. *)
|
|
|
|
|
- 1716 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
|
|
- 1717 = (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 1718 ( AssOrCall
|
|
|
|
|
- 1719 | IfStat
|
|
|
|
|
- 1720 | WhileStat
|
|
|
|
|
- 1721 | RepeatStat
|
|
|
|
|
- 1722 | LoopStat
|
|
|
|
|
- 1723 | ForStat
|
|
|
|
|
- 1724 | CaseStat
|
|
|
|
|
- 1725 | WithStat
|
|
|
|
|
- 1726 | ReturnStat
|
|
|
|
|
- 1727 | HaltStat
|
|
|
|
|
- 1728 | NewStat
|
|
|
|
|
- 1729 | DisposeStat
|
|
|
|
|
- 1730 | IncDecStat
|
|
|
|
|
- 1731 | InclExclStat
|
|
|
|
|
- 1732 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
|
|
- 1733 SemError(230) END;
|
|
|
|
|
- 1734 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
|
|
- 1735 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
|
|
- 1736 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
|
|
- 1737 AST.SetChild(astStmt, 0,
|
|
|
|
|
- 1738 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
|
|
- 1739 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
|
|
- 1740 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
|
|
- 1741 dk: INTEGER;
|
|
|
|
|
- 1742 qd, qe: QbeGen.QVal;
|
|
|
|
|
- 1743 qn: SymTab.Name;
|
|
|
|
|
- 1744 sfx, isInc: BOOLEAN;
|
|
|
|
|
- 1745 astNode, astD: AST.Node; .)
|
|
|
|
|
- 1746 = ( "INCL" (. isInc := TRUE; .)
|
|
|
|
|
- 1747 | "EXCL" (. isInc := FALSE; .) )
|
|
|
|
|
- 1748 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
|
|
- 1749 Expr<et2, qe> ")"
|
|
|
|
|
- 1750 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 1751 IF isInc THEN
|
|
|
|
|
- 1752 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1753 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
|
|
- 1754 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
- 1755 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
|
|
- 1756 END;
|
|
|
|
|
- 1757 IF astD # AST.NoNode THEN
|
|
|
|
|
- 1758 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
- 1759 IF astCur # AST.NoNode THEN
|
|
|
|
|
- 1760 AST.SetChild(astNode, 2, astCur) END;
|
|
|
|
|
- 1761 astStmt := astNode; .)
|
|
|
|
|
- 1762 (. IF (at # SymTab.InvalidType)
|
|
|
|
|
- 1763 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
|
|
- 1764 SemError(222)
|
|
|
|
|
- 1765 END; .) .
|
|
|
|
|
- 1766 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
|
|
- 1767 integer designator. *)
|
|
|
|
|
- 1768 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
|
|
- 1769 dk: INTEGER;
|
|
|
|
|
- 1770 qd, qv, qn2, qstep:
|
|
|
|
|
- 1771 QbeGen.QVal;
|
|
|
|
|
- 1772 qn: SymTab.Name;
|
|
|
|
|
- 1773 sfx, isInc: BOOLEAN;
|
|
|
|
|
- 1774 astNode, astD, astStep:
|
|
|
|
|
- 1775 AST.Node; .)
|
|
|
|
|
- 1776 = (. isInc := TRUE; .)
|
|
|
|
|
- 1777 ( "INC" (. isInc := TRUE; .)
|
|
|
|
|
- 1778 | "DEC" (. isInc := FALSE; .) )
|
|
|
|
|
- 1779 "(" (. astStep := AST.NoNode; .)
|
|
|
|
|
- 1780 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
|
|
- 1781 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
|
|
- 1782 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 1783 IF isInc THEN
|
|
|
|
|
- 1784 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1785 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
|
|
- 1786 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
- 1787 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
|
|
- 1788 END;
|
|
|
|
|
- 1789 IF astD # AST.NoNode THEN
|
|
|
|
|
- 1790 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
- 1791 IF astStep # AST.NoNode THEN
|
|
|
|
|
- 1792 AST.SetChild(astNode, 2, astStep) END;
|
|
|
|
|
- 1793 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1794 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
- 1795 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1796 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1797 SemError(210)
|
|
|
|
|
- 1798 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
|
|
- 1799 SemError(211)
|
|
|
|
|
- 1800 END; .) .
|
|
|
|
|
- 1801 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
|
|
- 1802 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
|
|
- 1803 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
|
|
- 1804 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
- 1805 dk: INTEGER;
|
|
|
|
|
- 1806 qd, qm: QbeGen.QVal;
|
|
|
|
|
- 1807 qn: SymTab.Name;
|
|
|
|
|
- 1808 sfx: BOOLEAN;
|
|
|
|
|
- 1809 bt: SymTab.TypeIndex;
|
|
|
|
|
- 1810 astNode, astD: AST.Node; .)
|
|
|
|
|
- 1811 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
|
|
- 1812 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 1813 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1814 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
|
|
- 1815 IF astD # AST.NoNode THEN
|
|
|
|
|
- 1816 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
- 1817 astStmt := astNode; .)
|
|
|
|
|
- 1818 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1819 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
- 1820 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1821 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1822 SemError(210)
|
|
|
|
|
- 1823 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
- 1824 SymTab.ClPtr THEN
|
|
|
|
|
- 1825 SemError(219)
|
|
|
|
|
- 1826 END; .) .
|
|
|
|
|
- 1827 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
- 1828 dk: INTEGER;
|
|
|
|
|
- 1829 qd, qv: QbeGen.QVal;
|
|
|
|
|
- 1830 qn: SymTab.Name;
|
|
|
|
|
- 1831 sfx: BOOLEAN;
|
|
|
|
|
- 1832 astNode, astD: AST.Node; .)
|
|
|
|
|
- 1833 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
|
|
- 1834 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 1835 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1836 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
|
|
- 1837 IF astD # AST.NoNode THEN
|
|
|
|
|
- 1838 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
- 1839 astStmt := astNode; .)
|
|
|
|
|
- 1840 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1841 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
- 1842 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1843 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1844 SemError(210)
|
|
|
|
|
- 1845 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
- 1846 SymTab.ClPtr THEN
|
|
|
|
|
- 1847 SemError(219)
|
|
|
|
|
- 1848 END; .) .
|
|
|
|
|
- 1849 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
|
|
- 1850 address; field designators resolve through both stacks. *)
|
|
|
|
|
- 1851 WithStat (. VAR nW: CARDINAL;
|
|
|
|
|
- 1852 astNode: AST.Node; .)
|
|
|
|
|
- 1853 = "WITH" (. nW := 0;
|
|
|
|
|
- 1854 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
|
|
- 1855 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
|
|
- 1856 "DO" (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 1857 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
|
|
- 1858 AST.NChild(astNode), astStmt);
|
|
|
|
|
- 1859 astStmt := astNode;
|
|
|
|
|
- 1860 WHILE nW > 0 DO
|
|
|
|
|
- 1861 SymTab.PopScope;
|
|
|
|
|
- 1862 QbeGen.PopWith;
|
|
|
|
|
- 1863 DEC(nW)
|
|
|
|
|
- 1864 END; .) .
|
|
|
|
|
- 1865 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
|
|
- 1866 (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
- 1867 dk: INTEGER;
|
|
|
|
|
- 1868 qd, qe: QbeGen.QVal;
|
|
|
|
|
- 1869 qn: SymTab.Name;
|
|
|
|
|
- 1870 sfx: BOOLEAN; .)
|
|
|
|
|
- 1871 = Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
- 1872 (. IF astCur # AST.NoNode THEN
|
|
|
|
|
- 1873 AST.SetChild(wnode,
|
|
|
|
|
- 1874 AST.NChild(wnode), astCur) END;
|
|
|
|
|
- 1875 IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 1876 ELSIF (SymTab.ClassOf(dt) #
|
|
|
|
|
- 1877 SymTab.ClRecord)
|
|
|
|
|
- 1878 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
- 1879 SymTab.ClClass) THEN
|
|
|
|
|
- 1880 SemError(215)
|
|
|
|
|
- 1881 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
|
|
- 1882 QbeGen.PushWith(qd);
|
|
|
|
|
- 1883 INC(nW)
|
|
|
|
|
- 1884 END; .) .
|
|
|
|
|
- 1885 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
|
|
- 1886 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
|
|
- 1887 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
|
|
- 1888 dk: INTEGER;
|
|
|
|
|
- 1889 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
|
|
- 1890 qn: SymTab.Name;
|
|
|
|
|
- 1891 ct2, res0: SymTab.TypeIndex;
|
|
|
|
|
- 1892 q2, mg0: QbeGen.QVal;
|
|
|
|
|
- 1893 isR, conv, wconv: BOOLEAN;
|
|
|
|
|
- 1894 called, sfx: BOOLEAN;
|
|
|
|
|
- 1895 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
|
|
- 1896 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
|
|
- 1897 = GetIdent<n>
|
|
|
|
|
- 1898 ( ":" (. NoteLabel(n);
|
|
|
|
|
- 1899 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
|
|
- 1900 AST.SetChild(astNode, 0,
|
|
|
|
|
- 1901 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
- 1902 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
|
|
- 1903 AST.SetChild(astLab, 0, astNode); .)
|
|
|
|
|
- 1904 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
|
|
- 1905 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
|
|
- 1906 astStmt := astLab; .)
|
|
|
|
|
- 1907 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
|
|
- 1908 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
|
|
- 1909 ( ":="
|
|
|
|
|
- 1910 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
|
|
- 1911 AST.NkAssign, 0, astLhs, astCur);
|
|
|
|
|
- 1912 IF (dt # SymTab.InvalidType)
|
|
|
|
|
- 1913 AND (dk # SymTab.KindVar)
|
|
|
|
|
- 1914 AND (dk # SymTab.KindParam)
|
|
|
|
|
- 1915 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
- 1916 SemError(210)
|
|
|
|
|
- 1917 ELSIF NOT SymTab.Assignable(et,
|
|
|
|
|
- 1918 dt) THEN
|
|
|
|
|
- 1919 SemError(210)
|
|
|
|
|
- 1920 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
- 1921 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
- 1922 SymTab.ClClass) THEN
|
|
|
|
|
- 1923 SemError(230) END;
|
|
|
|
|
- 1924 isR := (dt #
|
|
|
|
|
- 1925 SymTab.InvalidType)
|
|
|
|
|
- 1926 AND (SymTab.ClassOf(dt)
|
|
|
|
|
- 1927 = SymTab.ClReal);
|
|
|
|
|
- 1928 conv := isR
|
|
|
|
|
- 1929 AND SymTab.IsIntFamily(et);
|
|
|
|
|
- 1930 wconv := (dt #
|
|
|
|
|
- 1931 SymTab.InvalidType)
|
|
|
|
|
- 1932 AND SymTab.IsLongFamily(dt)
|
|
|
|
|
- 1933 AND SymTab.IsIntFamily(et);
|
|
|
|
|
- 1934 IF ((dk = SymTab.KindVar)
|
|
|
|
|
- 1935 OR (dk = SymTab.KindParam)
|
|
|
|
|
- 1936 OR (dk = SymTab.KindField))
|
|
|
|
|
- 1937 AND (dt # SymTab.InvalidType)
|
|
|
|
|
- 1938 AND (et # SymTab.InvalidType)
|
|
|
|
|
- 1939 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
- 1940 SymTab.ClClass) THEN
|
|
|
|
|
- 1941 END; .)
|
|
|
|
|
- 1942 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
|
|
- 1943 (. astRes := AstCallNode(astLhs);
|
|
|
|
|
- 1944 sfx := FALSE; .)
|
|
|
|
|
- 1945 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
|
|
- 1946 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
|
|
- 1947 AST.NkAssign, 0, astRes, astCur);
|
|
|
|
|
- 1948 IF NOT sfx THEN
|
|
|
|
|
- 1949 SemError(233)
|
|
|
|
|
- 1950 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
|
|
- 1951 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
|
|
- 1952 SemError(210)
|
|
|
|
|
- 1953 END; .)
|
|
|
|
|
- 1954 | (. IF ct2 #
|
|
|
|
|
- 1955 SymTab.InvalidType THEN
|
|
|
|
|
- 1956 SemError(233) END;
|
|
|
|
|
- 1957 astStmt := astRes; .) )
|
|
|
|
|
- 1958 | (* bare `P;`: proper parameterless
|
|
|
|
|
- 1959 procedure call; anything else
|
|
|
|
|
- 1960 here is 233 (was a bare syntax
|
|
|
|
|
- 1961 error before 4.2) *)
|
|
|
|
|
- 1962 (. astStmt := AstCallNode(astLhs);
|
|
|
|
|
- 1963 IF (dk = SymTab.KindProc)
|
|
|
|
|
- 1964 AND NOT sfx THEN
|
|
|
|
|
- 1965 res0 := SymTab.ProcRes(qn);
|
|
|
|
|
- 1966 IF res0 #
|
|
|
|
|
- 1967 SymTab.InvalidType THEN
|
|
|
|
|
- 1968 SemError(233)
|
|
|
|
|
- 1969 ELSIF SymTab.ProcNPar(qn) #
|
|
|
|
|
- 1970 0 THEN
|
|
|
|
|
- 1971 SemError(233)
|
|
|
|
|
- 1972 END
|
|
|
|
|
- 1973 ELSE SemError(233)
|
|
|
|
|
- 1974 END; .) ) ) .
|
|
|
|
|
- 1975 (* Actual-parameter list shared by statement and expression calls.
|
|
|
|
|
- 1976 want selects CallEnd's result handling; t/q carry the call
|
|
|
|
|
- 1977 value (statement calls discard). Arity/type failures are 233;
|
|
|
|
|
- 1978 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
|
|
- 1979 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
|
|
- 1980 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
|
|
- 1981 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
- 1982 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
|
|
- 1983 vs: INTEGER;
|
|
|
|
|
- 1984 res: SymTab.TypeIndex;
|
|
|
|
|
- 1985 mg: QbeGen.QVal;
|
|
|
|
|
- 1986 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
|
|
- 1987 = "(" (. called := TRUE;
|
|
|
|
|
- 1988 ok := TRUE;
|
|
|
|
|
- 1989 ind := FALSE;
|
|
|
|
|
- 1990 isMeth := methCls #
|
|
|
|
|
- 1991 SymTab.InvalidType;
|
|
|
|
|
- 1992 IF isMeth THEN
|
|
|
|
|
- 1993 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
|
|
- 1994 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
|
|
- 1995 res := SymTab.ProcRes(pn)
|
|
|
|
|
- 1996 ELSIF (pt # SymTab.InvalidType)
|
|
|
|
|
- 1997 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
|
|
- 1998 ind := TRUE;
|
|
|
|
|
- 1999 res := SymTab.ProcTypeRes(pt)
|
|
|
|
|
- 2000 ELSE SemError(233);
|
|
|
|
|
- 2001 ok := FALSE;
|
|
|
|
|
- 2002 res := SymTab.InvalidType
|
|
|
|
|
- 2003 END;
|
|
|
|
|
- 2004 i := 0; .)
|
|
|
|
|
- 2005 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
|
|
- 2006 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
|
|
- 2007 ")" (. IF ok THEN
|
|
|
|
|
- 2008 IF isMeth THEN
|
|
|
|
|
- 2009 np := SymTab.ClassMethodNPar(
|
|
|
|
|
- 2010 methCls, pn)
|
|
|
|
|
- 2011 ELSIF ind THEN
|
|
|
|
|
- 2012 np := SymTab.ProcTypeNPar(pt)
|
|
|
|
|
- 2013 ELSE np := SymTab.ProcNPar(pn)
|
|
|
|
|
- 2014 END;
|
|
|
|
|
- 2015 va := (NOT isMeth) AND (NOT ind)
|
|
|
|
|
- 2016 AND (SymTab.SymKind(pn) =
|
|
|
|
|
- 2017 SymTab.KindProc)
|
|
|
|
|
- 2018 AND SymTab.Varargs(pn);
|
|
|
|
|
- 2019 IF (i # np) AND NOT va THEN
|
|
|
|
|
- 2020 SemError(233); ok := FALSE
|
|
|
|
|
- 2021 END
|
|
|
|
|
- 2022 END;
|
|
|
|
|
- 2023 IF NOT ok THEN
|
|
|
|
|
- 2024 t := SymTab.InvalidType;
|
|
|
|
|
- 2025 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2026 ELSIF want THEN
|
|
|
|
|
- 2027 IF res =
|
|
|
|
|
- 2028 SymTab.InvalidType THEN
|
|
|
|
|
- 2029 IF NOT soft THEN SemError(233) END;
|
|
|
|
|
- 2030 t := SymTab.InvalidType;
|
|
|
|
|
- 2031 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2032 ELSE t := res;
|
|
|
|
|
- 2033 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2034 END
|
|
|
|
|
- 2035 ELSE
|
|
|
|
|
- 2036 IF res #
|
|
|
|
|
- 2037 SymTab.InvalidType THEN
|
|
|
|
|
- 2038 SemError(233)
|
|
|
|
|
- 2039 END;
|
|
|
|
|
- 2040 t := SymTab.InvalidType;
|
|
|
|
|
- 2041 QbeGen.CopyOp("0", q);
|
|
|
|
|
- 2042 END; .) .
|
|
|
|
|
- 2043 (* One actual: VAR formals take recorded designator addresses
|
|
|
|
|
- 2044 (233 otherwise); value formals take converted expressions. *)
|
|
|
|
|
- 2045 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
|
|
- 2046 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
|
|
- 2047 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
|
|
- 2048 qe, qa, qt: QbeGen.QVal;
|
|
|
|
|
- 2049 isV, conv, va: BOOLEAN;
|
|
|
|
|
- 2050 cl: CHAR;
|
|
|
|
|
- 2051 savedN, aj: CARDINAL;
|
|
|
|
|
- 2052 savedArgs: ARRAY [0 .. 31]
|
|
|
|
|
- 2053 OF AST.Node;
|
|
|
|
|
- 2054 astActual: AST.Node; .)
|
|
|
|
|
- 2055 = (. (* Parsing the actual can clobber
|
|
|
|
|
- 2056 the enclosing call's argument
|
|
|
|
|
- 2057 list (Factor resets astNArgs),
|
|
|
|
|
- 2058 so save/restore it. *)
|
|
|
|
|
- 2059 savedN := astNArgs; aj := 0;
|
|
|
|
|
- 2060 WHILE aj <= HIGH(astArgs) DO
|
|
|
|
|
- 2061 savedArgs[aj] := astArgs[aj];
|
|
|
|
|
- 2062 INC(aj)
|
|
|
|
|
- 2063 END; .)
|
|
|
|
|
- 2064 Expr<at, qe> (. astActual := astCur;
|
|
|
|
|
- 2065 astNArgs := savedN; aj := 0;
|
|
|
|
|
- 2066 WHILE aj <= HIGH(astArgs) DO
|
|
|
|
|
- 2067 astArgs[aj] := savedArgs[aj];
|
|
|
|
|
- 2068 INC(aj)
|
|
|
|
|
- 2069 END;
|
|
|
|
|
- 2070 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
|
|
- 2071 astArgs[astNArgs] := astCur;
|
|
|
|
|
- 2072 INC(astNArgs)
|
|
|
|
|
- 2073 END;
|
|
|
|
|
- 2074 va := (NOT ind)
|
|
|
|
|
- 2075 AND (methCls =
|
|
|
|
|
- 2076 SymTab.InvalidType)
|
|
|
|
|
- 2077 AND (SymTab.SymKind(pn) =
|
|
|
|
|
- 2078 SymTab.KindProc)
|
|
|
|
|
- 2079 AND SymTab.Varargs(pn);
|
|
|
|
|
- 2080 IF ind THEN
|
|
|
|
|
|
|
+ 1665 QbeGen.EndFunc(
|
|
|
|
|
+ 1666 SymTab.ProcRes(pn))
|
|
|
|
|
+ 1667 END; .) ) .
|
|
|
|
|
+ 1668 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; dfr: BOOLEAN; .)
|
|
|
|
|
+ 1669 = (. dfr := FALSE;
|
|
|
|
|
+ 1670 IF allowDefer AND twoPhaseParse
|
|
|
|
|
+ 1671 AND NOT repassing THEN
|
|
|
|
|
+ 1672 dfr := DeferSkip(pn)
|
|
|
|
|
+ 1673 END;
|
|
|
|
|
+ 1674 allowDefer := FALSE;
|
|
|
|
|
+ 1675 .)
|
|
|
|
|
+ 1676 DeclSeq (. astBlkDecls := astDecl;
|
|
|
|
|
+ 1677 astStmt := AST.NoNode;
|
|
|
|
|
+ 1678 nLab := 0; nGot := 0; .)
|
|
|
|
|
+ 1679 [ "BEGIN" (. (* an empty body is still a
|
|
|
|
|
+ 1680 body: mark it so Lower
|
|
|
|
|
+ 1681 does not read it as a
|
|
|
|
|
+ 1682 definition heading *)
|
|
|
|
|
+ 1683 IF NOT dfr THEN
|
|
|
|
|
+ 1684 IF astStmt = AST.NoNode THEN
|
|
|
|
|
+ 1685 astStmt :=
|
|
|
|
|
+ 1686 AST.MakeNode(AST.NkBlock)
|
|
|
|
|
+ 1687 END
|
|
|
|
|
+ 1688 END; .)
|
|
|
|
|
+ 1689 [ StatSeq ] ]
|
|
|
|
|
+ 1690 "END"
|
|
|
|
|
+ 1691 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
|
|
+ 1692 SemError(202) END;
|
|
|
|
|
+ 1693 CheckGotos; .) .
|
|
|
|
|
+ 1694 (* Two-phase, phase 2 (milestone 2c): re-parse every deferred module-
|
|
|
|
|
+ 1695 level body once the unit's declarations are complete. Inlined at
|
|
|
|
|
+ 1696 both call sites because a stand-alone epsilon production is
|
|
|
|
|
+ 1697 "unreachable" to Coco/R (referenced only from actions). *)
|
|
|
|
|
+ 1698 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
|
|
+ 1699 = (. astSeq := AST.NoNode;
|
|
|
|
|
+ 1700 astTail := AST.NoNode; .)
|
|
|
|
|
+ 1701 Statement (. AstAppend(AST.NkBlock,
|
|
|
|
|
+ 1702 astSeq, astTail, astStmt); .)
|
|
|
|
|
+ 1703 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
|
|
+ 1704 astSeq, astTail, astStmt); .) ] }
|
|
|
|
|
+ 1705 (. astStmt := astSeq; .) .
|
|
|
|
|
+ 1706 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
|
|
+ 1707 are accepted: the statement after ';' is optional. *)
|
|
|
|
|
+ 1708 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
|
|
+ 1709 = (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 1710 ( AssOrCall
|
|
|
|
|
+ 1711 | IfStat
|
|
|
|
|
+ 1712 | WhileStat
|
|
|
|
|
+ 1713 | RepeatStat
|
|
|
|
|
+ 1714 | LoopStat
|
|
|
|
|
+ 1715 | ForStat
|
|
|
|
|
+ 1716 | CaseStat
|
|
|
|
|
+ 1717 | WithStat
|
|
|
|
|
+ 1718 | ReturnStat
|
|
|
|
|
+ 1719 | HaltStat
|
|
|
|
|
+ 1720 | NewStat
|
|
|
|
|
+ 1721 | DisposeStat
|
|
|
|
|
+ 1722 | IncDecStat
|
|
|
|
|
+ 1723 | InclExclStat
|
|
|
|
|
+ 1724 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
|
|
+ 1725 SemError(230) END;
|
|
|
|
|
+ 1726 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
|
|
+ 1727 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
|
|
+ 1728 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
|
|
+ 1729 AST.SetChild(astStmt, 0,
|
|
|
|
|
+ 1730 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
|
|
+ 1731 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
|
|
+ 1732 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 1733 dk: INTEGER;
|
|
|
|
|
+ 1734 qd, qe: QbeGen.QVal;
|
|
|
|
|
+ 1735 qn: SymTab.Name;
|
|
|
|
|
+ 1736 sfx, isInc: BOOLEAN;
|
|
|
|
|
+ 1737 astNode, astD: AST.Node; .)
|
|
|
|
|
+ 1738 = ( "INCL" (. isInc := TRUE; .)
|
|
|
|
|
+ 1739 | "EXCL" (. isInc := FALSE; .) )
|
|
|
|
|
+ 1740 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
|
|
+ 1741 Expr<et2, qe> ")"
|
|
|
|
|
+ 1742 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 1743 IF isInc THEN
|
|
|
|
|
+ 1744 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1745 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
|
|
+ 1746 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1747 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
|
|
+ 1748 END;
|
|
|
|
|
+ 1749 IF astD # AST.NoNode THEN
|
|
|
|
|
+ 1750 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
+ 1751 IF astCur # AST.NoNode THEN
|
|
|
|
|
+ 1752 AST.SetChild(astNode, 2, astCur) END;
|
|
|
|
|
+ 1753 astStmt := astNode; .)
|
|
|
|
|
+ 1754 (. IF (at # SymTab.InvalidType)
|
|
|
|
|
+ 1755 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
|
|
+ 1756 SemError(222)
|
|
|
|
|
+ 1757 END; .) .
|
|
|
|
|
+ 1758 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
|
|
+ 1759 integer designator. *)
|
|
|
|
|
+ 1760 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 1761 dk: INTEGER;
|
|
|
|
|
+ 1762 qd, qv, qn2, qstep:
|
|
|
|
|
+ 1763 QbeGen.QVal;
|
|
|
|
|
+ 1764 qn: SymTab.Name;
|
|
|
|
|
+ 1765 sfx, isInc: BOOLEAN;
|
|
|
|
|
+ 1766 astNode, astD, astStep:
|
|
|
|
|
+ 1767 AST.Node; .)
|
|
|
|
|
+ 1768 = (. isInc := TRUE; .)
|
|
|
|
|
+ 1769 ( "INC" (. isInc := TRUE; .)
|
|
|
|
|
+ 1770 | "DEC" (. isInc := FALSE; .) )
|
|
|
|
|
+ 1771 "(" (. astStep := AST.NoNode; .)
|
|
|
|
|
+ 1772 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
|
|
+ 1773 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
|
|
+ 1774 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 1775 IF isInc THEN
|
|
|
|
|
+ 1776 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1777 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
|
|
+ 1778 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1779 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
|
|
+ 1780 END;
|
|
|
|
|
+ 1781 IF astD # AST.NoNode THEN
|
|
|
|
|
+ 1782 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
+ 1783 IF astStep # AST.NoNode THEN
|
|
|
|
|
+ 1784 AST.SetChild(astNode, 2, astStep) END;
|
|
|
|
|
+ 1785 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1786 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
+ 1787 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1788 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1789 SemError(210)
|
|
|
|
|
+ 1790 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
|
|
+ 1791 SemError(211)
|
|
|
|
|
+ 1792 END; .) .
|
|
|
|
|
+ 1793 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
|
|
+ 1794 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
|
|
+ 1795 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
|
|
+ 1796 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
+ 1797 dk: INTEGER;
|
|
|
|
|
+ 1798 qd, qm: QbeGen.QVal;
|
|
|
|
|
+ 1799 qn: SymTab.Name;
|
|
|
|
|
+ 1800 sfx: BOOLEAN;
|
|
|
|
|
+ 1801 bt: SymTab.TypeIndex;
|
|
|
|
|
+ 1802 astNode, astD: AST.Node; .)
|
|
|
|
|
+ 1803 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
|
|
+ 1804 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 1805 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1806 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
|
|
+ 1807 IF astD # AST.NoNode THEN
|
|
|
|
|
+ 1808 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
+ 1809 astStmt := astNode; .)
|
|
|
|
|
+ 1810 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1811 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
+ 1812 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1813 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1814 SemError(210)
|
|
|
|
|
+ 1815 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1816 SymTab.ClPtr THEN
|
|
|
|
|
+ 1817 SemError(219)
|
|
|
|
|
+ 1818 END; .) .
|
|
|
|
|
+ 1819 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
+ 1820 dk: INTEGER;
|
|
|
|
|
+ 1821 qd, qv: QbeGen.QVal;
|
|
|
|
|
+ 1822 qn: SymTab.Name;
|
|
|
|
|
+ 1823 sfx: BOOLEAN;
|
|
|
|
|
+ 1824 astNode, astD: AST.Node; .)
|
|
|
|
|
+ 1825 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
|
|
+ 1826 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 1827 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1828 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
|
|
+ 1829 IF astD # AST.NoNode THEN
|
|
|
|
|
+ 1830 AST.SetChild(astNode, 1, astD) END;
|
|
|
|
|
+ 1831 astStmt := astNode; .)
|
|
|
|
|
+ 1832 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1833 ELSIF (dk # SymTab.KindVar)
|
|
|
|
|
+ 1834 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1835 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1836 SemError(210)
|
|
|
|
|
+ 1837 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1838 SymTab.ClPtr THEN
|
|
|
|
|
+ 1839 SemError(219)
|
|
|
|
|
+ 1840 END; .) .
|
|
|
|
|
+ 1841 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
|
|
+ 1842 address; field designators resolve through both stacks. *)
|
|
|
|
|
+ 1843 WithStat (. VAR nW: CARDINAL;
|
|
|
|
|
+ 1844 astNode: AST.Node; .)
|
|
|
|
|
+ 1845 = "WITH" (. nW := 0;
|
|
|
|
|
+ 1846 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
|
|
+ 1847 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
|
|
+ 1848 "DO" (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 1849 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
|
|
+ 1850 AST.NChild(astNode), astStmt);
|
|
|
|
|
+ 1851 astStmt := astNode;
|
|
|
|
|
+ 1852 WHILE nW > 0 DO
|
|
|
|
|
+ 1853 SymTab.PopScope;
|
|
|
|
|
+ 1854 QbeGen.PopWith;
|
|
|
|
|
+ 1855 DEC(nW)
|
|
|
|
|
+ 1856 END; .) .
|
|
|
|
|
+ 1857 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
|
|
+ 1858 (. VAR dt: SymTab.TypeIndex;
|
|
|
|
|
+ 1859 dk: INTEGER;
|
|
|
|
|
+ 1860 qd, qe: QbeGen.QVal;
|
|
|
|
|
+ 1861 qn: SymTab.Name;
|
|
|
|
|
+ 1862 sfx: BOOLEAN; .)
|
|
|
|
|
+ 1863 = Design<dt, dk, qd, qn, sfx>
|
|
|
|
|
+ 1864 (. IF astCur # AST.NoNode THEN
|
|
|
|
|
+ 1865 AST.SetChild(wnode,
|
|
|
|
|
+ 1866 AST.NChild(wnode), astCur) END;
|
|
|
|
|
+ 1867 IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 1868 ELSIF (SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1869 SymTab.ClRecord)
|
|
|
|
|
+ 1870 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1871 SymTab.ClClass) THEN
|
|
|
|
|
+ 1872 SemError(215)
|
|
|
|
|
+ 1873 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
|
|
+ 1874 QbeGen.PushWith(qd);
|
|
|
|
|
+ 1875 INC(nW)
|
|
|
|
|
+ 1876 END; .) .
|
|
|
|
|
+ 1877 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
|
|
+ 1878 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
|
|
+ 1879 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
|
|
+ 1880 dk: INTEGER;
|
|
|
|
|
+ 1881 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
|
|
+ 1882 qn: SymTab.Name;
|
|
|
|
|
+ 1883 ct2, res0: SymTab.TypeIndex;
|
|
|
|
|
+ 1884 q2, mg0: QbeGen.QVal;
|
|
|
|
|
+ 1885 isR, conv, wconv: BOOLEAN;
|
|
|
|
|
+ 1886 called, sfx: BOOLEAN;
|
|
|
|
|
+ 1887 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
|
|
+ 1888 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
|
|
+ 1889 = GetIdent<n>
|
|
|
|
|
+ 1890 ( ":" (. NoteLabel(n);
|
|
|
|
|
+ 1891 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
|
|
+ 1892 AST.SetChild(astNode, 0,
|
|
|
|
|
+ 1893 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
|
|
+ 1894 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
|
|
+ 1895 AST.SetChild(astLab, 0, astNode); .)
|
|
|
|
|
+ 1896 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
|
|
+ 1897 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
|
|
+ 1898 astStmt := astLab; .)
|
|
|
|
|
+ 1899 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
|
|
+ 1900 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
|
|
+ 1901 ( ":="
|
|
|
|
|
+ 1902 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
|
|
+ 1903 AST.NkAssign, 0, astLhs, astCur);
|
|
|
|
|
+ 1904 IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 1905 AND (dk # SymTab.KindVar)
|
|
|
|
|
+ 1906 AND (dk # SymTab.KindParam)
|
|
|
|
|
+ 1907 AND (dk # SymTab.KindField) THEN
|
|
|
|
|
+ 1908 SemError(210)
|
|
|
|
|
+ 1909 ELSIF NOT SymTab.Assignable(et,
|
|
|
|
|
+ 1910 dt) THEN
|
|
|
|
|
+ 1911 SemError(210)
|
|
|
|
|
+ 1912 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 1913 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 1914 SymTab.ClClass) THEN
|
|
|
|
|
+ 1915 SemError(230) END;
|
|
|
|
|
+ 1916 isR := (dt #
|
|
|
|
|
+ 1917 SymTab.InvalidType)
|
|
|
|
|
+ 1918 AND (SymTab.ClassOf(dt)
|
|
|
|
|
+ 1919 = SymTab.ClReal);
|
|
|
|
|
+ 1920 conv := isR
|
|
|
|
|
+ 1921 AND SymTab.IsIntFamily(et);
|
|
|
|
|
+ 1922 wconv := (dt #
|
|
|
|
|
+ 1923 SymTab.InvalidType)
|
|
|
|
|
+ 1924 AND SymTab.IsLongFamily(dt)
|
|
|
|
|
+ 1925 AND SymTab.IsIntFamily(et);
|
|
|
|
|
+ 1926 IF ((dk = SymTab.KindVar)
|
|
|
|
|
+ 1927 OR (dk = SymTab.KindParam)
|
|
|
|
|
+ 1928 OR (dk = SymTab.KindField))
|
|
|
|
|
+ 1929 AND (dt # SymTab.InvalidType)
|
|
|
|
|
+ 1930 AND (et # SymTab.InvalidType)
|
|
|
|
|
+ 1931 AND (SymTab.ClassOf(dt) #
|
|
|
|
|
+ 1932 SymTab.ClClass) THEN
|
|
|
|
|
+ 1933 END; .)
|
|
|
|
|
+ 1934 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
|
|
+ 1935 (. astRes := AstCallNode(astLhs);
|
|
|
|
|
+ 1936 sfx := FALSE; .)
|
|
|
|
|
+ 1937 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
|
|
+ 1938 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
|
|
+ 1939 AST.NkAssign, 0, astRes, astCur);
|
|
|
|
|
+ 1940 IF NOT sfx THEN
|
|
|
|
|
+ 1941 SemError(233)
|
|
|
|
|
+ 1942 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
|
|
+ 1943 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
|
|
+ 1944 SemError(210)
|
|
|
|
|
+ 1945 END; .)
|
|
|
|
|
+ 1946 | (. IF ct2 #
|
|
|
|
|
+ 1947 SymTab.InvalidType THEN
|
|
|
|
|
+ 1948 SemError(233) END;
|
|
|
|
|
+ 1949 astStmt := astRes; .) )
|
|
|
|
|
+ 1950 | (* bare `P;`: proper parameterless
|
|
|
|
|
+ 1951 procedure call; anything else
|
|
|
|
|
+ 1952 here is 233 (was a bare syntax
|
|
|
|
|
+ 1953 error before 4.2) *)
|
|
|
|
|
+ 1954 (. astStmt := AstCallNode(astLhs);
|
|
|
|
|
+ 1955 IF (dk = SymTab.KindProc)
|
|
|
|
|
+ 1956 AND NOT sfx THEN
|
|
|
|
|
+ 1957 res0 := SymTab.ProcRes(qn);
|
|
|
|
|
+ 1958 IF res0 #
|
|
|
|
|
+ 1959 SymTab.InvalidType THEN
|
|
|
|
|
+ 1960 SemError(233)
|
|
|
|
|
+ 1961 ELSIF SymTab.ProcNPar(qn) #
|
|
|
|
|
+ 1962 0 THEN
|
|
|
|
|
+ 1963 SemError(233)
|
|
|
|
|
+ 1964 END
|
|
|
|
|
+ 1965 ELSE SemError(233)
|
|
|
|
|
+ 1966 END; .) ) ) .
|
|
|
|
|
+ 1967 (* Actual-parameter list shared by statement and expression calls.
|
|
|
|
|
+ 1968 want selects CallEnd's result handling; t/q carry the call
|
|
|
|
|
+ 1969 value (statement calls discard). Arity/type failures are 233;
|
|
|
|
|
+ 1970 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
|
|
+ 1971 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
|
|
+ 1972 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
|
|
+ 1973 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
+ 1974 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
|
|
+ 1975 vs: INTEGER;
|
|
|
|
|
+ 1976 res: SymTab.TypeIndex;
|
|
|
|
|
+ 1977 mg: QbeGen.QVal;
|
|
|
|
|
+ 1978 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
|
|
+ 1979 = "(" (. called := TRUE;
|
|
|
|
|
+ 1980 ok := TRUE;
|
|
|
|
|
+ 1981 ind := FALSE;
|
|
|
|
|
+ 1982 isMeth := methCls #
|
|
|
|
|
+ 1983 SymTab.InvalidType;
|
|
|
|
|
+ 1984 IF isMeth THEN
|
|
|
|
|
+ 1985 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
|
|
+ 1986 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
|
|
+ 1987 res := SymTab.ProcRes(pn)
|
|
|
|
|
+ 1988 ELSIF (pt # SymTab.InvalidType)
|
|
|
|
|
+ 1989 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
|
|
+ 1990 ind := TRUE;
|
|
|
|
|
+ 1991 res := SymTab.ProcTypeRes(pt)
|
|
|
|
|
+ 1992 ELSE SemError(233);
|
|
|
|
|
+ 1993 ok := FALSE;
|
|
|
|
|
+ 1994 res := SymTab.InvalidType
|
|
|
|
|
+ 1995 END;
|
|
|
|
|
+ 1996 i := 0; .)
|
|
|
|
|
+ 1997 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
|
|
+ 1998 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
|
|
+ 1999 ")" (. IF ok THEN
|
|
|
|
|
+ 2000 IF isMeth THEN
|
|
|
|
|
+ 2001 np := SymTab.ClassMethodNPar(
|
|
|
|
|
+ 2002 methCls, pn)
|
|
|
|
|
+ 2003 ELSIF ind THEN
|
|
|
|
|
+ 2004 np := SymTab.ProcTypeNPar(pt)
|
|
|
|
|
+ 2005 ELSE np := SymTab.ProcNPar(pn)
|
|
|
|
|
+ 2006 END;
|
|
|
|
|
+ 2007 va := (NOT isMeth) AND (NOT ind)
|
|
|
|
|
+ 2008 AND (SymTab.SymKind(pn) =
|
|
|
|
|
+ 2009 SymTab.KindProc)
|
|
|
|
|
+ 2010 AND SymTab.Varargs(pn);
|
|
|
|
|
+ 2011 IF (i # np) AND NOT va THEN
|
|
|
|
|
+ 2012 SemError(233); ok := FALSE
|
|
|
|
|
+ 2013 END
|
|
|
|
|
+ 2014 END;
|
|
|
|
|
+ 2015 IF NOT ok THEN
|
|
|
|
|
+ 2016 t := SymTab.InvalidType;
|
|
|
|
|
+ 2017 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2018 ELSIF want THEN
|
|
|
|
|
+ 2019 IF res =
|
|
|
|
|
+ 2020 SymTab.InvalidType THEN
|
|
|
|
|
+ 2021 IF NOT soft THEN SemError(233) END;
|
|
|
|
|
+ 2022 t := SymTab.InvalidType;
|
|
|
|
|
+ 2023 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2024 ELSE t := res;
|
|
|
|
|
+ 2025 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2026 END
|
|
|
|
|
+ 2027 ELSE
|
|
|
|
|
+ 2028 IF res #
|
|
|
|
|
+ 2029 SymTab.InvalidType THEN
|
|
|
|
|
+ 2030 SemError(233)
|
|
|
|
|
+ 2031 END;
|
|
|
|
|
+ 2032 t := SymTab.InvalidType;
|
|
|
|
|
+ 2033 QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 2034 END; .) .
|
|
|
|
|
+ 2035 (* One actual: VAR formals take recorded designator addresses
|
|
|
|
|
+ 2036 (233 otherwise); value formals take converted expressions. *)
|
|
|
|
|
+ 2037 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
|
|
+ 2038 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
|
|
+ 2039 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
|
|
+ 2040 qe, qa, qt: QbeGen.QVal;
|
|
|
|
|
+ 2041 isV, conv, va: BOOLEAN;
|
|
|
|
|
+ 2042 cl: CHAR;
|
|
|
|
|
+ 2043 savedN, aj: CARDINAL;
|
|
|
|
|
+ 2044 savedArgs: ARRAY [0 .. 31]
|
|
|
|
|
+ 2045 OF AST.Node;
|
|
|
|
|
+ 2046 astActual: AST.Node; .)
|
|
|
|
|
+ 2047 = (. (* Parsing the actual can clobber
|
|
|
|
|
+ 2048 the enclosing call's argument
|
|
|
|
|
+ 2049 list (Factor resets astNArgs),
|
|
|
|
|
+ 2050 so save/restore it. *)
|
|
|
|
|
+ 2051 savedN := astNArgs; aj := 0;
|
|
|
|
|
+ 2052 WHILE aj <= HIGH(astArgs) DO
|
|
|
|
|
+ 2053 savedArgs[aj] := astArgs[aj];
|
|
|
|
|
+ 2054 INC(aj)
|
|
|
|
|
+ 2055 END; .)
|
|
|
|
|
+ 2056 Expr<at, qe> (. astActual := astCur;
|
|
|
|
|
+ 2057 astNArgs := savedN; aj := 0;
|
|
|
|
|
+ 2058 WHILE aj <= HIGH(astArgs) DO
|
|
|
|
|
+ 2059 astArgs[aj] := savedArgs[aj];
|
|
|
|
|
+ 2060 INC(aj)
|
|
|
|
|
+ 2061 END;
|
|
|
|
|
+ 2062 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
|
|
+ 2063 astArgs[astNArgs] := astCur;
|
|
|
|
|
+ 2064 INC(astNArgs)
|
|
|
|
|
+ 2065 END;
|
|
|
|
|
+ 2066 va := (NOT ind)
|
|
|
|
|
+ 2067 AND (methCls =
|
|
|
|
|
+ 2068 SymTab.InvalidType)
|
|
|
|
|
+ 2069 AND (SymTab.SymKind(pn) =
|
|
|
|
|
+ 2070 SymTab.KindProc)
|
|
|
|
|
+ 2071 AND SymTab.Varargs(pn);
|
|
|
|
|
+ 2072 IF ind THEN
|
|
|
|
|
+ 2073 ft :=
|
|
|
|
|
+ 2074 SymTab.ProcTypeParamType(pt,
|
|
|
|
|
+ 2075 i);
|
|
|
|
|
+ 2076 isV :=
|
|
|
|
|
+ 2077 SymTab.ProcTypeParamIsVar(pt,
|
|
|
|
|
+ 2078 i)
|
|
|
|
|
+ 2079 ELSIF methCls #
|
|
|
|
|
+ 2080 SymTab.InvalidType THEN
|
|
|
2081 ft :=
|
|
2081 ft :=
|
|
|
- 2082 SymTab.ProcTypeParamType(pt,
|
|
|
|
|
- 2083 i);
|
|
|
|
|
|
|
+ 2082 SymTab.ClassMethodParamType(
|
|
|
|
|
+ 2083 methCls, pn, i);
|
|
|
2084 isV :=
|
|
2084 isV :=
|
|
|
- 2085 SymTab.ProcTypeParamIsVar(pt,
|
|
|
|
|
- 2086 i)
|
|
|
|
|
- 2087 ELSIF methCls #
|
|
|
|
|
- 2088 SymTab.InvalidType THEN
|
|
|
|
|
- 2089 ft :=
|
|
|
|
|
- 2090 SymTab.ClassMethodParamType(
|
|
|
|
|
- 2091 methCls, pn, i);
|
|
|
|
|
- 2092 isV :=
|
|
|
|
|
- 2093 SymTab.ClassMethodParamIsVar(
|
|
|
|
|
- 2094 methCls, pn, i)
|
|
|
|
|
- 2095 ELSE
|
|
|
|
|
- 2096 ft := SymTab.ParamType(pn, i);
|
|
|
|
|
- 2097 isV := SymTab.ParamIsVar(pn, i)
|
|
|
|
|
- 2098 END;
|
|
|
|
|
- 2099 IF (at = SymTab.InvalidType) THEN
|
|
|
|
|
- 2100 ELSIF ft = SymTab.InvalidType THEN
|
|
|
|
|
- 2101 ELSIF isV THEN
|
|
|
|
|
- 2102 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
|
|
- 2103 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
- 2104 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
|
|
- 2105 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
- 2106 ELSIF (AST.Kind(astActual) #
|
|
|
|
|
- 2107 AST.NkDesignator)
|
|
|
|
|
- 2108 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
|
|
- 2109 SemError(233)
|
|
|
|
|
- 2110 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
|
|
|
|
+ 2085 SymTab.ClassMethodParamIsVar(
|
|
|
|
|
+ 2086 methCls, pn, i)
|
|
|
|
|
+ 2087 ELSE
|
|
|
|
|
+ 2088 ft := SymTab.ParamType(pn, i);
|
|
|
|
|
+ 2089 isV := SymTab.ParamIsVar(pn, i)
|
|
|
|
|
+ 2090 END;
|
|
|
|
|
+ 2091 IF (at = SymTab.InvalidType) THEN
|
|
|
|
|
+ 2092 ELSIF ft = SymTab.InvalidType THEN
|
|
|
|
|
+ 2093 ELSIF isV THEN
|
|
|
|
|
+ 2094 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
|
|
+ 2095 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
+ 2096 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
|
|
+ 2097 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
+ 2098 ELSIF (AST.Kind(astActual) #
|
|
|
|
|
+ 2099 AST.NkDesignator)
|
|
|
|
|
+ 2100 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
|
|
+ 2101 SemError(233)
|
|
|
|
|
+ 2102 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
|
|
+ 2103 SemError(233)
|
|
|
|
|
+ 2104 END
|
|
|
|
|
+ 2105 ELSE
|
|
|
|
|
+ 2106 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
|
|
+ 2107 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
+ 2108 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
|
|
+ 2109 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
+ 2110 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
2111 SemError(233)
|
|
2111 SemError(233)
|
|
|
2112 END
|
|
2112 END
|
|
|
- 2113 ELSE
|
|
|
|
|
- 2114 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
|
|
- 2115 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
|
|
- 2116 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
|
|
- 2117 AND QbeGen.IsImm(qe) THEN
|
|
|
|
|
- 2118 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
|
|
- 2119 SemError(233)
|
|
|
|
|
- 2120 END
|
|
|
|
|
- 2121 END; .) .
|
|
|
|
|
- 2122 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 2123 q: QbeGen.QVal;
|
|
|
|
|
- 2124 hasElse: BOOLEAN;
|
|
|
|
|
- 2125 astCond, astIf, astLast,
|
|
|
|
|
- 2126 astNode: AST.Node; .)
|
|
|
|
|
- 2127 = "IF" (. hasElse := FALSE; .)
|
|
|
|
|
- 2128 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
|
|
- 2129 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 2130 SemError(214) END; .)
|
|
|
|
|
- 2131 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
|
|
- 2132 AST.SetChild(astNode, 0, astCond);
|
|
|
|
|
- 2133 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
- 2134 astIf := astNode;
|
|
|
|
|
- 2135 astLast := astNode; .)
|
|
|
|
|
- 2136 { "ELSIF"
|
|
|
|
|
- 2137 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
|
|
- 2138 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 2139 SemError(214) END; .)
|
|
|
|
|
- 2140 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
|
|
- 2141 AST.SetChild(astNode, 0, astCond);
|
|
|
|
|
- 2142 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
- 2143 AST.SetChild(astLast, 2, astNode);
|
|
|
|
|
- 2144 astLast := astNode; .) }
|
|
|
|
|
- 2145 [ "ELSE" (. hasElse := TRUE;
|
|
|
|
|
- 2146 astStmt := AST.NoNode; .)
|
|
|
|
|
- 2147 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
|
|
- 2148 "END" (. astStmt := astIf; .) .
|
|
|
|
|
- 2149 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 2150 q: QbeGen.QVal;
|
|
|
|
|
- 2151 astCond, astNode: AST.Node; .)
|
|
|
|
|
- 2152 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 2153 Expr<t, q> (. astCond := astCur;
|
|
|
|
|
- 2154 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 2155 SemError(214) END; .)
|
|
|
|
|
- 2156 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
|
|
- 2157 AST.SetChild(astNode, 0, astCond);
|
|
|
|
|
- 2158 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
- 2159 astStmt := astNode; .)
|
|
|
|
|
- 2160 "END" .
|
|
|
|
|
- 2161 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 2162 q: QbeGen.QVal;
|
|
|
|
|
- 2163 astCond, astBody, astNode:
|
|
|
|
|
- 2164 AST.Node; .)
|
|
|
|
|
- 2165 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 2166 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
|
|
- 2167 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
|
|
- 2168 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
|
|
- 2169 AST.SetChild(astNode, 0, astBody);
|
|
|
|
|
- 2170 AST.SetChild(astNode, 1, astCond);
|
|
|
|
|
- 2171 astStmt := astNode;
|
|
|
|
|
- 2172 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
- 2173 SemError(214) END; .) .
|
|
|
|
|
- 2174 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
|
|
- 2175 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
|
|
- 2176 QbeGen.NewLabel(lEnd);
|
|
|
|
|
- 2177 QbeGen.PushLoop(lEnd); .)
|
|
|
|
|
- 2178 [ StatSeq ]
|
|
|
|
|
- 2179 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
|
|
- 2180 AST.SetChild(astNode, 0, astStmt);
|
|
|
|
|
- 2181 astStmt := astNode;
|
|
|
|
|
- 2182 QbeGen.PopLoop; .) .
|
|
|
|
|
- 2183 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
|
|
- 2184 Runtime direction would need a compare-select; the literal
|
|
|
|
|
- 2185 sign picks cslew/csegew at "DO" time. *)
|
|
|
|
|
- 2186 ForStat (. VAR lv: SymTab.Name;
|
|
|
|
|
- 2187 tlo, thi, tby:
|
|
|
|
|
- 2188 SymTab.TypeIndex;
|
|
|
|
|
- 2189 qlo, qhi, qby, qt, qk, qb:
|
|
|
|
|
- 2190 QbeGen.QVal;
|
|
|
|
|
- 2191 lTop, lBody, lEnd:
|
|
|
|
|
- 2192 QbeGen.QVal;
|
|
|
|
|
- 2193 by: INTEGER;
|
|
|
|
|
- 2194 ok: BOOLEAN;
|
|
|
|
|
- 2195 astVar, astLo, astHi, astBy,
|
|
|
|
|
- 2196 astNode: AST.Node; .)
|
|
|
|
|
- 2197 = "FOR" (. by := 1; .)
|
|
|
|
|
- 2198 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
|
|
- 2199 astStmt := AST.NoNode;
|
|
|
|
|
- 2200 astBy := AST.NoNode;
|
|
|
|
|
- 2201 ok := SymTab.Lookup(lv);
|
|
|
|
|
- 2202 IF NOT ok THEN
|
|
|
|
|
- 2203 SemError(201)
|
|
|
|
|
- 2204 ELSIF (SymTab.SymKind(lv) #
|
|
|
|
|
- 2205 SymTab.KindVar)
|
|
|
|
|
- 2206 AND (SymTab.SymKind(lv) #
|
|
|
|
|
- 2207 SymTab.KindParam) THEN
|
|
|
|
|
- 2208 SemError(220); ok := FALSE
|
|
|
|
|
- 2209 ELSIF NOT SymTab.IsIntFamily(
|
|
|
|
|
- 2210 SymTab.SymType(lv)) THEN
|
|
|
|
|
|
|
+ 2113 END; .) .
|
|
|
|
|
+ 2114 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 2115 q: QbeGen.QVal;
|
|
|
|
|
+ 2116 hasElse: BOOLEAN;
|
|
|
|
|
+ 2117 astCond, astIf, astLast,
|
|
|
|
|
+ 2118 astNode: AST.Node; .)
|
|
|
|
|
+ 2119 = "IF" (. hasElse := FALSE; .)
|
|
|
|
|
+ 2120 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
|
|
+ 2121 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 2122 SemError(214) END; .)
|
|
|
|
|
+ 2123 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
|
|
+ 2124 AST.SetChild(astNode, 0, astCond);
|
|
|
|
|
+ 2125 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
+ 2126 astIf := astNode;
|
|
|
|
|
+ 2127 astLast := astNode; .)
|
|
|
|
|
+ 2128 { "ELSIF"
|
|
|
|
|
+ 2129 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
|
|
+ 2130 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 2131 SemError(214) END; .)
|
|
|
|
|
+ 2132 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
|
|
+ 2133 AST.SetChild(astNode, 0, astCond);
|
|
|
|
|
+ 2134 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
+ 2135 AST.SetChild(astLast, 2, astNode);
|
|
|
|
|
+ 2136 astLast := astNode; .) }
|
|
|
|
|
+ 2137 [ "ELSE" (. hasElse := TRUE;
|
|
|
|
|
+ 2138 astStmt := AST.NoNode; .)
|
|
|
|
|
+ 2139 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
|
|
+ 2140 "END" (. astStmt := astIf; .) .
|
|
|
|
|
+ 2141 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 2142 q: QbeGen.QVal;
|
|
|
|
|
+ 2143 astCond, astNode: AST.Node; .)
|
|
|
|
|
+ 2144 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 2145 Expr<t, q> (. astCond := astCur;
|
|
|
|
|
+ 2146 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 2147 SemError(214) END; .)
|
|
|
|
|
+ 2148 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
|
|
+ 2149 AST.SetChild(astNode, 0, astCond);
|
|
|
|
|
+ 2150 AST.SetChild(astNode, 1, astStmt);
|
|
|
|
|
+ 2151 astStmt := astNode; .)
|
|
|
|
|
+ 2152 "END" .
|
|
|
|
|
+ 2153 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 2154 q: QbeGen.QVal;
|
|
|
|
|
+ 2155 astCond, astBody, astNode:
|
|
|
|
|
+ 2156 AST.Node; .)
|
|
|
|
|
+ 2157 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 2158 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
|
|
+ 2159 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
|
|
+ 2160 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
|
|
+ 2161 AST.SetChild(astNode, 0, astBody);
|
|
|
|
|
+ 2162 AST.SetChild(astNode, 1, astCond);
|
|
|
|
|
+ 2163 astStmt := astNode;
|
|
|
|
|
+ 2164 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
|
|
+ 2165 SemError(214) END; .) .
|
|
|
|
|
+ 2166 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
|
|
+ 2167 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
|
|
+ 2168 QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ 2169 QbeGen.PushLoop(lEnd); .)
|
|
|
|
|
+ 2170 [ StatSeq ]
|
|
|
|
|
+ 2171 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
|
|
+ 2172 AST.SetChild(astNode, 0, astStmt);
|
|
|
|
|
+ 2173 astStmt := astNode;
|
|
|
|
|
+ 2174 QbeGen.PopLoop; .) .
|
|
|
|
|
+ 2175 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
|
|
+ 2176 Runtime direction would need a compare-select; the literal
|
|
|
|
|
+ 2177 sign picks cslew/csegew at "DO" time. *)
|
|
|
|
|
+ 2178 ForStat (. VAR lv: SymTab.Name;
|
|
|
|
|
+ 2179 tlo, thi, tby:
|
|
|
|
|
+ 2180 SymTab.TypeIndex;
|
|
|
|
|
+ 2181 qlo, qhi, qby, qt, qk, qb:
|
|
|
|
|
+ 2182 QbeGen.QVal;
|
|
|
|
|
+ 2183 lTop, lBody, lEnd:
|
|
|
|
|
+ 2184 QbeGen.QVal;
|
|
|
|
|
+ 2185 by: INTEGER;
|
|
|
|
|
+ 2186 ok: BOOLEAN;
|
|
|
|
|
+ 2187 astVar, astLo, astHi, astBy,
|
|
|
|
|
+ 2188 astNode: AST.Node; .)
|
|
|
|
|
+ 2189 = "FOR" (. by := 1; .)
|
|
|
|
|
+ 2190 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
|
|
+ 2191 astStmt := AST.NoNode;
|
|
|
|
|
+ 2192 astBy := AST.NoNode;
|
|
|
|
|
+ 2193 ok := SymTab.Lookup(lv);
|
|
|
|
|
+ 2194 IF NOT ok THEN
|
|
|
|
|
+ 2195 SemError(201)
|
|
|
|
|
+ 2196 ELSIF (SymTab.SymKind(lv) #
|
|
|
|
|
+ 2197 SymTab.KindVar)
|
|
|
|
|
+ 2198 AND (SymTab.SymKind(lv) #
|
|
|
|
|
+ 2199 SymTab.KindParam) THEN
|
|
|
|
|
+ 2200 SemError(220); ok := FALSE
|
|
|
|
|
+ 2201 ELSIF NOT SymTab.IsIntFamily(
|
|
|
|
|
+ 2202 SymTab.SymType(lv)) THEN
|
|
|
|
|
+ 2203 SemError(220); ok := FALSE
|
|
|
|
|
+ 2204 END; .)
|
|
|
|
|
+ 2205 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
|
|
+ 2206 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
|
|
+ 2207 SemError(220); ok := FALSE
|
|
|
|
|
+ 2208 END; .)
|
|
|
|
|
+ 2209 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
|
|
+ 2210 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
2211 SemError(220); ok := FALSE
|
|
2211 SemError(220); ok := FALSE
|
|
|
2212 END; .)
|
|
2212 END; .)
|
|
|
- 2213 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
|
|
- 2214 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
|
|
- 2215 SemError(220); ok := FALSE
|
|
|
|
|
- 2216 END; .)
|
|
|
|
|
- 2217 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
|
|
- 2218 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
|
|
- 2219 SemError(220); ok := FALSE
|
|
|
|
|
- 2220 END; .)
|
|
|
|
|
- 2221 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
|
|
- 2222 IF (tby #
|
|
|
|
|
- 2223 SymTab.InvalidType)
|
|
|
|
|
- 2224 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
|
|
- 2225 SemError(220); ok := FALSE
|
|
|
|
|
- 2226 END;
|
|
|
|
|
- 2227 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
|
|
- 2228 SemError(230); by := 1
|
|
|
|
|
- 2229 ELSIF by = 0 THEN
|
|
|
|
|
- 2230 SemError(220); by := 1
|
|
|
|
|
- 2231 END; .) ]
|
|
|
|
|
- 2232 "DO"
|
|
|
|
|
- 2233 [ StatSeq ]
|
|
|
|
|
- 2234 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
|
|
- 2235 AST.SetChild(astNode, 0, astVar);
|
|
|
|
|
- 2236 AST.SetChild(astNode, 1, astLo);
|
|
|
|
|
- 2237 AST.SetChild(astNode, 2, astHi);
|
|
|
|
|
- 2238 AST.SetChild(astNode, 3, astBy);
|
|
|
|
|
- 2239 AST.SetChild(astNode, 4, astStmt);
|
|
|
|
|
- 2240 astStmt := astNode;
|
|
|
|
|
- 2241 .) .
|
|
|
|
|
- 2242 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
|
|
- 2243 qsel, lEnd: QbeGen.QVal;
|
|
|
|
|
- 2244 arm, astNode, astArms,
|
|
|
|
|
- 2245 astArmsTail: AST.Node; .)
|
|
|
|
|
- 2246 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
|
|
- 2247 AST.SetChild(astNode, 0, astCur);
|
|
|
|
|
- 2248 astArms := AST.NoNode;
|
|
|
|
|
- 2249 astArmsTail := AST.NoNode;
|
|
|
|
|
- 2250 .)
|
|
|
|
|
- 2251 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
|
|
- 2252 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
|
|
- 2253 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 2254 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
|
|
- 2255 AST.SetOp(arm, 1);
|
|
|
|
|
- 2256 AST.SetChild(arm, 0, astStmt);
|
|
|
|
|
- 2257 AstAppend(AST.NkBlock,
|
|
|
|
|
- 2258 astArms, astArmsTail, arm); .) ]
|
|
|
|
|
- 2259 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
|
|
- 2260 astStmt := astNode;
|
|
|
|
|
- 2261 .) .
|
|
|
|
|
- 2262 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
|
|
- 2263 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
|
|
- 2264 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
|
|
- 2265 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
|
|
- 2266 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
- 2267 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
|
|
- 2268 (. VAR arm: AST.Node; .)
|
|
|
|
|
- 2269 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
|
|
- 2270 CaseLabel<tsel, qsel, arm>
|
|
|
|
|
- 2271 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
|
|
- 2272 ":" (. astStmt := AST.NoNode; .)
|
|
|
|
|
- 2273 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
|
|
- 2274 astStmt);
|
|
|
|
|
- 2275 AstAppend(AST.NkBlock,
|
|
|
|
|
- 2276 arms, armsTail, arm);
|
|
|
|
|
- 2277 .) .
|
|
|
|
|
- 2278 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
- 2279 arm: AST.Node>
|
|
|
|
|
- 2280 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
|
|
- 2281 q2, q3, qc, qd, qe:
|
|
|
|
|
- 2282 QbeGen.QVal;
|
|
|
|
|
- 2283 astLab: AST.Node;
|
|
|
|
|
- 2284 lNext: QbeGen.QVal; .)
|
|
|
|
|
- 2285 = Expr<t2, q2> (. astLab := astCur;
|
|
|
|
|
- 2286 IF (t2 #
|
|
|
|
|
- 2287 SymTab.InvalidType)
|
|
|
|
|
- 2288 AND (tsel #
|
|
|
|
|
- 2289 SymTab.InvalidType)
|
|
|
|
|
- 2290 AND ((SymTab.ClassOf(t2) =
|
|
|
|
|
- 2291 SymTab.ClSet)
|
|
|
|
|
- 2292 OR (SymTab.ClassOf(tsel) =
|
|
|
|
|
- 2293 SymTab.ClSet)) THEN
|
|
|
|
|
- 2294 SemError(230)
|
|
|
|
|
- 2295 ELSIF (t2 #
|
|
|
|
|
- 2296 SymTab.InvalidType)
|
|
|
|
|
- 2297 AND (tsel #
|
|
|
|
|
- 2298 SymTab.InvalidType)
|
|
|
|
|
- 2299 AND NOT SymTab.EqCheck(t2,
|
|
|
|
|
- 2300 tsel) THEN
|
|
|
|
|
- 2301 SemError(213) END;
|
|
|
|
|
- 2302 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
|
|
- 2303 SemError(230)
|
|
|
|
|
- 2304 END; .)
|
|
|
|
|
- 2305 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
|
|
- 2306 AST.NkSubrange, 0, astLab, astCur);
|
|
|
|
|
- 2307 IF (t3 #
|
|
|
|
|
- 2308 SymTab.InvalidType)
|
|
|
|
|
- 2309 AND (tsel #
|
|
|
|
|
- 2310 SymTab.InvalidType)
|
|
|
|
|
- 2311 AND NOT SymTab.EqCheck(t3,
|
|
|
|
|
- 2312 tsel) THEN
|
|
|
|
|
- 2313 SemError(213) END;
|
|
|
|
|
- 2314 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
|
|
- 2315 SemError(230)
|
|
|
|
|
- 2316 END; .) ]
|
|
|
|
|
- 2317 (. AST.SetChild(arm,
|
|
|
|
|
- 2318 AST.NChild(arm), astLab); .) .
|
|
|
|
|
- 2319 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 2320 q, qt: QbeGen.QVal;
|
|
|
|
|
- 2321 res: SymTab.TypeIndex;
|
|
|
|
|
- 2322 hadE, conv: BOOLEAN;
|
|
|
|
|
- 2323 astVal, astNode: AST.Node; .)
|
|
|
|
|
- 2324 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
|
|
- 2325 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
|
|
- 2326 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
|
|
- 2327 IF hadE THEN
|
|
|
|
|
- 2328 AST.SetChild(astNode, 0, astVal)
|
|
|
|
|
- 2329 END;
|
|
|
|
|
- 2330 astStmt := astNode;
|
|
|
|
|
- 2331 conv := FALSE;
|
|
|
|
|
- 2332 IF NOT SymTab.InProc() THEN
|
|
|
|
|
- 2333 SemError(232)
|
|
|
|
|
- 2334 ELSE res := SymTab.CurRes();
|
|
|
|
|
- 2335 IF NOT hadE THEN
|
|
|
|
|
- 2336 IF res #
|
|
|
|
|
- 2337 SymTab.InvalidType THEN
|
|
|
|
|
- 2338 SemError(232)
|
|
|
|
|
- 2339 END
|
|
|
|
|
- 2340 ELSIF (res =
|
|
|
|
|
- 2341 SymTab.InvalidType)
|
|
|
|
|
- 2342 OR (t #
|
|
|
|
|
- 2343 SymTab.InvalidType)
|
|
|
|
|
- 2344 AND NOT SymTab.Assignable(t,
|
|
|
|
|
- 2345 res) THEN
|
|
|
|
|
- 2346 SemError(232)
|
|
|
|
|
- 2347 END
|
|
|
|
|
- 2348 END; .) .
|
|
|
|
|
- 2349 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
- 2350 q: QbeGen.QVal;
|
|
|
|
|
- 2351 astVal, astNode: AST.Node; .)
|
|
|
|
|
- 2352 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
|
|
- 2353 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
|
|
- 2354 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
|
|
- 2355 IF astVal # AST.NoNode THEN
|
|
|
|
|
- 2356 AST.SetChild(astNode, 0, astVal)
|
|
|
|
|
- 2357 END;
|
|
|
|
|
- 2358 astStmt := astNode;
|
|
|
|
|
- 2359 .) .
|
|
|
|
|
- 2360 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
|
|
- 2361 Each index descends one level (bounds-checked, trap on breach);
|
|
|
|
|
- 2362 nested levels reload the inner descriptor address. q ends as the
|
|
|
|
|
- 2363 value (scalars), the descriptor address (plain arrays), or the
|
|
|
|
|
- 2364 element address (indexed); sfx marks the indexed form. *)
|
|
|
|
|
- 2365 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
- 2366 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
|
|
- 2367 (. VAR n: SymTab.Name; .)
|
|
|
|
|
- 2368 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
|
|
- 2369 (* The part of Design after the identifier: resolve it and walk the
|
|
|
|
|
- 2370 selectors. Split out so a statement can decide between a label
|
|
|
|
|
- 2371 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
|
|
- 2372 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
- 2373 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
|
|
- 2374 (. VAR fn, mal: SymTab.Name;
|
|
|
|
|
- 2375 cls: INTEGER;
|
|
|
|
|
- 2376 ic: SymTab.TypeIndex;
|
|
|
|
|
- 2377 curT, it, eT, bt:
|
|
|
|
|
- 2378 SymTab.TypeIndex;
|
|
|
|
|
- 2379 iq, ql, qlo, qhi, qe:
|
|
|
|
|
- 2380 QbeGen.QVal;
|
|
|
|
|
- 2381 lo, hi: INTEGER;
|
|
|
|
|
- 2382 fo: INTEGER;
|
|
|
|
|
- 2383 isOpen: BOOLEAN;
|
|
|
|
|
- 2384 qb, cv: QbeGen.QVal;
|
|
|
|
|
- 2385 r: BOOLEAN;
|
|
|
|
|
- 2386 astDes, astSel: AST.Node; .)
|
|
|
|
|
- 2387 = (. methCls := SymTab.InvalidType;
|
|
|
|
|
- 2388 QbeGen.CopyOp(n, qn);
|
|
|
|
|
- 2389 sfx := FALSE;
|
|
|
|
|
- 2390 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
- 2391 (* a bare method name inside
|
|
|
|
|
- 2392 a CLASS IMPLEMENTATION
|
|
|
|
|
- 2393 is a sibling call on
|
|
|
|
|
- 2394 THIS *)
|
|
|
|
|
- 2395 ic := SymTab.CurImplClass();
|
|
|
|
|
- 2396 IF (ic #
|
|
|
|
|
- 2397 SymTab.InvalidType)
|
|
|
|
|
- 2398 AND SymTab.MethodExists(ic, n) THEN
|
|
|
|
|
- 2399 sfx := FALSE;
|
|
|
|
|
- 2400 QbeGen.CopyOp("@", q);
|
|
|
|
|
- 2401 methCls := ic;
|
|
|
|
|
- 2402 k := SymTab.KindProc;
|
|
|
|
|
- 2403 t := SymTab.InvalidType
|
|
|
|
|
- 2404 ELSIF SymTab.InProc() THEN
|
|
|
|
|
- 2405 (* not declared anywhere
|
|
|
|
|
- 2406 in scope: with bodies
|
|
|
|
|
- 2407 parsed at unit end this
|
|
|
|
|
- 2408 is a genuine 201 (a
|
|
|
|
|
- 2409 nested-local forward is
|
|
|
|
|
- 2410 no longer tolerated). *)
|
|
|
|
|
- 2411 SemError(201);
|
|
|
|
|
- 2412 t := SymTab.InvalidType;
|
|
|
|
|
- 2413 k := -1;
|
|
|
|
|
- 2414 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2415 ELSE
|
|
|
|
|
- 2416 SemError(201);
|
|
|
|
|
- 2417 t :=
|
|
|
|
|
- 2418 SymTab.InvalidType;
|
|
|
|
|
- 2419 k := -1;
|
|
|
|
|
- 2420 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2421 END
|
|
|
|
|
- 2422 ELSE
|
|
|
|
|
- 2423 t := SymTab.SymType(n);
|
|
|
|
|
- 2424 k := SymTab.SymKind(n);
|
|
|
|
|
- 2425 IF k = SymTab.KindConst THEN
|
|
|
|
|
- 2426 IF SymTab.Equal(n,
|
|
|
|
|
- 2427 "TRUE") THEN
|
|
|
|
|
- 2428 t := SymTab.BoolType();
|
|
|
|
|
- 2429 QbeGen.CopyOp("1", q)
|
|
|
|
|
- 2430 ELSIF SymTab.Equal(n,
|
|
|
|
|
- 2431 "FALSE") THEN
|
|
|
|
|
- 2432 t := SymTab.BoolType();
|
|
|
|
|
- 2433 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2434 ELSIF SymTab.Equal(n,
|
|
|
|
|
- 2435 "NIL") THEN
|
|
|
|
|
- 2436 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2437 ELSE
|
|
|
|
|
- 2438 cls :=
|
|
|
|
|
- 2439 SymTab.ClassOf(t);
|
|
|
|
|
- 2440 IF (t #
|
|
|
|
|
- 2441 SymTab.InvalidType)
|
|
|
|
|
- 2442 AND ((cls = SymTab.ClInt)
|
|
|
|
|
|
|
+ 2213 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
|
|
+ 2214 IF (tby #
|
|
|
|
|
+ 2215 SymTab.InvalidType)
|
|
|
|
|
+ 2216 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
|
|
+ 2217 SemError(220); ok := FALSE
|
|
|
|
|
+ 2218 END;
|
|
|
|
|
+ 2219 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
|
|
+ 2220 SemError(230); by := 1
|
|
|
|
|
+ 2221 ELSIF by = 0 THEN
|
|
|
|
|
+ 2222 SemError(220); by := 1
|
|
|
|
|
+ 2223 END; .) ]
|
|
|
|
|
+ 2224 "DO"
|
|
|
|
|
+ 2225 [ StatSeq ]
|
|
|
|
|
+ 2226 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
|
|
+ 2227 AST.SetChild(astNode, 0, astVar);
|
|
|
|
|
+ 2228 AST.SetChild(astNode, 1, astLo);
|
|
|
|
|
+ 2229 AST.SetChild(astNode, 2, astHi);
|
|
|
|
|
+ 2230 AST.SetChild(astNode, 3, astBy);
|
|
|
|
|
+ 2231 AST.SetChild(astNode, 4, astStmt);
|
|
|
|
|
+ 2232 astStmt := astNode;
|
|
|
|
|
+ 2233 .) .
|
|
|
|
|
+ 2234 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
|
|
+ 2235 qsel, lEnd: QbeGen.QVal;
|
|
|
|
|
+ 2236 arm, astNode, astArms,
|
|
|
|
|
+ 2237 astArmsTail: AST.Node; .)
|
|
|
|
|
+ 2238 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
|
|
+ 2239 AST.SetChild(astNode, 0, astCur);
|
|
|
|
|
+ 2240 astArms := AST.NoNode;
|
|
|
|
|
+ 2241 astArmsTail := AST.NoNode;
|
|
|
|
|
+ 2242 .)
|
|
|
|
|
+ 2243 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
|
|
+ 2244 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
|
|
+ 2245 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 2246 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
|
|
+ 2247 AST.SetOp(arm, 1);
|
|
|
|
|
+ 2248 AST.SetChild(arm, 0, astStmt);
|
|
|
|
|
+ 2249 AstAppend(AST.NkBlock,
|
|
|
|
|
+ 2250 astArms, astArmsTail, arm); .) ]
|
|
|
|
|
+ 2251 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
|
|
+ 2252 astStmt := astNode;
|
|
|
|
|
+ 2253 .) .
|
|
|
|
|
+ 2254 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
|
|
+ 2255 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
|
|
+ 2256 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
|
|
+ 2257 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
|
|
+ 2258 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ 2259 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
|
|
+ 2260 (. VAR arm: AST.Node; .)
|
|
|
|
|
+ 2261 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
|
|
+ 2262 CaseLabel<tsel, qsel, arm>
|
|
|
|
|
+ 2263 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
|
|
+ 2264 ":" (. astStmt := AST.NoNode; .)
|
|
|
|
|
+ 2265 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
|
|
+ 2266 astStmt);
|
|
|
|
|
+ 2267 AstAppend(AST.NkBlock,
|
|
|
|
|
+ 2268 arms, armsTail, arm);
|
|
|
|
|
+ 2269 .) .
|
|
|
|
|
+ 2270 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
|
|
+ 2271 arm: AST.Node>
|
|
|
|
|
+ 2272 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
|
|
+ 2273 q2, q3, qc, qd, qe:
|
|
|
|
|
+ 2274 QbeGen.QVal;
|
|
|
|
|
+ 2275 astLab: AST.Node;
|
|
|
|
|
+ 2276 lNext: QbeGen.QVal; .)
|
|
|
|
|
+ 2277 = Expr<t2, q2> (. astLab := astCur;
|
|
|
|
|
+ 2278 IF (t2 #
|
|
|
|
|
+ 2279 SymTab.InvalidType)
|
|
|
|
|
+ 2280 AND (tsel #
|
|
|
|
|
+ 2281 SymTab.InvalidType)
|
|
|
|
|
+ 2282 AND ((SymTab.ClassOf(t2) =
|
|
|
|
|
+ 2283 SymTab.ClSet)
|
|
|
|
|
+ 2284 OR (SymTab.ClassOf(tsel) =
|
|
|
|
|
+ 2285 SymTab.ClSet)) THEN
|
|
|
|
|
+ 2286 SemError(230)
|
|
|
|
|
+ 2287 ELSIF (t2 #
|
|
|
|
|
+ 2288 SymTab.InvalidType)
|
|
|
|
|
+ 2289 AND (tsel #
|
|
|
|
|
+ 2290 SymTab.InvalidType)
|
|
|
|
|
+ 2291 AND NOT SymTab.EqCheck(t2,
|
|
|
|
|
+ 2292 tsel) THEN
|
|
|
|
|
+ 2293 SemError(213) END;
|
|
|
|
|
+ 2294 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 2295 SemError(230)
|
|
|
|
|
+ 2296 END; .)
|
|
|
|
|
+ 2297 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
|
|
+ 2298 AST.NkSubrange, 0, astLab, astCur);
|
|
|
|
|
+ 2299 IF (t3 #
|
|
|
|
|
+ 2300 SymTab.InvalidType)
|
|
|
|
|
+ 2301 AND (tsel #
|
|
|
|
|
+ 2302 SymTab.InvalidType)
|
|
|
|
|
+ 2303 AND NOT SymTab.EqCheck(t3,
|
|
|
|
|
+ 2304 tsel) THEN
|
|
|
|
|
+ 2305 SemError(213) END;
|
|
|
|
|
+ 2306 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
|
|
+ 2307 SemError(230)
|
|
|
|
|
+ 2308 END; .) ]
|
|
|
|
|
+ 2309 (. AST.SetChild(arm,
|
|
|
|
|
+ 2310 AST.NChild(arm), astLab); .) .
|
|
|
|
|
+ 2311 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 2312 q, qt: QbeGen.QVal;
|
|
|
|
|
+ 2313 res: SymTab.TypeIndex;
|
|
|
|
|
+ 2314 hadE, conv: BOOLEAN;
|
|
|
|
|
+ 2315 astVal, astNode: AST.Node; .)
|
|
|
|
|
+ 2316 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
|
|
+ 2317 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
|
|
+ 2318 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
|
|
+ 2319 IF hadE THEN
|
|
|
|
|
+ 2320 AST.SetChild(astNode, 0, astVal)
|
|
|
|
|
+ 2321 END;
|
|
|
|
|
+ 2322 astStmt := astNode;
|
|
|
|
|
+ 2323 conv := FALSE;
|
|
|
|
|
+ 2324 IF NOT SymTab.InProc() THEN
|
|
|
|
|
+ 2325 SemError(232)
|
|
|
|
|
+ 2326 ELSE res := SymTab.CurRes();
|
|
|
|
|
+ 2327 IF NOT hadE THEN
|
|
|
|
|
+ 2328 IF res #
|
|
|
|
|
+ 2329 SymTab.InvalidType THEN
|
|
|
|
|
+ 2330 SemError(232)
|
|
|
|
|
+ 2331 END
|
|
|
|
|
+ 2332 ELSIF (res =
|
|
|
|
|
+ 2333 SymTab.InvalidType)
|
|
|
|
|
+ 2334 OR (t #
|
|
|
|
|
+ 2335 SymTab.InvalidType)
|
|
|
|
|
+ 2336 AND NOT SymTab.Assignable(t,
|
|
|
|
|
+ 2337 res) THEN
|
|
|
|
|
+ 2338 SemError(232)
|
|
|
|
|
+ 2339 END
|
|
|
|
|
+ 2340 END; .) .
|
|
|
|
|
+ 2341 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
|
|
+ 2342 q: QbeGen.QVal;
|
|
|
|
|
+ 2343 astVal, astNode: AST.Node; .)
|
|
|
|
|
+ 2344 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
|
|
+ 2345 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
|
|
+ 2346 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
|
|
+ 2347 IF astVal # AST.NoNode THEN
|
|
|
|
|
+ 2348 AST.SetChild(astNode, 0, astVal)
|
|
|
|
|
+ 2349 END;
|
|
|
|
|
+ 2350 astStmt := astNode;
|
|
|
|
|
+ 2351 .) .
|
|
|
|
|
+ 2352 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
|
|
+ 2353 Each index descends one level (bounds-checked, trap on breach);
|
|
|
|
|
+ 2354 nested levels reload the inner descriptor address. q ends as the
|
|
|
|
|
+ 2355 value (scalars), the descriptor address (plain arrays), or the
|
|
|
|
|
+ 2356 element address (indexed); sfx marks the indexed form. *)
|
|
|
|
|
+ 2357 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
+ 2358 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
|
|
+ 2359 (. VAR n: SymTab.Name; .)
|
|
|
|
|
+ 2360 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
|
|
+ 2361 (* The part of Design after the identifier: resolve it and walk the
|
|
|
|
|
+ 2362 selectors. Split out so a statement can decide between a label
|
|
|
|
|
+ 2363 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
|
|
+ 2364 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
+ 2365 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
|
|
+ 2366 (. VAR fn, mal: SymTab.Name;
|
|
|
|
|
+ 2367 cls: INTEGER;
|
|
|
|
|
+ 2368 ic: SymTab.TypeIndex;
|
|
|
|
|
+ 2369 curT, it, eT, bt:
|
|
|
|
|
+ 2370 SymTab.TypeIndex;
|
|
|
|
|
+ 2371 iq, ql, qlo, qhi, qe:
|
|
|
|
|
+ 2372 QbeGen.QVal;
|
|
|
|
|
+ 2373 lo, hi: INTEGER;
|
|
|
|
|
+ 2374 fo: INTEGER;
|
|
|
|
|
+ 2375 isOpen: BOOLEAN;
|
|
|
|
|
+ 2376 qb, cv: QbeGen.QVal;
|
|
|
|
|
+ 2377 r: BOOLEAN;
|
|
|
|
|
+ 2378 astDes, astSel: AST.Node; .)
|
|
|
|
|
+ 2379 = (. methCls := SymTab.InvalidType;
|
|
|
|
|
+ 2380 QbeGen.CopyOp(n, qn);
|
|
|
|
|
+ 2381 sfx := FALSE;
|
|
|
|
|
+ 2382 IF NOT SymTab.Lookup(n) THEN
|
|
|
|
|
+ 2383 (* a bare method name inside
|
|
|
|
|
+ 2384 a CLASS IMPLEMENTATION
|
|
|
|
|
+ 2385 is a sibling call on
|
|
|
|
|
+ 2386 THIS *)
|
|
|
|
|
+ 2387 ic := SymTab.CurImplClass();
|
|
|
|
|
+ 2388 IF (ic #
|
|
|
|
|
+ 2389 SymTab.InvalidType)
|
|
|
|
|
+ 2390 AND SymTab.MethodExists(ic, n) THEN
|
|
|
|
|
+ 2391 sfx := FALSE;
|
|
|
|
|
+ 2392 QbeGen.CopyOp("@", q);
|
|
|
|
|
+ 2393 methCls := ic;
|
|
|
|
|
+ 2394 k := SymTab.KindProc;
|
|
|
|
|
+ 2395 t := SymTab.InvalidType
|
|
|
|
|
+ 2396 ELSIF SymTab.InProc() THEN
|
|
|
|
|
+ 2397 (* not declared anywhere
|
|
|
|
|
+ 2398 in scope: with bodies
|
|
|
|
|
+ 2399 parsed at unit end this
|
|
|
|
|
+ 2400 is a genuine 201 (a
|
|
|
|
|
+ 2401 nested-local forward is
|
|
|
|
|
+ 2402 no longer tolerated). *)
|
|
|
|
|
+ 2403 SemError(201);
|
|
|
|
|
+ 2404 t := SymTab.InvalidType;
|
|
|
|
|
+ 2405 k := -1;
|
|
|
|
|
+ 2406 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2407 ELSE
|
|
|
|
|
+ 2408 SemError(201);
|
|
|
|
|
+ 2409 t :=
|
|
|
|
|
+ 2410 SymTab.InvalidType;
|
|
|
|
|
+ 2411 k := -1;
|
|
|
|
|
+ 2412 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2413 END
|
|
|
|
|
+ 2414 ELSE
|
|
|
|
|
+ 2415 t := SymTab.SymType(n);
|
|
|
|
|
+ 2416 k := SymTab.SymKind(n);
|
|
|
|
|
+ 2417 IF k = SymTab.KindConst THEN
|
|
|
|
|
+ 2418 IF SymTab.Equal(n,
|
|
|
|
|
+ 2419 "TRUE") THEN
|
|
|
|
|
+ 2420 t := SymTab.BoolType();
|
|
|
|
|
+ 2421 QbeGen.CopyOp("1", q)
|
|
|
|
|
+ 2422 ELSIF SymTab.Equal(n,
|
|
|
|
|
+ 2423 "FALSE") THEN
|
|
|
|
|
+ 2424 t := SymTab.BoolType();
|
|
|
|
|
+ 2425 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2426 ELSIF SymTab.Equal(n,
|
|
|
|
|
+ 2427 "NIL") THEN
|
|
|
|
|
+ 2428 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2429 ELSE
|
|
|
|
|
+ 2430 cls :=
|
|
|
|
|
+ 2431 SymTab.ClassOf(t);
|
|
|
|
|
+ 2432 IF (t #
|
|
|
|
|
+ 2433 SymTab.InvalidType)
|
|
|
|
|
+ 2434 AND ((cls = SymTab.ClInt)
|
|
|
|
|
+ 2435 OR (cls
|
|
|
|
|
+ 2436 = SymTab.ClChar)
|
|
|
|
|
+ 2437 OR (cls
|
|
|
|
|
+ 2438 = SymTab.ClEnum)
|
|
|
|
|
+ 2439 OR (cls
|
|
|
|
|
+ 2440 = SymTab.ClReal)
|
|
|
|
|
+ 2441 OR (cls
|
|
|
|
|
+ 2442 = SymTab.ClLong)
|
|
|
2443 OR (cls
|
|
2443 OR (cls
|
|
|
- 2444 = SymTab.ClChar)
|
|
|
|
|
- 2445 OR (cls
|
|
|
|
|
- 2446 = SymTab.ClEnum)
|
|
|
|
|
- 2447 OR (cls
|
|
|
|
|
- 2448 = SymTab.ClReal)
|
|
|
|
|
- 2449 OR (cls
|
|
|
|
|
- 2450 = SymTab.ClLong)
|
|
|
|
|
- 2451 OR (cls
|
|
|
|
|
- 2452 = SymTab.ClNil)) THEN
|
|
|
|
|
- 2453 IF cls = SymTab.ClNil THEN
|
|
|
|
|
- 2454 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2455 ELSIF ((cls
|
|
|
|
|
- 2456 = SymTab.ClInt)
|
|
|
|
|
- 2457 OR (cls
|
|
|
|
|
- 2458 = SymTab.ClChar)
|
|
|
|
|
- 2459 OR (cls
|
|
|
|
|
- 2460 = SymTab.ClEnum)
|
|
|
|
|
- 2461 OR (cls
|
|
|
|
|
- 2462 = SymTab.ClLong))
|
|
|
|
|
- 2463 AND SymTab.GetSymVal(n, cv)
|
|
|
|
|
- 2464 AND QbeGen.IsImm(cv) THEN
|
|
|
|
|
- 2465 QbeGen.CopyOp(cv, q)
|
|
|
|
|
- 2466 ELSE
|
|
|
|
|
- 2467 QbeGen.LoadVar(n,
|
|
|
|
|
- 2468 cls = SymTab.ClReal,
|
|
|
|
|
- 2469 q)
|
|
|
|
|
- 2470 END
|
|
|
|
|
- 2471 ELSIF (cls = SymTab.ClArray)
|
|
|
|
|
- 2472 OR (cls = SymTab.ClRecord)
|
|
|
|
|
- 2473 OR (cls = SymTab.ClClass)
|
|
|
|
|
- 2474 OR (cls = SymTab.ClStr)
|
|
|
|
|
- 2475 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
- 2476 (* aggregate constant:
|
|
|
|
|
- 2477 its value IS the
|
|
|
|
|
- 2478 descriptor address *)
|
|
|
|
|
- 2479 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
|
|
- 2480 QbeGen.CopyOp(cv, q)
|
|
|
|
|
- 2481 ELSE
|
|
|
|
|
- 2482 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2483 END
|
|
|
|
|
- 2484 ELSE
|
|
|
|
|
- 2485 IF t #
|
|
|
|
|
- 2486 SymTab.InvalidType THEN
|
|
|
|
|
- 2487 SemError(230)
|
|
|
|
|
- 2488 END;
|
|
|
|
|
- 2489 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2490 END
|
|
|
|
|
- 2491 END
|
|
|
|
|
- 2492 ELSIF (k = SymTab.KindVar)
|
|
|
|
|
- 2493 OR (k = SymTab.KindParam) THEN
|
|
|
|
|
- 2494 cls := SymTab.ClassOf(t);
|
|
|
|
|
- 2495 IF (cls # SymTab.ClInt)
|
|
|
|
|
- 2496 AND (cls # SymTab.ClBool)
|
|
|
|
|
- 2497 AND (cls # SymTab.ClChar)
|
|
|
|
|
- 2498 AND (cls # SymTab.ClUChar)
|
|
|
|
|
- 2499 AND (cls # SymTab.ClEnum)
|
|
|
|
|
- 2500 AND (cls # SymTab.ClReal)
|
|
|
|
|
- 2501 AND (cls # SymTab.ClPtr)
|
|
|
|
|
- 2502 AND (cls # SymTab.ClProc)
|
|
|
|
|
- 2503 AND (cls # SymTab.ClLong)
|
|
|
|
|
- 2504 AND (cls # SymTab.ClArray)
|
|
|
|
|
- 2505 AND (cls # SymTab.ClSet)
|
|
|
|
|
- 2506 AND (cls # SymTab.ClRecord)
|
|
|
|
|
- 2507 AND (cls # SymTab.ClUStr)
|
|
|
|
|
- 2508 AND (cls # SymTab.ClClass) THEN
|
|
|
|
|
- 2509 SemError(230);
|
|
|
|
|
- 2510 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2511 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2512 END
|
|
|
|
|
- 2513 ELSE QbeGen.CopyOp("0", q);
|
|
|
|
|
- 2514 IF k = SymTab.KindImport THEN
|
|
|
|
|
- 2515 SemError(230)
|
|
|
|
|
- 2516 ELSIF k =
|
|
|
|
|
- 2517 SymTab.KindProc THEN
|
|
|
|
|
- 2518 (* bare procedure name:
|
|
|
|
|
- 2519 a following ArgList
|
|
|
|
|
- 2520 makes it a call;
|
|
|
|
|
- 2521 otherwise Fact
|
|
|
|
|
- 2522 reports 230 *)
|
|
|
|
|
- 2523 ELSE
|
|
|
|
|
- 2524 IF k = SymTab.KindField THEN
|
|
|
|
|
- 2525 IF QbeGen.TopWith(qb) THEN
|
|
|
|
|
- 2526 sfx := TRUE
|
|
|
|
|
- 2527 ELSE SemError(230);
|
|
|
|
|
- 2528 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2529 END
|
|
|
|
|
- 2530 END
|
|
|
|
|
- 2531 END
|
|
|
|
|
- 2532 END
|
|
|
|
|
- 2533 END; .)
|
|
|
|
|
- 2534 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
|
|
- 2535 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
- 2536 { "[" Expr<it, iq>
|
|
|
|
|
- 2537 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
|
|
- 2538 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2539 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2540 SymTab.ClArray THEN
|
|
|
|
|
- 2541 SemError(217);
|
|
|
|
|
- 2542 t := SymTab.InvalidType
|
|
|
|
|
- 2543 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
- 2544 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 2545 SymTab.ClChar)
|
|
|
|
|
- 2546 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 2547 SymTab.ClEnum) THEN
|
|
|
|
|
- 2548 SemError(218);
|
|
|
|
|
- 2549 t := SymTab.InvalidType
|
|
|
|
|
- 2550 ELSE
|
|
|
|
|
- 2551 eT := SymTab.ArrayElem(t);
|
|
|
|
|
- 2552 t := eT; sfx := TRUE
|
|
|
|
|
- 2553 END; .)
|
|
|
|
|
- 2554 { "," Expr<it, iq>
|
|
|
|
|
- 2555 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
|
|
- 2556 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2557 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2558 SymTab.ClArray THEN
|
|
|
|
|
- 2559 SemError(217);
|
|
|
|
|
- 2560 t := SymTab.InvalidType
|
|
|
|
|
- 2561 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
- 2562 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 2563 SymTab.ClChar)
|
|
|
|
|
- 2564 AND (SymTab.ClassOf(it) #
|
|
|
|
|
- 2565 SymTab.ClEnum) THEN
|
|
|
|
|
- 2566 SemError(218);
|
|
|
|
|
- 2567 t := SymTab.InvalidType
|
|
|
|
|
- 2568 ELSE
|
|
|
|
|
- 2569 eT := SymTab.ArrayElem(t);
|
|
|
|
|
- 2570 t := eT; sfx := TRUE
|
|
|
|
|
- 2571 END; .) }
|
|
|
|
|
- 2572 "]"
|
|
|
|
|
- 2573 | "." GetIdent<fn>
|
|
|
|
|
- 2574 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
|
|
- 2575 AST.SetOp(astSel, AST.SelField);
|
|
|
|
|
- 2576 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
|
|
- 2577 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
|
|
- 2578 (* qualified L.x: materialize
|
|
|
|
|
- 2579 the export, then load it *)
|
|
|
|
|
- 2580 IF NOT SymTab.MaterializeAlias(n,
|
|
|
|
|
- 2581 fn, mal) THEN
|
|
|
|
|
- 2582 SemError(201);
|
|
|
|
|
- 2583 t := SymTab.InvalidType;
|
|
|
|
|
- 2584 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2585 ELSE
|
|
|
|
|
- 2586 QbeGen.CopyOp(mal, qn);
|
|
|
|
|
- 2587 t := SymTab.SymType(mal);
|
|
|
|
|
- 2588 k := SymTab.SymKind(mal);
|
|
|
|
|
- 2589 sfx := FALSE;
|
|
|
|
|
- 2590 IF k = SymTab.KindProc THEN
|
|
|
|
|
- 2591 (* call: ArgList supplies
|
|
|
|
|
- 2592 the value *)
|
|
|
|
|
- 2593 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2594 END
|
|
|
|
|
- 2595 END
|
|
|
|
|
- 2596 ELSIF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2597 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
- 2598 SymTab.ClRecord)
|
|
|
|
|
- 2599 AND (SymTab.ClassOf(t) #
|
|
|
|
|
- 2600 SymTab.ClClass) THEN
|
|
|
|
|
- 2601 SemError(215);
|
|
|
|
|
- 2602 t := SymTab.InvalidType
|
|
|
|
|
- 2603 ELSIF (SymTab.ClassOf(t) =
|
|
|
|
|
- 2604 SymTab.ClClass)
|
|
|
|
|
- 2605 AND SymTab.MethodExists(t, fn) THEN
|
|
|
|
|
- 2606 (* obj.Method: bind the
|
|
|
|
|
- 2607 method and pass obj as
|
|
|
|
|
- 2608 the hidden receiver; q
|
|
|
|
|
- 2609 already holds the
|
|
|
|
|
- 2610 object's address *)
|
|
|
|
|
- 2611 QbeGen.CopyOp(fn, n);
|
|
|
|
|
- 2612 QbeGen.CopyOp(fn, qn);
|
|
|
|
|
- 2613 methCls := t;
|
|
|
|
|
- 2614 k := SymTab.KindProc;
|
|
|
|
|
- 2615 t := SymTab.InvalidType
|
|
|
|
|
- 2616 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
- 2617 fn) THEN
|
|
|
|
|
- 2618 SemError(216);
|
|
|
|
|
- 2619 t := SymTab.InvalidType
|
|
|
|
|
- 2620 ELSE
|
|
|
|
|
- 2621 t := SymTab.FieldType(t, fn);
|
|
|
|
|
- 2622 sfx := TRUE
|
|
|
|
|
- 2623 END; .)
|
|
|
|
|
- 2624 | "^"
|
|
|
|
|
- 2625 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
|
|
- 2626 AST.SetOp(astSel, AST.SelDeref);
|
|
|
|
|
- 2627 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2628 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2629 SymTab.ClPtr THEN
|
|
|
|
|
- 2630 SemError(219);
|
|
|
|
|
- 2631 t := SymTab.InvalidType
|
|
|
|
|
- 2632 ELSE
|
|
|
|
|
- 2633 bt := SymTab.PtrBase(t);
|
|
|
|
|
- 2634 IF bt = SymTab.InvalidType THEN
|
|
|
|
|
- 2635 ELSE
|
|
|
|
|
- 2636 t := bt;
|
|
|
|
|
- 2637 sfx := TRUE
|
|
|
|
|
- 2638 END
|
|
|
|
|
- 2639 END; .) } (. astCur := astDes; .) .
|
|
|
|
|
- 2640 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
|
|
- 2641 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
|
|
- 2642 (a value, or a descriptor address for aggregates); each component
|
|
|
|
|
- 2643 descends one level exactly like the Design components. *)
|
|
|
|
|
- 2644 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
- 2645 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
|
|
- 2646 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
|
|
- 2647 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
|
|
- 2648 iq, ql, qlo, qhi, qe, qb:
|
|
|
|
|
- 2649 QbeGen.QVal;
|
|
|
|
|
- 2650 lo, hi, fo: INTEGER;
|
|
|
|
|
- 2651 isOpen: BOOLEAN;
|
|
|
|
|
- 2652 fname: SymTab.Name;
|
|
|
|
|
- 2653 astWrap, astSel: AST.Node; .)
|
|
|
|
|
- 2654 = "[" Expr<it, iq>
|
|
|
|
|
- 2655 (. isM := FALSE;
|
|
|
|
|
- 2656 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
|
|
- 2657 astWrap := AST.MakeNode(
|
|
|
|
|
- 2658 AST.NkDesignator);
|
|
|
|
|
- 2659 AST.SetChild(astWrap, 0, node);
|
|
|
|
|
- 2660 node := astWrap
|
|
|
|
|
- 2661 END;
|
|
|
|
|
- 2662 AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
- 2663 AST.MakeUn(AST.NkSelector,
|
|
|
|
|
- 2664 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2665 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2666 SymTab.ClArray THEN
|
|
|
|
|
- 2667 SemError(217);
|
|
|
|
|
- 2668 t := SymTab.InvalidType
|
|
|
|
|
- 2669 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
- 2670 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
|
|
- 2671 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
|
|
- 2672 SemError(218);
|
|
|
|
|
- 2673 t := SymTab.InvalidType
|
|
|
|
|
- 2674 ELSE
|
|
|
|
|
- 2675 eT := SymTab.ArrayElem(t);
|
|
|
|
|
- 2676 t := eT; sfx := TRUE
|
|
|
|
|
- 2677 END; .)
|
|
|
|
|
- 2678 "]"
|
|
|
|
|
- 2679 | "." GetIdent<fname>
|
|
|
|
|
- 2680 (. isM := FALSE;
|
|
|
|
|
- 2681 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
|
|
- 2682 astWrap := AST.MakeNode(
|
|
|
|
|
- 2683 AST.NkDesignator);
|
|
|
|
|
- 2684 AST.SetChild(astWrap, 0, node);
|
|
|
|
|
- 2685 node := astWrap
|
|
|
|
|
- 2686 END;
|
|
|
|
|
- 2687 AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
- 2688 AST.MakeUn(AST.NkSelector,
|
|
|
|
|
- 2689 AST.SelField,
|
|
|
|
|
- 2690 AST.MakeLeaf(AST.NkIdent,
|
|
|
|
|
- 2691 fname))); IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2692 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
- 2693 SymTab.ClRecord)
|
|
|
|
|
- 2694 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
- 2695 SemError(215);
|
|
|
|
|
- 2696 t := SymTab.InvalidType
|
|
|
|
|
- 2697 ELSIF (SymTab.ClassOf(t) =
|
|
|
|
|
- 2698 SymTab.ClClass)
|
|
|
|
|
- 2699 AND SymTab.MethodExists(t, fname) THEN
|
|
|
|
|
- 2700 (* a method on the call result:
|
|
|
|
|
- 2701 a following ArgList makes
|
|
|
|
|
- 2702 the call *)
|
|
|
|
|
- 2703 mname := fname;
|
|
|
|
|
- 2704 methCls := t; isM := TRUE;
|
|
|
|
|
- 2705 t := SymTab.InvalidType
|
|
|
|
|
- 2706 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
- 2707 fname) THEN
|
|
|
|
|
- 2708 SemError(216);
|
|
|
|
|
- 2709 t := SymTab.InvalidType
|
|
|
|
|
- 2710 ELSE
|
|
|
|
|
- 2711 t := SymTab.FieldType(t, fname);
|
|
|
|
|
- 2712 sfx := TRUE
|
|
|
|
|
- 2713 END; .)
|
|
|
|
|
- 2714 | "^" (. isM := FALSE;
|
|
|
|
|
- 2715 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
|
|
- 2716 astWrap := AST.MakeNode(
|
|
|
|
|
- 2717 AST.NkDesignator);
|
|
|
|
|
- 2718 AST.SetChild(astWrap, 0, node);
|
|
|
|
|
- 2719 node := astWrap
|
|
|
|
|
- 2720 END;
|
|
|
|
|
- 2721 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
|
|
- 2722 AST.SetOp(astSel, AST.SelDeref);
|
|
|
|
|
- 2723 AST.SetChild(node,
|
|
|
|
|
- 2724 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 2725 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
- 2726 SymTab.ClPtr THEN
|
|
|
|
|
- 2727 SemError(219);
|
|
|
|
|
- 2728 t := SymTab.InvalidType
|
|
|
|
|
- 2729 ELSE
|
|
|
|
|
- 2730 bt := SymTab.PtrBase(t);
|
|
|
|
|
- 2731 IF bt # SymTab.InvalidType THEN
|
|
|
|
|
- 2732 t := bt; sfx := TRUE
|
|
|
|
|
- 2733 END
|
|
|
|
|
- 2734 END; .) .
|
|
|
|
|
- 2735 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2736 (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
- 2737 op: INTEGER;
|
|
|
|
|
- 2738 q2, qt, wl: QbeGen.QVal;
|
|
|
|
|
- 2739 astA, astB: AST.Node;
|
|
|
|
|
- 2740 astOp: INTEGER;
|
|
|
|
|
- 2741 astMade: BOOLEAN;
|
|
|
|
|
- 2742 isR: BOOLEAN; .)
|
|
|
|
|
- 2743 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
|
|
- 2744 [ Rel<op> SimExpr<t2, q2>
|
|
|
|
|
- 2745 (. astB := astCur; astMade := TRUE;
|
|
|
|
|
- 2746 astOp := AST.OpEq;
|
|
|
|
|
- 2747 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
|
|
- 2748 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
|
|
- 2749 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
|
|
- 2750 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
|
|
- 2751 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
|
|
- 2752 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
|
|
- 2753 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
|
|
- 2754 END;
|
|
|
|
|
- 2755 IF op = SymTab.OpIn THEN
|
|
|
|
|
- 2756 IF SymTab.InCheck(t, t2) THEN
|
|
|
|
|
- 2757 IF (t = SymTab.InvalidType)
|
|
|
|
|
- 2758 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
- 2759 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2760 ELSE
|
|
|
|
|
- 2761 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2762 END
|
|
|
|
|
- 2763 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
|
|
- 2764 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2765 END
|
|
|
|
|
- 2766 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
|
|
- 2767 IF (t = SymTab.InvalidType)
|
|
|
|
|
- 2768 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
- 2769 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2770 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
|
|
- 2771 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
|
|
- 2772 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
|
|
- 2773 AND (op # SymTab.OpNeq2) THEN
|
|
|
|
|
- 2774 SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
- 2775 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2776 ELSE
|
|
|
|
|
- 2777 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2778 END
|
|
|
|
|
- 2779 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
- 2780 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
- 2781 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2782 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
|
|
- 2783 QbeGen.StrEq(op, q, q2, qt);
|
|
|
|
|
- 2784 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2785 ELSIF SymTab.IsLongFamily(t)
|
|
|
|
|
- 2786 OR SymTab.IsLongFamily(t2) THEN
|
|
|
|
|
- 2787 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2788 ELSE
|
|
|
|
|
- 2789 t := SymTab.BoolType();
|
|
|
|
|
- 2790 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2791 END
|
|
|
|
|
- 2792 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
- 2793 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2794 END;
|
|
|
|
|
- 2795 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
|
|
- 2796 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
|
|
- 2797 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
- 2798 Rel<VAR op: INTEGER>
|
|
|
|
|
- 2799 = "=" (. op := SymTab.OpEq; .)
|
|
|
|
|
- 2800 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
|
|
- 2801 | "<" (. op := SymTab.OpLt; .)
|
|
|
|
|
- 2802 | "<=" (. op := SymTab.OpLe; .)
|
|
|
|
|
- 2803 | ">" (. op := SymTab.OpGt; .)
|
|
|
|
|
- 2804 | ">=" (. op := SymTab.OpGe; .)
|
|
|
|
|
- 2805 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
|
|
- 2806 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2807 (. VAR t2, res2, lt, rt:
|
|
|
|
|
- 2808 SymTab.TypeIndex;
|
|
|
|
|
- 2809 op: INTEGER;
|
|
|
|
|
- 2810 q2, qt, wq, qf, q2a, q2b:
|
|
|
|
|
- 2811 QbeGen.QVal;
|
|
|
|
|
- 2812 neg, isR, isL, folded:
|
|
|
|
|
- 2813 BOOLEAN;
|
|
|
|
|
- 2814 fok: BOOLEAN;
|
|
|
|
|
- 2815 lw, rw, mw: CARDINAL;
|
|
|
|
|
- 2816 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
|
|
- 2817 astA, astB: AST.Node;
|
|
|
|
|
- 2818 astSign, astOp: INTEGER; .)
|
|
|
|
|
- 2819 = (. neg := FALSE; astSign := 0; .)
|
|
|
|
|
- 2820 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
|
|
- 2821 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
|
|
- 2822 Term<t, q> (. astA := astCur;
|
|
|
|
|
- 2823 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
|
|
- 2824 QbeGen.NegFold(q, q)
|
|
|
|
|
- 2825 END;
|
|
|
|
|
- 2826 IF astSign < 0 THEN
|
|
|
|
|
- 2827 astCur := AST.MakeUn(
|
|
|
|
|
- 2828 AST.NkUnary, AST.OpSub, astA);
|
|
|
|
|
- 2829 astA := astCur
|
|
|
|
|
- 2830 END; .)
|
|
|
|
|
- 2831 { AddOp<op>
|
|
|
|
|
- 2832 Term<t2, q2> (. astB := astCur; .)
|
|
|
|
|
- 2833 (. astOp := AST.OpAdd;
|
|
|
|
|
- 2834 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
|
|
- 2835 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
|
|
- 2836 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
|
|
- 2837 astCur := astA;
|
|
|
|
|
- 2838 IF op = SymTab.OpOr THEN
|
|
|
|
|
- 2839 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
|
|
- 2840 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
- 2841 t := SymTab.BoolType()
|
|
|
|
|
- 2842 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
- 2843 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2844 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2845 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2846 END
|
|
|
|
|
- 2847 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
- 2848 AND (SymTab.UStrCompat(t, t2)
|
|
|
|
|
- 2849 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
- 2850 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
|
|
- 2851 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
|
|
- 2852 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
|
|
- 2853 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
- 2854 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
|
|
- 2855 (* UString concatenation: a UCHAR operand becomes a
|
|
|
|
|
- 2856 1-codepoint UString; the result is a descriptor in the
|
|
|
|
|
- 2857 shim's concat buffer. Work on copies so neither
|
|
|
|
|
- 2858 operand is clobbered. *)
|
|
|
|
|
- 2859 t := SymTab.NewUStr();
|
|
|
|
|
- 2860 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2861 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
- 2862 AND (SymTab.StrCompat(t, t2)
|
|
|
|
|
- 2863 OR (SymTab.IsStrType(t)
|
|
|
|
|
- 2864 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
|
|
- 2865 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
|
|
- 2866 AND SymTab.IsStrType(t2))) THEN
|
|
|
|
|
- 2867 (* string concatenation; a CHAR operand becomes a
|
|
|
|
|
- 2868 1-character string literal. When both operands are
|
|
|
|
|
- 2869 constants, fold to a single string literal so a
|
|
|
|
|
- 2870 constructor element stays compile-time. *)
|
|
|
|
|
- 2871 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
|
|
- 2872 qt, fok);
|
|
|
|
|
- 2873 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
|
|
- 2874 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2875 END;
|
|
|
|
|
- 2876 t := SymTab.NewStr()
|
|
|
|
|
- 2877 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
- 2878 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
- 2879 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
- 2880 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
- 2881 mw := lw;
|
|
|
|
|
- 2882 IF rw > mw THEN mw := rw END;
|
|
|
|
|
- 2883 t := SymTab.NewSet(
|
|
|
|
|
- 2884 SymTab.NewSubR(0,
|
|
|
|
|
- 2885 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
- 2886 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2887 ELSE
|
|
|
|
|
- 2888 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
- 2889 lt := t; rt := t2; t := res2
|
|
|
|
|
- 2890 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
- 2891 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2892 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
- 2893 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
- 2894 folded := FALSE;
|
|
|
|
|
- 2895 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
- 2896 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
- 2897 IF op = SymTab.OpAdd THEN
|
|
|
|
|
- 2898 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
|
|
- 2899 ELSE
|
|
|
|
|
- 2900 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
|
|
- 2901 END
|
|
|
|
|
- 2902 END;
|
|
|
|
|
- 2903 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
- 2904 ELSE
|
|
|
|
|
- 2905 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2906 END
|
|
|
|
|
- 2907 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2908 END
|
|
|
|
|
- 2909 END; .) }
|
|
|
|
|
- 2910 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
- 2911 AddOp<VAR op: INTEGER>
|
|
|
|
|
- 2912 = "+" (. op := SymTab.OpAdd; .)
|
|
|
|
|
- 2913 | "-" (. op := SymTab.OpSub; .)
|
|
|
|
|
- 2914 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
|
|
- 2915 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2916 (. VAR t2, res2, lt, rt:
|
|
|
|
|
- 2917 SymTab.TypeIndex;
|
|
|
|
|
- 2918 op: INTEGER;
|
|
|
|
|
- 2919 q2, qt, wq, qf:
|
|
|
|
|
- 2920 QbeGen.QVal;
|
|
|
|
|
- 2921 isR, isL, folded: BOOLEAN;
|
|
|
|
|
- 2922 lw, rw, mw: CARDINAL;
|
|
|
|
|
- 2923 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
|
|
- 2924 astA, astB: AST.Node;
|
|
|
|
|
- 2925 astOp: INTEGER; .)
|
|
|
|
|
- 2926 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
|
|
- 2927 Fact<t2, q2> (. astB := astCur; .)
|
|
|
|
|
- 2928 (. astOp := AST.OpMul;
|
|
|
|
|
- 2929 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
|
|
- 2930 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
|
|
- 2931 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
|
|
- 2932 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
|
|
- 2933 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
|
|
- 2934 astCur := astA;
|
|
|
|
|
- 2935 IF op = SymTab.OpAnd THEN
|
|
|
|
|
- 2936 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
|
|
- 2937 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
- 2938 t := SymTab.BoolType()
|
|
|
|
|
- 2939 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
- 2940 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2941 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2942 END
|
|
|
|
|
- 2943 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
- 2944 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
- 2945 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
- 2946 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
- 2947 mw := lw;
|
|
|
|
|
- 2948 IF rw > mw THEN mw := rw END;
|
|
|
|
|
- 2949 t := SymTab.NewSet(
|
|
|
|
|
- 2950 SymTab.NewSubR(0,
|
|
|
|
|
- 2951 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
- 2952 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2953 ELSE
|
|
|
|
|
- 2954 IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
- 2955 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
- 2956 res2) THEN
|
|
|
|
|
- 2957 lt := t; rt := t2; t := res2
|
|
|
|
|
- 2958 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
- 2959 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 2960 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
- 2961 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
- 2962 folded := FALSE;
|
|
|
|
|
- 2963 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
- 2964 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
- 2965 IF op = SymTab.OpTimes THEN
|
|
|
|
|
- 2966 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
|
|
- 2967 ELSIF op = SymTab.OpDiv THEN
|
|
|
|
|
- 2968 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
|
|
- 2969 ELSIF op = SymTab.OpMod THEN
|
|
|
|
|
- 2970 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
|
|
- 2971 END
|
|
|
|
|
- 2972 END;
|
|
|
|
|
- 2973 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
- 2974 ELSE
|
|
|
|
|
- 2975 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 2976 END
|
|
|
|
|
- 2977 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 2978 END
|
|
|
|
|
- 2979 END; .) }
|
|
|
|
|
- 2980 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
- 2981 MulOp<VAR op: INTEGER>
|
|
|
|
|
- 2982 = "*" (. op := SymTab.OpTimes; .)
|
|
|
|
|
- 2983 | "/" (. op := SymTab.OpSlash; .)
|
|
|
|
|
- 2984 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
|
|
- 2985 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
|
|
- 2986 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
|
|
- 2987 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 2988 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
|
|
- 2989 et, dt, t2, st, ct2, et2:
|
|
|
|
|
- 2990 SymTab.TypeIndex;
|
|
|
|
|
- 2991 dk: INTEGER;
|
|
|
|
|
- 2992 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
|
|
- 2993 QbeGen.QVal;
|
|
|
|
|
- 2994 qn, vn: SymTab.Name;
|
|
|
|
|
- 2995 vt: SymTab.TypeIndex;
|
|
|
|
|
- 2996 c1, c2: INTEGER;
|
|
|
|
|
- 2997 lo, hi: INTEGER;
|
|
|
|
|
- 2998 isMax: BOOLEAN;
|
|
|
|
|
- 2999 called, isHigh, sfx, isCh,
|
|
|
|
|
- 3000 isU, uok, isStr: BOOLEAN;
|
|
|
|
|
- 3001 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
|
|
- 3002 astD: AST.Node;
|
|
|
|
|
- 3003 astCall: BOOLEAN;
|
|
|
|
|
- 3004 astNode, astNot: AST.Node;
|
|
|
|
|
- 3005 j: CARDINAL;
|
|
|
|
|
- 3006 astArg2: AST.Node;
|
|
|
|
|
- 3007 astBrace: AST.Node;
|
|
|
|
|
- 3008 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
|
|
|
|
|
- 3009 = (. astIsLit := FALSE; .)
|
|
|
|
|
- 3010 ( integer (. LexString(s);
|
|
|
|
|
- 3011 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
|
|
- 3012 t := SymTab.IntType(); .)
|
|
|
|
|
- 3013 | charConst (. LexString(s);
|
|
|
|
|
- 3014 QbeGen.NormLit(s, q, isCh);
|
|
|
|
|
- 3015 IF twoPhase THEN
|
|
|
|
|
- 3016 astIsLit := TRUE;
|
|
|
|
|
- 3017 astCur := AST.MakeLeaf(
|
|
|
|
|
- 3018 AST.NkCharLit, s)
|
|
|
|
|
- 3019 END;
|
|
|
|
|
- 3020 t := SymTab.CharType(); .)
|
|
|
|
|
- 3021 | real (. LexString(s);
|
|
|
|
|
- 3022 QbeGen.NormReal(s, q);
|
|
|
|
|
- 3023 IF twoPhase THEN
|
|
|
|
|
- 3024 astIsLit := TRUE;
|
|
|
|
|
- 3025 astCur := AST.MakeLeaf(
|
|
|
|
|
- 3026 AST.NkRealLit, s)
|
|
|
|
|
- 3027 END;
|
|
|
|
|
- 3028 t := SymTab.RealType(); .)
|
|
|
|
|
- 3029 | string (. LexString(s);
|
|
|
|
|
- 3030 IF twoPhase THEN
|
|
|
|
|
- 3031 astIsLit := TRUE;
|
|
|
|
|
- 3032 astCur := AST.MakeLeaf(
|
|
|
|
|
- 3033 AST.NkStrLit, s)
|
|
|
|
|
- 3034 END;
|
|
|
|
|
- 3035 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
- 3036 t := SymTab.CharType();
|
|
|
|
|
- 3037 QbeGen.IntStr(
|
|
|
|
|
- 3038 QbeGen.CharVal(s), q)
|
|
|
|
|
- 3039 ELSE t := SymTab.NewStr();
|
|
|
|
|
- 3040 QbeGen.DeclStr(s, q);
|
|
|
|
|
- 3041 (* a literal's value IS its
|
|
|
|
|
- 3042 static descriptor address *)
|
|
|
|
|
- 3043 END; .)
|
|
|
|
|
- 3044 | ustring (. LexString(s);
|
|
|
|
|
- 3045 IF twoPhase THEN
|
|
|
|
|
- 3046 astIsLit := TRUE;
|
|
|
|
|
- 3047 astCur := AST.MakeLeaf(
|
|
|
|
|
- 3048 AST.NkStrLit, s)
|
|
|
|
|
- 3049 END;
|
|
|
|
|
- 3050 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
|
|
- 3051 uok);
|
|
|
|
|
- 3052 IF NOT uok THEN
|
|
|
|
|
- 3053 SemError(234);
|
|
|
|
|
- 3054 t := SymTab.InvalidType
|
|
|
|
|
- 3055 ELSIF isU THEN
|
|
|
|
|
- 3056 t := SymTab.UCharType();
|
|
|
|
|
- 3057 QbeGen.IntStr(ucp, q)
|
|
|
|
|
- 3058 ELSE
|
|
|
|
|
- 3059 t := SymTab.NewUStr();
|
|
|
|
|
- 3060 END; .)
|
|
|
|
|
- 3061 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
|
|
- 3062 astNArgs := 0; called := FALSE;
|
|
|
|
|
- 3063 t := dt;
|
|
|
|
|
- 3064 IF dk = SymTab.KindConst THEN
|
|
|
|
|
- 3065 QbeGen.CopyOp(qd, q)
|
|
|
|
|
- 3066 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3067 END; .)
|
|
|
|
|
- 3068 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
|
|
- 3069 astBrace := astCur; .) ]
|
|
|
|
|
- 3070 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
- 3071 (. astCall := TRUE;
|
|
|
|
|
- 3072 astNode := AstCallNode(astD);
|
|
|
|
|
- 3073 astRes := astNode;
|
|
|
|
|
- 3074 t := ct2;
|
|
|
|
|
- 3075 QbeGen.CopyOp(q2, q);
|
|
|
|
|
- 3076 sfx := FALSE; .)
|
|
|
|
|
- 3077 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
|
|
- 3078 [ (. astNArgs := 0; .)
|
|
|
|
|
- 3079 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
- 3080 (. astNode := AstCallNode(astRes);
|
|
|
|
|
- 3081 astRes := astNode;
|
|
|
|
|
- 3082 t := ct2;
|
|
|
|
|
- 3083 QbeGen.CopyOp(q2, q);
|
|
|
|
|
- 3084 sfx := FALSE; .) ] }
|
|
|
|
|
- 3085 (. IF sfx THEN
|
|
|
|
|
- 3086 IF t = SymTab.InvalidType THEN
|
|
|
|
|
- 3087 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3088 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
- 3089 SymTab.ClRecord)
|
|
|
|
|
- 3090 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
|
|
- 3091 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
|
|
- 3092 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
- 3093 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3094 END
|
|
|
|
|
- 3095 END; .) ]
|
|
|
|
|
- 3096 (. IF called THEN
|
|
|
|
|
- 3097 astCur := astRes
|
|
|
|
|
- 3098 ELSIF astCall THEN
|
|
|
|
|
- 3099 astCur := astBrace
|
|
|
|
|
- 3100 ELSE astCur := astD
|
|
|
|
|
- 3101 END;
|
|
|
|
|
- 3102 astIsLit := TRUE;
|
|
|
|
|
- 3103 IF NOT called
|
|
|
|
|
- 3104 AND (dk = SymTab.KindProc) THEN
|
|
|
|
|
- 3105 (* bare zero-arg function
|
|
|
|
|
- 3106 call (parentheses may be
|
|
|
|
|
- 3107 omitted); a proper or
|
|
|
|
|
- 3108 parameterised proc here
|
|
|
|
|
- 3109 is 230 *)
|
|
|
|
|
- 3110 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
|
|
- 3111 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
|
|
- 3112 t := SymTab.ProcRes(qn);
|
|
|
|
|
- 3113 QbeGen.CopyOp("@", q);
|
|
|
|
|
- 3114 astCur := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3115 AST.SetChild(astCur, 0, astD)
|
|
|
|
|
- 3116 ELSE
|
|
|
|
|
- 3117 t := SymTab.ProcTypeOf(qn);
|
|
|
|
|
- 3118 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3119 END
|
|
|
|
|
- 3120 END; .)
|
|
|
|
|
- 3121 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
|
|
- 3122 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
|
|
- 3123 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
|
|
- 3124 isU := FALSE; .)
|
|
|
|
|
- 3125 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
|
|
- 3126 isStr := TRUE;
|
|
|
|
|
- 3127 isU := FALSE;
|
|
|
|
|
- 3128 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
- 3129 dt := SymTab.CharType();
|
|
|
|
|
- 3130 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
|
|
- 3131 qd)
|
|
|
|
|
- 3132 ELSE
|
|
|
|
|
- 3133 dt := SymTab.NewStr();
|
|
|
|
|
- 3134 QbeGen.DeclStr(s, qd);
|
|
|
|
|
- 3135 END;
|
|
|
|
|
- 3136 dk := -1;
|
|
|
|
|
- 3137 qn[0] := CHR(0); .)
|
|
|
|
|
- 3138 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
|
|
- 3139 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
|
|
- 3140 uok);
|
|
|
|
|
- 3141 isStr := FALSE;
|
|
|
|
|
- 3142 IF NOT uok THEN
|
|
|
|
|
- 3143 SemError(234);
|
|
|
|
|
- 3144 dt := SymTab.InvalidType
|
|
|
|
|
- 3145 ELSIF isU THEN
|
|
|
|
|
- 3146 (* one codepoint: a UCHAR;
|
|
|
|
|
- 3147 LEN is 1, HIGH is 0 *)
|
|
|
|
|
- 3148 dt := SymTab.UCharType();
|
|
|
|
|
- 3149 QbeGen.IntStr(ucp, qd)
|
|
|
|
|
- 3150 ELSE
|
|
|
|
|
- 3151 dt := SymTab.NewUStr();
|
|
|
|
|
- 3152 END;
|
|
|
|
|
- 3153 dk := -1;
|
|
|
|
|
- 3154 qn[0] := CHR(0); .) )
|
|
|
|
|
- 3155 ")"
|
|
|
|
|
- 3156 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3157 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
|
|
- 3158 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
|
|
- 3159 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
- 3160 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
|
|
- 3161 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3162 astCur := astNode; astIsLit := TRUE;
|
|
|
|
|
- 3163 IF (dt # SymTab.InvalidType)
|
|
|
|
|
- 3164 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
|
|
- 3165 (* UString: the count is
|
|
|
|
|
- 3166 the descriptor header *)
|
|
|
|
|
- 3167 t := SymTab.IntType();
|
|
|
|
|
- 3168 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3169 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
- 3170 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
|
|
- 3171 (* single UCHAR codepoint *)
|
|
|
|
|
|
|
+ 2444 = SymTab.ClNil)) THEN
|
|
|
|
|
+ 2445 IF cls = SymTab.ClNil THEN
|
|
|
|
|
+ 2446 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2447 ELSIF ((cls
|
|
|
|
|
+ 2448 = SymTab.ClInt)
|
|
|
|
|
+ 2449 OR (cls
|
|
|
|
|
+ 2450 = SymTab.ClChar)
|
|
|
|
|
+ 2451 OR (cls
|
|
|
|
|
+ 2452 = SymTab.ClEnum)
|
|
|
|
|
+ 2453 OR (cls
|
|
|
|
|
+ 2454 = SymTab.ClLong))
|
|
|
|
|
+ 2455 AND SymTab.GetSymVal(n, cv)
|
|
|
|
|
+ 2456 AND QbeGen.IsImm(cv) THEN
|
|
|
|
|
+ 2457 QbeGen.CopyOp(cv, q)
|
|
|
|
|
+ 2458 ELSE
|
|
|
|
|
+ 2459 QbeGen.LoadVar(n,
|
|
|
|
|
+ 2460 cls = SymTab.ClReal,
|
|
|
|
|
+ 2461 q)
|
|
|
|
|
+ 2462 END
|
|
|
|
|
+ 2463 ELSIF (cls = SymTab.ClArray)
|
|
|
|
|
+ 2464 OR (cls = SymTab.ClRecord)
|
|
|
|
|
+ 2465 OR (cls = SymTab.ClClass)
|
|
|
|
|
+ 2466 OR (cls = SymTab.ClStr)
|
|
|
|
|
+ 2467 OR (cls = SymTab.ClUStr) THEN
|
|
|
|
|
+ 2468 (* aggregate constant:
|
|
|
|
|
+ 2469 its value IS the
|
|
|
|
|
+ 2470 descriptor address *)
|
|
|
|
|
+ 2471 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
|
|
+ 2472 QbeGen.CopyOp(cv, q)
|
|
|
|
|
+ 2473 ELSE
|
|
|
|
|
+ 2474 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2475 END
|
|
|
|
|
+ 2476 ELSE
|
|
|
|
|
+ 2477 IF t #
|
|
|
|
|
+ 2478 SymTab.InvalidType THEN
|
|
|
|
|
+ 2479 SemError(230)
|
|
|
|
|
+ 2480 END;
|
|
|
|
|
+ 2481 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2482 END
|
|
|
|
|
+ 2483 END
|
|
|
|
|
+ 2484 ELSIF (k = SymTab.KindVar)
|
|
|
|
|
+ 2485 OR (k = SymTab.KindParam) THEN
|
|
|
|
|
+ 2486 cls := SymTab.ClassOf(t);
|
|
|
|
|
+ 2487 IF (cls # SymTab.ClInt)
|
|
|
|
|
+ 2488 AND (cls # SymTab.ClBool)
|
|
|
|
|
+ 2489 AND (cls # SymTab.ClChar)
|
|
|
|
|
+ 2490 AND (cls # SymTab.ClUChar)
|
|
|
|
|
+ 2491 AND (cls # SymTab.ClEnum)
|
|
|
|
|
+ 2492 AND (cls # SymTab.ClReal)
|
|
|
|
|
+ 2493 AND (cls # SymTab.ClPtr)
|
|
|
|
|
+ 2494 AND (cls # SymTab.ClProc)
|
|
|
|
|
+ 2495 AND (cls # SymTab.ClLong)
|
|
|
|
|
+ 2496 AND (cls # SymTab.ClArray)
|
|
|
|
|
+ 2497 AND (cls # SymTab.ClSet)
|
|
|
|
|
+ 2498 AND (cls # SymTab.ClRecord)
|
|
|
|
|
+ 2499 AND (cls # SymTab.ClUStr)
|
|
|
|
|
+ 2500 AND (cls # SymTab.ClClass) THEN
|
|
|
|
|
+ 2501 SemError(230);
|
|
|
|
|
+ 2502 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2503 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2504 END
|
|
|
|
|
+ 2505 ELSE QbeGen.CopyOp("0", q);
|
|
|
|
|
+ 2506 IF k = SymTab.KindImport THEN
|
|
|
|
|
+ 2507 SemError(230)
|
|
|
|
|
+ 2508 ELSIF k =
|
|
|
|
|
+ 2509 SymTab.KindProc THEN
|
|
|
|
|
+ 2510 (* bare procedure name:
|
|
|
|
|
+ 2511 a following ArgList
|
|
|
|
|
+ 2512 makes it a call;
|
|
|
|
|
+ 2513 otherwise Fact
|
|
|
|
|
+ 2514 reports 230 *)
|
|
|
|
|
+ 2515 ELSE
|
|
|
|
|
+ 2516 IF k = SymTab.KindField THEN
|
|
|
|
|
+ 2517 IF QbeGen.TopWith(qb) THEN
|
|
|
|
|
+ 2518 sfx := TRUE
|
|
|
|
|
+ 2519 ELSE SemError(230);
|
|
|
|
|
+ 2520 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2521 END
|
|
|
|
|
+ 2522 END
|
|
|
|
|
+ 2523 END
|
|
|
|
|
+ 2524 END
|
|
|
|
|
+ 2525 END; .)
|
|
|
|
|
+ 2526 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
|
|
+ 2527 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
|
|
+ 2528 { "[" Expr<it, iq>
|
|
|
|
|
+ 2529 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
|
|
+ 2530 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2531 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2532 SymTab.ClArray THEN
|
|
|
|
|
+ 2533 SemError(217);
|
|
|
|
|
+ 2534 t := SymTab.InvalidType
|
|
|
|
|
+ 2535 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
+ 2536 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 2537 SymTab.ClChar)
|
|
|
|
|
+ 2538 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 2539 SymTab.ClEnum) THEN
|
|
|
|
|
+ 2540 SemError(218);
|
|
|
|
|
+ 2541 t := SymTab.InvalidType
|
|
|
|
|
+ 2542 ELSE
|
|
|
|
|
+ 2543 eT := SymTab.ArrayElem(t);
|
|
|
|
|
+ 2544 t := eT; sfx := TRUE
|
|
|
|
|
+ 2545 END; .)
|
|
|
|
|
+ 2546 { "," Expr<it, iq>
|
|
|
|
|
+ 2547 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
|
|
+ 2548 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2549 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2550 SymTab.ClArray THEN
|
|
|
|
|
+ 2551 SemError(217);
|
|
|
|
|
+ 2552 t := SymTab.InvalidType
|
|
|
|
|
+ 2553 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
+ 2554 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 2555 SymTab.ClChar)
|
|
|
|
|
+ 2556 AND (SymTab.ClassOf(it) #
|
|
|
|
|
+ 2557 SymTab.ClEnum) THEN
|
|
|
|
|
+ 2558 SemError(218);
|
|
|
|
|
+ 2559 t := SymTab.InvalidType
|
|
|
|
|
+ 2560 ELSE
|
|
|
|
|
+ 2561 eT := SymTab.ArrayElem(t);
|
|
|
|
|
+ 2562 t := eT; sfx := TRUE
|
|
|
|
|
+ 2563 END; .) }
|
|
|
|
|
+ 2564 "]"
|
|
|
|
|
+ 2565 | "." GetIdent<fn>
|
|
|
|
|
+ 2566 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
|
|
+ 2567 AST.SetOp(astSel, AST.SelField);
|
|
|
|
|
+ 2568 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
|
|
+ 2569 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
|
|
+ 2570 (* qualified L.x: materialize
|
|
|
|
|
+ 2571 the export, then load it *)
|
|
|
|
|
+ 2572 IF NOT SymTab.MaterializeAlias(n,
|
|
|
|
|
+ 2573 fn, mal) THEN
|
|
|
|
|
+ 2574 SemError(201);
|
|
|
|
|
+ 2575 t := SymTab.InvalidType;
|
|
|
|
|
+ 2576 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2577 ELSE
|
|
|
|
|
+ 2578 QbeGen.CopyOp(mal, qn);
|
|
|
|
|
+ 2579 t := SymTab.SymType(mal);
|
|
|
|
|
+ 2580 k := SymTab.SymKind(mal);
|
|
|
|
|
+ 2581 sfx := FALSE;
|
|
|
|
|
+ 2582 IF k = SymTab.KindProc THEN
|
|
|
|
|
+ 2583 (* call: ArgList supplies
|
|
|
|
|
+ 2584 the value *)
|
|
|
|
|
+ 2585 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2586 END
|
|
|
|
|
+ 2587 END
|
|
|
|
|
+ 2588 ELSIF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2589 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2590 SymTab.ClRecord)
|
|
|
|
|
+ 2591 AND (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2592 SymTab.ClClass) THEN
|
|
|
|
|
+ 2593 SemError(215);
|
|
|
|
|
+ 2594 t := SymTab.InvalidType
|
|
|
|
|
+ 2595 ELSIF (SymTab.ClassOf(t) =
|
|
|
|
|
+ 2596 SymTab.ClClass)
|
|
|
|
|
+ 2597 AND SymTab.MethodExists(t, fn) THEN
|
|
|
|
|
+ 2598 (* obj.Method: bind the
|
|
|
|
|
+ 2599 method and pass obj as
|
|
|
|
|
+ 2600 the hidden receiver; q
|
|
|
|
|
+ 2601 already holds the
|
|
|
|
|
+ 2602 object's address *)
|
|
|
|
|
+ 2603 QbeGen.CopyOp(fn, n);
|
|
|
|
|
+ 2604 QbeGen.CopyOp(fn, qn);
|
|
|
|
|
+ 2605 methCls := t;
|
|
|
|
|
+ 2606 k := SymTab.KindProc;
|
|
|
|
|
+ 2607 t := SymTab.InvalidType
|
|
|
|
|
+ 2608 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
+ 2609 fn) THEN
|
|
|
|
|
+ 2610 SemError(216);
|
|
|
|
|
+ 2611 t := SymTab.InvalidType
|
|
|
|
|
+ 2612 ELSE
|
|
|
|
|
+ 2613 t := SymTab.FieldType(t, fn);
|
|
|
|
|
+ 2614 sfx := TRUE
|
|
|
|
|
+ 2615 END; .)
|
|
|
|
|
+ 2616 | "^"
|
|
|
|
|
+ 2617 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
|
|
+ 2618 AST.SetOp(astSel, AST.SelDeref);
|
|
|
|
|
+ 2619 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2620 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2621 SymTab.ClPtr THEN
|
|
|
|
|
+ 2622 SemError(219);
|
|
|
|
|
+ 2623 t := SymTab.InvalidType
|
|
|
|
|
+ 2624 ELSE
|
|
|
|
|
+ 2625 bt := SymTab.PtrBase(t);
|
|
|
|
|
+ 2626 IF bt = SymTab.InvalidType THEN
|
|
|
|
|
+ 2627 ELSE
|
|
|
|
|
+ 2628 t := bt;
|
|
|
|
|
+ 2629 sfx := TRUE
|
|
|
|
|
+ 2630 END
|
|
|
|
|
+ 2631 END; .) } (. astCur := astDes; .) .
|
|
|
|
|
+ 2632 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
|
|
+ 2633 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
|
|
+ 2634 (a value, or a descriptor address for aggregates); each component
|
|
|
|
|
+ 2635 descends one level exactly like the Design components. *)
|
|
|
|
|
+ 2636 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
|
|
+ 2637 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
|
|
+ 2638 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
|
|
+ 2639 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
|
|
+ 2640 iq, ql, qlo, qhi, qe, qb:
|
|
|
|
|
+ 2641 QbeGen.QVal;
|
|
|
|
|
+ 2642 lo, hi, fo: INTEGER;
|
|
|
|
|
+ 2643 isOpen: BOOLEAN;
|
|
|
|
|
+ 2644 fname: SymTab.Name;
|
|
|
|
|
+ 2645 astWrap, astSel: AST.Node; .)
|
|
|
|
|
+ 2646 = "[" Expr<it, iq>
|
|
|
|
|
+ 2647 (. isM := FALSE;
|
|
|
|
|
+ 2648 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
|
|
+ 2649 astWrap := AST.MakeNode(
|
|
|
|
|
+ 2650 AST.NkDesignator);
|
|
|
|
|
+ 2651 AST.SetChild(astWrap, 0, node);
|
|
|
|
|
+ 2652 node := astWrap
|
|
|
|
|
+ 2653 END;
|
|
|
|
|
+ 2654 AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
+ 2655 AST.MakeUn(AST.NkSelector,
|
|
|
|
|
+ 2656 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2657 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2658 SymTab.ClArray THEN
|
|
|
|
|
+ 2659 SemError(217);
|
|
|
|
|
+ 2660 t := SymTab.InvalidType
|
|
|
|
|
+ 2661 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
|
|
+ 2662 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
|
|
+ 2663 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
|
|
+ 2664 SemError(218);
|
|
|
|
|
+ 2665 t := SymTab.InvalidType
|
|
|
|
|
+ 2666 ELSE
|
|
|
|
|
+ 2667 eT := SymTab.ArrayElem(t);
|
|
|
|
|
+ 2668 t := eT; sfx := TRUE
|
|
|
|
|
+ 2669 END; .)
|
|
|
|
|
+ 2670 "]"
|
|
|
|
|
+ 2671 | "." GetIdent<fname>
|
|
|
|
|
+ 2672 (. isM := FALSE;
|
|
|
|
|
+ 2673 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
|
|
+ 2674 astWrap := AST.MakeNode(
|
|
|
|
|
+ 2675 AST.NkDesignator);
|
|
|
|
|
+ 2676 AST.SetChild(astWrap, 0, node);
|
|
|
|
|
+ 2677 node := astWrap
|
|
|
|
|
+ 2678 END;
|
|
|
|
|
+ 2679 AST.SetChild(node, AST.NChild(node),
|
|
|
|
|
+ 2680 AST.MakeUn(AST.NkSelector,
|
|
|
|
|
+ 2681 AST.SelField,
|
|
|
|
|
+ 2682 AST.MakeLeaf(AST.NkIdent,
|
|
|
|
|
+ 2683 fname))); IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2684 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
+ 2685 SymTab.ClRecord)
|
|
|
|
|
+ 2686 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
+ 2687 SemError(215);
|
|
|
|
|
+ 2688 t := SymTab.InvalidType
|
|
|
|
|
+ 2689 ELSIF (SymTab.ClassOf(t) =
|
|
|
|
|
+ 2690 SymTab.ClClass)
|
|
|
|
|
+ 2691 AND SymTab.MethodExists(t, fname) THEN
|
|
|
|
|
+ 2692 (* a method on the call result:
|
|
|
|
|
+ 2693 a following ArgList makes
|
|
|
|
|
+ 2694 the call *)
|
|
|
|
|
+ 2695 mname := fname;
|
|
|
|
|
+ 2696 methCls := t; isM := TRUE;
|
|
|
|
|
+ 2697 t := SymTab.InvalidType
|
|
|
|
|
+ 2698 ELSIF NOT SymTab.FieldExists(t,
|
|
|
|
|
+ 2699 fname) THEN
|
|
|
|
|
+ 2700 SemError(216);
|
|
|
|
|
+ 2701 t := SymTab.InvalidType
|
|
|
|
|
+ 2702 ELSE
|
|
|
|
|
+ 2703 t := SymTab.FieldType(t, fname);
|
|
|
|
|
+ 2704 sfx := TRUE
|
|
|
|
|
+ 2705 END; .)
|
|
|
|
|
+ 2706 | "^" (. isM := FALSE;
|
|
|
|
|
+ 2707 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
|
|
+ 2708 astWrap := AST.MakeNode(
|
|
|
|
|
+ 2709 AST.NkDesignator);
|
|
|
|
|
+ 2710 AST.SetChild(astWrap, 0, node);
|
|
|
|
|
+ 2711 node := astWrap
|
|
|
|
|
+ 2712 END;
|
|
|
|
|
+ 2713 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
|
|
+ 2714 AST.SetOp(astSel, AST.SelDeref);
|
|
|
|
|
+ 2715 AST.SetChild(node,
|
|
|
|
|
+ 2716 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 2717 ELSIF SymTab.ClassOf(t) #
|
|
|
|
|
+ 2718 SymTab.ClPtr THEN
|
|
|
|
|
+ 2719 SemError(219);
|
|
|
|
|
+ 2720 t := SymTab.InvalidType
|
|
|
|
|
+ 2721 ELSE
|
|
|
|
|
+ 2722 bt := SymTab.PtrBase(t);
|
|
|
|
|
+ 2723 IF bt # SymTab.InvalidType THEN
|
|
|
|
|
+ 2724 t := bt; sfx := TRUE
|
|
|
|
|
+ 2725 END
|
|
|
|
|
+ 2726 END; .) .
|
|
|
|
|
+ 2727 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2728 (. VAR t2: SymTab.TypeIndex;
|
|
|
|
|
+ 2729 op: INTEGER;
|
|
|
|
|
+ 2730 q2, qt, wl: QbeGen.QVal;
|
|
|
|
|
+ 2731 astA, astB: AST.Node;
|
|
|
|
|
+ 2732 astOp: INTEGER;
|
|
|
|
|
+ 2733 astMade: BOOLEAN;
|
|
|
|
|
+ 2734 isR: BOOLEAN; .)
|
|
|
|
|
+ 2735 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
|
|
+ 2736 [ Rel<op> SimExpr<t2, q2>
|
|
|
|
|
+ 2737 (. astB := astCur; astMade := TRUE;
|
|
|
|
|
+ 2738 astOp := AST.OpEq;
|
|
|
|
|
+ 2739 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
|
|
+ 2740 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
|
|
+ 2741 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
|
|
+ 2742 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
|
|
+ 2743 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
|
|
+ 2744 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
|
|
+ 2745 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
|
|
+ 2746 END;
|
|
|
|
|
+ 2747 IF op = SymTab.OpIn THEN
|
|
|
|
|
+ 2748 IF SymTab.InCheck(t, t2) THEN
|
|
|
|
|
+ 2749 IF (t = SymTab.InvalidType)
|
|
|
|
|
+ 2750 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
+ 2751 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2752 ELSE
|
|
|
|
|
+ 2753 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2754 END
|
|
|
|
|
+ 2755 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
|
|
+ 2756 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2757 END
|
|
|
|
|
+ 2758 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
|
|
+ 2759 IF (t = SymTab.InvalidType)
|
|
|
|
|
+ 2760 OR (t2 = SymTab.InvalidType) THEN
|
|
|
|
|
+ 2761 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2762 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
|
|
+ 2763 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
|
|
+ 2764 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
|
|
+ 2765 AND (op # SymTab.OpNeq2) THEN
|
|
|
|
|
+ 2766 SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
+ 2767 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2768 ELSE
|
|
|
|
|
+ 2769 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2770 END
|
|
|
|
|
+ 2771 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
+ 2772 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
+ 2773 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2774 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
|
|
+ 2775 QbeGen.StrEq(op, q, q2, qt);
|
|
|
|
|
+ 2776 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2777 ELSIF SymTab.IsLongFamily(t)
|
|
|
|
|
+ 2778 OR SymTab.IsLongFamily(t2) THEN
|
|
|
|
|
+ 2779 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2780 ELSE
|
|
|
|
|
+ 2781 t := SymTab.BoolType();
|
|
|
|
|
+ 2782 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2783 END
|
|
|
|
|
+ 2784 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
|
|
+ 2785 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2786 END;
|
|
|
|
|
+ 2787 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
|
|
+ 2788 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
|
|
+ 2789 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
+ 2790 Rel<VAR op: INTEGER>
|
|
|
|
|
+ 2791 = "=" (. op := SymTab.OpEq; .)
|
|
|
|
|
+ 2792 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
|
|
+ 2793 | "<" (. op := SymTab.OpLt; .)
|
|
|
|
|
+ 2794 | "<=" (. op := SymTab.OpLe; .)
|
|
|
|
|
+ 2795 | ">" (. op := SymTab.OpGt; .)
|
|
|
|
|
+ 2796 | ">=" (. op := SymTab.OpGe; .)
|
|
|
|
|
+ 2797 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
|
|
+ 2798 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2799 (. VAR t2, res2, lt, rt:
|
|
|
|
|
+ 2800 SymTab.TypeIndex;
|
|
|
|
|
+ 2801 op: INTEGER;
|
|
|
|
|
+ 2802 q2, qt, wq, qf, q2a, q2b:
|
|
|
|
|
+ 2803 QbeGen.QVal;
|
|
|
|
|
+ 2804 neg, isR, isL, folded:
|
|
|
|
|
+ 2805 BOOLEAN;
|
|
|
|
|
+ 2806 fok: BOOLEAN;
|
|
|
|
|
+ 2807 lw, rw, mw: CARDINAL;
|
|
|
|
|
+ 2808 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
|
|
+ 2809 astA, astB: AST.Node;
|
|
|
|
|
+ 2810 astSign, astOp: INTEGER; .)
|
|
|
|
|
+ 2811 = (. neg := FALSE; astSign := 0; .)
|
|
|
|
|
+ 2812 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
|
|
+ 2813 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
|
|
+ 2814 Term<t, q> (. astA := astCur;
|
|
|
|
|
+ 2815 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
|
|
+ 2816 QbeGen.NegFold(q, q)
|
|
|
|
|
+ 2817 END;
|
|
|
|
|
+ 2818 IF astSign < 0 THEN
|
|
|
|
|
+ 2819 astCur := AST.MakeUn(
|
|
|
|
|
+ 2820 AST.NkUnary, AST.OpSub, astA);
|
|
|
|
|
+ 2821 astA := astCur
|
|
|
|
|
+ 2822 END; .)
|
|
|
|
|
+ 2823 { AddOp<op>
|
|
|
|
|
+ 2824 Term<t2, q2> (. astB := astCur; .)
|
|
|
|
|
+ 2825 (. astOp := AST.OpAdd;
|
|
|
|
|
+ 2826 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
|
|
+ 2827 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
|
|
+ 2828 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
|
|
+ 2829 astCur := astA;
|
|
|
|
|
+ 2830 IF op = SymTab.OpOr THEN
|
|
|
|
|
+ 2831 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
|
|
+ 2832 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 2833 t := SymTab.BoolType()
|
|
|
|
|
+ 2834 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2835 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2836 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2837 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2838 END
|
|
|
|
|
+ 2839 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
+ 2840 AND (SymTab.UStrCompat(t, t2)
|
|
|
|
|
+ 2841 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
+ 2842 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
|
|
+ 2843 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
|
|
+ 2844 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
|
|
+ 2845 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
|
|
+ 2846 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
|
|
+ 2847 (* UString concatenation: a UCHAR operand becomes a
|
|
|
|
|
+ 2848 1-codepoint UString; the result is a descriptor in the
|
|
|
|
|
+ 2849 shim's concat buffer. Work on copies so neither
|
|
|
|
|
+ 2850 operand is clobbered. *)
|
|
|
|
|
+ 2851 t := SymTab.NewUStr();
|
|
|
|
|
+ 2852 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2853 ELSIF (op = SymTab.OpAdd)
|
|
|
|
|
+ 2854 AND (SymTab.StrCompat(t, t2)
|
|
|
|
|
+ 2855 OR (SymTab.IsStrType(t)
|
|
|
|
|
+ 2856 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
|
|
+ 2857 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
|
|
+ 2858 AND SymTab.IsStrType(t2))) THEN
|
|
|
|
|
+ 2859 (* string concatenation; a CHAR operand becomes a
|
|
|
|
|
+ 2860 1-character string literal. When both operands are
|
|
|
|
|
+ 2861 constants, fold to a single string literal so a
|
|
|
|
|
+ 2862 constructor element stays compile-time. *)
|
|
|
|
|
+ 2863 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
|
|
+ 2864 qt, fok);
|
|
|
|
|
+ 2865 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
|
|
+ 2866 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2867 END;
|
|
|
|
|
+ 2868 t := SymTab.NewStr()
|
|
|
|
|
+ 2869 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
+ 2870 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
+ 2871 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
+ 2872 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
+ 2873 mw := lw;
|
|
|
|
|
+ 2874 IF rw > mw THEN mw := rw END;
|
|
|
|
|
+ 2875 t := SymTab.NewSet(
|
|
|
|
|
+ 2876 SymTab.NewSubR(0,
|
|
|
|
|
+ 2877 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
+ 2878 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2879 ELSE
|
|
|
|
|
+ 2880 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
|
|
+ 2881 lt := t; rt := t2; t := res2
|
|
|
|
|
+ 2882 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2883 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2884 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
+ 2885 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 2886 folded := FALSE;
|
|
|
|
|
+ 2887 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
+ 2888 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 2889 IF op = SymTab.OpAdd THEN
|
|
|
|
|
+ 2890 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
|
|
+ 2891 ELSE
|
|
|
|
|
+ 2892 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
|
|
+ 2893 END
|
|
|
|
|
+ 2894 END;
|
|
|
|
|
+ 2895 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
+ 2896 ELSE
|
|
|
|
|
+ 2897 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2898 END
|
|
|
|
|
+ 2899 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2900 END
|
|
|
|
|
+ 2901 END; .) }
|
|
|
|
|
+ 2902 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
+ 2903 AddOp<VAR op: INTEGER>
|
|
|
|
|
+ 2904 = "+" (. op := SymTab.OpAdd; .)
|
|
|
|
|
+ 2905 | "-" (. op := SymTab.OpSub; .)
|
|
|
|
|
+ 2906 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
|
|
+ 2907 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2908 (. VAR t2, res2, lt, rt:
|
|
|
|
|
+ 2909 SymTab.TypeIndex;
|
|
|
|
|
+ 2910 op: INTEGER;
|
|
|
|
|
+ 2911 q2, qt, wq, qf:
|
|
|
|
|
+ 2912 QbeGen.QVal;
|
|
|
|
|
+ 2913 isR, isL, folded: BOOLEAN;
|
|
|
|
|
+ 2914 lw, rw, mw: CARDINAL;
|
|
|
|
|
+ 2915 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
|
|
+ 2916 astA, astB: AST.Node;
|
|
|
|
|
+ 2917 astOp: INTEGER; .)
|
|
|
|
|
+ 2918 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
|
|
+ 2919 Fact<t2, q2> (. astB := astCur; .)
|
|
|
|
|
+ 2920 (. astOp := AST.OpMul;
|
|
|
|
|
+ 2921 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
|
|
+ 2922 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
|
|
+ 2923 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
|
|
+ 2924 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
|
|
+ 2925 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
|
|
+ 2926 astCur := astA;
|
|
|
|
|
+ 2927 IF op = SymTab.OpAnd THEN
|
|
|
|
|
+ 2928 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
|
|
+ 2929 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 2930 t := SymTab.BoolType()
|
|
|
|
|
+ 2931 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2932 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2933 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2934 END
|
|
|
|
|
+ 2935 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
|
|
+ 2936 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
|
|
+ 2937 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
|
|
+ 2938 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
|
|
+ 2939 mw := lw;
|
|
|
|
|
+ 2940 IF rw > mw THEN mw := rw END;
|
|
|
|
|
+ 2941 t := SymTab.NewSet(
|
|
|
|
|
+ 2942 SymTab.NewSubR(0,
|
|
|
|
|
+ 2943 VAL(INTEGER, mw) * 32 - 1));
|
|
|
|
|
+ 2944 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2945 ELSE
|
|
|
|
|
+ 2946 IF SymTab.ArithCheck(t, t2,
|
|
|
|
|
+ 2947 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
|
|
+ 2948 res2) THEN
|
|
|
|
|
+ 2949 lt := t; rt := t2; t := res2
|
|
|
|
|
+ 2950 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
|
|
+ 2951 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 2952 isL := SymTab.IsLongFamily(t);
|
|
|
|
|
+ 2953 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
|
|
+ 2954 folded := FALSE;
|
|
|
|
|
+ 2955 IF (NOT isL) AND (NOT isR)
|
|
|
|
|
+ 2956 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
|
|
+ 2957 IF op = SymTab.OpTimes THEN
|
|
|
|
|
+ 2958 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
|
|
+ 2959 ELSIF op = SymTab.OpDiv THEN
|
|
|
|
|
+ 2960 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
|
|
+ 2961 ELSIF op = SymTab.OpMod THEN
|
|
|
|
|
+ 2962 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
|
|
+ 2963 END
|
|
|
|
|
+ 2964 END;
|
|
|
|
|
+ 2965 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
|
|
+ 2966 ELSE
|
|
|
|
|
+ 2967 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 2968 END
|
|
|
|
|
+ 2969 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 2970 END
|
|
|
|
|
+ 2971 END; .) }
|
|
|
|
|
+ 2972 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
+ 2973 MulOp<VAR op: INTEGER>
|
|
|
|
|
+ 2974 = "*" (. op := SymTab.OpTimes; .)
|
|
|
|
|
+ 2975 | "/" (. op := SymTab.OpSlash; .)
|
|
|
|
|
+ 2976 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
|
|
+ 2977 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
|
|
+ 2978 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
|
|
+ 2979 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 2980 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
|
|
+ 2981 et, dt, t2, st, ct2, et2:
|
|
|
|
|
+ 2982 SymTab.TypeIndex;
|
|
|
|
|
+ 2983 dk: INTEGER;
|
|
|
|
|
+ 2984 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
|
|
+ 2985 QbeGen.QVal;
|
|
|
|
|
+ 2986 qn, vn: SymTab.Name;
|
|
|
|
|
+ 2987 vt: SymTab.TypeIndex;
|
|
|
|
|
+ 2988 c1, c2: INTEGER;
|
|
|
|
|
+ 2989 lo, hi: INTEGER;
|
|
|
|
|
+ 2990 isMax: BOOLEAN;
|
|
|
|
|
+ 2991 called, isHigh, sfx, isCh,
|
|
|
|
|
+ 2992 isU, uok, isStr: BOOLEAN;
|
|
|
|
|
+ 2993 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
|
|
+ 2994 astD: AST.Node;
|
|
|
|
|
+ 2995 astCall: BOOLEAN;
|
|
|
|
|
+ 2996 astNode, astNot: AST.Node;
|
|
|
|
|
+ 2997 j: CARDINAL;
|
|
|
|
|
+ 2998 astArg2: AST.Node;
|
|
|
|
|
+ 2999 astBrace: AST.Node;
|
|
|
|
|
+ 3000 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
|
|
|
|
|
+ 3001 = (. astIsLit := FALSE; .)
|
|
|
|
|
+ 3002 ( integer (. LexString(s);
|
|
|
|
|
+ 3003 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
|
|
+ 3004 t := SymTab.IntType(); .)
|
|
|
|
|
+ 3005 | charConst (. LexString(s);
|
|
|
|
|
+ 3006 QbeGen.NormLit(s, q, isCh);
|
|
|
|
|
+ 3007 astIsLit := TRUE;
|
|
|
|
|
+ 3008 astCur := AST.MakeLeaf(
|
|
|
|
|
+ 3009 AST.NkCharLit, s);
|
|
|
|
|
+ 3010 t := SymTab.CharType(); .)
|
|
|
|
|
+ 3011 | real (. LexString(s);
|
|
|
|
|
+ 3012 QbeGen.NormReal(s, q);
|
|
|
|
|
+ 3013 astIsLit := TRUE;
|
|
|
|
|
+ 3014 astCur := AST.MakeLeaf(
|
|
|
|
|
+ 3015 AST.NkRealLit, s);
|
|
|
|
|
+ 3016 t := SymTab.RealType(); .)
|
|
|
|
|
+ 3017 | string (. LexString(s);
|
|
|
|
|
+ 3018 astIsLit := TRUE;
|
|
|
|
|
+ 3019 astCur := AST.MakeLeaf(
|
|
|
|
|
+ 3020 AST.NkStrLit, s);
|
|
|
|
|
+ 3021 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
+ 3022 t := SymTab.CharType();
|
|
|
|
|
+ 3023 QbeGen.IntStr(
|
|
|
|
|
+ 3024 QbeGen.CharVal(s), q)
|
|
|
|
|
+ 3025 ELSE t := SymTab.NewStr();
|
|
|
|
|
+ 3026 QbeGen.DeclStr(s, q);
|
|
|
|
|
+ 3027 (* a literal's value IS its
|
|
|
|
|
+ 3028 static descriptor address *)
|
|
|
|
|
+ 3029 END; .)
|
|
|
|
|
+ 3030 | ustring (. LexString(s);
|
|
|
|
|
+ 3031 astIsLit := TRUE;
|
|
|
|
|
+ 3032 astCur := AST.MakeLeaf(
|
|
|
|
|
+ 3033 AST.NkStrLit, s);
|
|
|
|
|
+ 3034 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
|
|
+ 3035 uok);
|
|
|
|
|
+ 3036 IF NOT uok THEN
|
|
|
|
|
+ 3037 SemError(234);
|
|
|
|
|
+ 3038 t := SymTab.InvalidType
|
|
|
|
|
+ 3039 ELSIF isU THEN
|
|
|
|
|
+ 3040 t := SymTab.UCharType();
|
|
|
|
|
+ 3041 QbeGen.IntStr(ucp, q)
|
|
|
|
|
+ 3042 ELSE
|
|
|
|
|
+ 3043 t := SymTab.NewUStr();
|
|
|
|
|
+ 3044 END; .)
|
|
|
|
|
+ 3045 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
|
|
+ 3046 astNArgs := 0; called := FALSE;
|
|
|
|
|
+ 3047 t := dt;
|
|
|
|
|
+ 3048 IF dk = SymTab.KindConst THEN
|
|
|
|
|
+ 3049 QbeGen.CopyOp(qd, q)
|
|
|
|
|
+ 3050 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3051 END; .)
|
|
|
|
|
+ 3052 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
|
|
+ 3053 astBrace := astCur; .) ]
|
|
|
|
|
+ 3054 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
+ 3055 (. astCall := TRUE;
|
|
|
|
|
+ 3056 astNode := AstCallNode(astD);
|
|
|
|
|
+ 3057 astRes := astNode;
|
|
|
|
|
+ 3058 t := ct2;
|
|
|
|
|
+ 3059 QbeGen.CopyOp(q2, q);
|
|
|
|
|
+ 3060 sfx := FALSE; .)
|
|
|
|
|
+ 3061 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
|
|
+ 3062 [ (. astNArgs := 0; .)
|
|
|
|
|
+ 3063 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
|
|
+ 3064 (. astNode := AstCallNode(astRes);
|
|
|
|
|
+ 3065 astRes := astNode;
|
|
|
|
|
+ 3066 t := ct2;
|
|
|
|
|
+ 3067 QbeGen.CopyOp(q2, q);
|
|
|
|
|
+ 3068 sfx := FALSE; .) ] }
|
|
|
|
|
+ 3069 (. IF sfx THEN
|
|
|
|
|
+ 3070 IF t = SymTab.InvalidType THEN
|
|
|
|
|
+ 3071 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3072 ELSIF (SymTab.ClassOf(t) #
|
|
|
|
|
+ 3073 SymTab.ClRecord)
|
|
|
|
|
+ 3074 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
|
|
+ 3075 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
|
|
+ 3076 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
|
|
+ 3077 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3078 END
|
|
|
|
|
+ 3079 END; .) ]
|
|
|
|
|
+ 3080 (. IF called THEN
|
|
|
|
|
+ 3081 astCur := astRes
|
|
|
|
|
+ 3082 ELSIF astCall THEN
|
|
|
|
|
+ 3083 astCur := astBrace
|
|
|
|
|
+ 3084 ELSE astCur := astD
|
|
|
|
|
+ 3085 END;
|
|
|
|
|
+ 3086 astIsLit := TRUE;
|
|
|
|
|
+ 3087 IF NOT called
|
|
|
|
|
+ 3088 AND (dk = SymTab.KindProc) THEN
|
|
|
|
|
+ 3089 (* bare zero-arg function
|
|
|
|
|
+ 3090 call (parentheses may be
|
|
|
|
|
+ 3091 omitted); a proper or
|
|
|
|
|
+ 3092 parameterised proc here
|
|
|
|
|
+ 3093 is 230 *)
|
|
|
|
|
+ 3094 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
|
|
+ 3095 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
|
|
+ 3096 t := SymTab.ProcRes(qn);
|
|
|
|
|
+ 3097 QbeGen.CopyOp("@", q);
|
|
|
|
|
+ 3098 astCur := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3099 AST.SetChild(astCur, 0, astD)
|
|
|
|
|
+ 3100 ELSE
|
|
|
|
|
+ 3101 t := SymTab.ProcTypeOf(qn);
|
|
|
|
|
+ 3102 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3103 END
|
|
|
|
|
+ 3104 END; .)
|
|
|
|
|
+ 3105 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
|
|
+ 3106 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
|
|
+ 3107 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
|
|
+ 3108 isU := FALSE; .)
|
|
|
|
|
+ 3109 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
|
|
+ 3110 isStr := TRUE;
|
|
|
|
|
+ 3111 isU := FALSE;
|
|
|
|
|
+ 3112 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
+ 3113 dt := SymTab.CharType();
|
|
|
|
|
+ 3114 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
|
|
+ 3115 qd)
|
|
|
|
|
+ 3116 ELSE
|
|
|
|
|
+ 3117 dt := SymTab.NewStr();
|
|
|
|
|
+ 3118 QbeGen.DeclStr(s, qd);
|
|
|
|
|
+ 3119 END;
|
|
|
|
|
+ 3120 dk := -1;
|
|
|
|
|
+ 3121 qn[0] := CHR(0); .)
|
|
|
|
|
+ 3122 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
|
|
+ 3123 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
|
|
+ 3124 uok);
|
|
|
|
|
+ 3125 isStr := FALSE;
|
|
|
|
|
+ 3126 IF NOT uok THEN
|
|
|
|
|
+ 3127 SemError(234);
|
|
|
|
|
+ 3128 dt := SymTab.InvalidType
|
|
|
|
|
+ 3129 ELSIF isU THEN
|
|
|
|
|
+ 3130 (* one codepoint: a UCHAR;
|
|
|
|
|
+ 3131 LEN is 1, HIGH is 0 *)
|
|
|
|
|
+ 3132 dt := SymTab.UCharType();
|
|
|
|
|
+ 3133 QbeGen.IntStr(ucp, qd)
|
|
|
|
|
+ 3134 ELSE
|
|
|
|
|
+ 3135 dt := SymTab.NewUStr();
|
|
|
|
|
+ 3136 END;
|
|
|
|
|
+ 3137 dk := -1;
|
|
|
|
|
+ 3138 qn[0] := CHR(0); .) )
|
|
|
|
|
+ 3139 ")"
|
|
|
|
|
+ 3140 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3141 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
|
|
+ 3142 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
|
|
+ 3143 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
+ 3144 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
|
|
+ 3145 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3146 astCur := astNode; astIsLit := TRUE;
|
|
|
|
|
+ 3147 IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 3148 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
|
|
+ 3149 (* UString: the count is
|
|
|
|
|
+ 3150 the descriptor header *)
|
|
|
|
|
+ 3151 t := SymTab.IntType();
|
|
|
|
|
+ 3152 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3153 ELSIF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 3154 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
|
|
+ 3155 (* single UCHAR codepoint *)
|
|
|
|
|
+ 3156 IF isHigh THEN
|
|
|
|
|
+ 3157 QbeGen.CopyOp("0", qr)
|
|
|
|
|
+ 3158 ELSE
|
|
|
|
|
+ 3159 QbeGen.CopyOp("1", qr)
|
|
|
|
|
+ 3160 END;
|
|
|
|
|
+ 3161 t := SymTab.IntType();
|
|
|
|
|
+ 3162 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 3163 ELSIF isStr THEN
|
|
|
|
|
+ 3164 (* fold: content length at
|
|
|
|
|
+ 3165 compile time *)
|
|
|
|
|
+ 3166 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
+ 3167 c1 := 1
|
|
|
|
|
+ 3168 ELSE
|
|
|
|
|
+ 3169 c1 :=
|
|
|
|
|
+ 3170 SymTab.StrLen(s) - 2
|
|
|
|
|
+ 3171 END;
|
|
|
3172 IF isHigh THEN
|
|
3172 IF isHigh THEN
|
|
|
- 3173 QbeGen.CopyOp("0", qr)
|
|
|
|
|
- 3174 ELSE
|
|
|
|
|
- 3175 QbeGen.CopyOp("1", qr)
|
|
|
|
|
- 3176 END;
|
|
|
|
|
- 3177 t := SymTab.IntType();
|
|
|
|
|
- 3178 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 3179 ELSIF isStr THEN
|
|
|
|
|
- 3180 (* fold: content length at
|
|
|
|
|
- 3181 compile time *)
|
|
|
|
|
- 3182 IF SymTab.StrLen(s) = 3 THEN
|
|
|
|
|
- 3183 c1 := 1
|
|
|
|
|
- 3184 ELSE
|
|
|
|
|
- 3185 c1 :=
|
|
|
|
|
- 3186 SymTab.StrLen(s) - 2
|
|
|
|
|
- 3187 END;
|
|
|
|
|
- 3188 IF isHigh THEN
|
|
|
|
|
- 3189 DEC(c1)
|
|
|
|
|
- 3190 END;
|
|
|
|
|
- 3191 QbeGen.IntStr(c1, qr);
|
|
|
|
|
- 3192 t := SymTab.IntType();
|
|
|
|
|
- 3193 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 3194 ELSIF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 3195 t := SymTab.InvalidType;
|
|
|
|
|
- 3196 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3197 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
- 3198 SymTab.ClArray THEN
|
|
|
|
|
- 3199 SemError(217);
|
|
|
|
|
- 3200 t := SymTab.InvalidType;
|
|
|
|
|
- 3201 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3202 ELSE
|
|
|
|
|
- 3203 IF SymTab.IsOpenArray(dt) THEN
|
|
|
|
|
- 3204 t := SymTab.IntType();
|
|
|
|
|
- 3205 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3206 ELSE
|
|
|
|
|
- 3207 IF isHigh THEN
|
|
|
|
|
- 3208 QbeGen.IntStr(
|
|
|
|
|
- 3209 SymTab.ArrayHi(dt), qr)
|
|
|
|
|
- 3210 ELSE
|
|
|
|
|
- 3211 QbeGen.IntStr(VAL(
|
|
|
|
|
- 3212 INTEGER,
|
|
|
|
|
- 3213 SymTab.ArrayLen(dt)),
|
|
|
|
|
- 3214 qr)
|
|
|
|
|
- 3215 END;
|
|
|
|
|
- 3216 t := SymTab.IntType();
|
|
|
|
|
- 3217 QbeGen.CopyOp(qr, q)
|
|
|
|
|
- 3218 END
|
|
|
|
|
- 3219 END; .)
|
|
|
|
|
- 3220 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 3221 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3222 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
|
|
- 3223 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3224 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3225 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 3226 t := SymTab.InvalidType;
|
|
|
|
|
- 3227 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3228 ELSE
|
|
|
|
|
- 3229 QbeGen.IntStr(VAL(INTEGER,
|
|
|
|
|
- 3230 SymTab.ObjectSize(dt)), q);
|
|
|
|
|
- 3231 t := SymTab.IntType()
|
|
|
|
|
- 3232 END; .)
|
|
|
|
|
- 3233 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
|
|
- 3234 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
|
|
- 3235 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
|
|
- 3236 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3237 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
|
|
- 3238 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
|
|
- 3239 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
- 3240 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
|
|
- 3241 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
|
|
- 3242 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
|
|
- 3243 astCur := astNode; astIsLit := TRUE;
|
|
|
|
|
- 3244 (* set shift/rotate: isMax
|
|
|
|
|
- 3245 doubles as "rotate" *)
|
|
|
|
|
- 3246 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 3247 AND (SymTab.ClassOf(et) =
|
|
|
|
|
- 3248 SymTab.ClSet) THEN
|
|
|
|
|
- 3249 t := et;
|
|
|
|
|
- 3250 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3251 ELSE SemError(230);
|
|
|
|
|
- 3252 t := SymTab.InvalidType;
|
|
|
|
|
- 3253 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3254 END; .)
|
|
|
|
|
- 3255 | ( "MIN" (. isMax := FALSE; .)
|
|
|
|
|
- 3256 | "MAX" (. isMax := TRUE; .) )
|
|
|
|
|
- 3257 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 3258 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3259 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
|
|
- 3260 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
|
|
- 3261 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
- 3262 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
|
|
- 3263 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3264 astCur := astNode; astIsLit := TRUE;
|
|
|
|
|
- 3265 IF (dt # SymTab.InvalidType)
|
|
|
|
|
- 3266 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
|
|
- 3267 (* REAL/LONGREAL: the
|
|
|
|
|
- 3268 implementation bounds *)
|
|
|
|
|
- 3269 IF isMax THEN
|
|
|
|
|
- 3270 QbeGen.NormReal(
|
|
|
|
|
- 3271 "3.402823e38", q)
|
|
|
|
|
- 3272 ELSE QbeGen.NormReal(
|
|
|
|
|
- 3273 "-3.402823e38", q)
|
|
|
|
|
- 3274 END;
|
|
|
|
|
- 3275 t := SymTab.RealType()
|
|
|
|
|
- 3276 ELSIF (dt #
|
|
|
|
|
- 3277 SymTab.InvalidType)
|
|
|
|
|
- 3278 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
- 3279 SymTab.ClLong) THEN
|
|
|
|
|
- 3280 IF isMax THEN
|
|
|
|
|
- 3281 QbeGen.CopyOp(
|
|
|
|
|
- 3282 "9223372036854775807", q)
|
|
|
|
|
- 3283 ELSE QbeGen.CopyOp(
|
|
|
|
|
- 3284 "-9223372036854775808", q)
|
|
|
|
|
- 3285 END;
|
|
|
|
|
- 3286 t := SymTab.LongType()
|
|
|
|
|
- 3287 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
|
|
- 3288 hi) THEN
|
|
|
|
|
- 3289 IF isMax THEN
|
|
|
|
|
- 3290 QbeGen.IntStr(hi, q)
|
|
|
|
|
- 3291 ELSE QbeGen.IntStr(lo, q)
|
|
|
|
|
- 3292 END;
|
|
|
|
|
- 3293 t := SymTab.IntType()
|
|
|
|
|
- 3294 ELSE SemError(230);
|
|
|
|
|
- 3295 t := SymTab.InvalidType;
|
|
|
|
|
- 3296 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3297 END; .)
|
|
|
|
|
- 3298 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
- 3299 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3300 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
|
|
- 3301 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3302 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3303 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
- 3304 t := SymTab.InvalidType;
|
|
|
|
|
- 3305 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3306 ELSE
|
|
|
|
|
- 3307 IF sfx
|
|
|
|
|
- 3308 OR (dk = SymTab.KindVar)
|
|
|
|
|
- 3309 OR (dk = SymTab.KindParam) THEN
|
|
|
|
|
- 3310 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3311 ELSE SemError(230);
|
|
|
|
|
- 3312 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3313 END;
|
|
|
|
|
- 3314 t := SymTab.AddrType()
|
|
|
|
|
- 3315 END; .)
|
|
|
|
|
- 3316 | "CHR" "(" Expr<et, q> ")"
|
|
|
|
|
- 3317 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3318 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
|
|
- 3319 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3320 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3321 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
- 3322 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
- 3323 SemError(211) END;
|
|
|
|
|
- 3324 t := SymTab.CharType(); .)
|
|
|
|
|
- 3325 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
|
|
|
|
+ 3173 DEC(c1)
|
|
|
|
|
+ 3174 END;
|
|
|
|
|
+ 3175 QbeGen.IntStr(c1, qr);
|
|
|
|
|
+ 3176 t := SymTab.IntType();
|
|
|
|
|
+ 3177 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 3178 ELSIF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3179 t := SymTab.InvalidType;
|
|
|
|
|
+ 3180 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3181 ELSIF SymTab.ClassOf(dt) #
|
|
|
|
|
+ 3182 SymTab.ClArray THEN
|
|
|
|
|
+ 3183 SemError(217);
|
|
|
|
|
+ 3184 t := SymTab.InvalidType;
|
|
|
|
|
+ 3185 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3186 ELSE
|
|
|
|
|
+ 3187 IF SymTab.IsOpenArray(dt) THEN
|
|
|
|
|
+ 3188 t := SymTab.IntType();
|
|
|
|
|
+ 3189 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3190 ELSE
|
|
|
|
|
+ 3191 IF isHigh THEN
|
|
|
|
|
+ 3192 QbeGen.IntStr(
|
|
|
|
|
+ 3193 SymTab.ArrayHi(dt), qr)
|
|
|
|
|
+ 3194 ELSE
|
|
|
|
|
+ 3195 QbeGen.IntStr(VAL(
|
|
|
|
|
+ 3196 INTEGER,
|
|
|
|
|
+ 3197 SymTab.ArrayLen(dt)),
|
|
|
|
|
+ 3198 qr)
|
|
|
|
|
+ 3199 END;
|
|
|
|
|
+ 3200 t := SymTab.IntType();
|
|
|
|
|
+ 3201 QbeGen.CopyOp(qr, q)
|
|
|
|
|
+ 3202 END
|
|
|
|
|
+ 3203 END; .)
|
|
|
|
|
+ 3204 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 3205 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3206 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
|
|
+ 3207 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3208 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3209 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3210 t := SymTab.InvalidType;
|
|
|
|
|
+ 3211 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3212 ELSE
|
|
|
|
|
+ 3213 QbeGen.IntStr(VAL(INTEGER,
|
|
|
|
|
+ 3214 SymTab.ObjectSize(dt)), q);
|
|
|
|
|
+ 3215 t := SymTab.IntType()
|
|
|
|
|
+ 3216 END; .)
|
|
|
|
|
+ 3217 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
|
|
+ 3218 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
|
|
+ 3219 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
|
|
+ 3220 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3221 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
|
|
+ 3222 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
|
|
+ 3223 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
+ 3224 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
|
|
+ 3225 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
|
|
+ 3226 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
|
|
+ 3227 astCur := astNode; astIsLit := TRUE;
|
|
|
|
|
+ 3228 (* set shift/rotate: isMax
|
|
|
|
|
+ 3229 doubles as "rotate" *)
|
|
|
|
|
+ 3230 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 3231 AND (SymTab.ClassOf(et) =
|
|
|
|
|
+ 3232 SymTab.ClSet) THEN
|
|
|
|
|
+ 3233 t := et;
|
|
|
|
|
+ 3234 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3235 ELSE SemError(230);
|
|
|
|
|
+ 3236 t := SymTab.InvalidType;
|
|
|
|
|
+ 3237 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3238 END; .)
|
|
|
|
|
+ 3239 | ( "MIN" (. isMax := FALSE; .)
|
|
|
|
|
+ 3240 | "MAX" (. isMax := TRUE; .) )
|
|
|
|
|
+ 3241 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 3242 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3243 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
|
|
+ 3244 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
|
|
+ 3245 ELSE AST.SetChild(astNode, 0,
|
|
|
|
|
+ 3246 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
|
|
+ 3247 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3248 astCur := astNode; astIsLit := TRUE;
|
|
|
|
|
+ 3249 IF (dt # SymTab.InvalidType)
|
|
|
|
|
+ 3250 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
|
|
+ 3251 (* REAL/LONGREAL: the
|
|
|
|
|
+ 3252 implementation bounds *)
|
|
|
|
|
+ 3253 IF isMax THEN
|
|
|
|
|
+ 3254 QbeGen.NormReal(
|
|
|
|
|
+ 3255 "3.402823e38", q)
|
|
|
|
|
+ 3256 ELSE QbeGen.NormReal(
|
|
|
|
|
+ 3257 "-3.402823e38", q)
|
|
|
|
|
+ 3258 END;
|
|
|
|
|
+ 3259 t := SymTab.RealType()
|
|
|
|
|
+ 3260 ELSIF (dt #
|
|
|
|
|
+ 3261 SymTab.InvalidType)
|
|
|
|
|
+ 3262 AND (SymTab.ClassOf(dt) =
|
|
|
|
|
+ 3263 SymTab.ClLong) THEN
|
|
|
|
|
+ 3264 IF isMax THEN
|
|
|
|
|
+ 3265 QbeGen.CopyOp(
|
|
|
|
|
+ 3266 "9223372036854775807", q)
|
|
|
|
|
+ 3267 ELSE QbeGen.CopyOp(
|
|
|
|
|
+ 3268 "-9223372036854775808", q)
|
|
|
|
|
+ 3269 END;
|
|
|
|
|
+ 3270 t := SymTab.LongType()
|
|
|
|
|
+ 3271 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
|
|
+ 3272 hi) THEN
|
|
|
|
|
+ 3273 IF isMax THEN
|
|
|
|
|
+ 3274 QbeGen.IntStr(hi, q)
|
|
|
|
|
+ 3275 ELSE QbeGen.IntStr(lo, q)
|
|
|
|
|
+ 3276 END;
|
|
|
|
|
+ 3277 t := SymTab.IntType()
|
|
|
|
|
+ 3278 ELSE SemError(230);
|
|
|
|
|
+ 3279 t := SymTab.InvalidType;
|
|
|
|
|
+ 3280 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3281 END; .)
|
|
|
|
|
+ 3282 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
|
|
+ 3283 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3284 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
|
|
+ 3285 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3286 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3287 (. IF dt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3288 t := SymTab.InvalidType;
|
|
|
|
|
+ 3289 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3290 ELSE
|
|
|
|
|
+ 3291 IF sfx
|
|
|
|
|
+ 3292 OR (dk = SymTab.KindVar)
|
|
|
|
|
+ 3293 OR (dk = SymTab.KindParam) THEN
|
|
|
|
|
+ 3294 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3295 ELSE SemError(230);
|
|
|
|
|
+ 3296 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3297 END;
|
|
|
|
|
+ 3298 t := SymTab.AddrType()
|
|
|
|
|
+ 3299 END; .)
|
|
|
|
|
+ 3300 | "CHR" "(" Expr<et, q> ")"
|
|
|
|
|
+ 3301 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3302 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
|
|
+ 3303 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3304 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3305 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 3306 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
+ 3307 SemError(211) END;
|
|
|
|
|
+ 3308 t := SymTab.CharType(); .)
|
|
|
|
|
+ 3309 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
|
|
+ 3310 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3311 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
|
|
+ 3312 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3313 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3314 (. IF et # SymTab.InvalidType THEN
|
|
|
|
|
+ 3315 IF (SymTab.ClassOf(et) #
|
|
|
|
|
+ 3316 SymTab.ClChar)
|
|
|
|
|
+ 3317 AND (SymTab.ClassOf(et) #
|
|
|
|
|
+ 3318 SymTab.ClBool)
|
|
|
|
|
+ 3319 AND (SymTab.ClassOf(et) #
|
|
|
|
|
+ 3320 SymTab.ClEnum)
|
|
|
|
|
+ 3321 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
+ 3322 SemError(211) END
|
|
|
|
|
+ 3323 END;
|
|
|
|
|
+ 3324 t := SymTab.IntType(); .)
|
|
|
|
|
+ 3325 | "CAP" "(" Expr<et, q> ")"
|
|
|
3326 (. astNode := AST.MakeNode(AST.NkCall);
|
|
3326 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3327 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
|
|
|
|
+ 3327 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
3328 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
3328 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
3329 astCur := astNode; astIsLit := TRUE; .)
|
|
3329 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3330 (. IF et # SymTab.InvalidType THEN
|
|
|
|
|
- 3331 IF (SymTab.ClassOf(et) #
|
|
|
|
|
- 3332 SymTab.ClChar)
|
|
|
|
|
- 3333 AND (SymTab.ClassOf(et) #
|
|
|
|
|
- 3334 SymTab.ClBool)
|
|
|
|
|
- 3335 AND (SymTab.ClassOf(et) #
|
|
|
|
|
- 3336 SymTab.ClEnum)
|
|
|
|
|
- 3337 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
- 3338 SemError(211) END
|
|
|
|
|
- 3339 END;
|
|
|
|
|
- 3340 t := SymTab.IntType(); .)
|
|
|
|
|
- 3341 | "CAP" "(" Expr<et, q> ")"
|
|
|
|
|
- 3342 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3343 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
|
|
- 3344 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3345 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3346 (. QbeGen.CopyOp("@", q);
|
|
|
|
|
- 3347 t := SymTab.CharType(); .)
|
|
|
|
|
- 3348 | "UCHR" "(" Expr<et, q> ")"
|
|
|
|
|
- 3349 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3350 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
|
|
- 3351 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3352 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3353 (. (* UCHR: the UCHAR constructor.
|
|
|
|
|
- 3354 CHAR -> UCHAR (identity);
|
|
|
|
|
- 3355 INTEGER familly -> UCHAR
|
|
|
|
|
- 3356 (codepoint value). *)
|
|
|
|
|
- 3357 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 3358 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
|
|
- 3359 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
- 3360 SemError(211) END;
|
|
|
|
|
- 3361 t := SymTab.UCharType(); .)
|
|
|
|
|
- 3362 | "CHR8" "(" Expr<et, q> ")"
|
|
|
|
|
- 3363 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3364 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
|
|
- 3365 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3366 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3367 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
- 3368 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
- 3369 SemError(211) END;
|
|
|
|
|
- 3370 t := SymTab.CharType(); .)
|
|
|
|
|
- 3371 | "UORD" "(" Expr<et, q> ")"
|
|
|
|
|
- 3372 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3373 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
|
|
- 3374 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3375 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3376 (. (* UORD(u): the codepoint as a
|
|
|
|
|
- 3377 32-bit ordinal (INTEGER),
|
|
|
|
|
- 3378 cf. ORD for CHAR. *)
|
|
|
|
|
- 3379 IF (et # SymTab.InvalidType)
|
|
|
|
|
- 3380 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
- 3381 SemError(211) END;
|
|
|
|
|
- 3382 t := SymTab.IntType(); .)
|
|
|
|
|
- 3383 | "ABS" "(" Expr<et, q> ")"
|
|
|
|
|
- 3384 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3385 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
|
|
- 3386 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
- 3387 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3388 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
- 3389 AND NOT SymTab.IsIntFamily(et)
|
|
|
|
|
- 3390 AND (SymTab.ClassOf(et) #
|
|
|
|
|
- 3391 SymTab.ClReal) THEN
|
|
|
|
|
- 3392 SemError(211)
|
|
|
|
|
- 3393 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3394 END;
|
|
|
|
|
- 3395 t := et; .)
|
|
|
|
|
- 3396 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
|
|
- 3397 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
- 3398 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
|
|
- 3399 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
|
|
- 3400 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
|
|
- 3401 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
- 3402 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
|
|
- 3403 SemError(201);
|
|
|
|
|
- 3404 t := SymTab.InvalidType
|
|
|
|
|
- 3405 ELSE vt := SymTab.SymType(vn);
|
|
|
|
|
- 3406 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
- 3407 t := SymTab.InvalidType
|
|
|
|
|
- 3408 ELSIF et =
|
|
|
|
|
- 3409 SymTab.InvalidType THEN
|
|
|
|
|
- 3410 t := vt
|
|
|
|
|
- 3411 ELSE
|
|
|
|
|
- 3412 c1 := SymTab.ClassOf(et);
|
|
|
|
|
- 3413 c2 := SymTab.ClassOf(vt);
|
|
|
|
|
- 3414 IF (c1 = SymTab.ClInt)
|
|
|
|
|
- 3415 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
- 3416 QbeGen.WidenLong(q, qa);
|
|
|
|
|
- 3417 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 3418 t := vt
|
|
|
|
|
- 3419 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
- 3420 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
- 3421 QbeGen.NarrowLong(q, qa);
|
|
|
|
|
- 3422 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 3423 t := vt
|
|
|
|
|
- 3424 ELSIF (c1 = SymTab.ClInt)
|
|
|
|
|
- 3425 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
- 3426 QbeGen.ConvIR(q, qa);
|
|
|
|
|
- 3427 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 3428 t := vt
|
|
|
|
|
- 3429 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
- 3430 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
- 3431 QbeGen.ConvLR(q, qa);
|
|
|
|
|
- 3432 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 3433 t := vt
|
|
|
|
|
- 3434 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
- 3435 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
- 3436 QbeGen.ConvRI(q, qa);
|
|
|
|
|
- 3437 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 3438 t := vt
|
|
|
|
|
- 3439 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
- 3440 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
- 3441 QbeGen.ConvRL(q, qa);
|
|
|
|
|
- 3442 QbeGen.CopyOp(qa, q);
|
|
|
|
|
- 3443 t := vt
|
|
|
|
|
- 3444 ELSIF ((c1 = SymTab.ClInt)
|
|
|
|
|
- 3445 OR (c1 =
|
|
|
|
|
- 3446 SymTab.ClChar)
|
|
|
|
|
- 3447 OR (c1 =
|
|
|
|
|
- 3448 SymTab.ClBool)
|
|
|
|
|
- 3449 OR (c1 =
|
|
|
|
|
- 3450 SymTab.ClEnum))
|
|
|
|
|
- 3451 AND ((c2 = SymTab.ClInt)
|
|
|
|
|
- 3452 OR (c2 =
|
|
|
|
|
- 3453 SymTab.ClChar)
|
|
|
|
|
- 3454 OR (c2 =
|
|
|
|
|
- 3455 SymTab.ClBool)
|
|
|
|
|
- 3456 OR (c2 =
|
|
|
|
|
- 3457 SymTab.ClEnum)) THEN
|
|
|
|
|
- 3458 t := vt
|
|
|
|
|
- 3459 ELSIF (c1 = SymTab.ClPtr)
|
|
|
|
|
- 3460 AND (c2 = SymTab.ClPtr) THEN
|
|
|
|
|
- 3461 t := vt
|
|
|
|
|
- 3462 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
- 3463 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
- 3464 t := vt
|
|
|
|
|
- 3465 ELSE SemError(230);
|
|
|
|
|
- 3466 t := SymTab.InvalidType
|
|
|
|
|
- 3467 END
|
|
|
|
|
- 3468 END
|
|
|
|
|
- 3469 END; .)
|
|
|
|
|
- 3470 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
|
|
- 3471 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
|
|
- 3472 QbeGen.CopyOp(sq, q); .)
|
|
|
|
|
- 3473 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
|
|
- 3474 IF SymTab.BoolCheck(t2) THEN
|
|
|
|
|
- 3475 t := SymTab.BoolType()
|
|
|
|
|
- 3476 ELSE SemError(212);
|
|
|
|
|
- 3477 t := SymTab.InvalidType END;
|
|
|
|
|
- 3478 IF t # SymTab.InvalidType THEN
|
|
|
|
|
- 3479 QbeGen.CopyOp("@", q)
|
|
|
|
|
- 3480 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3481 END;
|
|
|
|
|
- 3482 astIsLit := TRUE;
|
|
|
|
|
- 3483 astCur := AST.MakeUn(
|
|
|
|
|
- 3484 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
|
|
- 3485 )
|
|
|
|
|
- 3486 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
|
|
- 3487 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
- 3488 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
|
|
- 3489 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
|
|
- 3490 for computed elements. Ranges always lower via SetRange. *)
|
|
|
|
|
- 3491 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 3492 (. VAR astNode: AST.Node; .)
|
|
|
|
|
- 3493 = "{" (. t := SymTab.NewSet(
|
|
|
|
|
- 3494 SymTab.NewSubR(0, 255));
|
|
|
|
|
- 3495 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
|
|
- 3496 QbeGen.NewSetTemp(8, q);
|
|
|
|
|
- 3497 QbeGen.SetZero(q, 8); .)
|
|
|
|
|
- 3498 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
|
|
- 3499 "}" (. astCur := astNode; .) .
|
|
|
|
|
- 3500 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
|
|
- 3501 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
|
|
- 3502 declared type sets the width (set) or element type (array). *)
|
|
|
|
|
- 3503 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
- 3504 (. VAR nw: CARDINAL;
|
|
|
|
|
- 3505 astNode, astTail: AST.Node;
|
|
|
|
|
- 3506 savedCls: INTEGER; .)
|
|
|
|
|
- 3507 = "{" (. savedCls := braceCls;
|
|
|
|
|
- 3508 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
|
|
- 3509 AST.SetTy(astNode, vt);
|
|
|
|
|
- 3510 astTail := astNode;
|
|
|
|
|
- 3511 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
- 3512 braceCls := -1
|
|
|
|
|
- 3513 ELSE braceCls :=
|
|
|
|
|
- 3514 SymTab.ClassOf(vt)
|
|
|
|
|
- 3515 END;
|
|
|
|
|
- 3516 IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
- 3517 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
- 3518 nw := 8
|
|
|
|
|
- 3519 ELSE nw := SymTab.SetWords(vt);
|
|
|
|
|
- 3520 IF nw = 0 THEN nw := 8 END
|
|
|
|
|
- 3521 END;
|
|
|
|
|
- 3522 QbeGen.NewSetTemp(nw, q);
|
|
|
|
|
- 3523 QbeGen.SetZero(q, nw)
|
|
|
|
|
- 3524 ELSIF (braceCls =
|
|
|
|
|
- 3525 SymTab.ClArray)
|
|
|
|
|
- 3526 OR (braceCls =
|
|
|
|
|
- 3527 SymTab.ClRecord)
|
|
|
|
|
- 3528 OR (braceCls =
|
|
|
|
|
- 3529 SymTab.ClClass) THEN
|
|
|
|
|
- 3530 QbeGen.CtorBegin(vt)
|
|
|
|
|
- 3531 ELSE
|
|
|
|
|
- 3532 IF vt # SymTab.InvalidType THEN
|
|
|
|
|
- 3533 SemError(230) END;
|
|
|
|
|
- 3534 braceCls := -1
|
|
|
|
|
- 3535 END; .)
|
|
|
|
|
- 3536 [ BraceElem<vt, q, astNode, astTail>
|
|
|
|
|
- 3537 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
|
|
- 3538 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
|
|
- 3539 OR (braceCls =
|
|
|
|
|
- 3540 SymTab.ClRecord)
|
|
|
|
|
- 3541 OR (braceCls =
|
|
|
|
|
- 3542 SymTab.ClClass) THEN
|
|
|
|
|
- 3543 QbeGen.CtorEnd(q)
|
|
|
|
|
- 3544 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
|
|
- 3545 QbeGen.CopyOp("0", q)
|
|
|
|
|
- 3546 END;
|
|
|
|
|
- 3547 braceCls := savedCls; .)
|
|
|
|
|
- 3548 (. astCur := astNode; .) .
|
|
|
|
|
- 3549 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
|
|
- 3550 VAR node, tail: AST.Node>
|
|
|
|
|
- 3551 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
- 3552 qe, q2: QbeGen.QVal;
|
|
|
|
|
- 3553 v, v2, reps, k: INTEGER;
|
|
|
|
|
- 3554 elem: SymTab.TypeIndex;
|
|
|
|
|
- 3555 lo: INTEGER;
|
|
|
|
|
- 3556 span: CARDINAL;
|
|
|
|
|
- 3557 cl, cl2: INTEGER;
|
|
|
|
|
- 3558 hasR, hasB: BOOLEAN;
|
|
|
|
|
- 3559 astEl: AST.Node; .)
|
|
|
|
|
- 3560 = (. hasR := FALSE; hasB := FALSE;
|
|
|
|
|
- 3561 reps := 1; .)
|
|
|
|
|
- 3562 Expr<et, qe> (. astEl := astCur; .)
|
|
|
|
|
- 3563 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
|
|
- 3564 AST.NkSubrange, 0, astEl, astCur);
|
|
|
|
|
- 3565 hasR := TRUE; .) ]
|
|
|
|
|
- 3566 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
|
|
- 3567 (. IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
- 3568 IF hasB THEN SemError(230) END;
|
|
|
|
|
- 3569 lo := SymTab.SetBaseLo(vt);
|
|
|
|
|
- 3570 span := SymTab.SetCount(vt);
|
|
|
|
|
- 3571 IF (et = SymTab.InvalidType)
|
|
|
|
|
- 3572 OR (hasR AND (et2 =
|
|
|
|
|
- 3573 SymTab.InvalidType)) THEN
|
|
|
|
|
- 3574 ELSE cl :=
|
|
|
|
|
- 3575 SymTab.ClassOf(et);
|
|
|
|
|
- 3576 IF hasR THEN
|
|
|
|
|
- 3577 cl2 :=
|
|
|
|
|
- 3578 SymTab.ClassOf(et2)
|
|
|
|
|
- 3579 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
- 3580 END;
|
|
|
|
|
- 3581 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
- 3582 OR (hasR AND NOT
|
|
|
|
|
- 3583 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
- 3584 THEN
|
|
|
|
|
- 3585 SemError(222)
|
|
|
|
|
- 3586 ELSIF hasR
|
|
|
|
|
- 3587 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
- 3588 AND SymTab.ConstInt(q2,
|
|
|
|
|
- 3589 v2)
|
|
|
|
|
- 3590 AND ((v < lo)
|
|
|
|
|
- 3591 OR (v2 < lo)
|
|
|
|
|
- 3592 OR (v >= lo +
|
|
|
|
|
- 3593 VAL(INTEGER, span))
|
|
|
|
|
- 3594 OR (v2 >= lo +
|
|
|
|
|
- 3595 VAL(INTEGER, span))
|
|
|
|
|
- 3596 OR (v > v2)) THEN
|
|
|
|
|
- 3597 SemError(222)
|
|
|
|
|
- 3598 ELSIF hasR THEN
|
|
|
|
|
- 3599 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
- 3600 lo, span)
|
|
|
|
|
- 3601 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
- 3602 v)
|
|
|
|
|
- 3603 AND ((v < lo)
|
|
|
|
|
- 3604 OR (v >= lo +
|
|
|
|
|
- 3605 VAL(INTEGER,
|
|
|
|
|
- 3606 span))) THEN
|
|
|
|
|
- 3607 SemError(222)
|
|
|
|
|
- 3608 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
- 3609 lo, span)
|
|
|
|
|
- 3610 END
|
|
|
|
|
- 3611 END
|
|
|
|
|
- 3612 ELSIF (braceCls = SymTab.ClArray)
|
|
|
|
|
- 3613 OR (braceCls =
|
|
|
|
|
- 3614 SymTab.ClRecord)
|
|
|
|
|
- 3615 OR (braceCls =
|
|
|
|
|
- 3616 SymTab.ClClass) THEN
|
|
|
|
|
- 3617 IF hasR THEN SemError(230) END;
|
|
|
|
|
- 3618 reps := 1;
|
|
|
|
|
- 3619 IF hasB THEN
|
|
|
|
|
- 3620 IF SymTab.ConstInt(q2, v2)
|
|
|
|
|
- 3621 AND (v2 >= 1) THEN
|
|
|
|
|
- 3622 reps := v2
|
|
|
|
|
- 3623 ELSE SemError(230)
|
|
|
|
|
- 3624 END
|
|
|
|
|
- 3625 END;
|
|
|
|
|
- 3626 k := 0;
|
|
|
|
|
- 3627 WHILE k < reps DO
|
|
|
|
|
- 3628 QbeGen.CtorElem(qe);
|
|
|
|
|
- 3629 INC(k)
|
|
|
|
|
- 3630 END
|
|
|
|
|
- 3631 END; .)
|
|
|
|
|
- 3632 (. (* the BY form repeats the
|
|
|
|
|
- 3633 element; keep the AST in
|
|
|
|
|
- 3634 step with CtorElem *)
|
|
|
|
|
- 3635 k := 0;
|
|
|
|
|
- 3636 WHILE k < reps DO
|
|
|
|
|
- 3637 AstAppend(AST.NkBlock,
|
|
|
|
|
- 3638 node, tail, astEl);
|
|
|
|
|
- 3639 INC(k)
|
|
|
|
|
- 3640 END; .) .
|
|
|
|
|
- 3641 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
- 3642 qe, q2: QbeGen.QVal;
|
|
|
|
|
- 3643 v, v2: INTEGER;
|
|
|
|
|
- 3644 lo: INTEGER;
|
|
|
|
|
- 3645 span: CARDINAL;
|
|
|
|
|
- 3646 cl, cl2: INTEGER;
|
|
|
|
|
- 3647 hasR: BOOLEAN;
|
|
|
|
|
- 3648 astEl: AST.Node; .)
|
|
|
|
|
- 3649 = (. hasR := FALSE; .)
|
|
|
|
|
- 3650 Expr<et, qe> (. astEl := astCur; .)
|
|
|
|
|
- 3651 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
|
|
- 3652 AST.NkSubrange, 0, astEl, astCur);
|
|
|
|
|
- 3653 hasR := TRUE; .) ]
|
|
|
|
|
- 3654 (. lo := SymTab.SetBaseLo(st);
|
|
|
|
|
- 3655 span := SymTab.SetCount(st);
|
|
|
|
|
- 3656 IF (et = SymTab.InvalidType)
|
|
|
|
|
- 3657 OR (hasR AND (et2 =
|
|
|
|
|
- 3658 SymTab.InvalidType)) THEN
|
|
|
|
|
- 3659 ELSE cl :=
|
|
|
|
|
- 3660 SymTab.ClassOf(et);
|
|
|
|
|
- 3661 IF hasR THEN
|
|
|
|
|
- 3662 cl2 :=
|
|
|
|
|
- 3663 SymTab.ClassOf(et2)
|
|
|
|
|
- 3664 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
- 3665 END;
|
|
|
|
|
- 3666 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
- 3667 OR (hasR AND NOT
|
|
|
|
|
- 3668 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
- 3669 THEN
|
|
|
|
|
- 3670 SemError(222)
|
|
|
|
|
- 3671 ELSIF hasR
|
|
|
|
|
- 3672 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
- 3673 AND SymTab.ConstInt(q2,
|
|
|
|
|
- 3674 v2)
|
|
|
|
|
- 3675 AND ((v < lo)
|
|
|
|
|
- 3676 OR (v2 < lo)
|
|
|
|
|
- 3677 OR (v >= lo +
|
|
|
|
|
- 3678 VAL(INTEGER, span))
|
|
|
|
|
- 3679 OR (v2 >= lo +
|
|
|
|
|
- 3680 VAL(INTEGER, span))
|
|
|
|
|
- 3681 OR (v > v2)) THEN
|
|
|
|
|
- 3682 SemError(222)
|
|
|
|
|
- 3683 ELSIF hasR THEN
|
|
|
|
|
- 3684 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
- 3685 lo, span)
|
|
|
|
|
- 3686 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
- 3687 v)
|
|
|
|
|
- 3688 AND ((v < lo)
|
|
|
|
|
- 3689 OR (v >= lo +
|
|
|
|
|
- 3690 VAL(INTEGER,
|
|
|
|
|
- 3691 span))) THEN
|
|
|
|
|
- 3692 SemError(222)
|
|
|
|
|
- 3693 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
- 3694 lo, span)
|
|
|
|
|
- 3695 END
|
|
|
|
|
- 3696 END; .)
|
|
|
|
|
- 3697 (. AST.SetChild(node,
|
|
|
|
|
- 3698 AST.NChild(node), astEl); .) .
|
|
|
|
|
- 3699 GetIdent<VAR n: SymTab.Name>
|
|
|
|
|
- 3700 = ident (. LexName(n); .) .
|
|
|
|
|
- 3701
|
|
|
|
|
- 3702 END M2.
|
|
|
|
|
|
|
+ 3330 (. QbeGen.CopyOp("@", q);
|
|
|
|
|
+ 3331 t := SymTab.CharType(); .)
|
|
|
|
|
+ 3332 | "UCHR" "(" Expr<et, q> ")"
|
|
|
|
|
+ 3333 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3334 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
|
|
+ 3335 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3336 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3337 (. (* UCHR: the UCHAR constructor.
|
|
|
|
|
+ 3338 CHAR -> UCHAR (identity);
|
|
|
|
|
+ 3339 INTEGER familly -> UCHAR
|
|
|
|
|
+ 3340 (codepoint value). *)
|
|
|
|
|
+ 3341 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 3342 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
|
|
+ 3343 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
|
|
+ 3344 SemError(211) END;
|
|
|
|
|
+ 3345 t := SymTab.UCharType(); .)
|
|
|
|
|
+ 3346 | "CHR8" "(" Expr<et, q> ")"
|
|
|
|
|
+ 3347 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3348 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
|
|
+ 3349 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3350 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3351 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 3352 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
+ 3353 SemError(211) END;
|
|
|
|
|
+ 3354 t := SymTab.CharType(); .)
|
|
|
|
|
+ 3355 | "UORD" "(" Expr<et, q> ")"
|
|
|
|
|
+ 3356 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3357 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
|
|
+ 3358 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3359 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3360 (. (* UORD(u): the codepoint as a
|
|
|
|
|
+ 3361 32-bit ordinal (INTEGER),
|
|
|
|
|
+ 3362 cf. ORD for CHAR. *)
|
|
|
|
|
+ 3363 IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 3364 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
|
|
+ 3365 SemError(211) END;
|
|
|
|
|
+ 3366 t := SymTab.IntType(); .)
|
|
|
|
|
+ 3367 | "ABS" "(" Expr<et, q> ")"
|
|
|
|
|
+ 3368 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3369 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
|
|
+ 3370 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
|
|
+ 3371 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3372 (. IF (et # SymTab.InvalidType)
|
|
|
|
|
+ 3373 AND NOT SymTab.IsIntFamily(et)
|
|
|
|
|
+ 3374 AND (SymTab.ClassOf(et) #
|
|
|
|
|
+ 3375 SymTab.ClReal) THEN
|
|
|
|
|
+ 3376 SemError(211)
|
|
|
|
|
+ 3377 ELSE QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3378 END;
|
|
|
|
|
+ 3379 t := et; .)
|
|
|
|
|
+ 3380 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
|
|
+ 3381 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
|
|
+ 3382 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
|
|
+ 3383 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
|
|
+ 3384 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
|
|
+ 3385 astCur := astNode; astIsLit := TRUE; .)
|
|
|
|
|
+ 3386 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
|
|
+ 3387 SemError(201);
|
|
|
|
|
+ 3388 t := SymTab.InvalidType
|
|
|
|
|
+ 3389 ELSE vt := SymTab.SymType(vn);
|
|
|
|
|
+ 3390 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3391 t := SymTab.InvalidType
|
|
|
|
|
+ 3392 ELSIF et =
|
|
|
|
|
+ 3393 SymTab.InvalidType THEN
|
|
|
|
|
+ 3394 t := vt
|
|
|
|
|
+ 3395 ELSE
|
|
|
|
|
+ 3396 c1 := SymTab.ClassOf(et);
|
|
|
|
|
+ 3397 c2 := SymTab.ClassOf(vt);
|
|
|
|
|
+ 3398 IF (c1 = SymTab.ClInt)
|
|
|
|
|
+ 3399 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
+ 3400 QbeGen.WidenLong(q, qa);
|
|
|
|
|
+ 3401 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 3402 t := vt
|
|
|
|
|
+ 3403 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
+ 3404 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
+ 3405 QbeGen.NarrowLong(q, qa);
|
|
|
|
|
+ 3406 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 3407 t := vt
|
|
|
|
|
+ 3408 ELSIF (c1 = SymTab.ClInt)
|
|
|
|
|
+ 3409 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
+ 3410 QbeGen.ConvIR(q, qa);
|
|
|
|
|
+ 3411 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 3412 t := vt
|
|
|
|
|
+ 3413 ELSIF (c1 = SymTab.ClLong)
|
|
|
|
|
+ 3414 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
+ 3415 QbeGen.ConvLR(q, qa);
|
|
|
|
|
+ 3416 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 3417 t := vt
|
|
|
|
|
+ 3418 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
+ 3419 AND (c2 = SymTab.ClInt) THEN
|
|
|
|
|
+ 3420 QbeGen.ConvRI(q, qa);
|
|
|
|
|
+ 3421 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 3422 t := vt
|
|
|
|
|
+ 3423 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
+ 3424 AND (c2 = SymTab.ClLong) THEN
|
|
|
|
|
+ 3425 QbeGen.ConvRL(q, qa);
|
|
|
|
|
+ 3426 QbeGen.CopyOp(qa, q);
|
|
|
|
|
+ 3427 t := vt
|
|
|
|
|
+ 3428 ELSIF ((c1 = SymTab.ClInt)
|
|
|
|
|
+ 3429 OR (c1 =
|
|
|
|
|
+ 3430 SymTab.ClChar)
|
|
|
|
|
+ 3431 OR (c1 =
|
|
|
|
|
+ 3432 SymTab.ClBool)
|
|
|
|
|
+ 3433 OR (c1 =
|
|
|
|
|
+ 3434 SymTab.ClEnum))
|
|
|
|
|
+ 3435 AND ((c2 = SymTab.ClInt)
|
|
|
|
|
+ 3436 OR (c2 =
|
|
|
|
|
+ 3437 SymTab.ClChar)
|
|
|
|
|
+ 3438 OR (c2 =
|
|
|
|
|
+ 3439 SymTab.ClBool)
|
|
|
|
|
+ 3440 OR (c2 =
|
|
|
|
|
+ 3441 SymTab.ClEnum)) THEN
|
|
|
|
|
+ 3442 t := vt
|
|
|
|
|
+ 3443 ELSIF (c1 = SymTab.ClPtr)
|
|
|
|
|
+ 3444 AND (c2 = SymTab.ClPtr) THEN
|
|
|
|
|
+ 3445 t := vt
|
|
|
|
|
+ 3446 ELSIF (c1 = SymTab.ClReal)
|
|
|
|
|
+ 3447 AND (c2 = SymTab.ClReal) THEN
|
|
|
|
|
+ 3448 t := vt
|
|
|
|
|
+ 3449 ELSE SemError(230);
|
|
|
|
|
+ 3450 t := SymTab.InvalidType
|
|
|
|
|
+ 3451 END
|
|
|
|
|
+ 3452 END
|
|
|
|
|
+ 3453 END; .)
|
|
|
|
|
+ 3454 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
|
|
+ 3455 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
|
|
+ 3456 QbeGen.CopyOp(sq, q); .)
|
|
|
|
|
+ 3457 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
|
|
+ 3458 IF SymTab.BoolCheck(t2) THEN
|
|
|
|
|
+ 3459 t := SymTab.BoolType()
|
|
|
|
|
+ 3460 ELSE SemError(212);
|
|
|
|
|
+ 3461 t := SymTab.InvalidType END;
|
|
|
|
|
+ 3462 IF t # SymTab.InvalidType THEN
|
|
|
|
|
+ 3463 QbeGen.CopyOp("@", q)
|
|
|
|
|
+ 3464 ELSE QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3465 END;
|
|
|
|
|
+ 3466 astIsLit := TRUE;
|
|
|
|
|
+ 3467 astCur := AST.MakeUn(
|
|
|
|
|
+ 3468 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
|
|
+ 3469 )
|
|
|
|
|
+ 3470 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
|
|
+ 3471 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
|
|
+ 3472 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
|
|
+ 3473 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
|
|
+ 3474 for computed elements. Ranges always lower via SetRange. *)
|
|
|
|
|
+ 3475 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 3476 (. VAR astNode: AST.Node; .)
|
|
|
|
|
+ 3477 = "{" (. t := SymTab.NewSet(
|
|
|
|
|
+ 3478 SymTab.NewSubR(0, 255));
|
|
|
|
|
+ 3479 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
|
|
+ 3480 QbeGen.NewSetTemp(8, q);
|
|
|
|
|
+ 3481 QbeGen.SetZero(q, 8); .)
|
|
|
|
|
+ 3482 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
|
|
+ 3483 "}" (. astCur := astNode; .) .
|
|
|
|
|
+ 3484 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
|
|
+ 3485 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
|
|
+ 3486 declared type sets the width (set) or element type (array). *)
|
|
|
|
|
+ 3487 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
|
|
+ 3488 (. VAR nw: CARDINAL;
|
|
|
|
|
+ 3489 astNode, astTail: AST.Node;
|
|
|
|
|
+ 3490 savedCls: INTEGER; .)
|
|
|
|
|
+ 3491 = "{" (. savedCls := braceCls;
|
|
|
|
|
+ 3492 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
|
|
+ 3493 AST.SetTy(astNode, vt);
|
|
|
|
|
+ 3494 astTail := astNode;
|
|
|
|
|
+ 3495 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3496 braceCls := -1
|
|
|
|
|
+ 3497 ELSE braceCls :=
|
|
|
|
|
+ 3498 SymTab.ClassOf(vt)
|
|
|
|
|
+ 3499 END;
|
|
|
|
|
+ 3500 IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
+ 3501 IF vt = SymTab.InvalidType THEN
|
|
|
|
|
+ 3502 nw := 8
|
|
|
|
|
+ 3503 ELSE nw := SymTab.SetWords(vt);
|
|
|
|
|
+ 3504 IF nw = 0 THEN nw := 8 END
|
|
|
|
|
+ 3505 END;
|
|
|
|
|
+ 3506 QbeGen.NewSetTemp(nw, q);
|
|
|
|
|
+ 3507 QbeGen.SetZero(q, nw)
|
|
|
|
|
+ 3508 ELSIF (braceCls =
|
|
|
|
|
+ 3509 SymTab.ClArray)
|
|
|
|
|
+ 3510 OR (braceCls =
|
|
|
|
|
+ 3511 SymTab.ClRecord)
|
|
|
|
|
+ 3512 OR (braceCls =
|
|
|
|
|
+ 3513 SymTab.ClClass) THEN
|
|
|
|
|
+ 3514 QbeGen.CtorBegin(vt)
|
|
|
|
|
+ 3515 ELSE
|
|
|
|
|
+ 3516 IF vt # SymTab.InvalidType THEN
|
|
|
|
|
+ 3517 SemError(230) END;
|
|
|
|
|
+ 3518 braceCls := -1
|
|
|
|
|
+ 3519 END; .)
|
|
|
|
|
+ 3520 [ BraceElem<vt, q, astNode, astTail>
|
|
|
|
|
+ 3521 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
|
|
+ 3522 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
|
|
+ 3523 OR (braceCls =
|
|
|
|
|
+ 3524 SymTab.ClRecord)
|
|
|
|
|
+ 3525 OR (braceCls =
|
|
|
|
|
+ 3526 SymTab.ClClass) THEN
|
|
|
|
|
+ 3527 QbeGen.CtorEnd(q)
|
|
|
|
|
+ 3528 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
|
|
+ 3529 QbeGen.CopyOp("0", q)
|
|
|
|
|
+ 3530 END;
|
|
|
|
|
+ 3531 braceCls := savedCls; .)
|
|
|
|
|
+ 3532 (. astCur := astNode; .) .
|
|
|
|
|
+ 3533 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
|
|
+ 3534 VAR node, tail: AST.Node>
|
|
|
|
|
+ 3535 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 3536 qe, q2: QbeGen.QVal;
|
|
|
|
|
+ 3537 v, v2, reps, k: INTEGER;
|
|
|
|
|
+ 3538 elem: SymTab.TypeIndex;
|
|
|
|
|
+ 3539 lo: INTEGER;
|
|
|
|
|
+ 3540 span: CARDINAL;
|
|
|
|
|
+ 3541 cl, cl2: INTEGER;
|
|
|
|
|
+ 3542 hasR, hasB: BOOLEAN;
|
|
|
|
|
+ 3543 astEl: AST.Node; .)
|
|
|
|
|
+ 3544 = (. hasR := FALSE; hasB := FALSE;
|
|
|
|
|
+ 3545 reps := 1; .)
|
|
|
|
|
+ 3546 Expr<et, qe> (. astEl := astCur; .)
|
|
|
|
|
+ 3547 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
|
|
+ 3548 AST.NkSubrange, 0, astEl, astCur);
|
|
|
|
|
+ 3549 hasR := TRUE; .) ]
|
|
|
|
|
+ 3550 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
|
|
+ 3551 (. IF braceCls = SymTab.ClSet THEN
|
|
|
|
|
+ 3552 IF hasB THEN SemError(230) END;
|
|
|
|
|
+ 3553 lo := SymTab.SetBaseLo(vt);
|
|
|
|
|
+ 3554 span := SymTab.SetCount(vt);
|
|
|
|
|
+ 3555 IF (et = SymTab.InvalidType)
|
|
|
|
|
+ 3556 OR (hasR AND (et2 =
|
|
|
|
|
+ 3557 SymTab.InvalidType)) THEN
|
|
|
|
|
+ 3558 ELSE cl :=
|
|
|
|
|
+ 3559 SymTab.ClassOf(et);
|
|
|
|
|
+ 3560 IF hasR THEN
|
|
|
|
|
+ 3561 cl2 :=
|
|
|
|
|
+ 3562 SymTab.ClassOf(et2)
|
|
|
|
|
+ 3563 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
+ 3564 END;
|
|
|
|
|
+ 3565 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
+ 3566 OR (hasR AND NOT
|
|
|
|
|
+ 3567 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
+ 3568 THEN
|
|
|
|
|
+ 3569 SemError(222)
|
|
|
|
|
+ 3570 ELSIF hasR
|
|
|
|
|
+ 3571 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
+ 3572 AND SymTab.ConstInt(q2,
|
|
|
|
|
+ 3573 v2)
|
|
|
|
|
+ 3574 AND ((v < lo)
|
|
|
|
|
+ 3575 OR (v2 < lo)
|
|
|
|
|
+ 3576 OR (v >= lo +
|
|
|
|
|
+ 3577 VAL(INTEGER, span))
|
|
|
|
|
+ 3578 OR (v2 >= lo +
|
|
|
|
|
+ 3579 VAL(INTEGER, span))
|
|
|
|
|
+ 3580 OR (v > v2)) THEN
|
|
|
|
|
+ 3581 SemError(222)
|
|
|
|
|
+ 3582 ELSIF hasR THEN
|
|
|
|
|
+ 3583 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
+ 3584 lo, span)
|
|
|
|
|
+ 3585 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
+ 3586 v)
|
|
|
|
|
+ 3587 AND ((v < lo)
|
|
|
|
|
+ 3588 OR (v >= lo +
|
|
|
|
|
+ 3589 VAL(INTEGER,
|
|
|
|
|
+ 3590 span))) THEN
|
|
|
|
|
+ 3591 SemError(222)
|
|
|
|
|
+ 3592 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
+ 3593 lo, span)
|
|
|
|
|
+ 3594 END
|
|
|
|
|
+ 3595 END
|
|
|
|
|
+ 3596 ELSIF (braceCls = SymTab.ClArray)
|
|
|
|
|
+ 3597 OR (braceCls =
|
|
|
|
|
+ 3598 SymTab.ClRecord)
|
|
|
|
|
+ 3599 OR (braceCls =
|
|
|
|
|
+ 3600 SymTab.ClClass) THEN
|
|
|
|
|
+ 3601 IF hasR THEN SemError(230) END;
|
|
|
|
|
+ 3602 reps := 1;
|
|
|
|
|
+ 3603 IF hasB THEN
|
|
|
|
|
+ 3604 IF SymTab.ConstInt(q2, v2)
|
|
|
|
|
+ 3605 AND (v2 >= 1) THEN
|
|
|
|
|
+ 3606 reps := v2
|
|
|
|
|
+ 3607 ELSE SemError(230)
|
|
|
|
|
+ 3608 END
|
|
|
|
|
+ 3609 END;
|
|
|
|
|
+ 3610 k := 0;
|
|
|
|
|
+ 3611 WHILE k < reps DO
|
|
|
|
|
+ 3612 QbeGen.CtorElem(qe);
|
|
|
|
|
+ 3613 INC(k)
|
|
|
|
|
+ 3614 END
|
|
|
|
|
+ 3615 END; .)
|
|
|
|
|
+ 3616 (. (* the BY form repeats the
|
|
|
|
|
+ 3617 element; keep the AST in
|
|
|
|
|
+ 3618 step with CtorElem *)
|
|
|
|
|
+ 3619 k := 0;
|
|
|
|
|
+ 3620 WHILE k < reps DO
|
|
|
|
|
+ 3621 AstAppend(AST.NkBlock,
|
|
|
|
|
+ 3622 node, tail, astEl);
|
|
|
|
|
+ 3623 INC(k)
|
|
|
|
|
+ 3624 END; .) .
|
|
|
|
|
+ 3625 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
|
|
+ 3626 qe, q2: QbeGen.QVal;
|
|
|
|
|
+ 3627 v, v2: INTEGER;
|
|
|
|
|
+ 3628 lo: INTEGER;
|
|
|
|
|
+ 3629 span: CARDINAL;
|
|
|
|
|
+ 3630 cl, cl2: INTEGER;
|
|
|
|
|
+ 3631 hasR: BOOLEAN;
|
|
|
|
|
+ 3632 astEl: AST.Node; .)
|
|
|
|
|
+ 3633 = (. hasR := FALSE; .)
|
|
|
|
|
+ 3634 Expr<et, qe> (. astEl := astCur; .)
|
|
|
|
|
+ 3635 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
|
|
+ 3636 AST.NkSubrange, 0, astEl, astCur);
|
|
|
|
|
+ 3637 hasR := TRUE; .) ]
|
|
|
|
|
+ 3638 (. lo := SymTab.SetBaseLo(st);
|
|
|
|
|
+ 3639 span := SymTab.SetCount(st);
|
|
|
|
|
+ 3640 IF (et = SymTab.InvalidType)
|
|
|
|
|
+ 3641 OR (hasR AND (et2 =
|
|
|
|
|
+ 3642 SymTab.InvalidType)) THEN
|
|
|
|
|
+ 3643 ELSE cl :=
|
|
|
|
|
+ 3644 SymTab.ClassOf(et);
|
|
|
|
|
+ 3645 IF hasR THEN
|
|
|
|
|
+ 3646 cl2 :=
|
|
|
|
|
+ 3647 SymTab.ClassOf(et2)
|
|
|
|
|
+ 3648 ELSE cl2 := SymTab.ClInt
|
|
|
|
|
+ 3649 END;
|
|
|
|
|
+ 3650 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
|
|
+ 3651 OR (hasR AND NOT
|
|
|
|
|
+ 3652 SymTab.SetElemClassOk(cl2))
|
|
|
|
|
+ 3653 THEN
|
|
|
|
|
+ 3654 SemError(222)
|
|
|
|
|
+ 3655 ELSIF hasR
|
|
|
|
|
+ 3656 AND SymTab.ConstInt(qe, v)
|
|
|
|
|
+ 3657 AND SymTab.ConstInt(q2,
|
|
|
|
|
+ 3658 v2)
|
|
|
|
|
+ 3659 AND ((v < lo)
|
|
|
|
|
+ 3660 OR (v2 < lo)
|
|
|
|
|
+ 3661 OR (v >= lo +
|
|
|
|
|
+ 3662 VAL(INTEGER, span))
|
|
|
|
|
+ 3663 OR (v2 >= lo +
|
|
|
|
|
+ 3664 VAL(INTEGER, span))
|
|
|
|
|
+ 3665 OR (v > v2)) THEN
|
|
|
|
|
+ 3666 SemError(222)
|
|
|
|
|
+ 3667 ELSIF hasR THEN
|
|
|
|
|
+ 3668 QbeGen.SetRange(sq, qe, q2,
|
|
|
|
|
+ 3669 lo, span)
|
|
|
|
|
+ 3670 ELSIF SymTab.ConstInt(qe,
|
|
|
|
|
+ 3671 v)
|
|
|
|
|
+ 3672 AND ((v < lo)
|
|
|
|
|
+ 3673 OR (v >= lo +
|
|
|
|
|
+ 3674 VAL(INTEGER,
|
|
|
|
|
+ 3675 span))) THEN
|
|
|
|
|
+ 3676 SemError(222)
|
|
|
|
|
+ 3677 ELSE QbeGen.SetBit(sq, qe,
|
|
|
|
|
+ 3678 lo, span)
|
|
|
|
|
+ 3679 END
|
|
|
|
|
+ 3680 END; .)
|
|
|
|
|
+ 3681 (. AST.SetChild(node,
|
|
|
|
|
+ 3682 AST.NChild(node), astEl); .) .
|
|
|
|
|
+ 3683 GetIdent<VAR n: SymTab.Name>
|
|
|
|
|
+ 3684 = ident (. LexName(n); .) .
|
|
|
|
|
+ 3685
|
|
|
|
|
+ 3686 END M2.
|
|
|
|
|
|
|
|
0 errors
|
|
0 errors
|
|
|
|
|
|