|
|
@@ -94,3497 +94,3500 @@ Listing:
|
|
|
75 nSpans: CARDINAL;
|
|
|
76 spanName: ARRAY [0 .. 1023] OF SymTab.Name;
|
|
|
77 spanStart: ARRAY [0 .. 1023] OF M2S.INT32;
|
|
|
- 78
|
|
|
- 79 (* Result slot for the expression-AST builder (slice 2). Every
|
|
|
- 80 Expr/SimExpr/Term/Fact leaves its node here; the combination
|
|
|
- 81 productions save it into locals before parsing the next operand.
|
|
|
- 82 `astIsLit` in Fact is per-invocation, so a nested Fact cannot make
|
|
|
- 83 an outer non-literal Fact look literal. *)
|
|
|
- 84 astCur: AST.Node;
|
|
|
- 85
|
|
|
- 86 (* Actual-argument nodes collected by ActParam for the call being
|
|
|
- 87 parsed by ArgList (slice 4). Fact resets the count before the
|
|
|
- 88 optional ArgList and then folds the nodes into an NkCall. *)
|
|
|
- 89 astNArgs: CARDINAL;
|
|
|
- 90 astArgs: ARRAY [0 .. 31] OF AST.Node;
|
|
|
- 91
|
|
|
- 92 (* Statement-AST result slot (slice 5): the most recently parsed
|
|
|
- 93 statement. StatSeq folds these into an NkBlock. *)
|
|
|
- 94 astStmt: AST.Node;
|
|
|
- 95
|
|
|
- 96 (* Declaration-AST result slot (slice 6): the most recently built
|
|
|
- 97 declaration; DeclSeq folds these into an NkDeclSeq. *)
|
|
|
- 98 astDecl: AST.Node;
|
|
|
- 99
|
|
|
- 100 (* The local declarations of the most recent Block (a procedure body);
|
|
|
- 101 ProcDecl stores them as the proc node's child 2. *)
|
|
|
- 102 astBlkDecls: AST.Node;
|
|
|
- 103
|
|
|
- 104 (* Unit-AST root (slice 7): NkUnit(name, decls, body). *)
|
|
|
- 105 astUnit: AST.Node;
|
|
|
- 106
|
|
|
- 107 (* Import accumulator (slice 11): `{ Import }` appends NkImport
|
|
|
- 108 nodes here; each unit stores them as NkUnit child[3]. *)
|
|
|
- 109 astImp, astImpTail: AST.Node;
|
|
|
- 110
|
|
|
- 111 (* Class-AST accumulators (slice 13): the class node currently being
|
|
|
- 112 parsed and its parent/field/method lists. Classes are not nested
|
|
|
- 113 inside one another, so module-level state is safe. *)
|
|
|
- 114 astCls, astClsP, astClsPTail, astClsF, astClsFTail,
|
|
|
- 115 astClsM, astClsMTail, astMethod: AST.Node;
|
|
|
- 116
|
|
|
- 117 (* Class of the method named by the last `obj.Method` designator
|
|
|
- 118 (InvalidType when the callee is an ordinary procedure). Set by
|
|
|
- 119 Design, consumed by the following ArgList. *)
|
|
|
- 120 methCls: SymTab.TypeIndex;
|
|
|
- 121 (* Class of the type of the innermost `TypeName{...}` brace
|
|
|
- 122 constructor (ClSet or ClArray); dispatches BraceElem. *)
|
|
|
- 123 braceCls: INTEGER;
|
|
|
- 124 (* Module-level VAR declarations whose type was still an unresolved
|
|
|
- 125 forward alias at declaration time; emitted once the TYPE block
|
|
|
- 126 completes (module scope only). *)
|
|
|
- 127 nPendVar: CARDINAL;
|
|
|
- 128 pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
- 129 pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
|
|
|
- 130 (* Forward module-level variables referenced from a procedure body. *)
|
|
|
- 131 (* GOTO/labels: the label and goto names of the procedure being parsed,
|
|
|
- 132 reset per procedure and checked at its END. *)
|
|
|
- 133 nLab, nGot: CARDINAL;
|
|
|
- 134 labNm, gotNm: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
- 135
|
|
|
- 136 (* Generics (Increment 1): the last refining module seen — instance
|
|
|
- 137 name, generic name, and the actual type parameters. *)
|
|
|
- 138 refInst, refGen: SymTab.Name;
|
|
|
- 139 refN: CARDINAL;
|
|
|
- 140 refActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
- 141 isGen: BOOLEAN;
|
|
|
- 142
|
|
|
- 143 (* Generics (Increment 2): instantiation re-parse context. When the
|
|
|
- 144 driver re-parses a generic's source to instantiate it as `instName`,
|
|
|
- 145 instActive is TRUE, the module is renamed, and each type formal is
|
|
|
- 146 bound to the corresponding instActual entry. *)
|
|
|
- 147 instActive: BOOLEAN;
|
|
|
- 148 instName: SymTab.Name;
|
|
|
- 149 instActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
- 150 instN: CARDINAL;
|
|
|
- 151 instFk: CARDINAL; (* formal cursor while binding during re-parse *)
|
|
|
- 152
|
|
|
- 153 (* Identity of the last-parsed unit and refinement, for the driver's
|
|
|
- 154 generic registry and its re-parse decision. *)
|
|
|
- 155 unitName: SymTab.Name;
|
|
|
- 156 unitWasGen: BOOLEAN;
|
|
|
- 157 unitWasDef: BOOLEAN;
|
|
|
- 158 refSeen: BOOLEAN;
|
|
|
- 159 refIsDef: BOOLEAN;
|
|
|
- 160
|
|
|
+ 78 spanIdx: ARRAY [0 .. 1023] OF CARDINAL;
|
|
|
+ 79
|
|
|
+ 80 (* Result slot for the expression-AST builder (slice 2). Every
|
|
|
+ 81 Expr/SimExpr/Term/Fact leaves its node here; the combination
|
|
|
+ 82 productions save it into locals before parsing the next operand.
|
|
|
+ 83 `astIsLit` in Fact is per-invocation, so a nested Fact cannot make
|
|
|
+ 84 an outer non-literal Fact look literal. *)
|
|
|
+ 85 astCur: AST.Node;
|
|
|
+ 86
|
|
|
+ 87 (* Actual-argument nodes collected by ActParam for the call being
|
|
|
+ 88 parsed by ArgList (slice 4). Fact resets the count before the
|
|
|
+ 89 optional ArgList and then folds the nodes into an NkCall. *)
|
|
|
+ 90 astNArgs: CARDINAL;
|
|
|
+ 91 astArgs: ARRAY [0 .. 31] OF AST.Node;
|
|
|
+ 92
|
|
|
+ 93 (* Statement-AST result slot (slice 5): the most recently parsed
|
|
|
+ 94 statement. StatSeq folds these into an NkBlock. *)
|
|
|
+ 95 astStmt: AST.Node;
|
|
|
+ 96
|
|
|
+ 97 (* Declaration-AST result slot (slice 6): the most recently built
|
|
|
+ 98 declaration; DeclSeq folds these into an NkDeclSeq. *)
|
|
|
+ 99 astDecl: AST.Node;
|
|
|
+ 100
|
|
|
+ 101 (* The local declarations of the most recent Block (a procedure body);
|
|
|
+ 102 ProcDecl stores them as the proc node's child 2. *)
|
|
|
+ 103 astBlkDecls: AST.Node;
|
|
|
+ 104
|
|
|
+ 105 (* Unit-AST root (slice 7): NkUnit(name, decls, body). *)
|
|
|
+ 106 astUnit: AST.Node;
|
|
|
+ 107
|
|
|
+ 108 (* Import accumulator (slice 11): `{ Import }` appends NkImport
|
|
|
+ 109 nodes here; each unit stores them as NkUnit child[3]. *)
|
|
|
+ 110 astImp, astImpTail: AST.Node;
|
|
|
+ 111
|
|
|
+ 112 (* Class-AST accumulators (slice 13): the class node currently being
|
|
|
+ 113 parsed and its parent/field/method lists. Classes are not nested
|
|
|
+ 114 inside one another, so module-level state is safe. *)
|
|
|
+ 115 astCls, astClsP, astClsPTail, astClsF, astClsFTail,
|
|
|
+ 116 astClsM, astClsMTail, astMethod: AST.Node;
|
|
|
+ 117
|
|
|
+ 118 (* Class of the method named by the last `obj.Method` designator
|
|
|
+ 119 (InvalidType when the callee is an ordinary procedure). Set by
|
|
|
+ 120 Design, consumed by the following ArgList. *)
|
|
|
+ 121 methCls: SymTab.TypeIndex;
|
|
|
+ 122 (* Class of the type of the innermost `TypeName{...}` brace
|
|
|
+ 123 constructor (ClSet or ClArray); dispatches BraceElem. *)
|
|
|
+ 124 braceCls: INTEGER;
|
|
|
+ 125 (* Module-level VAR declarations whose type was still an unresolved
|
|
|
+ 126 forward alias at declaration time; emitted once the TYPE block
|
|
|
+ 127 completes (module scope only). *)
|
|
|
+ 128 nPendVar: CARDINAL;
|
|
|
+ 129 pendVarName: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
+ 130 pendVarT: ARRAY [0 .. 255] OF SymTab.TypeIndex;
|
|
|
+ 131 (* Forward module-level variables referenced from a procedure body. *)
|
|
|
+ 132 (* GOTO/labels: the label and goto names of the procedure being parsed,
|
|
|
+ 133 reset per procedure and checked at its END. *)
|
|
|
+ 134 nLab, nGot: CARDINAL;
|
|
|
+ 135 labNm, gotNm: ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
+ 136
|
|
|
+ 137 (* Generics (Increment 1): the last refining module seen — instance
|
|
|
+ 138 name, generic name, and the actual type parameters. *)
|
|
|
+ 139 refInst, refGen: SymTab.Name;
|
|
|
+ 140 refN: CARDINAL;
|
|
|
+ 141 refActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
+ 142 isGen: BOOLEAN;
|
|
|
+ 143
|
|
|
+ 144 (* Generics (Increment 2): instantiation re-parse context. When the
|
|
|
+ 145 driver re-parses a generic's source to instantiate it as `instName`,
|
|
|
+ 146 instActive is TRUE, the module is renamed, and each type formal is
|
|
|
+ 147 bound to the corresponding instActual entry. *)
|
|
|
+ 148 instActive: BOOLEAN;
|
|
|
+ 149 instName: SymTab.Name;
|
|
|
+ 150 instActual: ARRAY [0 .. 15] OF SymTab.TypeIndex;
|
|
|
+ 151 instN: CARDINAL;
|
|
|
+ 152 instFk: CARDINAL; (* formal cursor while binding during re-parse *)
|
|
|
+ 153
|
|
|
+ 154 (* Identity of the last-parsed unit and refinement, for the driver's
|
|
|
+ 155 generic registry and its re-parse decision. *)
|
|
|
+ 156 unitName: SymTab.Name;
|
|
|
+ 157 unitWasGen: BOOLEAN;
|
|
|
+ 158 unitWasDef: BOOLEAN;
|
|
|
+ 159 refSeen: BOOLEAN;
|
|
|
+ 160 refIsDef: BOOLEAN;
|
|
|
161
|
|
|
- 162 PROCEDURE CopyNm (src: ARRAY OF CHAR; VAR dst: SymTab.Name);
|
|
|
- 163 VAR i: CARDINAL;
|
|
|
- 164 BEGIN
|
|
|
- 165 i := 0;
|
|
|
- 166 WHILE (i <= HIGH(dst)) AND (i <= HIGH(src)) AND (src[i] # CHR(0)) DO
|
|
|
- 167 dst[i] := src[i]; INC(i)
|
|
|
- 168 END;
|
|
|
- 169 IF i <= HIGH(dst) THEN dst[i] := CHR(0) END
|
|
|
- 170 END CopyNm;
|
|
|
- 171
|
|
|
- 172 PROCEDURE InInst () : BOOLEAN;
|
|
|
- 173 BEGIN RETURN instActive END InInst;
|
|
|
- 174
|
|
|
- 175 PROCEDURE InstNameGet (VAR nm: SymTab.Name);
|
|
|
- 176 BEGIN CopyNm(instName, nm) END InstNameGet;
|
|
|
- 177
|
|
|
- 178 PROCEDURE InstActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
- 179 BEGIN
|
|
|
- 180 IF i >= instN THEN RETURN SymTab.InvalidType END;
|
|
|
- 181 RETURN instActual[i]
|
|
|
- 182 END InstActualGet;
|
|
|
- 183
|
|
|
- 184 PROCEDURE InstBegin (name: ARRAY OF CHAR);
|
|
|
- 185 BEGIN instActive := TRUE; CopyNm(name, instName); instN := 0;
|
|
|
- 186 instFk := 0 END InstBegin;
|
|
|
- 187
|
|
|
- 188 PROCEDURE InstAddActual (t: SymTab.TypeIndex);
|
|
|
- 189 BEGIN
|
|
|
- 190 IF instN <= HIGH(instActual) THEN instActual[instN] := t; INC(instN) END
|
|
|
- 191 END InstAddActual;
|
|
|
- 192
|
|
|
- 193 PROCEDURE InstEnd;
|
|
|
- 194 BEGIN instActive := FALSE; instN := 0 END InstEnd;
|
|
|
- 195
|
|
|
- 196 PROCEDURE UnitNameGet (VAR nm: SymTab.Name);
|
|
|
- 197 BEGIN CopyNm(unitName, nm) END UnitNameGet;
|
|
|
- 198
|
|
|
- 199 PROCEDURE UnitIsGeneric () : BOOLEAN;
|
|
|
- 200 BEGIN RETURN unitWasGen END UnitIsGeneric;
|
|
|
- 201
|
|
|
- 202 PROCEDURE UnitIsDefModule () : BOOLEAN;
|
|
|
- 203 BEGIN RETURN unitWasDef END UnitIsDefModule;
|
|
|
- 204
|
|
|
- 205 PROCEDURE RefineSeen () : BOOLEAN;
|
|
|
- 206 BEGIN RETURN refSeen END RefineSeen;
|
|
|
- 207
|
|
|
- 208 PROCEDURE RefineIsDef () : BOOLEAN;
|
|
|
- 209 BEGIN RETURN refIsDef END RefineIsDef;
|
|
|
- 210
|
|
|
- 211 PROCEDURE RefineInst (VAR nm: SymTab.Name);
|
|
|
- 212 BEGIN CopyNm(refInst, nm) END RefineInst;
|
|
|
- 213
|
|
|
- 214 PROCEDURE RefineGen (VAR nm: SymTab.Name);
|
|
|
- 215 BEGIN CopyNm(refGen, nm) END RefineGen;
|
|
|
- 216
|
|
|
- 217 PROCEDURE RefineActualCount () : CARDINAL;
|
|
|
- 218 BEGIN RETURN refN END RefineActualCount;
|
|
|
- 219
|
|
|
- 220 PROCEDURE RefineActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
- 221 BEGIN
|
|
|
- 222 IF i >= refN THEN RETURN SymTab.InvalidType END;
|
|
|
- 223 RETURN refActual[i]
|
|
|
- 224 END RefineActualGet;
|
|
|
- 225
|
|
|
- 226 PROCEDURE NoteLabel (nm: ARRAY OF CHAR);
|
|
|
- 227 (* Record a statement label; duplicate is 200. *)
|
|
|
- 228 VAR i: CARDINAL;
|
|
|
- 229 BEGIN
|
|
|
- 230 i := 0;
|
|
|
- 231 WHILE i < nLab DO
|
|
|
- 232 IF SymTab.Equal(labNm[i], nm) THEN SemError(200); RETURN END;
|
|
|
- 233 INC(i)
|
|
|
- 234 END;
|
|
|
- 235 IF nLab <= HIGH(labNm) THEN
|
|
|
- 236 CopyNm(nm, labNm[nLab]); INC(nLab)
|
|
|
- 237 END
|
|
|
- 238 END NoteLabel;
|
|
|
- 239
|
|
|
- 240 PROCEDURE NoteGoto (nm: ARRAY OF CHAR);
|
|
|
- 241 VAR i: CARDINAL;
|
|
|
- 242 BEGIN
|
|
|
- 243 i := 0;
|
|
|
- 244 WHILE i < nGot DO
|
|
|
- 245 IF SymTab.Equal(gotNm[i], nm) THEN RETURN END;
|
|
|
- 246 INC(i)
|
|
|
- 247 END;
|
|
|
- 248 IF nGot <= HIGH(gotNm) THEN
|
|
|
- 249 CopyNm(nm, gotNm[nGot]); INC(nGot)
|
|
|
- 250 END
|
|
|
- 251 END NoteGoto;
|
|
|
- 252
|
|
|
- 253 PROCEDURE CheckGotos;
|
|
|
- 254 (* At a procedure's END: every GOTO must name a label in that procedure. *)
|
|
|
- 255 VAR i, j: CARDINAL; found: BOOLEAN;
|
|
|
- 256 BEGIN
|
|
|
- 257 i := 0;
|
|
|
- 258 WHILE i < nGot DO
|
|
|
- 259 found := FALSE; j := 0;
|
|
|
- 260 WHILE (j < nLab) AND NOT found DO
|
|
|
- 261 IF SymTab.Equal(labNm[j], gotNm[i]) THEN found := TRUE END;
|
|
|
- 262 INC(j)
|
|
|
- 263 END;
|
|
|
- 264 IF NOT found THEN SemError(201) END;
|
|
|
- 265 INC(i)
|
|
|
- 266 END
|
|
|
- 267 END CheckGotos;
|
|
|
- 268
|
|
|
- 269 PROCEDURE FlushPend;
|
|
|
- 270 (* Emit module-level globals whose forward type is now resolved. *)
|
|
|
- 271 VAR k: CARDINAL;
|
|
|
- 272 BEGIN
|
|
|
- 273 k := 0;
|
|
|
- 274 WHILE k < nPendVar DO
|
|
|
- 275 INC(k)
|
|
|
- 276 END;
|
|
|
- 277 nPendVar := 0
|
|
|
- 278 END FlushPend;
|
|
|
- 279
|
|
|
- 280 PROCEDURE AstAppend (kind: INTEGER; VAR head, tail: AST.Node;
|
|
|
- 281 item: AST.Node);
|
|
|
- 282 (* Appends `item` to a chunked sequence: each node holds up to
|
|
|
- 283 AST.MaxChild-1 items; child[MaxChild-1] continues into the next
|
|
|
- 284 chunk. Unbounded, so blocks/decl sequences are not capped at 8. *)
|
|
|
- 285 VAR n: AST.Node;
|
|
|
- 286 BEGIN
|
|
|
- 287 IF item = AST.NoNode THEN RETURN END;
|
|
|
- 288 IF head = AST.NoNode THEN
|
|
|
- 289 head := AST.MakeNode(kind); tail := head
|
|
|
- 290 END;
|
|
|
- 291 IF AST.NChild(tail) >= AST.MaxChild - 1 THEN
|
|
|
- 292 n := AST.MakeNode(kind);
|
|
|
- 293 AST.SetChild(tail, AST.MaxChild - 1, n);
|
|
|
- 294 tail := n
|
|
|
- 295 END;
|
|
|
- 296 AST.SetChild(tail, AST.NChild(tail), item)
|
|
|
- 297 END AstAppend;
|
|
|
- 298
|
|
|
- 299 PROCEDURE AstCallNode (callee: AST.Node) : AST.Node;
|
|
|
- 300 (* Builds NkCall(callee, actuals...) from astArgs/astNArgs. The actuals
|
|
|
- 301 are a chunked sequence (AstAppend): a call can have more than
|
|
|
- 302 MaxChild-1 arguments (the generic ArgList has 9), and SetChild would
|
|
|
- 303 silently drop the tail. NkBlock marks the continuation chunks. *)
|
|
|
- 304 VAR n, tail: AST.Node; j: CARDINAL;
|
|
|
- 305 BEGIN
|
|
|
- 306 n := AST.MakeNode(AST.NkCall);
|
|
|
- 307 AST.SetChild(n, 0, callee);
|
|
|
- 308 tail := n;
|
|
|
- 309 j := 0;
|
|
|
- 310 WHILE j < astNArgs DO
|
|
|
- 311 AstAppend(AST.NkBlock, n, tail, astArgs[j]);
|
|
|
- 312 INC(j)
|
|
|
- 313 END;
|
|
|
- 314 RETURN n
|
|
|
- 315 END AstCallNode;
|
|
|
- 316
|
|
|
+ 162
|
|
|
+ 163 PROCEDURE CopyNm (src: ARRAY OF CHAR; VAR dst: SymTab.Name);
|
|
|
+ 164 VAR i: CARDINAL;
|
|
|
+ 165 BEGIN
|
|
|
+ 166 i := 0;
|
|
|
+ 167 WHILE (i <= HIGH(dst)) AND (i <= HIGH(src)) AND (src[i] # CHR(0)) DO
|
|
|
+ 168 dst[i] := src[i]; INC(i)
|
|
|
+ 169 END;
|
|
|
+ 170 IF i <= HIGH(dst) THEN dst[i] := CHR(0) END
|
|
|
+ 171 END CopyNm;
|
|
|
+ 172
|
|
|
+ 173 PROCEDURE InInst () : BOOLEAN;
|
|
|
+ 174 BEGIN RETURN instActive END InInst;
|
|
|
+ 175
|
|
|
+ 176 PROCEDURE InstNameGet (VAR nm: SymTab.Name);
|
|
|
+ 177 BEGIN CopyNm(instName, nm) END InstNameGet;
|
|
|
+ 178
|
|
|
+ 179 PROCEDURE InstActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
+ 180 BEGIN
|
|
|
+ 181 IF i >= instN THEN RETURN SymTab.InvalidType END;
|
|
|
+ 182 RETURN instActual[i]
|
|
|
+ 183 END InstActualGet;
|
|
|
+ 184
|
|
|
+ 185 PROCEDURE InstBegin (name: ARRAY OF CHAR);
|
|
|
+ 186 BEGIN instActive := TRUE; CopyNm(name, instName); instN := 0;
|
|
|
+ 187 instFk := 0 END InstBegin;
|
|
|
+ 188
|
|
|
+ 189 PROCEDURE InstAddActual (t: SymTab.TypeIndex);
|
|
|
+ 190 BEGIN
|
|
|
+ 191 IF instN <= HIGH(instActual) THEN instActual[instN] := t; INC(instN) END
|
|
|
+ 192 END InstAddActual;
|
|
|
+ 193
|
|
|
+ 194 PROCEDURE InstEnd;
|
|
|
+ 195 BEGIN instActive := FALSE; instN := 0 END InstEnd;
|
|
|
+ 196
|
|
|
+ 197 PROCEDURE UnitNameGet (VAR nm: SymTab.Name);
|
|
|
+ 198 BEGIN CopyNm(unitName, nm) END UnitNameGet;
|
|
|
+ 199
|
|
|
+ 200 PROCEDURE UnitIsGeneric () : BOOLEAN;
|
|
|
+ 201 BEGIN RETURN unitWasGen END UnitIsGeneric;
|
|
|
+ 202
|
|
|
+ 203 PROCEDURE UnitIsDefModule () : BOOLEAN;
|
|
|
+ 204 BEGIN RETURN unitWasDef END UnitIsDefModule;
|
|
|
+ 205
|
|
|
+ 206 PROCEDURE RefineSeen () : BOOLEAN;
|
|
|
+ 207 BEGIN RETURN refSeen END RefineSeen;
|
|
|
+ 208
|
|
|
+ 209 PROCEDURE RefineIsDef () : BOOLEAN;
|
|
|
+ 210 BEGIN RETURN refIsDef END RefineIsDef;
|
|
|
+ 211
|
|
|
+ 212 PROCEDURE RefineInst (VAR nm: SymTab.Name);
|
|
|
+ 213 BEGIN CopyNm(refInst, nm) END RefineInst;
|
|
|
+ 214
|
|
|
+ 215 PROCEDURE RefineGen (VAR nm: SymTab.Name);
|
|
|
+ 216 BEGIN CopyNm(refGen, nm) END RefineGen;
|
|
|
+ 217
|
|
|
+ 218 PROCEDURE RefineActualCount () : CARDINAL;
|
|
|
+ 219 BEGIN RETURN refN END RefineActualCount;
|
|
|
+ 220
|
|
|
+ 221 PROCEDURE RefineActualGet (i: CARDINAL) : SymTab.TypeIndex;
|
|
|
+ 222 BEGIN
|
|
|
+ 223 IF i >= refN THEN RETURN SymTab.InvalidType END;
|
|
|
+ 224 RETURN refActual[i]
|
|
|
+ 225 END RefineActualGet;
|
|
|
+ 226
|
|
|
+ 227 PROCEDURE NoteLabel (nm: ARRAY OF CHAR);
|
|
|
+ 228 (* Record a statement label; duplicate is 200. *)
|
|
|
+ 229 VAR i: CARDINAL;
|
|
|
+ 230 BEGIN
|
|
|
+ 231 i := 0;
|
|
|
+ 232 WHILE i < nLab DO
|
|
|
+ 233 IF SymTab.Equal(labNm[i], nm) THEN SemError(200); RETURN END;
|
|
|
+ 234 INC(i)
|
|
|
+ 235 END;
|
|
|
+ 236 IF nLab <= HIGH(labNm) THEN
|
|
|
+ 237 CopyNm(nm, labNm[nLab]); INC(nLab)
|
|
|
+ 238 END
|
|
|
+ 239 END NoteLabel;
|
|
|
+ 240
|
|
|
+ 241 PROCEDURE NoteGoto (nm: ARRAY OF CHAR);
|
|
|
+ 242 VAR i: CARDINAL;
|
|
|
+ 243 BEGIN
|
|
|
+ 244 i := 0;
|
|
|
+ 245 WHILE i < nGot DO
|
|
|
+ 246 IF SymTab.Equal(gotNm[i], nm) THEN RETURN END;
|
|
|
+ 247 INC(i)
|
|
|
+ 248 END;
|
|
|
+ 249 IF nGot <= HIGH(gotNm) THEN
|
|
|
+ 250 CopyNm(nm, gotNm[nGot]); INC(nGot)
|
|
|
+ 251 END
|
|
|
+ 252 END NoteGoto;
|
|
|
+ 253
|
|
|
+ 254 PROCEDURE CheckGotos;
|
|
|
+ 255 (* At a procedure's END: every GOTO must name a label in that procedure. *)
|
|
|
+ 256 VAR i, j: CARDINAL; found: BOOLEAN;
|
|
|
+ 257 BEGIN
|
|
|
+ 258 i := 0;
|
|
|
+ 259 WHILE i < nGot DO
|
|
|
+ 260 found := FALSE; j := 0;
|
|
|
+ 261 WHILE (j < nLab) AND NOT found DO
|
|
|
+ 262 IF SymTab.Equal(labNm[j], gotNm[i]) THEN found := TRUE END;
|
|
|
+ 263 INC(j)
|
|
|
+ 264 END;
|
|
|
+ 265 IF NOT found THEN SemError(201) END;
|
|
|
+ 266 INC(i)
|
|
|
+ 267 END
|
|
|
+ 268 END CheckGotos;
|
|
|
+ 269
|
|
|
+ 270 PROCEDURE FlushPend;
|
|
|
+ 271 (* Emit module-level globals whose forward type is now resolved. *)
|
|
|
+ 272 VAR k: CARDINAL;
|
|
|
+ 273 BEGIN
|
|
|
+ 274 k := 0;
|
|
|
+ 275 WHILE k < nPendVar DO
|
|
|
+ 276 INC(k)
|
|
|
+ 277 END;
|
|
|
+ 278 nPendVar := 0
|
|
|
+ 279 END FlushPend;
|
|
|
+ 280
|
|
|
+ 281 PROCEDURE AstAppend (kind: INTEGER; VAR head, tail: AST.Node;
|
|
|
+ 282 item: AST.Node);
|
|
|
+ 283 (* Appends `item` to a chunked sequence: each node holds up to
|
|
|
+ 284 AST.MaxChild-1 items; child[MaxChild-1] continues into the next
|
|
|
+ 285 chunk. Unbounded, so blocks/decl sequences are not capped at 8. *)
|
|
|
+ 286 VAR n: AST.Node;
|
|
|
+ 287 BEGIN
|
|
|
+ 288 IF item = AST.NoNode THEN RETURN END;
|
|
|
+ 289 IF head = AST.NoNode THEN
|
|
|
+ 290 head := AST.MakeNode(kind); tail := head
|
|
|
+ 291 END;
|
|
|
+ 292 IF AST.NChild(tail) >= AST.MaxChild - 1 THEN
|
|
|
+ 293 n := AST.MakeNode(kind);
|
|
|
+ 294 AST.SetChild(tail, AST.MaxChild - 1, n);
|
|
|
+ 295 tail := n
|
|
|
+ 296 END;
|
|
|
+ 297 AST.SetChild(tail, AST.NChild(tail), item)
|
|
|
+ 298 END AstAppend;
|
|
|
+ 299
|
|
|
+ 300 PROCEDURE AstCallNode (callee: AST.Node) : AST.Node;
|
|
|
+ 301 (* Builds NkCall(callee, actuals...) from astArgs/astNArgs. The actuals
|
|
|
+ 302 are a chunked sequence (AstAppend): a call can have more than
|
|
|
+ 303 MaxChild-1 arguments (the generic ArgList has 9), and SetChild would
|
|
|
+ 304 silently drop the tail. NkBlock marks the continuation chunks. *)
|
|
|
+ 305 VAR n, tail: AST.Node; j: CARDINAL;
|
|
|
+ 306 BEGIN
|
|
|
+ 307 n := AST.MakeNode(AST.NkCall);
|
|
|
+ 308 AST.SetChild(n, 0, callee);
|
|
|
+ 309 tail := n;
|
|
|
+ 310 j := 0;
|
|
|
+ 311 WHILE j < astNArgs DO
|
|
|
+ 312 AstAppend(AST.NkBlock, n, tail, astArgs[j]);
|
|
|
+ 313 INC(j)
|
|
|
+ 314 END;
|
|
|
+ 315 RETURN n
|
|
|
+ 316 END AstCallNode;
|
|
|
317
|
|
|
318
|
|
|
- 319 PROCEDURE GetUnit (): AST.Node;
|
|
|
- 320 (* The most recently parsed unit's AST root (for the Lower comparison). *)
|
|
|
- 321 BEGIN
|
|
|
- 322 RETURN astUnit
|
|
|
- 323 END GetUnit;
|
|
|
- 324
|
|
|
- 325 PROCEDURE SetTwoPhase (b: BOOLEAN);
|
|
|
- 326 (* Driver switch for the two-phase parse probe (milestone 1). *)
|
|
|
- 327 BEGIN
|
|
|
- 328 twoPhaseParse := b
|
|
|
- 329 END SetTwoPhase;
|
|
|
- 330
|
|
|
- 331 PROCEDURE TokIs (kw: ARRAY OF CHAR): BOOLEAN;
|
|
|
- 332 (* The current lookahead token's source text equals kw. Compares text,
|
|
|
- 333 not token codes, so grammar renumbering cannot desync the skipper. *)
|
|
|
- 334 VAR tok: ARRAY [0 .. 63] OF CHAR;
|
|
|
- 335 BEGIN
|
|
|
- 336 M2S.GetName(M2S.nextPos, M2S.nextLen, tok);
|
|
|
- 337 RETURN SymTab.Equal(tok, kw)
|
|
|
- 338 END TokIs;
|
|
|
- 339
|
|
|
- 340 PROCEDURE Adv;
|
|
|
- 341 (* Advance one token: exactly the parser frame's Get for a grammar
|
|
|
- 342 without pragmas (its pragma branch is empty and the scanner never
|
|
|
- 343 returns a token above maxT, so the repeat loop runs once). A
|
|
|
- 344 separate name because the frame's Get is declared later in this
|
|
|
- 345 module: a bare Get here would bind the imported M2S.Get (which takes
|
|
|
- 346 a parameter) under single-pass compilers. *)
|
|
|
- 347 BEGIN
|
|
|
- 348 M2S.Get(sym);
|
|
|
- 349 INC(errDist)
|
|
|
- 350 END Adv;
|
|
|
- 351
|
|
|
- 352 PROCEDURE NoteSpan (pn: SymTab.Name; start: M2S.INT32);
|
|
|
- 353 (* Records an outermost body span for the re-parse pass (milestone 2).
|
|
|
- 354 Diagnostic only for now: nothing consumes the table yet. Declared
|
|
|
- 355 before its caller: V3 resolves single-pass (declaration before use),
|
|
|
- 356 with no forward tolerance for procedure calls. *)
|
|
|
- 357 BEGIN
|
|
|
- 358 IF nSpans > HIGH(spanName) THEN RETURN END;
|
|
|
- 359 CopyNm(pn, spanName[nSpans]);
|
|
|
- 360 spanStart[nSpans] := start;
|
|
|
- 361 INC(nSpans)
|
|
|
- 362 END NoteSpan;
|
|
|
- 363
|
|
|
- 364 PROCEDURE ProbeBody (pn: SymTab.Name);
|
|
|
- 365 (* Shadow-skip the body starting at the current token: consume tokens
|
|
|
- 366 counting block openers until the matching END, check the procedure
|
|
|
- 367 name after it, record the body span for the re-parse pass, verify
|
|
|
- 368 SeekTo repositions exactly, then restore the exact scanner/parser
|
|
|
- 369 state. The body then parses normally, so a correct skipper is
|
|
|
- 370 output-neutral; a wrong one reports to StdOut (never into the
|
|
|
- 371 listing). The SeekTo check's side effects are discarded by the
|
|
|
- 372 trailing PopPos, so it is output-neutral too. *)
|
|
|
- 373 VAR savedSym, savedErr, depth, guard: CARDINAL;
|
|
|
- 374 nm: SymTab.Name;
|
|
|
- 375 ok, sok: BOOLEAN;
|
|
|
- 376 start: M2S.INT32;
|
|
|
- 377 BEGIN
|
|
|
- 378 savedSym := sym; savedErr := errDist; start := M2S.nextPos;
|
|
|
- 379 M2S.PushPos;
|
|
|
- 380 depth := 0; guard := 0; ok := TRUE;
|
|
|
- 381 LOOP
|
|
|
- 382 IF sym = 0 THEN ok := FALSE; EXIT END;
|
|
|
- 383 IF TokIs("END") THEN
|
|
|
- 384 IF depth = 0 THEN EXIT END;
|
|
|
- 385 DEC(depth)
|
|
|
- 386 ELSIF TokIs("MODULE") OR TokIs("PROCEDURE") OR TokIs("CLASS")
|
|
|
- 387 OR TokIs("RECORD") OR TokIs("IF") OR TokIs("CASE")
|
|
|
- 388 OR TokIs("WHILE") OR TokIs("FOR") OR TokIs("LOOP")
|
|
|
- 389 OR TokIs("WITH") THEN
|
|
|
- 390 INC(depth)
|
|
|
- 391 END;
|
|
|
- 392 Adv;
|
|
|
- 393 INC(guard);
|
|
|
- 394 IF guard > 1000000 THEN ok := FALSE; EXIT END
|
|
|
- 395 END;
|
|
|
- 396 IF ok THEN
|
|
|
- 397 Adv;
|
|
|
- 398 M2S.GetName(M2S.nextPos, M2S.nextLen, nm);
|
|
|
- 399 IF (sym = 0) OR NOT SymTab.Equal(nm, pn) THEN ok := FALSE END
|
|
|
- 400 END;
|
|
|
- 401 IF ok THEN NoteSpan(pn, start) END;
|
|
|
- 402 sok := TRUE;
|
|
|
- 403 IF ok THEN
|
|
|
- 404 M2S.SeekTo(start);
|
|
|
- 405 Adv;
|
|
|
- 406 IF (sym # savedSym) OR (M2S.nextPos # start) THEN sok := FALSE END
|
|
|
- 407 END;
|
|
|
- 408 M2S.PopPos;
|
|
|
- 409 sym := savedSym; errDist := savedErr;
|
|
|
- 410 IF NOT ok THEN
|
|
|
- 411 FileIO.WriteString(FileIO.StdOut, "twophase probe mismatch in ");
|
|
|
- 412 FileIO.WriteString(FileIO.StdOut, pn);
|
|
|
- 413 FileIO.WriteLn(FileIO.StdOut)
|
|
|
- 414 ELSIF NOT sok THEN
|
|
|
- 415 FileIO.WriteString(FileIO.StdOut, "twophase seek mismatch in ");
|
|
|
- 416 FileIO.WriteString(FileIO.StdOut, pn);
|
|
|
- 417 FileIO.WriteLn(FileIO.StdOut)
|
|
|
- 418 END
|
|
|
- 419 END ProbeBody;
|
|
|
- 420
|
|
|
- 421 CHARACTERS
|
|
|
- 422 eol = CHR(13) .
|
|
|
- 423 lf = CHR(10) .
|
|
|
- 424 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
- 425 digit = "0123456789" .
|
|
|
- 426 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
- 427 noQuote1 = ANY - "'" - eol .
|
|
|
- 428 noQuote2 = ANY - '"' - eol .
|
|
|
- 429
|
|
|
- 430 IGNORE CHR(9) .. CHR(13)
|
|
|
+ 319
|
|
|
+ 320 PROCEDURE GetUnit (): AST.Node;
|
|
|
+ 321 (* The most recently parsed unit's AST root (for the Lower comparison). *)
|
|
|
+ 322 BEGIN
|
|
|
+ 323 RETURN astUnit
|
|
|
+ 324 END GetUnit;
|
|
|
+ 325
|
|
|
+ 326 PROCEDURE SetTwoPhase (b: BOOLEAN);
|
|
|
+ 327 (* Driver switch for the two-phase parse probe (milestone 1). *)
|
|
|
+ 328 BEGIN
|
|
|
+ 329 twoPhaseParse := b
|
|
|
+ 330 END SetTwoPhase;
|
|
|
+ 331
|
|
|
+ 332 PROCEDURE TokIs (kw: ARRAY OF CHAR): BOOLEAN;
|
|
|
+ 333 (* The current lookahead token's source text equals kw. Compares text,
|
|
|
+ 334 not token codes, so grammar renumbering cannot desync the skipper. *)
|
|
|
+ 335 VAR tok: ARRAY [0 .. 63] OF CHAR;
|
|
|
+ 336 BEGIN
|
|
|
+ 337 M2S.GetName(M2S.nextPos, M2S.nextLen, tok);
|
|
|
+ 338 RETURN SymTab.Equal(tok, kw)
|
|
|
+ 339 END TokIs;
|
|
|
+ 340
|
|
|
+ 341 PROCEDURE Adv;
|
|
|
+ 342 (* Advance one token: exactly the parser frame's Get for a grammar
|
|
|
+ 343 without pragmas (its pragma branch is empty and the scanner never
|
|
|
+ 344 returns a token above maxT, so the repeat loop runs once). A
|
|
|
+ 345 separate name because the frame's Get is declared later in this
|
|
|
+ 346 module: a bare Get here would bind the imported M2S.Get (which takes
|
|
|
+ 347 a parameter) under single-pass compilers. *)
|
|
|
+ 348 BEGIN
|
|
|
+ 349 M2S.Get(sym);
|
|
|
+ 350 INC(errDist)
|
|
|
+ 351 END Adv;
|
|
|
+ 352
|
|
|
+ 353 PROCEDURE NoteSpan (pn: SymTab.Name; start: M2S.INT32);
|
|
|
+ 354 (* Records an outermost body span for the re-parse pass (milestone 2).
|
|
|
+ 355 Diagnostic only for now: nothing consumes the table yet. Declared
|
|
|
+ 356 before its caller: V3 resolves single-pass (declaration before use),
|
|
|
+ 357 with no forward tolerance for procedure calls. *)
|
|
|
+ 358 BEGIN
|
|
|
+ 359 IF nSpans > HIGH(spanName) THEN RETURN END;
|
|
|
+ 360 CopyNm(pn, spanName[nSpans]);
|
|
|
+ 361 spanStart[nSpans] := start;
|
|
|
+ 362 spanIdx[nSpans] := SymTab.DeferBody();
|
|
|
+ 363 INC(nSpans)
|
|
|
+ 364 END NoteSpan;
|
|
|
+ 365
|
|
|
+ 366 PROCEDURE ProbeBody (pn: SymTab.Name);
|
|
|
+ 367 (* Shadow-skip the body starting at the current token: consume tokens
|
|
|
+ 368 counting block openers until the matching END, check the procedure
|
|
|
+ 369 name after it, record the body span for the re-parse pass, verify
|
|
|
+ 370 SeekTo repositions exactly, then restore the exact scanner/parser
|
|
|
+ 371 state. The body then parses normally, so a correct skipper is
|
|
|
+ 372 output-neutral; a wrong one reports to StdOut (never into the
|
|
|
+ 373 listing). The SeekTo check's side effects are discarded by the
|
|
|
+ 374 trailing PopPos, so it is output-neutral too. *)
|
|
|
+ 375 VAR savedSym, savedErr, depth, guard: CARDINAL;
|
|
|
+ 376 nm: SymTab.Name;
|
|
|
+ 377 ok, sok: BOOLEAN;
|
|
|
+ 378 start: M2S.INT32;
|
|
|
+ 379 BEGIN
|
|
|
+ 380 savedSym := sym; savedErr := errDist; start := M2S.nextPos;
|
|
|
+ 381 M2S.PushPos;
|
|
|
+ 382 depth := 0; guard := 0; ok := TRUE;
|
|
|
+ 383 LOOP
|
|
|
+ 384 IF sym = 0 THEN ok := FALSE; EXIT END;
|
|
|
+ 385 IF TokIs("END") THEN
|
|
|
+ 386 IF depth = 0 THEN EXIT END;
|
|
|
+ 387 DEC(depth)
|
|
|
+ 388 ELSIF TokIs("MODULE") OR TokIs("PROCEDURE") OR TokIs("CLASS")
|
|
|
+ 389 OR TokIs("RECORD") OR TokIs("IF") OR TokIs("CASE")
|
|
|
+ 390 OR TokIs("WHILE") OR TokIs("FOR") OR TokIs("LOOP")
|
|
|
+ 391 OR TokIs("WITH") THEN
|
|
|
+ 392 INC(depth)
|
|
|
+ 393 END;
|
|
|
+ 394 Adv;
|
|
|
+ 395 INC(guard);
|
|
|
+ 396 IF guard > 1000000 THEN ok := FALSE; EXIT END
|
|
|
+ 397 END;
|
|
|
+ 398 IF ok THEN
|
|
|
+ 399 Adv;
|
|
|
+ 400 M2S.GetName(M2S.nextPos, M2S.nextLen, nm);
|
|
|
+ 401 IF (sym = 0) OR NOT SymTab.Equal(nm, pn) THEN ok := FALSE END
|
|
|
+ 402 END;
|
|
|
+ 403 IF ok THEN NoteSpan(pn, start) END;
|
|
|
+ 404 sok := TRUE;
|
|
|
+ 405 IF ok THEN
|
|
|
+ 406 M2S.SeekTo(start);
|
|
|
+ 407 Adv;
|
|
|
+ 408 IF (sym # savedSym) OR (M2S.nextPos # start) THEN sok := FALSE END
|
|
|
+ 409 END;
|
|
|
+ 410 M2S.PopPos;
|
|
|
+ 411 sym := savedSym; errDist := savedErr;
|
|
|
+ 412 IF NOT ok THEN
|
|
|
+ 413 FileIO.WriteString(FileIO.StdOut, "twophase probe mismatch in ");
|
|
|
+ 414 FileIO.WriteString(FileIO.StdOut, pn);
|
|
|
+ 415 FileIO.WriteLn(FileIO.StdOut)
|
|
|
+ 416 ELSIF NOT sok THEN
|
|
|
+ 417 FileIO.WriteString(FileIO.StdOut, "twophase seek mismatch in ");
|
|
|
+ 418 FileIO.WriteString(FileIO.StdOut, pn);
|
|
|
+ 419 FileIO.WriteLn(FileIO.StdOut)
|
|
|
+ 420 END
|
|
|
+ 421 END ProbeBody;
|
|
|
+ 422
|
|
|
+ 423 CHARACTERS
|
|
|
+ 424 eol = CHR(13) .
|
|
|
+ 425 lf = CHR(10) .
|
|
|
+ 426 letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" .
|
|
|
+ 427 digit = "0123456789" .
|
|
|
+ 428 hexDigit = digit + "ABCDEFabcdef" .
|
|
|
+ 429 noQuote1 = ANY - "'" - eol .
|
|
|
+ 430 noQuote2 = ANY - '"' - eol .
|
|
|
431
|
|
|
- 432 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
- 433 COMMENTS FROM "//" TO lf
|
|
|
- 434
|
|
|
- 435 TOKENS
|
|
|
- 436 ident = letter { letter | digit | "_" } .
|
|
|
- 437 integer = digit { digit }
|
|
|
- 438 | digit { digit } CONTEXT("..")
|
|
|
- 439 | "0x" hexDigit { hexDigit }
|
|
|
- 440 | "0X" hexDigit { hexDigit } .
|
|
|
- 441 real = digit { digit } "." { digit }
|
|
|
- 442 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
- 443 string = "'" { noQuote1 } "'"
|
|
|
- 444 | '"' { noQuote2 } '"' .
|
|
|
- 445 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
- 446 ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
|
|
|
- 447
|
|
|
- 448 PRODUCTIONS
|
|
|
- 449 M2
|
|
|
- 450 = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
|
|
|
- 451 astImp := AST.NoNode;
|
|
|
- 452 astImpTail := AST.NoNode;
|
|
|
- 453 procNest := 0; nSpans := 0; .)
|
|
|
- 454 Unit "." .
|
|
|
- 455 (* Units: program modules compile fully; DEFINITION and
|
|
|
- 456 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
- 457 (each ends with one 230); same for nested local modules. *)
|
|
|
- 458 (* Generics (Increment 1): formal and actual parameters. Formals are
|
|
|
- 459 TYPE parameters only; actuals are type identifiers. *)
|
|
|
- 460 GenericFormals
|
|
|
- 461 = "(" GenericFormal { ";" GenericFormal } ")" .
|
|
|
- 462 GenericFormal (. VAR nm: SymTab.Name; .)
|
|
|
- 463 = GetIdent<nm> (. IF instActive THEN
|
|
|
- 464 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
- 465 InstActualGet(instFk)) THEN
|
|
|
- 466 SemError(200) END
|
|
|
- 467 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
- 468 SemError(200) END;
|
|
|
- 469 INC(instFk); .)
|
|
|
- 470 { "," GetIdent<nm> (. IF instActive THEN
|
|
|
- 471 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
- 472 InstActualGet(instFk)) THEN
|
|
|
- 473 SemError(200) END
|
|
|
- 474 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
- 475 SemError(200) END;
|
|
|
- 476 INC(instFk); .) }
|
|
|
- 477 ":" "TYPE" .
|
|
|
- 478 Actuals
|
|
|
- 479 = Actual { "," Actual } .
|
|
|
- 480 Actual (. VAR at: SymTab.TypeIndex; .)
|
|
|
- 481 = TypeIdent<at> (. IF refN <= HIGH(refActual) THEN
|
|
|
- 482 refActual[refN] := at; INC(refN)
|
|
|
- 483 END; .) .
|
|
|
- 484 Unit
|
|
|
- 485 = (. isGen := FALSE; .)
|
|
|
- 486 [ "GENERIC" (. isGen := TRUE; .) ]
|
|
|
- 487 ( DefUnit | ImplUnit | ProgModule ) .
|
|
|
- 488 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
- 489 and one program (last) into one image. Units share the symbol
|
|
|
- 490 table; imports materialize exported names. *)
|
|
|
- 491 DefUnit (. VAR m1, m2, pn: SymTab.Name;
|
|
|
- 492 g: SymTab.Name;
|
|
|
- 493 astSeq, astTail, astProc: AST.Node; .)
|
|
|
- 494 = (. refN := 0; refSeen := FALSE; .)
|
|
|
- 495 "DEFINITION" "MODULE"
|
|
|
- 496 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
- 497 IF instActive THEN
|
|
|
- 498 IF NOT SymTab.Reenter(m1,
|
|
|
- 499 SymTab.UnitDef) THEN
|
|
|
- 500 SemError(200) END
|
|
|
- 501 ELSIF NOT SymTab.BeginDef(m1) THEN
|
|
|
- 502 SemError(200) END;
|
|
|
- 503 QbeGen.SetModule(m1);
|
|
|
- 504 CopyNm(m1, unitName);
|
|
|
- 505 unitWasGen := isGen
|
|
|
- 506 AND NOT instActive;
|
|
|
- 507 unitWasDef := TRUE; .)
|
|
|
- 508 [ GenericFormals ]
|
|
|
- 509 ( ";"
|
|
|
- 510 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 511 astImp, astImpTail, astDecl); .) }
|
|
|
- 512 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
- 513 list: parsed, and the
|
|
|
- 514 names are already exported
|
|
|
- 515 by the module scope *) .)
|
|
|
- 516 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
- 517 (. astSeq := AST.NoNode;
|
|
|
- 518 astTail := AST.NoNode; .)
|
|
|
- 519 { ConstBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
- 520 astSeq, astTail, astDecl); .)
|
|
|
- 521 | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
|
|
|
- 522 astSeq, astTail, astDecl); .)
|
|
|
- 523 | VarBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
- 524 astSeq, astTail, astDecl); .)
|
|
|
- 525 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 526 (. (* a heading only: record it so
|
|
|
- 527 Lower can replay it *)
|
|
|
- 528 astProc := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 529 AST.SetOp(astProc, 0);
|
|
|
- 530 AST.SetChild(astProc, 0,
|
|
|
- 531 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 532 AstAppend(AST.NkDeclSeq,
|
|
|
- 533 astSeq, astTail, astProc);
|
|
|
- 534 Lower.NoteProcNode(astProc);
|
|
|
- 535 Lower.ScopeLeave;
|
|
|
- 536 SymTab.CloseProc;
|
|
|
- 537 QbeGen.AbortFunc; .) }
|
|
|
- 538 (. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
- 539 AST.SetChild(astUnit, 0,
|
|
|
- 540 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 541 AST.SetChild(astUnit, 1, astSeq);
|
|
|
- 542 AST.SetChild(astUnit, 3, astImp);
|
|
|
- 543 astDecl := AST.NoNode;
|
|
|
- 544 astStmt := AST.NoNode; .)
|
|
|
- 545 "END"
|
|
|
- 546 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
- 547 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 548 SemError(202) END;
|
|
|
- 549 SymTab.EndUnit; .)
|
|
|
- 550 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
- 551 (. CopyNm(m1, refInst);
|
|
|
- 552 CopyNm(g, refGen);
|
|
|
- 553 refSeen := TRUE; refIsDef := TRUE;
|
|
|
- 554 astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
- 555 AST.SetChild(astUnit, 0,
|
|
|
- 556 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 557 astDecl := AST.NoNode;
|
|
|
- 558 astStmt := AST.NoNode; .)
|
|
|
- 559 "END"
|
|
|
- 560 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 561 SemError(202) END;
|
|
|
- 562 SymTab.EndUnit; .) ) .
|
|
|
- 563 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
- 564 g: SymTab.Name;
|
|
|
- 565 k: CARDINAL;
|
|
|
- 566 fname: SymTab.Name;
|
|
|
- 567 unres: BOOLEAN;
|
|
|
- 568 astNode: AST.Node; .)
|
|
|
- 569 = (. refN := 0; refSeen := FALSE; .)
|
|
|
- 570 "IMPLEMENTATION" "MODULE"
|
|
|
- 571 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
- 572 IF instActive THEN
|
|
|
- 573 IF NOT SymTab.Reenter(m1,
|
|
|
- 574 SymTab.UnitImpl) THEN
|
|
|
- 575 SemError(201) END
|
|
|
- 576 ELSIF NOT SymTab.BeginImpl(m1) THEN
|
|
|
- 577 SemError(201) END;
|
|
|
- 578 astStmt := AST.NoNode;
|
|
|
- 579 astDecl := AST.NoNode;
|
|
|
- 580 astImp := AST.NoNode;
|
|
|
- 581 astImpTail := AST.NoNode;
|
|
|
- 582 nPendVar := 0;
|
|
|
- 583 CopyNm(m1, unitName);
|
|
|
- 584 unitWasGen := isGen AND NOT instActive;
|
|
|
- 585 unitWasDef := FALSE;
|
|
|
- 586 QbeGen.SetModule(m1); .)
|
|
|
- 587 [ GenericFormals ]
|
|
|
- 588 ( ";"
|
|
|
- 589 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 590 astImp, astImpTail, astDecl); .) }
|
|
|
- 591 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
- 592 [ "BEGIN" (. FlushPend;
|
|
|
- 593 k := 0;
|
|
|
- 594 WHILE k < SymTab.FwdPending() DO
|
|
|
- 595 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 596 IF unres THEN SemError(201) END;
|
|
|
- 597 INC(k)
|
|
|
- 598 END;
|
|
|
- 599 SymTab.FwdClear;
|
|
|
- 600
|
|
|
- 601 nLab := 0; nGot := 0; .)
|
|
|
- 602 [ StatSeq ] ]
|
|
|
- 603 "END"
|
|
|
- 604 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
- 605 FlushPend;
|
|
|
- 606 k := 0;
|
|
|
- 607 WHILE k < SymTab.FwdPending() DO
|
|
|
- 608 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 609 IF unres THEN SemError(201) END;
|
|
|
- 610 INC(k)
|
|
|
- 611 END;
|
|
|
- 612 SymTab.FwdClear;
|
|
|
- 613
|
|
|
- 614 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 615 AST.SetChild(astNode, 0,
|
|
|
- 616 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 617 AST.SetChild(astNode, 1, astDecl);
|
|
|
- 618 AST.SetChild(astNode, 2, astStmt);
|
|
|
- 619 AST.SetChild(astNode, 3, astImp);
|
|
|
- 620 astUnit := astNode;
|
|
|
- 621 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 622 SemError(202) END;
|
|
|
- 623 CheckGotos;
|
|
|
- 624 SymTab.EndUnit; .)
|
|
|
- 625 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
- 626 (. CopyNm(m1, refInst);
|
|
|
- 627 CopyNm(g, refGen);
|
|
|
- 628 refSeen := TRUE; refIsDef := FALSE;
|
|
|
- 629 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 630 AST.SetChild(astNode, 0,
|
|
|
- 631 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 632 astDecl := AST.NoNode;
|
|
|
- 633 astStmt := AST.NoNode; .)
|
|
|
- 634 "END"
|
|
|
- 635 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 636 SemError(202) END;
|
|
|
- 637 SymTab.EndUnit; .) ) .
|
|
|
- 638 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
- 639 k: CARDINAL;
|
|
|
- 640 fname: SymTab.Name;
|
|
|
- 641 unres: BOOLEAN;
|
|
|
- 642 astNode: AST.Node; .)
|
|
|
- 643 = "MODULE"
|
|
|
- 644 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
- 645 SemError(200) END;
|
|
|
- 646 astStmt := AST.NoNode;
|
|
|
- 647 astDecl := AST.NoNode;
|
|
|
- 648 astImp := AST.NoNode;
|
|
|
- 649 astImpTail := AST.NoNode;
|
|
|
- 650 nPendVar := 0;
|
|
|
- 651 QbeGen.SetModule(m1); .)
|
|
|
- 652 [ Priority ]
|
|
|
- 653 ";"
|
|
|
- 654 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 655 astImp, astImpTail, astDecl); .) }
|
|
|
- 656 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
- 657 [ "BEGIN" (. FlushPend;
|
|
|
- 658 k := 0;
|
|
|
- 659 WHILE k < SymTab.FwdPending() DO
|
|
|
- 660 SymTab.FwdInfo(k, fname, unres);
|
|
|
- 661 IF unres THEN SemError(201) END;
|
|
|
- 662 INC(k)
|
|
|
- 663 END;
|
|
|
- 664 SymTab.FwdClear;
|
|
|
- 665
|
|
|
- 666 nLab := 0; nGot := 0; .)
|
|
|
- 667 [ StatSeq ] ]
|
|
|
- 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 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 680 SemError(202) END;
|
|
|
- 681 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 682 AST.SetChild(astNode, 0,
|
|
|
- 683 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 684 AST.SetChild(astNode, 1, astDecl);
|
|
|
- 685 AST.SetChild(astNode, 2, astStmt);
|
|
|
- 686 AST.SetChild(astNode, 3, astImp);
|
|
|
- 687 astUnit := astNode;
|
|
|
- 688 CheckGotos;
|
|
|
- 689 SymTab.EndUnit; .) .
|
|
|
- 690 DeclSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 691 = (. astSeq := AST.NoNode;
|
|
|
- 692 astTail := AST.NoNode; .)
|
|
|
- 693 { (. astDecl := AST.NoNode; .)
|
|
|
- 694 ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
- 695 | NestedModule ";" | ClassItem ";" )
|
|
|
- 696 (. AstAppend(AST.NkDeclSeq,
|
|
|
- 697 astSeq, astTail, astDecl); .) }
|
|
|
- 698 (. astDecl := astSeq; .) .
|
|
|
- 699 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
- 700 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
- 701 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
- 702 scope at END. *)
|
|
|
- 703 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
- 704 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
- 705 expCount, k: CARDINAL;
|
|
|
- 706 astNode, nImp, nImpTail:
|
|
|
- 707 AST.Node; .)
|
|
|
- 708 = "MODULE"
|
|
|
- 709 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
- 710 SymTab.KindModule) THEN
|
|
|
- 711 SemError(200) END;
|
|
|
- 712 SymTab.PushScope;
|
|
|
- 713 expCount := 0;
|
|
|
- 714 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
- 715 AST.SetChild(astNode, 0,
|
|
|
- 716 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
- 717 astStmt := AST.NoNode;
|
|
|
- 718 astDecl := AST.NoNode;
|
|
|
- 719 nImp := AST.NoNode;
|
|
|
- 720 nImpTail := AST.NoNode; .)
|
|
|
- 721 [ Priority ]
|
|
|
- 722 ";"
|
|
|
- 723 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
- 724 nImp, nImpTail, astDecl); .) }
|
|
|
- 725 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
- 726 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
- 727 { "," GetIdent<expNames[expCount]>
|
|
|
- 728 (. INC(expCount); .) }
|
|
|
- 729 ";" ]
|
|
|
- 730 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
- 731 [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
- 732 .)
|
|
|
- 733 [ StatSeq ] ]
|
|
|
- 734 "END"
|
|
|
- 735 GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
|
|
|
- 736 AST.SetChild(astNode, 2, astStmt);
|
|
|
- 737 AST.SetChild(astNode, 3, nImp);
|
|
|
- 738 astDecl := astNode;
|
|
|
- 739 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 740 SemError(202) END;
|
|
|
- 741 k := 0;
|
|
|
- 742 WHILE k < expCount DO
|
|
|
- 743 SymTab.ExportUp(expNames[k]);
|
|
|
- 744 INC(k)
|
|
|
- 745 END;
|
|
|
- 746 SymTab.PopScope; .) .
|
|
|
- 747 Priority
|
|
|
- 748 = "[" integer "]" (. SemError(230); .) .
|
|
|
- 749 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
- 750 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
- 751 materializes on first use (Design). *)
|
|
|
- 752 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
- 753 import lines don't fail); a known module's missing export is
|
|
|
- 754 201. *)
|
|
|
- 755 Import (. VAR n: SymTab.Name;
|
|
|
- 756 astImport: AST.Node; .)
|
|
|
- 757 = "FROM"
|
|
|
- 758 GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
- 759 AST.SetChild(astImport, 0,
|
|
|
- 760 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 761 "IMPORT"
|
|
|
- 762 ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
- 763 | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
- 764 ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
- 765 ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
- 766 (. VAR n: SymTab.Name; .)
|
|
|
- 767 = ImpName<mod, node>
|
|
|
- 768 { "," ImpName<mod, node> } .
|
|
|
- 769 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
- 770 accepted and ignored: the built-in applies regardless. *)
|
|
|
- 771 ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
- 772 (. VAR n: SymTab.Name; .)
|
|
|
- 773 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
- 774 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 775 IF SymTab.Equal(mod, "libc") THEN
|
|
|
- 776 (* intrinsic C library:
|
|
|
- 777 permissive external *)
|
|
|
- 778 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
- 779 SemError(201) END;
|
|
|
- 780 Lower.NoteCProc(n)
|
|
|
- 781 ELSIF SymTab.ModKnown(mod) THEN
|
|
|
- 782 IF NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
- 783 SemError(201)
|
|
|
- 784 ELSE Lower.NoteImportedProc(n)
|
|
|
- 785 END
|
|
|
- 786 END; .)
|
|
|
- 787 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
- 788 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
- 789 | "UCHR" | "CHR8" | "UORD"
|
|
|
- 790 | "INC" | "DEC" ) .
|
|
|
- 791 ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
- 792 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
- 793 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 794 { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
- 795 AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
- 796 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
- 797 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
- 798 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
- 799 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
- 800 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
- 801 TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 802 = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
- 803 astSeq := AST.NoNode;
|
|
|
- 804 astTail := AST.NoNode; .)
|
|
|
- 805 { (. astDecl := AST.NoNode; .)
|
|
|
- 806 ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
- 807 (. AstAppend(AST.NkDeclSeq,
|
|
|
- 808 astSeq, astTail, astDecl); .) }
|
|
|
- 809 (. SymTab.EndTypeBlock;
|
|
|
- 810 astDecl := astSeq; .) .
|
|
|
- 811 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
- 812 t, op: SymTab.TypeIndex;
|
|
|
- 813 astNode: AST.Node; .)
|
|
|
- 814 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
- 815 IF op = SymTab.InvalidType THEN
|
|
|
- 816 IF NOT SymTab.Enter(n,
|
|
|
- 817 SymTab.KindType) THEN
|
|
|
- 818 SemError(200) END
|
|
|
- 819 END; .)
|
|
|
- 820 ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
|
|
|
- 821 AST.SetChild(astNode, 0,
|
|
|
- 822 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 823 AST.SetTy(astNode, t);
|
|
|
- 824 astDecl := astNode;
|
|
|
- 825 IF op # SymTab.InvalidType THEN
|
|
|
- 826 SymTab.SetTarget(op, t)
|
|
|
- 827 ELSE SymTab.SetSymType(n, t)
|
|
|
- 828 END; .)
|
|
|
- 829 | (. IF op # SymTab.InvalidType THEN
|
|
|
- 830 (* stays opaque *)
|
|
|
- 831 ELSIF NOT isDef THEN
|
|
|
- 832 SemError(231)
|
|
|
- 833 ELSE SymTab.SetSymType(n,
|
|
|
- 834 SymTab.NewAlias()) END; .) ) .
|
|
|
- 835 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 836 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
- 837 | Subrange<t>
|
|
|
- 838 | Enum<t>
|
|
|
- 839 | ArrayType<t, allowOpen>
|
|
|
- 840 | SetType<t>
|
|
|
- 841 | RecordType<t>
|
|
|
- 842 | PointerType<t>
|
|
|
- 843 | ProcType<t> .
|
|
|
- 844 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
- 845 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
- 846 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
- 847 are code pointers; params are collected into the descriptor. *)
|
|
|
- 848 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
- 849 isV: BOOLEAN; .)
|
|
|
- 850 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
- 851 t := SymTab.NewProcType(res); .)
|
|
|
- 852 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
- 853 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
- 854 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
- 855 isV: BOOLEAN;
|
|
|
- 856 cnt, k: CARDINAL;
|
|
|
- 857 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
- 858 = (. isV := FALSE; cnt := 0; .)
|
|
|
- 859 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 860 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
- 861 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
- 862 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
- 863 WHILE k < cnt DO
|
|
|
- 864 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
- 865 INC(k)
|
|
|
- 866 END; .)
|
|
|
- 867 | (. (* type-only parameter list:
|
|
|
- 868 each name is a type (GNU
|
|
|
- 869 shorthand used by the
|
|
|
- 870 Coco/R scanner frame) *)
|
|
|
- 871 k := 0;
|
|
|
- 872 WHILE k < cnt DO
|
|
|
- 873 IF SymTab.Lookup(names[k])
|
|
|
- 874 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
- 875 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
- 876 pt := SymTab.SymType(names[k])
|
|
|
- 877 ELSE SemError(201);
|
|
|
- 878 pt := SymTab.InvalidType
|
|
|
- 879 END;
|
|
|
- 880 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
- 881 INC(k)
|
|
|
- 882 END; .) )
|
|
|
- 883 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
- 884 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
- 885 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
- 886 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
- 887 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
- 888 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
- 889 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
- 890 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 891 (. VAR elem: SymTab.TypeIndex;
|
|
|
- 892 ok: BOOLEAN;
|
|
|
- 893 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
- 894 nb, k: CARDINAL;
|
|
|
- 895 idx: SymTab.TypeIndex;
|
|
|
- 896 ilo, ihi: INTEGER; .)
|
|
|
- 897 = "ARRAY"
|
|
|
- 898 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
- 899 SemError(230) END;
|
|
|
- 900 t := SymTab.NewOpenArray(elem); .)
|
|
|
- 901 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
- 902 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
- 903 type's ordinal bounds give the
|
|
|
- 904 [lo..hi] pair *)
|
|
|
- 905 IF SymTab.TypeBounds(idx, ilo,
|
|
|
- 906 ihi)
|
|
|
- 907 THEN t := SymTab.NewArrayB(elem,
|
|
|
- 908 ilo, ihi)
|
|
|
- 909 ELSE SemError(230);
|
|
|
- 910 t := SymTab.InvalidType
|
|
|
- 911 END; .)
|
|
|
- 912 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
- 913 BoundPair<ok>
|
|
|
- 914 { "," BoundPair<ok> }
|
|
|
- 915 "]" (. (* snapshot before the element
|
|
|
- 916 type, which reuses the bound
|
|
|
- 917 buffer for a nested ARRAY *)
|
|
|
- 918 nb := SymTab.BoundCount();
|
|
|
- 919 k := 0;
|
|
|
- 920 WHILE k < nb DO
|
|
|
- 921 bnds[k] := SymTab.BoundLo(k);
|
|
|
- 922 bndh[k] := SymTab.BoundHi(k);
|
|
|
- 923 INC(k)
|
|
|
- 924 END; .)
|
|
|
- 925 "OF" Type<elem, FALSE>
|
|
|
- 926 (. IF ok THEN
|
|
|
- 927 k := nb;
|
|
|
- 928 WHILE k > 0 DO
|
|
|
- 929 DEC(k);
|
|
|
- 930 elem := SymTab.NewArrayB(
|
|
|
- 931 elem, bnds[k], bndh[k])
|
|
|
- 932 END;
|
|
|
- 933 t := elem
|
|
|
- 934 ELSE t := SymTab.InvalidType
|
|
|
- 935 END; .) ) .
|
|
|
- 936 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 937 qlo, qhi: QbeGen.QVal;
|
|
|
- 938 lo, hi: INTEGER;
|
|
|
- 939 cl, cl2: INTEGER; .)
|
|
|
- 940 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 941 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 942 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 943 ok := FALSE
|
|
|
- 944 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
- 945 cl2 := SymTab.ClassOf(thi);
|
|
|
- 946 IF ((cl # SymTab.ClInt)
|
|
|
- 947 AND (cl # SymTab.ClChar))
|
|
|
- 948 OR ((cl2 # SymTab.ClInt)
|
|
|
- 949 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
- 950 SemError(230); ok := FALSE
|
|
|
- 951 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 952 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 953 OR (lo > hi) THEN
|
|
|
- 954 SemError(230); ok := FALSE
|
|
|
- 955 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
- 956 SemError(230); ok := FALSE
|
|
|
- 957 END;
|
|
|
- 958 END; .) .
|
|
|
- 959 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
- 960 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
- 961 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
- 962 comparison across suitable bases are lenient (masks over min
|
|
|
- 963 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
- 964 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
- 965 blo, bhi, bspan: INTEGER;
|
|
|
- 966 bcls: INTEGER; .)
|
|
|
- 967 = "SET" "OF" Type<base, FALSE>
|
|
|
- 968 (. IF base = SymTab.InvalidType THEN
|
|
|
- 969 t := SymTab.InvalidType
|
|
|
- 970 ELSE bcls :=
|
|
|
- 971 SymTab.ClassOf(base);
|
|
|
- 972 IF bcls = SymTab.ClBool THEN
|
|
|
- 973 blo := 0; bspan := 2
|
|
|
- 974 ELSIF bcls = SymTab.ClChar THEN
|
|
|
- 975 blo := 0; bspan := 256
|
|
|
- 976 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
- 977 blo := 0;
|
|
|
- 978 bspan := VAL(INTEGER,
|
|
|
- 979 SymTab.EnumCount(base))
|
|
|
- 980 ELSIF SymTab.SubBounds(base,
|
|
|
- 981 blo, bhi) THEN
|
|
|
- 982 bspan := bhi - blo + 1
|
|
|
- 983 ELSE bspan := 0 END;
|
|
|
- 984 IF (bspan <= 0)
|
|
|
- 985 OR (bspan > 65536) THEN
|
|
|
- 986 SemError(230);
|
|
|
- 987 t := SymTab.InvalidType
|
|
|
- 988 ELSE t := SymTab.NewSet(base)
|
|
|
- 989 END
|
|
|
- 990 END; .) .
|
|
|
- 991 (* Records: flat blobs; array fields are pointers to static
|
|
|
- 992 descriptors (locked amendment), nested records inline. Field
|
|
|
- 993 offsets static and declaration-ordered. *)
|
|
|
- 994 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
- 995 variant part is a `CASE ... END` item; because it starts with the
|
|
|
- 996 CASE keyword it is unambiguously distinguishable from a field
|
|
|
- 997 (which starts with an identifier). *)
|
|
|
- 998 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
- 999 tagOk: BOOLEAN; .)
|
|
|
- 1000 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
- 1001 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
- 1002 "END" (. SymTab.LayoutRecord(t); .) .
|
|
|
- 1003 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
- 1004 = RecField<rec>
|
|
|
- 1005 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
- 1006 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
- 1007 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
- 1008 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
- 1009 tagN: SymTab.Name; .)
|
|
|
- 1010 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
- 1011 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1012 tagN) THEN
|
|
|
- 1013 SemError(200) END; .)
|
|
|
- 1014 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
- 1015 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
- 1016 SemError(224)
|
|
|
- 1017 END;
|
|
|
- 1018 SymTab.FixPendingF(rec, tagT);
|
|
|
- 1019 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
- 1020 "OF"
|
|
|
- 1021 RecFieldList<rec>
|
|
|
- 1022 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
- 1023 RecFieldList<rec> }
|
|
|
- 1024 "END" .
|
|
|
- 1025 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
- 1026 lv1, lv2: QbeGen.QVal; .)
|
|
|
- 1027 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
- 1028 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
- 1029 (* Variant case label: a constant (or a constant range). Values are
|
|
|
- 1030 not interpreted (the layout overlays regardless). *)
|
|
|
- 1031 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1032 (. VAR lname: SymTab.Name; .)
|
|
|
- 1033 = ( ident (. LexName(lname);
|
|
|
- 1034 QbeGen.CopyOp("0", q);
|
|
|
- 1035 t := SymTab.IntType(); .)
|
|
|
- 1036 | integer (. LexString(lname);
|
|
|
+ 432 IGNORE CHR(9) .. CHR(13)
|
|
|
+ 433
|
|
|
+ 434 COMMENTS FROM "(*" TO "*)" NESTED
|
|
|
+ 435 COMMENTS FROM "//" TO lf
|
|
|
+ 436
|
|
|
+ 437 TOKENS
|
|
|
+ 438 ident = letter { letter | digit | "_" } .
|
|
|
+ 439 integer = digit { digit }
|
|
|
+ 440 | digit { digit } CONTEXT("..")
|
|
|
+ 441 | "0x" hexDigit { hexDigit }
|
|
|
+ 442 | "0X" hexDigit { hexDigit } .
|
|
|
+ 443 real = digit { digit } "." { digit }
|
|
|
+ 444 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
+ 445 string = "'" { noQuote1 } "'"
|
|
|
+ 446 | '"' { noQuote2 } '"' .
|
|
|
+ 447 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
+ 448 ustring = ( "U" | "u" ) ( "'" { noQuote1 } "'" | '"' { noQuote2 } '"' ) .
|
|
|
+ 449
|
|
|
+ 450 PRODUCTIONS
|
|
|
+ 451 M2
|
|
|
+ 452 = (. twoPhase := TRUE; astCur := AST.NoNode; astStmt := AST.NoNode; astDecl := AST.NoNode; astImp := AST.NoNode; astImpTail := AST.NoNode;
|
|
|
+ 453 astImp := AST.NoNode;
|
|
|
+ 454 astImpTail := AST.NoNode;
|
|
|
+ 455 procNest := 0; nSpans := 0;
|
|
|
+ 456 SymTab.DeferReset; .)
|
|
|
+ 457 Unit "." .
|
|
|
+ 458 (* Units: program modules compile fully; DEFINITION and
|
|
|
+ 459 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
+ 460 (each ends with one 230); same for nested local modules. *)
|
|
|
+ 461 (* Generics (Increment 1): formal and actual parameters. Formals are
|
|
|
+ 462 TYPE parameters only; actuals are type identifiers. *)
|
|
|
+ 463 GenericFormals
|
|
|
+ 464 = "(" GenericFormal { ";" GenericFormal } ")" .
|
|
|
+ 465 GenericFormal (. VAR nm: SymTab.Name; .)
|
|
|
+ 466 = GetIdent<nm> (. IF instActive THEN
|
|
|
+ 467 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
+ 468 InstActualGet(instFk)) THEN
|
|
|
+ 469 SemError(200) END
|
|
|
+ 470 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
+ 471 SemError(200) END;
|
|
|
+ 472 INC(instFk); .)
|
|
|
+ 473 { "," GetIdent<nm> (. IF instActive THEN
|
|
|
+ 474 IF NOT SymTab.EnterTypeParamBound(nm,
|
|
|
+ 475 InstActualGet(instFk)) THEN
|
|
|
+ 476 SemError(200) END
|
|
|
+ 477 ELSIF NOT SymTab.EnterTypeParam(nm) THEN
|
|
|
+ 478 SemError(200) END;
|
|
|
+ 479 INC(instFk); .) }
|
|
|
+ 480 ":" "TYPE" .
|
|
|
+ 481 Actuals
|
|
|
+ 482 = Actual { "," Actual } .
|
|
|
+ 483 Actual (. VAR at: SymTab.TypeIndex; .)
|
|
|
+ 484 = TypeIdent<at> (. IF refN <= HIGH(refActual) THEN
|
|
|
+ 485 refActual[refN] := at; INC(refN)
|
|
|
+ 486 END; .) .
|
|
|
+ 487 Unit
|
|
|
+ 488 = (. isGen := FALSE; .)
|
|
|
+ 489 [ "GENERIC" (. isGen := TRUE; .) ]
|
|
|
+ 490 ( DefUnit | ImplUnit | ProgModule ) .
|
|
|
+ 491 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
+ 492 and one program (last) into one image. Units share the symbol
|
|
|
+ 493 table; imports materialize exported names. *)
|
|
|
+ 494 DefUnit (. VAR m1, m2, pn: SymTab.Name;
|
|
|
+ 495 g: SymTab.Name;
|
|
|
+ 496 astSeq, astTail, astProc: AST.Node; .)
|
|
|
+ 497 = (. refN := 0; refSeen := FALSE; .)
|
|
|
+ 498 "DEFINITION" "MODULE"
|
|
|
+ 499 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
+ 500 IF instActive THEN
|
|
|
+ 501 IF NOT SymTab.Reenter(m1,
|
|
|
+ 502 SymTab.UnitDef) THEN
|
|
|
+ 503 SemError(200) END
|
|
|
+ 504 ELSIF NOT SymTab.BeginDef(m1) THEN
|
|
|
+ 505 SemError(200) END;
|
|
|
+ 506 QbeGen.SetModule(m1);
|
|
|
+ 507 CopyNm(m1, unitName);
|
|
|
+ 508 unitWasGen := isGen
|
|
|
+ 509 AND NOT instActive;
|
|
|
+ 510 unitWasDef := TRUE; .)
|
|
|
+ 511 [ GenericFormals ]
|
|
|
+ 512 ( ";"
|
|
|
+ 513 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 514 astImp, astImpTail, astDecl); .) }
|
|
|
+ 515 [ "EXPORT" [ "QUALIFIED" ] (. (* definition-module export
|
|
|
+ 516 list: parsed, and the
|
|
|
+ 517 names are already exported
|
|
|
+ 518 by the module scope *) .)
|
|
|
+ 519 GetIdent<pn> { "," GetIdent<pn> } ";" ]
|
|
|
+ 520 (. astSeq := AST.NoNode;
|
|
|
+ 521 astTail := AST.NoNode; .)
|
|
|
+ 522 { ConstBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 523 astSeq, astTail, astDecl); .)
|
|
|
+ 524 | TypeBlock<TRUE> (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 525 astSeq, astTail, astDecl); .)
|
|
|
+ 526 | VarBlock (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 527 astSeq, astTail, astDecl); .)
|
|
|
+ 528 | ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 529 (. (* a heading only: record it so
|
|
|
+ 530 Lower can replay it *)
|
|
|
+ 531 astProc := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 532 AST.SetOp(astProc, 0);
|
|
|
+ 533 AST.SetChild(astProc, 0,
|
|
|
+ 534 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 535 AstAppend(AST.NkDeclSeq,
|
|
|
+ 536 astSeq, astTail, astProc);
|
|
|
+ 537 Lower.NoteProcNode(astProc);
|
|
|
+ 538 Lower.ScopeLeave;
|
|
|
+ 539 SymTab.CloseProc;
|
|
|
+ 540 QbeGen.AbortFunc; .) }
|
|
|
+ 541 (. astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
+ 542 AST.SetChild(astUnit, 0,
|
|
|
+ 543 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 544 AST.SetChild(astUnit, 1, astSeq);
|
|
|
+ 545 AST.SetChild(astUnit, 3, astImp);
|
|
|
+ 546 astDecl := AST.NoNode;
|
|
|
+ 547 astStmt := AST.NoNode; .)
|
|
|
+ 548 "END"
|
|
|
+ 549 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
+ 550 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 551 SemError(202) END;
|
|
|
+ 552 SymTab.EndUnit; .)
|
|
|
+ 553 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
+ 554 (. CopyNm(m1, refInst);
|
|
|
+ 555 CopyNm(g, refGen);
|
|
|
+ 556 refSeen := TRUE; refIsDef := TRUE;
|
|
|
+ 557 astUnit := AST.MakeNode(AST.NkUnit);
|
|
|
+ 558 AST.SetChild(astUnit, 0,
|
|
|
+ 559 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 560 astDecl := AST.NoNode;
|
|
|
+ 561 astStmt := AST.NoNode; .)
|
|
|
+ 562 "END"
|
|
|
+ 563 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 564 SemError(202) END;
|
|
|
+ 565 SymTab.EndUnit; .) ) .
|
|
|
+ 566 ImplUnit (. VAR m1, m2: SymTab.Name;
|
|
|
+ 567 g: SymTab.Name;
|
|
|
+ 568 k: CARDINAL;
|
|
|
+ 569 fname: SymTab.Name;
|
|
|
+ 570 unres: BOOLEAN;
|
|
|
+ 571 astNode: AST.Node; .)
|
|
|
+ 572 = (. refN := 0; refSeen := FALSE; .)
|
|
|
+ 573 "IMPLEMENTATION" "MODULE"
|
|
|
+ 574 GetIdent<m1> (. IF instActive THEN InstNameGet(m1) END;
|
|
|
+ 575 IF instActive THEN
|
|
|
+ 576 IF NOT SymTab.Reenter(m1,
|
|
|
+ 577 SymTab.UnitImpl) THEN
|
|
|
+ 578 SemError(201) END
|
|
|
+ 579 ELSIF NOT SymTab.BeginImpl(m1) THEN
|
|
|
+ 580 SemError(201) END;
|
|
|
+ 581 astStmt := AST.NoNode;
|
|
|
+ 582 astDecl := AST.NoNode;
|
|
|
+ 583 astImp := AST.NoNode;
|
|
|
+ 584 astImpTail := AST.NoNode;
|
|
|
+ 585 nPendVar := 0;
|
|
|
+ 586 CopyNm(m1, unitName);
|
|
|
+ 587 unitWasGen := isGen AND NOT instActive;
|
|
|
+ 588 unitWasDef := FALSE;
|
|
|
+ 589 QbeGen.SetModule(m1); .)
|
|
|
+ 590 [ GenericFormals ]
|
|
|
+ 591 ( ";"
|
|
|
+ 592 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 593 astImp, astImpTail, astDecl); .) }
|
|
|
+ 594 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
+ 595 [ "BEGIN" (. FlushPend;
|
|
|
+ 596 k := 0;
|
|
|
+ 597 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 598 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 599 IF unres THEN SemError(201) END;
|
|
|
+ 600 INC(k)
|
|
|
+ 601 END;
|
|
|
+ 602 SymTab.FwdClear;
|
|
|
+ 603
|
|
|
+ 604 nLab := 0; nGot := 0; .)
|
|
|
+ 605 [ StatSeq ] ]
|
|
|
+ 606 "END"
|
|
|
+ 607 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
+ 608 FlushPend;
|
|
|
+ 609 k := 0;
|
|
|
+ 610 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 611 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 612 IF unres THEN SemError(201) END;
|
|
|
+ 613 INC(k)
|
|
|
+ 614 END;
|
|
|
+ 615 SymTab.FwdClear;
|
|
|
+ 616
|
|
|
+ 617 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 618 AST.SetChild(astNode, 0,
|
|
|
+ 619 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 620 AST.SetChild(astNode, 1, astDecl);
|
|
|
+ 621 AST.SetChild(astNode, 2, astStmt);
|
|
|
+ 622 AST.SetChild(astNode, 3, astImp);
|
|
|
+ 623 astUnit := astNode;
|
|
|
+ 624 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 625 SemError(202) END;
|
|
|
+ 626 CheckGotos;
|
|
|
+ 627 SymTab.EndUnit; .)
|
|
|
+ 628 | "=" GetIdent<g> [ "(" Actuals ")" ] ";"
|
|
|
+ 629 (. CopyNm(m1, refInst);
|
|
|
+ 630 CopyNm(g, refGen);
|
|
|
+ 631 refSeen := TRUE; refIsDef := FALSE;
|
|
|
+ 632 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 633 AST.SetChild(astNode, 0,
|
|
|
+ 634 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 635 astDecl := AST.NoNode;
|
|
|
+ 636 astStmt := AST.NoNode; .)
|
|
|
+ 637 "END"
|
|
|
+ 638 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 639 SemError(202) END;
|
|
|
+ 640 SymTab.EndUnit; .) ) .
|
|
|
+ 641 ProgModule (. VAR m1, m2: SymTab.Name;
|
|
|
+ 642 k: CARDINAL;
|
|
|
+ 643 fname: SymTab.Name;
|
|
|
+ 644 unres: BOOLEAN;
|
|
|
+ 645 astNode: AST.Node; .)
|
|
|
+ 646 = "MODULE"
|
|
|
+ 647 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
+ 648 SemError(200) END;
|
|
|
+ 649 astStmt := AST.NoNode;
|
|
|
+ 650 astDecl := AST.NoNode;
|
|
|
+ 651 astImp := AST.NoNode;
|
|
|
+ 652 astImpTail := AST.NoNode;
|
|
|
+ 653 nPendVar := 0;
|
|
|
+ 654 QbeGen.SetModule(m1); .)
|
|
|
+ 655 [ Priority ]
|
|
|
+ 656 ";"
|
|
|
+ 657 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 658 astImp, astImpTail, astDecl); .) }
|
|
|
+ 659 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
+ 660 [ "BEGIN" (. FlushPend;
|
|
|
+ 661 k := 0;
|
|
|
+ 662 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 663 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 664 IF unres THEN SemError(201) END;
|
|
|
+ 665 INC(k)
|
|
|
+ 666 END;
|
|
|
+ 667 SymTab.FwdClear;
|
|
|
+ 668
|
|
|
+ 669 nLab := 0; nGot := 0; .)
|
|
|
+ 670 [ StatSeq ] ]
|
|
|
+ 671 "END"
|
|
|
+ 672 GetIdent<m2> (. IF instActive THEN InstNameGet(m2) END;
|
|
|
+ 673 FlushPend;
|
|
|
+ 674 k := 0;
|
|
|
+ 675 WHILE k < SymTab.FwdPending() DO
|
|
|
+ 676 SymTab.FwdInfo(k, fname, unres);
|
|
|
+ 677 IF unres THEN SemError(201) END;
|
|
|
+ 678 INC(k)
|
|
|
+ 679 END;
|
|
|
+ 680 SymTab.FwdClear;
|
|
|
+ 681
|
|
|
+ 682 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 683 SemError(202) END;
|
|
|
+ 684 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 685 AST.SetChild(astNode, 0,
|
|
|
+ 686 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 687 AST.SetChild(astNode, 1, astDecl);
|
|
|
+ 688 AST.SetChild(astNode, 2, astStmt);
|
|
|
+ 689 AST.SetChild(astNode, 3, astImp);
|
|
|
+ 690 astUnit := astNode;
|
|
|
+ 691 CheckGotos;
|
|
|
+ 692 SymTab.EndUnit; .) .
|
|
|
+ 693 DeclSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 694 = (. astSeq := AST.NoNode;
|
|
|
+ 695 astTail := AST.NoNode; .)
|
|
|
+ 696 { (. astDecl := AST.NoNode; .)
|
|
|
+ 697 ( ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
+ 698 | NestedModule ";" | ClassItem ";" )
|
|
|
+ 699 (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 700 astSeq, astTail, astDecl); .) }
|
|
|
+ 701 (. astDecl := astSeq; .) .
|
|
|
+ 702 (* Local module, Wirth form. Declarations lower like top-level ones
|
|
|
+ 703 (same QBE module prefix); a BEGIN body becomes an init function
|
|
|
+ 704 that main calls; the EXPORT list is hoisted into the enclosing
|
|
|
+ 705 scope at END. *)
|
|
|
+ 706 NestedModule (. VAR m1, m2: SymTab.Name;
|
|
|
+ 707 expNames: ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
+ 708 expCount, k: CARDINAL;
|
|
|
+ 709 astNode, nImp, nImpTail:
|
|
|
+ 710 AST.Node; .)
|
|
|
+ 711 = "MODULE"
|
|
|
+ 712 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
+ 713 SymTab.KindModule) THEN
|
|
|
+ 714 SemError(200) END;
|
|
|
+ 715 SymTab.PushScope;
|
|
|
+ 716 expCount := 0;
|
|
|
+ 717 astNode := AST.MakeNode(AST.NkUnit);
|
|
|
+ 718 AST.SetChild(astNode, 0,
|
|
|
+ 719 AST.MakeLeaf(AST.NkIdent, m1));
|
|
|
+ 720 astStmt := AST.NoNode;
|
|
|
+ 721 astDecl := AST.NoNode;
|
|
|
+ 722 nImp := AST.NoNode;
|
|
|
+ 723 nImpTail := AST.NoNode; .)
|
|
|
+ 724 [ Priority ]
|
|
|
+ 725 ";"
|
|
|
+ 726 { Import (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 727 nImp, nImpTail, astDecl); .) }
|
|
|
+ 728 [ "EXPORT" [ "QUALIFIED" ]
|
|
|
+ 729 GetIdent<expNames[expCount]> (. INC(expCount); .)
|
|
|
+ 730 { "," GetIdent<expNames[expCount]>
|
|
|
+ 731 (. INC(expCount); .) }
|
|
|
+ 732 ";" ]
|
|
|
+ 733 DeclSeq (. astStmt := AST.NoNode; .)
|
|
|
+ 734 [ "BEGIN" (. astStmt := AST.NoNode;
|
|
|
+ 735 .)
|
|
|
+ 736 [ StatSeq ] ]
|
|
|
+ 737 "END"
|
|
|
+ 738 GetIdent<m2> (. AST.SetChild(astNode, 1, astDecl);
|
|
|
+ 739 AST.SetChild(astNode, 2, astStmt);
|
|
|
+ 740 AST.SetChild(astNode, 3, nImp);
|
|
|
+ 741 astDecl := astNode;
|
|
|
+ 742 IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 743 SemError(202) END;
|
|
|
+ 744 k := 0;
|
|
|
+ 745 WHILE k < expCount DO
|
|
|
+ 746 SymTab.ExportUp(expNames[k]);
|
|
|
+ 747 INC(k)
|
|
|
+ 748 END;
|
|
|
+ 749 SymTab.PopScope; .) .
|
|
|
+ 750 Priority
|
|
|
+ 751 = "[" integer "]" (. SemError(230); .) .
|
|
|
+ 752 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
+ 753 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
+ 754 materializes on first use (Design). *)
|
|
|
+ 755 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
+ 756 import lines don't fail); a known module's missing export is
|
|
|
+ 757 201. *)
|
|
|
+ 758 Import (. VAR n: SymTab.Name;
|
|
|
+ 759 astImport: AST.Node; .)
|
|
|
+ 760 = "FROM"
|
|
|
+ 761 GetIdent<n> (. astImport := AST.MakeNode(AST.NkImport);
|
|
|
+ 762 AST.SetChild(astImport, 0,
|
|
|
+ 763 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 764 "IMPORT"
|
|
|
+ 765 ImpList<n, astImport> ";" (. astDecl := astImport; .)
|
|
|
+ 766 | "IMPORT" (. astImport := AST.MakeNode(AST.NkImport); .)
|
|
|
+ 767 ImpModList<astImport> ";" (. astDecl := astImport; .) .
|
|
|
+ 768 ImpList<mod: SymTab.Name; node: AST.Node>
|
|
|
+ 769 (. VAR n: SymTab.Name; .)
|
|
|
+ 770 = ImpName<mod, node>
|
|
|
+ 771 { "," ImpName<mod, node> } .
|
|
|
+ 772 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
+ 773 accepted and ignored: the built-in applies regardless. *)
|
|
|
+ 774 ImpName<mod: SymTab.Name; node: AST.Node>
|
|
|
+ 775 (. VAR n: SymTab.Name; .)
|
|
|
+ 776 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ 777 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 778 IF SymTab.Equal(mod, "libc") THEN
|
|
|
+ 779 (* intrinsic C library:
|
|
|
+ 780 permissive external *)
|
|
|
+ 781 IF NOT SymTab.DeclareCProc(n) THEN
|
|
|
+ 782 SemError(201) END;
|
|
|
+ 783 Lower.NoteCProc(n)
|
|
|
+ 784 ELSIF SymTab.ModKnown(mod) THEN
|
|
|
+ 785 IF NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
+ 786 SemError(201)
|
|
|
+ 787 ELSE Lower.NoteImportedProc(n)
|
|
|
+ 788 END
|
|
|
+ 789 END; .)
|
|
|
+ 790 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
+ 791 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
+ 792 | "UCHR" | "CHR8" | "UORD"
|
|
|
+ 793 | "INC" | "DEC" ) .
|
|
|
+ 794 ImpModList<node: AST.Node> (. VAR n: SymTab.Name; .)
|
|
|
+ 795 = GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ 796 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 797 { "," GetIdent<n> (. AST.SetChild(node, AST.NChild(node),
|
|
|
+ 798 AST.MakeLeaf(AST.NkIdent, n)); .) } .
|
|
|
+ 799 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
+ 800 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
+ 801 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
+ 802 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
+ 803 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
+ 804 TypeBlock<isDef: BOOLEAN> (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 805 = "TYPE" (. SymTab.BeginTypeBlock;
|
|
|
+ 806 astSeq := AST.NoNode;
|
|
|
+ 807 astTail := AST.NoNode; .)
|
|
|
+ 808 { (. astDecl := AST.NoNode; .)
|
|
|
+ 809 ( TypeItem<isDef> ";" | ClassItem ";" )
|
|
|
+ 810 (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 811 astSeq, astTail, astDecl); .) }
|
|
|
+ 812 (. SymTab.EndTypeBlock;
|
|
|
+ 813 astDecl := astSeq; .) .
|
|
|
+ 814 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
+ 815 t, op: SymTab.TypeIndex;
|
|
|
+ 816 astNode: AST.Node; .)
|
|
|
+ 817 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
+ 818 IF op = SymTab.InvalidType THEN
|
|
|
+ 819 IF NOT SymTab.Enter(n,
|
|
|
+ 820 SymTab.KindType) THEN
|
|
|
+ 821 SemError(200) END
|
|
|
+ 822 END; .)
|
|
|
+ 823 ( "=" Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkTypeDecl);
|
|
|
+ 824 AST.SetChild(astNode, 0,
|
|
|
+ 825 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 826 AST.SetTy(astNode, t);
|
|
|
+ 827 astDecl := astNode;
|
|
|
+ 828 IF op # SymTab.InvalidType THEN
|
|
|
+ 829 SymTab.SetTarget(op, t)
|
|
|
+ 830 ELSE SymTab.SetSymType(n, t)
|
|
|
+ 831 END; .)
|
|
|
+ 832 | (. IF op # SymTab.InvalidType THEN
|
|
|
+ 833 (* stays opaque *)
|
|
|
+ 834 ELSIF NOT isDef THEN
|
|
|
+ 835 SemError(231)
|
|
|
+ 836 ELSE SymTab.SetSymType(n,
|
|
|
+ 837 SymTab.NewAlias()) END; .) ) .
|
|
|
+ 838 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 839 = TypeIdent<t> [ Subrange<t> ] (* anchored subrange: T[lo..hi] *)
|
|
|
+ 840 | Subrange<t>
|
|
|
+ 841 | Enum<t>
|
|
|
+ 842 | ArrayType<t, allowOpen>
|
|
|
+ 843 | SetType<t>
|
|
|
+ 844 | RecordType<t>
|
|
|
+ 845 | PointerType<t>
|
|
|
+ 846 | ProcType<t> .
|
|
|
+ 847 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
+ 848 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
+ 849 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
+ 850 are code pointers; params are collected into the descriptor. *)
|
|
|
+ 851 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
+ 852 isV: BOOLEAN; .)
|
|
|
+ 853 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
+ 854 t := SymTab.NewProcType(res); .)
|
|
|
+ 855 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
+ 856 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
+ 857 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
+ 858 isV: BOOLEAN;
|
|
|
+ 859 cnt, k: CARDINAL;
|
|
|
+ 860 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
+ 861 = (. isV := FALSE; cnt := 0; .)
|
|
|
+ 862 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 863 ( GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
+ 864 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
+ 865 ( ":" Type<pt, TRUE> (. k := 0;
|
|
|
+ 866 WHILE k < cnt DO
|
|
|
+ 867 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
+ 868 INC(k)
|
|
|
+ 869 END; .)
|
|
|
+ 870 | (. (* type-only parameter list:
|
|
|
+ 871 each name is a type (GNU
|
|
|
+ 872 shorthand used by the
|
|
|
+ 873 Coco/R scanner frame) *)
|
|
|
+ 874 k := 0;
|
|
|
+ 875 WHILE k < cnt DO
|
|
|
+ 876 IF SymTab.Lookup(names[k])
|
|
|
+ 877 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
+ 878 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
+ 879 pt := SymTab.SymType(names[k])
|
|
|
+ 880 ELSE SemError(201);
|
|
|
+ 881 pt := SymTab.InvalidType
|
|
|
+ 882 END;
|
|
|
+ 883 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
+ 884 INC(k)
|
|
|
+ 885 END; .) )
|
|
|
+ 886 | Type<pt, TRUE> (. (* unnamed parameter (PIM):
|
|
|
+ 887 e.g. PROCEDURE (VAR ARRAY OF REAL) *)
|
|
|
+ 888 SymTab.ProcTypeAdd(t, isV, pt); .) ) .
|
|
|
+ 889 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
+ 890 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
+ 891 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
+ 892 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
+ 893 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 894 (. VAR elem: SymTab.TypeIndex;
|
|
|
+ 895 ok: BOOLEAN;
|
|
|
+ 896 bnds, bndh: ARRAY [0 .. 7] OF INTEGER;
|
|
|
+ 897 nb, k: CARDINAL;
|
|
|
+ 898 idx: SymTab.TypeIndex;
|
|
|
+ 899 ilo, ihi: INTEGER; .)
|
|
|
+ 900 = "ARRAY"
|
|
|
+ 901 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
+ 902 SemError(230) END;
|
|
|
+ 903 t := SymTab.NewOpenArray(elem); .)
|
|
|
+ 904 | TypeIdent<idx> [ Subrange<idx> ]
|
|
|
+ 905 "OF" Type<elem, FALSE> (. (* index-type array: the index
|
|
|
+ 906 type's ordinal bounds give the
|
|
|
+ 907 [lo..hi] pair *)
|
|
|
+ 908 IF SymTab.TypeBounds(idx, ilo,
|
|
|
+ 909 ihi)
|
|
|
+ 910 THEN t := SymTab.NewArrayB(elem,
|
|
|
+ 911 ilo, ihi)
|
|
|
+ 912 ELSE SemError(230);
|
|
|
+ 913 t := SymTab.InvalidType
|
|
|
+ 914 END; .)
|
|
|
+ 915 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
+ 916 BoundPair<ok>
|
|
|
+ 917 { "," BoundPair<ok> }
|
|
|
+ 918 "]" (. (* snapshot before the element
|
|
|
+ 919 type, which reuses the bound
|
|
|
+ 920 buffer for a nested ARRAY *)
|
|
|
+ 921 nb := SymTab.BoundCount();
|
|
|
+ 922 k := 0;
|
|
|
+ 923 WHILE k < nb DO
|
|
|
+ 924 bnds[k] := SymTab.BoundLo(k);
|
|
|
+ 925 bndh[k] := SymTab.BoundHi(k);
|
|
|
+ 926 INC(k)
|
|
|
+ 927 END; .)
|
|
|
+ 928 "OF" Type<elem, FALSE>
|
|
|
+ 929 (. IF ok THEN
|
|
|
+ 930 k := nb;
|
|
|
+ 931 WHILE k > 0 DO
|
|
|
+ 932 DEC(k);
|
|
|
+ 933 elem := SymTab.NewArrayB(
|
|
|
+ 934 elem, bnds[k], bndh[k])
|
|
|
+ 935 END;
|
|
|
+ 936 t := elem
|
|
|
+ 937 ELSE t := SymTab.InvalidType
|
|
|
+ 938 END; .) ) .
|
|
|
+ 939 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 940 qlo, qhi: QbeGen.QVal;
|
|
|
+ 941 lo, hi: INTEGER;
|
|
|
+ 942 cl, cl2: INTEGER; .)
|
|
|
+ 943 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 944 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 945 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 946 ok := FALSE
|
|
|
+ 947 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
+ 948 cl2 := SymTab.ClassOf(thi);
|
|
|
+ 949 IF ((cl # SymTab.ClInt)
|
|
|
+ 950 AND (cl # SymTab.ClChar))
|
|
|
+ 951 OR ((cl2 # SymTab.ClInt)
|
|
|
+ 952 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
+ 953 SemError(230); ok := FALSE
|
|
|
+ 954 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 955 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 956 OR (lo > hi) THEN
|
|
|
+ 957 SemError(230); ok := FALSE
|
|
|
+ 958 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
+ 959 SemError(230); ok := FALSE
|
|
|
+ 960 END;
|
|
|
+ 961 END; .) .
|
|
|
+ 962 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
+ 963 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
+ 964 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
+ 965 comparison across suitable bases are lenient (masks over min
|
|
|
+ 966 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
+ 967 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
+ 968 blo, bhi, bspan: INTEGER;
|
|
|
+ 969 bcls: INTEGER; .)
|
|
|
+ 970 = "SET" "OF" Type<base, FALSE>
|
|
|
+ 971 (. IF base = SymTab.InvalidType THEN
|
|
|
+ 972 t := SymTab.InvalidType
|
|
|
+ 973 ELSE bcls :=
|
|
|
+ 974 SymTab.ClassOf(base);
|
|
|
+ 975 IF bcls = SymTab.ClBool THEN
|
|
|
+ 976 blo := 0; bspan := 2
|
|
|
+ 977 ELSIF bcls = SymTab.ClChar THEN
|
|
|
+ 978 blo := 0; bspan := 256
|
|
|
+ 979 ELSIF bcls = SymTab.ClEnum THEN
|
|
|
+ 980 blo := 0;
|
|
|
+ 981 bspan := VAL(INTEGER,
|
|
|
+ 982 SymTab.EnumCount(base))
|
|
|
+ 983 ELSIF SymTab.SubBounds(base,
|
|
|
+ 984 blo, bhi) THEN
|
|
|
+ 985 bspan := bhi - blo + 1
|
|
|
+ 986 ELSE bspan := 0 END;
|
|
|
+ 987 IF (bspan <= 0)
|
|
|
+ 988 OR (bspan > 65536) THEN
|
|
|
+ 989 SemError(230);
|
|
|
+ 990 t := SymTab.InvalidType
|
|
|
+ 991 ELSE t := SymTab.NewSet(base)
|
|
|
+ 992 END
|
|
|
+ 993 END; .) .
|
|
|
+ 994 (* Records: flat blobs; array fields are pointers to static
|
|
|
+ 995 descriptors (locked amendment), nested records inline. Field
|
|
|
+ 996 offsets static and declaration-ordered. *)
|
|
|
+ 997 (* Field list: plain fields and (optionally) one variant part. The
|
|
|
+ 998 variant part is a `CASE ... END` item; because it starts with the
|
|
|
+ 999 CASE keyword it is unambiguously distinguishable from a field
|
|
|
+ 1000 (which starts with an identifier). *)
|
|
|
+ 1001 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 1002 tagOk: BOOLEAN; .)
|
|
|
+ 1003 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
+ 1004 [ RecItem<t> { ";" [ RecItem<t> ] } ]
|
|
|
+ 1005 "END" (. SymTab.LayoutRecord(t); .) .
|
|
|
+ 1006 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
+ 1007 = RecField<rec>
|
|
|
+ 1008 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
+ 1009 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
+ 1010 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
+ 1011 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
+ 1012 tagN: SymTab.Name; .)
|
|
|
+ 1013 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
+ 1014 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1015 tagN) THEN
|
|
|
+ 1016 SemError(200) END; .)
|
|
|
+ 1017 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
+ 1018 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
+ 1019 SemError(224)
|
|
|
+ 1020 END;
|
|
|
+ 1021 SymTab.FixPendingF(rec, tagT);
|
|
|
+ 1022 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
+ 1023 "OF"
|
|
|
+ 1024 RecFieldList<rec>
|
|
|
+ 1025 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
+ 1026 RecFieldList<rec> }
|
|
|
+ 1027 "END" .
|
|
|
+ 1028 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
+ 1029 lv1, lv2: QbeGen.QVal; .)
|
|
|
+ 1030 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
+ 1031 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
+ 1032 (* Variant case label: a constant (or a constant range). Values are
|
|
|
+ 1033 not interpreted (the layout overlays regardless). *)
|
|
|
+ 1034 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1035 (. VAR lname: SymTab.Name; .)
|
|
|
+ 1036 = ( ident (. LexName(lname);
|
|
|
1037 QbeGen.CopyOp("0", q);
|
|
|
1038 t := SymTab.IntType(); .)
|
|
|
- 1039 | charConst (. LexString(lname);
|
|
|
+ 1039 | integer (. LexString(lname);
|
|
|
1040 QbeGen.CopyOp("0", q);
|
|
|
- 1041 t := SymTab.CharType(); .) ) .
|
|
|
- 1042 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 1043 t2: SymTab.TypeIndex; .)
|
|
|
- 1044 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
- 1045 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
- 1046 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1047 n) THEN
|
|
|
- 1048 SemError(200) END; .)
|
|
|
- 1049 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1041 t := SymTab.IntType(); .)
|
|
|
+ 1042 | charConst (. LexString(lname);
|
|
|
+ 1043 QbeGen.CopyOp("0", q);
|
|
|
+ 1044 t := SymTab.CharType(); .) ) .
|
|
|
+ 1045 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 1046 t2: SymTab.TypeIndex; .)
|
|
|
+ 1047 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
+ 1048 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ 1049 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
1050 n) THEN
|
|
|
- 1051 SemError(200) END; .) } .
|
|
|
- 1052 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
- 1053 k: INTEGER;
|
|
|
- 1054 dotted: BOOLEAN; .)
|
|
|
- 1055 = GetIdent<n> (. dotted := FALSE;
|
|
|
- 1056 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 1057 k := -1;
|
|
|
- 1058 t := SymTab.ForwardType(n);
|
|
|
- 1059 IF t = SymTab.InvalidType THEN
|
|
|
- 1060 SemError(201)
|
|
|
- 1061 END
|
|
|
- 1062 ELSE k := SymTab.SymKind(n);
|
|
|
- 1063 IF (k = SymTab.KindType)
|
|
|
- 1064 OR (k = SymTab.KindPredef) THEN
|
|
|
- 1065 t := SymTab.SymType(n)
|
|
|
- 1066 ELSE t := SymTab.InvalidType
|
|
|
- 1067 END
|
|
|
- 1068 END; .)
|
|
|
- 1069 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
- 1070 IF k = SymTab.KindModule THEN
|
|
|
- 1071 t := SymTab.QualType(n, qid);
|
|
|
- 1072 IF t = SymTab.InvalidType THEN
|
|
|
- 1073 SemError(201)
|
|
|
- 1074 END
|
|
|
- 1075 ELSE SemError(221);
|
|
|
- 1076 t := SymTab.InvalidType
|
|
|
- 1077 END; .) ]
|
|
|
- 1078 (. IF NOT dotted THEN
|
|
|
- 1079 IF (k = SymTab.KindModule)
|
|
|
- 1080 OR ((k # SymTab.KindType)
|
|
|
- 1081 AND (k # SymTab.KindPredef)
|
|
|
- 1082 AND (k # SymTab.KindImport)
|
|
|
- 1083 AND (k # -1)) THEN
|
|
|
- 1084 SemError(221)
|
|
|
- 1085 END
|
|
|
- 1086 END; .) .
|
|
|
- 1087 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 1088 qlo, qhi: QbeGen.QVal;
|
|
|
- 1089 lo, hi: INTEGER; .)
|
|
|
- 1090 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 1091 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 1092 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 1093 t := SymTab.InvalidType
|
|
|
- 1094 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
- 1095 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
- 1096 SemError(230);
|
|
|
- 1097 t := SymTab.InvalidType
|
|
|
- 1098 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 1099 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 1100 OR (lo > hi) THEN
|
|
|
- 1101 SemError(230);
|
|
|
- 1102 t := SymTab.InvalidType
|
|
|
- 1103 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
- 1104 END; .)
|
|
|
- 1105 "]" .
|
|
|
- 1106 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 1107 ord: INTEGER;
|
|
|
- 1108 qv: QbeGen.QVal; .)
|
|
|
- 1109 = "(" (. t := SymTab.NewEnum();
|
|
|
- 1110 ord := 0; .)
|
|
|
- 1111 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1112 SymTab.KindConst) THEN
|
|
|
- 1113 SemError(200) END;
|
|
|
- 1114 SymTab.SetSymType(n, t);
|
|
|
- 1115 QbeGen.IntStr(ord, qv);
|
|
|
- 1116 SymTab.SetSymVal(n, qv);
|
|
|
- 1117 Lower.NoteVar(n,
|
|
|
- 1118 SymTab.KindConst, t);
|
|
|
- 1119 Lower.NoteConstVal(qv);
|
|
|
- 1120 INC(ord); .)
|
|
|
- 1121 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1122 SymTab.KindConst) THEN
|
|
|
- 1123 SemError(200) END;
|
|
|
- 1124 SymTab.SetSymType(n, t);
|
|
|
- 1125 QbeGen.IntStr(ord, qv);
|
|
|
- 1126 SymTab.SetSymVal(n, qv);
|
|
|
- 1127 Lower.NoteVar(n,
|
|
|
- 1128 SymTab.KindConst, t);
|
|
|
- 1129 Lower.NoteConstVal(qv);
|
|
|
- 1130 INC(ord); .) }
|
|
|
- 1131 ")" (. SymTab.SetEnumCount(t,
|
|
|
- 1132 VAL(CARDINAL, ord)); .) .
|
|
|
- 1133 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
- 1134 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
- 1135 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
- 1136 class/impl block. Methods end with ";" per the Table example
|
|
|
- 1137 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
- 1138 (* Single CLASS item in both loops: separating declaration from
|
|
|
- 1139 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
- 1140 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
- 1141 The second token decides after CLASS is consumed. A misplaced
|
|
|
- 1142 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
- 1143 whole unit ends 230 until lowering). *)
|
|
|
- 1144 ClassItem
|
|
|
- 1145 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
- 1146 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
- 1147 ct: SymTab.TypeIndex; .)
|
|
|
- 1148 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
- 1149 SymTab.KindType) THEN
|
|
|
- 1150 SemError(200) END;
|
|
|
- 1151 ct := SymTab.NewClass();
|
|
|
- 1152 SymTab.SetSymType(cn, ct);
|
|
|
- 1153 SymTab.PushClassScope(ct);
|
|
|
- 1154 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
- 1155 AST.SetChild(astCls, 0,
|
|
|
- 1156 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
- 1157 astClsP := AST.NoNode;
|
|
|
- 1158 astClsPTail := AST.NoNode;
|
|
|
- 1159 astClsF := AST.NoNode;
|
|
|
- 1160 astClsFTail := AST.NoNode;
|
|
|
- 1161 astClsM := AST.NoNode;
|
|
|
- 1162 astClsMTail := AST.NoNode; .)
|
|
|
- 1163 [ Parents<ct> ]
|
|
|
- 1164 ";"
|
|
|
- 1165 { ClassField<ct> ";" }
|
|
|
- 1166 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1167 (. Lower.ScopeLeave;
|
|
|
- 1168 SymTab.CloseProc;
|
|
|
- 1169 QbeGen.AbortFunc; .) }
|
|
|
- 1170 "END"
|
|
|
- 1171 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 1172 SemError(202) END;
|
|
|
- 1173 SymTab.LayoutClass(ct);
|
|
|
- 1174 SymTab.PopScope;
|
|
|
- 1175 AST.SetChild(astCls, 1, astClsP);
|
|
|
- 1176 AST.SetChild(astCls, 2, astClsF);
|
|
|
- 1177 AST.SetChild(astCls, 3, astClsM);
|
|
|
- 1178 astDecl := astCls; .) .
|
|
|
- 1179 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
- 1180 = "(" Parent1<ct>
|
|
|
- 1181 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
- 1182 ")" .
|
|
|
- 1183 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
- 1184 pt: SymTab.TypeIndex; .)
|
|
|
- 1185 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
- 1186 SemError(201)
|
|
|
- 1187 ELSE pt := SymTab.SymType(p);
|
|
|
- 1188 IF SymTab.ClassOf(pt) #
|
|
|
- 1189 SymTab.ClClass THEN
|
|
|
- 1190 SemError(230)
|
|
|
- 1191 ELSE SymTab.SetParent(ct, pt)
|
|
|
- 1192 END
|
|
|
- 1193 END;
|
|
|
- 1194 AstAppend(AST.NkFieldDecl,
|
|
|
- 1195 astClsP, astClsPTail,
|
|
|
- 1196 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
- 1197 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
- 1198 t: SymTab.TypeIndex;
|
|
|
- 1199 astNode: AST.Node; .)
|
|
|
- 1200 = GetIdent<n>
|
|
|
- 1201 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
- 1202 SymTab.KindConst) THEN
|
|
|
- 1203 SemError(200) END;
|
|
|
- 1204 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1205 AST.SetChild(astNode, 0,
|
|
|
- 1206 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1207 AST.SetChild(astNode, 1,
|
|
|
- 1208 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
- 1209 AstAppend(AST.NkFieldDecl,
|
|
|
- 1210 astClsF, astClsFTail, astNode);
|
|
|
- 1211 IF SymTab.Lookup(rhs) THEN
|
|
|
- 1212 SymTab.SetSymType(n,
|
|
|
- 1213 SymTab.SymType(rhs))
|
|
|
- 1214 END; .)
|
|
|
- 1215 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 1216 n) THEN
|
|
|
- 1217 SemError(200) END;
|
|
|
- 1218 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1219 AST.SetChild(astNode, 0,
|
|
|
- 1220 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 1221 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 1222 n) THEN
|
|
|
- 1223 SemError(200) END;
|
|
|
- 1224 AST.SetChild(astNode,
|
|
|
- 1225 AST.NChild(astNode),
|
|
|
- 1226 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
- 1227 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
- 1228 AST.SetTy(astNode, t);
|
|
|
- 1229 AstAppend(AST.NkFieldDecl,
|
|
|
- 1230 astClsF, astClsFTail, astNode); .) ) .
|
|
|
- 1231 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
- 1232 (. VAR wantVirt: BOOLEAN; .)
|
|
|
- 1233 = (. wantVirt := FALSE; .)
|
|
|
- 1234 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
- 1235 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
- 1236 SymTab.MarkVirtual END;
|
|
|
- 1237 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1238 AST.SetChild(astMethod, 0,
|
|
|
- 1239 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1240 IF wantVirt THEN
|
|
|
- 1241 AST.SetOp(astMethod, 3)
|
|
|
- 1242 ELSE AST.SetOp(astMethod, 0)
|
|
|
- 1243 END;
|
|
|
- 1244 AstAppend(AST.NkFieldDecl,
|
|
|
- 1245 astClsM, astClsMTail, astMethod); .) .
|
|
|
- 1246 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
- 1247 ct: SymTab.TypeIndex; .)
|
|
|
- 1248 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
- 1249 SemError(201);
|
|
|
- 1250 ct := SymTab.InvalidType
|
|
|
- 1251 ELSE ct := SymTab.SymType(cn);
|
|
|
- 1252 IF SymTab.ClassOf(ct) #
|
|
|
- 1253 SymTab.ClClass THEN
|
|
|
- 1254 SemError(230);
|
|
|
- 1255 ct := SymTab.InvalidType
|
|
|
- 1256 END
|
|
|
- 1257 END;
|
|
|
- 1258 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
- 1259 AST.SetOp(astCls, 1);
|
|
|
- 1260 AST.SetChild(astCls, 0,
|
|
|
- 1261 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
- 1262 astClsM := AST.NoNode;
|
|
|
- 1263 astClsMTail := AST.NoNode;
|
|
|
- 1264 astStmt := AST.NoNode;
|
|
|
- 1265 IF ct #
|
|
|
- 1266 SymTab.InvalidType THEN
|
|
|
- 1267 IF NOT SymTab.PushClassMembers(
|
|
|
- 1268 ct) THEN
|
|
|
- 1269 SemError(230) END;
|
|
|
- 1270 SymTab.PushImplClass(ct)
|
|
|
- 1271 END; .)
|
|
|
- 1272 ";" { MethodImpl<ct> ";" }
|
|
|
- 1273 (. astStmt := AST.NoNode; .)
|
|
|
- 1274 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
- 1275 .)
|
|
|
- 1276 [ StatSeq ] ]
|
|
|
- 1277 "END"
|
|
|
- 1278 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 1279 SemError(202) END;
|
|
|
- 1280 SymTab.PopImplClass;
|
|
|
- 1281 SymTab.PopScope;
|
|
|
- 1282 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
- 1283 AST.SetChild(astCls, 2, astStmt);
|
|
|
- 1284 AST.SetChild(astCls, 3, astClsM);
|
|
|
- 1285 astDecl := astCls; .) .
|
|
|
- 1286 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
- 1287 thisQ: QbeGen.QVal;
|
|
|
- 1288 methRes: SymTab.TypeIndex; .)
|
|
|
- 1289 = MethodHeading<pn, ct> ";"
|
|
|
- 1290 (. IF (ct #
|
|
|
- 1291 SymTab.InvalidType)
|
|
|
- 1292 AND NOT SymTab.MethodExists(ct,
|
|
|
- 1293 pn) THEN
|
|
|
- 1294 SemError(201) END; .)
|
|
|
- 1295 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
- 1296 SymTab.MarkFwd;
|
|
|
- 1297 QbeGen.AbortFunc;
|
|
|
- 1298 Lower.ScopeLeave;
|
|
|
- 1299 SymTab.CloseProc; .)
|
|
|
- 1300 | (.
|
|
|
- 1301 (* bind the receiver: bare
|
|
|
- 1302 field names resolve
|
|
|
- 1303 against THIS *)
|
|
|
- 1304 QbeGen.CopyOp("@", thisQ);
|
|
|
- 1305 QbeGen.PushWith(thisQ); .)
|
|
|
- 1306 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
- 1307 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
- 1308 QbeGen.PopWith;
|
|
|
- 1309 methRes := SymTab.CurRes();
|
|
|
- 1310 Lower.ScopeLeave;
|
|
|
- 1311 SymTab.CloseProc;
|
|
|
- 1312 QbeGen.EndFunc(methRes); .) ) .
|
|
|
- 1313 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1314 = "CONST" (. astSeq := AST.NoNode;
|
|
|
- 1315 astTail := AST.NoNode; .)
|
|
|
- 1316 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1317 astSeq, astTail, astDecl); .) }
|
|
|
- 1318 (. astDecl := astSeq; .) .
|
|
|
- 1319 ConstDecl (. VAR n: SymTab.Name;
|
|
|
- 1320 t: SymTab.TypeIndex;
|
|
|
- 1321 qv: QbeGen.QVal;
|
|
|
- 1322 cls: INTEGER;
|
|
|
- 1323 astNode: AST.Node; .)
|
|
|
- 1324 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1325 SymTab.KindConst) THEN
|
|
|
- 1326 SemError(200) END; .)
|
|
|
- 1327 "="
|
|
|
- 1328 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1329 AST.SetChild(astNode, 0,
|
|
|
- 1330 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1331 AST.SetChild(astNode, 1, astCur);
|
|
|
- 1332 AST.SetTy(astNode, t);
|
|
|
- 1333 astDecl := astNode;
|
|
|
- 1334 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
- 1335 Lower.NoteConstVal(qv);
|
|
|
- 1336 SymTab.SetSymType(n, t);
|
|
|
- 1337 cls := SymTab.ClassOf(t);
|
|
|
- 1338 IF (cls = SymTab.ClArray)
|
|
|
- 1339 OR (cls = SymTab.ClRecord)
|
|
|
- 1340 OR (cls = SymTab.ClClass)
|
|
|
- 1341 OR (cls = SymTab.ClStr)
|
|
|
- 1342 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 1343 (* an aggregate/string
|
|
|
- 1344 constant: qv is its
|
|
|
- 1345 descriptor address; no
|
|
|
- 1346 scalar data *)
|
|
|
- 1347 SymTab.SetSymVal(n, qv)
|
|
|
- 1348 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
- 1349 SemError(230)
|
|
|
- 1350 ELSE
|
|
|
- 1351 SymTab.SetSymVal(n, qv);
|
|
|
- 1352 END; .) .
|
|
|
- 1353 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1354 = "VAR" (. astSeq := AST.NoNode;
|
|
|
- 1355 astTail := AST.NoNode; .)
|
|
|
- 1356 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1357 astSeq, astTail, astDecl); .) }
|
|
|
- 1358 (. astDecl := astSeq; .) .
|
|
|
- 1359 VarDecl (. VAR nm: SymTab.Name;
|
|
|
- 1360 t: SymTab.TypeIndex;
|
|
|
- 1361 i: CARDINAL;
|
|
|
- 1362 cls: INTEGER;
|
|
|
- 1363 astNode, astTail: AST.Node; .)
|
|
|
- 1364 = VarIdents ":"
|
|
|
- 1365 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1366 astTail := astNode;
|
|
|
- 1367 i := 0;
|
|
|
- 1368 WHILE i < SymTab.PendCount() DO
|
|
|
- 1369 SymTab.PendName(i, nm);
|
|
|
- 1370 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
- 1371 (* chunked: a VAR list can
|
|
|
- 1372 exceed AST.MaxChild *)
|
|
|
- 1373 AstAppend(AST.NkBlock,
|
|
|
- 1374 astNode, astTail,
|
|
|
- 1375 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
- 1376 INC(i)
|
|
|
- 1377 END;
|
|
|
- 1378 AST.SetTy(astNode, t);
|
|
|
- 1379 astDecl := astNode;
|
|
|
- 1380 cls := SymTab.ClassOf(t);
|
|
|
- 1381 IF (t # SymTab.InvalidType)
|
|
|
- 1382 AND NOT SymTab.IsUnresolved(t)
|
|
|
- 1383 AND (cls # SymTab.ClInt)
|
|
|
- 1384 AND (cls # SymTab.ClBool)
|
|
|
- 1385 AND (cls # SymTab.ClChar)
|
|
|
- 1386 AND (cls # SymTab.ClReal)
|
|
|
- 1387 AND (cls # SymTab.ClArray)
|
|
|
- 1388 AND (cls # SymTab.ClSet)
|
|
|
- 1389 AND (cls # SymTab.ClRecord)
|
|
|
- 1390 AND (cls # SymTab.ClPtr)
|
|
|
- 1391 AND (cls # SymTab.ClLong)
|
|
|
- 1392 AND (cls # SymTab.ClProc)
|
|
|
- 1393 AND (cls # SymTab.ClUChar)
|
|
|
- 1394 AND (cls # SymTab.ClUStr)
|
|
|
- 1395 AND (cls # SymTab.ClEnum)
|
|
|
- 1396 AND (cls # SymTab.ClClass) THEN
|
|
|
- 1397 SemError(230) END;
|
|
|
- 1398 IF QbeGen.LocFull() THEN
|
|
|
- 1399 SemError(233) END;
|
|
|
- 1400 i := 0;
|
|
|
- 1401 IF SymTab.IsUnresolved(t)
|
|
|
- 1402 AND NOT SymTab.InProc() THEN
|
|
|
- 1403 (* a forward-typed global:
|
|
|
- 1404 defer emission until the
|
|
|
- 1405 TYPE block completes *)
|
|
|
- 1406 AST.SetOp(astNode, 1);
|
|
|
- 1407 WHILE i < SymTab.PendCount() DO
|
|
|
- 1408 SymTab.PendName(i, nm);
|
|
|
- 1409 IF nPendVar <=
|
|
|
- 1410 HIGH(pendVarName) THEN
|
|
|
- 1411 pendVarName[nPendVar] := nm;
|
|
|
- 1412 pendVarT[nPendVar] := t;
|
|
|
- 1413 INC(nPendVar)
|
|
|
- 1414 END;
|
|
|
- 1415 INC(i)
|
|
|
- 1416 END
|
|
|
- 1417 ELSE
|
|
|
- 1418 WHILE i < SymTab.PendCount() DO
|
|
|
- 1419 SymTab.PendName(i, nm);
|
|
|
- 1420 INC(i)
|
|
|
- 1421 END
|
|
|
- 1422 END;
|
|
|
- 1423 (* a plain VAR list, not a
|
|
|
- 1424 heading: the signature
|
|
|
- 1425 result is discarded *)
|
|
|
- 1426 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1427 END; .) .
|
|
|
- 1428 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 1429 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1430 SymTab.KindVar) THEN
|
|
|
- 1431 SemError(200) END; .)
|
|
|
- 1432 { ","
|
|
|
- 1433 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1434 SymTab.KindVar) THEN
|
|
|
- 1435 SemError(200) END; .) } .
|
|
|
- 1436 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 1437 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1438 SemError(200) END; .)
|
|
|
- 1439 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1440 SemError(200) END; .) } .
|
|
|
- 1441 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
- 1442 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
- 1443 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 1444 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
- 1445 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
- 1446 (. VAR t: SymTab.TypeIndex;
|
|
|
- 1447 mg: QbeGen.QVal; .)
|
|
|
- 1448 = "PROCEDURE"
|
|
|
- 1449 GetIdent<pn> (. IF methCls #
|
|
|
- 1450 SymTab.InvalidType THEN
|
|
|
- 1451 (* a method: resume the
|
|
|
- 1452 declared symbol (reuse
|
|
|
- 1453 its uid) *)
|
|
|
- 1454 IF NOT SymTab.ResumeMethod(
|
|
|
- 1455 methCls, pn) THEN
|
|
|
- 1456 SemError(200) END
|
|
|
- 1457 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
- 1458 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
- 1459 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
- 1460 SemError(200) END
|
|
|
- 1461 END
|
|
|
- 1462 END;
|
|
|
- 1463 Lower.ScopeEnter;
|
|
|
- 1464 Lower.NoteProc(pn,
|
|
|
- 1465 SymTab.ProcUid(pn),
|
|
|
- 1466 SymTab.InvalidType,
|
|
|
- 1467 SymTab.ProcDepthOf(pn),
|
|
|
- 1468 FALSE);
|
|
|
- 1469 QbeGen.BeginFunc("");
|
|
|
- 1470 IF methCls #
|
|
|
- 1471 SymTab.InvalidType THEN
|
|
|
- 1472 (* hidden THIS receiver:
|
|
|
- 1473 a VAR param of the
|
|
|
- 1474 class type, pushed as
|
|
|
- 1475 the WITH base *)
|
|
|
- 1476 IF NOT SymTab.EnterThisParam(
|
|
|
- 1477 methCls) THEN
|
|
|
- 1478 SemError(200) END;
|
|
|
- 1479 IF NOT QbeGen.FuncParam(
|
|
|
- 1480 "THIS", TRUE,
|
|
|
- 1481 methCls) THEN
|
|
|
- 1482 SemError(233) END
|
|
|
- 1483 END; .)
|
|
|
- 1484 [ FormalParams ]
|
|
|
- 1485 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
- 1486 SemError(235) END;
|
|
|
- 1487 Lower.SetProcRes(t); .) ] .
|
|
|
- 1488 FormalParams
|
|
|
- 1489 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 1490 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 1491 nm: SymTab.Name;
|
|
|
- 1492 i: CARDINAL;
|
|
|
- 1493 isV: BOOLEAN; .)
|
|
|
- 1494 = (. isV := FALSE; .)
|
|
|
- 1495 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 1496 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
- 1497 WHILE i < SymTab.PendCount() DO
|
|
|
- 1498 SymTab.PendName(i, nm);
|
|
|
- 1499 Lower.NoteParam(nm, t, isV);
|
|
|
- 1500 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
- 1501 (* value open arrays are
|
|
|
- 1502 passed as descriptor
|
|
|
- 1503 addresses (no copy):
|
|
|
- 1504 same representation as
|
|
|
- 1505 VAR formals *)
|
|
|
- 1506 IF NOT QbeGen.FuncParam(nm,
|
|
|
- 1507 isV
|
|
|
- 1508 OR SymTab.IsOpenArray(t),
|
|
|
- 1509 t) THEN
|
|
|
- 1510 SemError(233) END;
|
|
|
- 1511 INC(i)
|
|
|
- 1512 END;
|
|
|
- 1513 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1514 SemError(235) END; .) .
|
|
|
- 1515 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
- 1516 static link gives them their parent's frame. Methods keep
|
|
|
- 1517 parse-now/230-later. *)
|
|
|
- 1518 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
- 1519 astNode: AST.Node; .)
|
|
|
- 1520 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1521 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1522 AST.SetOp(astNode, 0);
|
|
|
- 1523 AST.SetChild(astNode, 0,
|
|
|
- 1524 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1525 Lower.NoteProcNode(astNode); .)
|
|
|
- 1526 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
- 1527 astDecl := astNode;
|
|
|
- 1528 Lower.ScopeLeave;
|
|
|
- 1529 SymTab.MarkFwd;
|
|
|
- 1530 SymTab.CloseProc;
|
|
|
- 1531 QbeGen.AbortFunc; .)
|
|
|
- 1532 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
- 1533 astDecl := astNode;
|
|
|
- 1534 Lower.MarkProcExternal;
|
|
|
- 1535 Lower.ScopeLeave;
|
|
|
- 1536 SymTab.MarkExternal("");
|
|
|
- 1537 SymTab.CloseProc;
|
|
|
- 1538 QbeGen.AbortFunc; .)
|
|
|
- 1539 |
|
|
|
- 1540 Block<pn> (. AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1541 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
- 1542 astDecl := astNode;
|
|
|
- 1543 Lower.ScopeLeave;
|
|
|
- 1544 SymTab.CloseProc;
|
|
|
- 1545 QbeGen.EndFunc(
|
|
|
- 1546 SymTab.ProcRes(pn)); .) ) .
|
|
|
- 1547 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
- 1548 = (. IF twoPhaseParse AND (procNest = 0) THEN
|
|
|
- 1549 ProbeBody(pn) END;
|
|
|
- 1550 INC(procNest); .)
|
|
|
- 1551 DeclSeq (. astBlkDecls := astDecl;
|
|
|
- 1552 astStmt := AST.NoNode;
|
|
|
- 1553 nLab := 0; nGot := 0; .)
|
|
|
- 1554 [ "BEGIN" (. (* an empty body is still a
|
|
|
- 1555 body: mark it so Lower
|
|
|
- 1556 does not read it as a
|
|
|
- 1557 definition heading *)
|
|
|
- 1558 IF astStmt = AST.NoNode THEN
|
|
|
- 1559 astStmt :=
|
|
|
- 1560 AST.MakeNode(AST.NkBlock)
|
|
|
- 1561 END; .)
|
|
|
- 1562 [ StatSeq ] ]
|
|
|
- 1563 "END"
|
|
|
- 1564 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
- 1565 SemError(202) END;
|
|
|
- 1566 DEC(procNest);
|
|
|
- 1567 CheckGotos; .) .
|
|
|
- 1568 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1569 = (. astSeq := AST.NoNode;
|
|
|
- 1570 astTail := AST.NoNode; .)
|
|
|
- 1571 Statement (. AstAppend(AST.NkBlock,
|
|
|
- 1572 astSeq, astTail, astStmt); .)
|
|
|
- 1573 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
- 1574 astSeq, astTail, astStmt); .) ] }
|
|
|
- 1575 (. astStmt := astSeq; .) .
|
|
|
- 1576 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
- 1577 are accepted: the statement after ';' is optional. *)
|
|
|
- 1578 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
- 1579 = (. astStmt := AST.NoNode; .)
|
|
|
- 1580 ( AssOrCall
|
|
|
- 1581 | IfStat
|
|
|
- 1582 | WhileStat
|
|
|
- 1583 | RepeatStat
|
|
|
- 1584 | LoopStat
|
|
|
- 1585 | ForStat
|
|
|
- 1586 | CaseStat
|
|
|
- 1587 | WithStat
|
|
|
- 1588 | ReturnStat
|
|
|
- 1589 | HaltStat
|
|
|
- 1590 | NewStat
|
|
|
- 1591 | DisposeStat
|
|
|
- 1592 | IncDecStat
|
|
|
- 1593 | InclExclStat
|
|
|
- 1594 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
- 1595 SemError(230) END;
|
|
|
- 1596 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
- 1597 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
- 1598 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
- 1599 AST.SetChild(astStmt, 0,
|
|
|
- 1600 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
- 1601 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
- 1602 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
- 1603 dk: INTEGER;
|
|
|
- 1604 qd, qe: QbeGen.QVal;
|
|
|
- 1605 qn: SymTab.Name;
|
|
|
- 1606 sfx, isInc: BOOLEAN;
|
|
|
- 1607 astNode, astD: AST.Node; .)
|
|
|
- 1608 = ( "INCL" (. isInc := TRUE; .)
|
|
|
- 1609 | "EXCL" (. isInc := FALSE; .) )
|
|
|
- 1610 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
- 1611 Expr<et2, qe> ")"
|
|
|
- 1612 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1613 IF isInc THEN
|
|
|
- 1614 AST.SetChild(astNode, 0,
|
|
|
- 1615 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
- 1616 ELSE AST.SetChild(astNode, 0,
|
|
|
- 1617 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
- 1618 END;
|
|
|
- 1619 IF astD # AST.NoNode THEN
|
|
|
- 1620 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1621 IF astCur # AST.NoNode THEN
|
|
|
- 1622 AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 1623 astStmt := astNode; .)
|
|
|
- 1624 (. IF (at # SymTab.InvalidType)
|
|
|
- 1625 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
- 1626 SemError(222)
|
|
|
- 1627 END; .) .
|
|
|
- 1628 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
- 1629 integer designator. *)
|
|
|
- 1630 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
- 1631 dk: INTEGER;
|
|
|
- 1632 qd, qv, qn2, qstep:
|
|
|
- 1633 QbeGen.QVal;
|
|
|
- 1634 qn: SymTab.Name;
|
|
|
- 1635 sfx, isInc: BOOLEAN;
|
|
|
- 1636 astNode, astD, astStep:
|
|
|
- 1637 AST.Node; .)
|
|
|
- 1638 = (. isInc := TRUE; .)
|
|
|
- 1639 ( "INC" (. isInc := TRUE; .)
|
|
|
- 1640 | "DEC" (. isInc := FALSE; .) )
|
|
|
- 1641 "(" (. astStep := AST.NoNode; .)
|
|
|
- 1642 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
- 1643 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
- 1644 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1645 IF isInc THEN
|
|
|
- 1646 AST.SetChild(astNode, 0,
|
|
|
- 1647 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
- 1648 ELSE AST.SetChild(astNode, 0,
|
|
|
- 1649 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
- 1650 END;
|
|
|
- 1651 IF astD # AST.NoNode THEN
|
|
|
- 1652 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1653 IF astStep # AST.NoNode THEN
|
|
|
- 1654 AST.SetChild(astNode, 2, astStep) END;
|
|
|
- 1655 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1656 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1657 AND (dk # SymTab.KindParam)
|
|
|
- 1658 AND (dk # SymTab.KindField) THEN
|
|
|
- 1659 SemError(210)
|
|
|
- 1660 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
- 1661 SemError(211)
|
|
|
- 1662 END; .) .
|
|
|
- 1663 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
- 1664 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
- 1665 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
- 1666 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1667 dk: INTEGER;
|
|
|
- 1668 qd, qm: QbeGen.QVal;
|
|
|
- 1669 qn: SymTab.Name;
|
|
|
- 1670 sfx: BOOLEAN;
|
|
|
- 1671 bt: SymTab.TypeIndex;
|
|
|
- 1672 astNode, astD: AST.Node; .)
|
|
|
- 1673 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 1674 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1675 AST.SetChild(astNode, 0,
|
|
|
- 1676 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
- 1677 IF astD # AST.NoNode THEN
|
|
|
- 1678 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1679 astStmt := astNode; .)
|
|
|
- 1680 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1681 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1682 AND (dk # SymTab.KindParam)
|
|
|
- 1683 AND (dk # SymTab.KindField) THEN
|
|
|
- 1684 SemError(210)
|
|
|
- 1685 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1686 SymTab.ClPtr THEN
|
|
|
- 1687 SemError(219)
|
|
|
- 1688 END; .) .
|
|
|
- 1689 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1690 dk: INTEGER;
|
|
|
- 1691 qd, qv: QbeGen.QVal;
|
|
|
- 1692 qn: SymTab.Name;
|
|
|
- 1693 sfx: BOOLEAN;
|
|
|
- 1694 astNode, astD: AST.Node; .)
|
|
|
- 1695 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 1696 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1697 AST.SetChild(astNode, 0,
|
|
|
- 1698 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
- 1699 IF astD # AST.NoNode THEN
|
|
|
- 1700 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1701 astStmt := astNode; .)
|
|
|
- 1702 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1703 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1704 AND (dk # SymTab.KindParam)
|
|
|
- 1705 AND (dk # SymTab.KindField) THEN
|
|
|
- 1706 SemError(210)
|
|
|
- 1707 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1708 SymTab.ClPtr THEN
|
|
|
- 1709 SemError(219)
|
|
|
- 1710 END; .) .
|
|
|
- 1711 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
- 1712 address; field designators resolve through both stacks. *)
|
|
|
- 1713 WithStat (. VAR nW: CARDINAL;
|
|
|
- 1714 astNode: AST.Node; .)
|
|
|
- 1715 = "WITH" (. nW := 0;
|
|
|
- 1716 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
- 1717 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
- 1718 "DO" (. astStmt := AST.NoNode; .)
|
|
|
- 1719 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
- 1720 AST.NChild(astNode), astStmt);
|
|
|
- 1721 astStmt := astNode;
|
|
|
- 1722 WHILE nW > 0 DO
|
|
|
- 1723 SymTab.PopScope;
|
|
|
- 1724 QbeGen.PopWith;
|
|
|
- 1725 DEC(nW)
|
|
|
- 1726 END; .) .
|
|
|
- 1727 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
- 1728 (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1729 dk: INTEGER;
|
|
|
- 1730 qd, qe: QbeGen.QVal;
|
|
|
- 1731 qn: SymTab.Name;
|
|
|
- 1732 sfx: BOOLEAN; .)
|
|
|
- 1733 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 1734 (. IF astCur # AST.NoNode THEN
|
|
|
- 1735 AST.SetChild(wnode,
|
|
|
- 1736 AST.NChild(wnode), astCur) END;
|
|
|
- 1737 IF dt = SymTab.InvalidType THEN
|
|
|
- 1738 ELSIF (SymTab.ClassOf(dt) #
|
|
|
- 1739 SymTab.ClRecord)
|
|
|
- 1740 AND (SymTab.ClassOf(dt) #
|
|
|
- 1741 SymTab.ClClass) THEN
|
|
|
- 1742 SemError(215)
|
|
|
- 1743 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
- 1744 QbeGen.PushWith(qd);
|
|
|
- 1745 INC(nW)
|
|
|
- 1746 END; .) .
|
|
|
- 1747 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
- 1748 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
- 1749 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 1750 dk: INTEGER;
|
|
|
- 1751 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
- 1752 qn: SymTab.Name;
|
|
|
- 1753 ct2, res0: SymTab.TypeIndex;
|
|
|
- 1754 q2, mg0: QbeGen.QVal;
|
|
|
- 1755 isR, conv, wconv: BOOLEAN;
|
|
|
- 1756 called, sfx: BOOLEAN;
|
|
|
- 1757 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
- 1758 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
- 1759 = GetIdent<n>
|
|
|
- 1760 ( ":" (. NoteLabel(n);
|
|
|
- 1761 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
- 1762 AST.SetChild(astNode, 0,
|
|
|
- 1763 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1764 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
- 1765 AST.SetChild(astLab, 0, astNode); .)
|
|
|
- 1766 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
- 1767 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
- 1768 astStmt := astLab; .)
|
|
|
- 1769 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
- 1770 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
- 1771 ( ":="
|
|
|
- 1772 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 1773 AST.NkAssign, 0, astLhs, astCur);
|
|
|
- 1774 IF (dt # SymTab.InvalidType)
|
|
|
- 1775 AND (dk # SymTab.KindVar)
|
|
|
- 1776 AND (dk # SymTab.KindParam)
|
|
|
- 1777 AND (dk # SymTab.KindField) THEN
|
|
|
- 1778 SemError(210)
|
|
|
- 1779 ELSIF NOT SymTab.Assignable(et,
|
|
|
- 1780 dt) THEN
|
|
|
+ 1051 SemError(200) END; .)
|
|
|
+ 1052 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1053 n) THEN
|
|
|
+ 1054 SemError(200) END; .) } .
|
|
|
+ 1055 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
+ 1056 k: INTEGER;
|
|
|
+ 1057 dotted: BOOLEAN; .)
|
|
|
+ 1058 = GetIdent<n> (. dotted := FALSE;
|
|
|
+ 1059 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 1060 k := -1;
|
|
|
+ 1061 t := SymTab.ForwardType(n);
|
|
|
+ 1062 IF t = SymTab.InvalidType THEN
|
|
|
+ 1063 SemError(201)
|
|
|
+ 1064 END
|
|
|
+ 1065 ELSE k := SymTab.SymKind(n);
|
|
|
+ 1066 IF (k = SymTab.KindType)
|
|
|
+ 1067 OR (k = SymTab.KindPredef) THEN
|
|
|
+ 1068 t := SymTab.SymType(n)
|
|
|
+ 1069 ELSE t := SymTab.InvalidType
|
|
|
+ 1070 END
|
|
|
+ 1071 END; .)
|
|
|
+ 1072 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
+ 1073 IF k = SymTab.KindModule THEN
|
|
|
+ 1074 t := SymTab.QualType(n, qid);
|
|
|
+ 1075 IF t = SymTab.InvalidType THEN
|
|
|
+ 1076 SemError(201)
|
|
|
+ 1077 END
|
|
|
+ 1078 ELSE SemError(221);
|
|
|
+ 1079 t := SymTab.InvalidType
|
|
|
+ 1080 END; .) ]
|
|
|
+ 1081 (. IF NOT dotted THEN
|
|
|
+ 1082 IF (k = SymTab.KindModule)
|
|
|
+ 1083 OR ((k # SymTab.KindType)
|
|
|
+ 1084 AND (k # SymTab.KindPredef)
|
|
|
+ 1085 AND (k # SymTab.KindImport)
|
|
|
+ 1086 AND (k # -1)) THEN
|
|
|
+ 1087 SemError(221)
|
|
|
+ 1088 END
|
|
|
+ 1089 END; .) .
|
|
|
+ 1090 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 1091 qlo, qhi: QbeGen.QVal;
|
|
|
+ 1092 lo, hi: INTEGER; .)
|
|
|
+ 1093 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 1094 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 1095 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 1096 t := SymTab.InvalidType
|
|
|
+ 1097 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
+ 1098 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
+ 1099 SemError(230);
|
|
|
+ 1100 t := SymTab.InvalidType
|
|
|
+ 1101 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 1102 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 1103 OR (lo > hi) THEN
|
|
|
+ 1104 SemError(230);
|
|
|
+ 1105 t := SymTab.InvalidType
|
|
|
+ 1106 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
+ 1107 END; .)
|
|
|
+ 1108 "]" .
|
|
|
+ 1109 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 1110 ord: INTEGER;
|
|
|
+ 1111 qv: QbeGen.QVal; .)
|
|
|
+ 1112 = "(" (. t := SymTab.NewEnum();
|
|
|
+ 1113 ord := 0; .)
|
|
|
+ 1114 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1115 SymTab.KindConst) THEN
|
|
|
+ 1116 SemError(200) END;
|
|
|
+ 1117 SymTab.SetSymType(n, t);
|
|
|
+ 1118 QbeGen.IntStr(ord, qv);
|
|
|
+ 1119 SymTab.SetSymVal(n, qv);
|
|
|
+ 1120 Lower.NoteVar(n,
|
|
|
+ 1121 SymTab.KindConst, t);
|
|
|
+ 1122 Lower.NoteConstVal(qv);
|
|
|
+ 1123 INC(ord); .)
|
|
|
+ 1124 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1125 SymTab.KindConst) THEN
|
|
|
+ 1126 SemError(200) END;
|
|
|
+ 1127 SymTab.SetSymType(n, t);
|
|
|
+ 1128 QbeGen.IntStr(ord, qv);
|
|
|
+ 1129 SymTab.SetSymVal(n, qv);
|
|
|
+ 1130 Lower.NoteVar(n,
|
|
|
+ 1131 SymTab.KindConst, t);
|
|
|
+ 1132 Lower.NoteConstVal(qv);
|
|
|
+ 1133 INC(ord); .) }
|
|
|
+ 1134 ")" (. SymTab.SetEnumCount(t,
|
|
|
+ 1135 VAL(CARDINAL, ord)); .) .
|
|
|
+ 1136 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
+ 1137 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
+ 1138 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
+ 1139 class/impl block. Methods end with ";" per the Table example
|
|
|
+ 1140 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
+ 1141 (* Single CLASS item in both loops: separating declaration from
|
|
|
+ 1142 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
+ 1143 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
+ 1144 The second token decides after CLASS is consumed. A misplaced
|
|
|
+ 1145 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
+ 1146 whole unit ends 230 until lowering). *)
|
|
|
+ 1147 ClassItem
|
|
|
+ 1148 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
+ 1149 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
+ 1150 ct: SymTab.TypeIndex; .)
|
|
|
+ 1151 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
+ 1152 SymTab.KindType) THEN
|
|
|
+ 1153 SemError(200) END;
|
|
|
+ 1154 ct := SymTab.NewClass();
|
|
|
+ 1155 SymTab.SetSymType(cn, ct);
|
|
|
+ 1156 SymTab.PushClassScope(ct);
|
|
|
+ 1157 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ 1158 AST.SetChild(astCls, 0,
|
|
|
+ 1159 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ 1160 astClsP := AST.NoNode;
|
|
|
+ 1161 astClsPTail := AST.NoNode;
|
|
|
+ 1162 astClsF := AST.NoNode;
|
|
|
+ 1163 astClsFTail := AST.NoNode;
|
|
|
+ 1164 astClsM := AST.NoNode;
|
|
|
+ 1165 astClsMTail := AST.NoNode; .)
|
|
|
+ 1166 [ Parents<ct> ]
|
|
|
+ 1167 ";"
|
|
|
+ 1168 { ClassField<ct> ";" }
|
|
|
+ 1169 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1170 (. Lower.ScopeLeave;
|
|
|
+ 1171 SymTab.CloseProc;
|
|
|
+ 1172 QbeGen.AbortFunc; .) }
|
|
|
+ 1173 "END"
|
|
|
+ 1174 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 1175 SemError(202) END;
|
|
|
+ 1176 SymTab.LayoutClass(ct);
|
|
|
+ 1177 SymTab.PopScope;
|
|
|
+ 1178 AST.SetChild(astCls, 1, astClsP);
|
|
|
+ 1179 AST.SetChild(astCls, 2, astClsF);
|
|
|
+ 1180 AST.SetChild(astCls, 3, astClsM);
|
|
|
+ 1181 astDecl := astCls; .) .
|
|
|
+ 1182 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
+ 1183 = "(" Parent1<ct>
|
|
|
+ 1184 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
+ 1185 ")" .
|
|
|
+ 1186 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
+ 1187 pt: SymTab.TypeIndex; .)
|
|
|
+ 1188 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
+ 1189 SemError(201)
|
|
|
+ 1190 ELSE pt := SymTab.SymType(p);
|
|
|
+ 1191 IF SymTab.ClassOf(pt) #
|
|
|
+ 1192 SymTab.ClClass THEN
|
|
|
+ 1193 SemError(230)
|
|
|
+ 1194 ELSE SymTab.SetParent(ct, pt)
|
|
|
+ 1195 END
|
|
|
+ 1196 END;
|
|
|
+ 1197 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1198 astClsP, astClsPTail,
|
|
|
+ 1199 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
+ 1200 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
+ 1201 t: SymTab.TypeIndex;
|
|
|
+ 1202 astNode: AST.Node; .)
|
|
|
+ 1203 = GetIdent<n>
|
|
|
+ 1204 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1205 SymTab.KindConst) THEN
|
|
|
+ 1206 SemError(200) END;
|
|
|
+ 1207 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1208 AST.SetChild(astNode, 0,
|
|
|
+ 1209 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1210 AST.SetChild(astNode, 1,
|
|
|
+ 1211 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
+ 1212 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1213 astClsF, astClsFTail, astNode);
|
|
|
+ 1214 IF SymTab.Lookup(rhs) THEN
|
|
|
+ 1215 SymTab.SetSymType(n,
|
|
|
+ 1216 SymTab.SymType(rhs))
|
|
|
+ 1217 END; .)
|
|
|
+ 1218 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 1219 n) THEN
|
|
|
+ 1220 SemError(200) END;
|
|
|
+ 1221 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1222 AST.SetChild(astNode, 0,
|
|
|
+ 1223 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 1224 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 1225 n) THEN
|
|
|
+ 1226 SemError(200) END;
|
|
|
+ 1227 AST.SetChild(astNode,
|
|
|
+ 1228 AST.NChild(astNode),
|
|
|
+ 1229 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
+ 1230 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
+ 1231 AST.SetTy(astNode, t);
|
|
|
+ 1232 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1233 astClsF, astClsFTail, astNode); .) ) .
|
|
|
+ 1234 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
+ 1235 (. VAR wantVirt: BOOLEAN; .)
|
|
|
+ 1236 = (. wantVirt := FALSE; .)
|
|
|
+ 1237 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
+ 1238 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
+ 1239 SymTab.MarkVirtual END;
|
|
|
+ 1240 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1241 AST.SetChild(astMethod, 0,
|
|
|
+ 1242 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1243 IF wantVirt THEN
|
|
|
+ 1244 AST.SetOp(astMethod, 3)
|
|
|
+ 1245 ELSE AST.SetOp(astMethod, 0)
|
|
|
+ 1246 END;
|
|
|
+ 1247 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1248 astClsM, astClsMTail, astMethod); .) .
|
|
|
+ 1249 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
+ 1250 ct: SymTab.TypeIndex; .)
|
|
|
+ 1251 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
+ 1252 SemError(201);
|
|
|
+ 1253 ct := SymTab.InvalidType
|
|
|
+ 1254 ELSE ct := SymTab.SymType(cn);
|
|
|
+ 1255 IF SymTab.ClassOf(ct) #
|
|
|
+ 1256 SymTab.ClClass THEN
|
|
|
+ 1257 SemError(230);
|
|
|
+ 1258 ct := SymTab.InvalidType
|
|
|
+ 1259 END
|
|
|
+ 1260 END;
|
|
|
+ 1261 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ 1262 AST.SetOp(astCls, 1);
|
|
|
+ 1263 AST.SetChild(astCls, 0,
|
|
|
+ 1264 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ 1265 astClsM := AST.NoNode;
|
|
|
+ 1266 astClsMTail := AST.NoNode;
|
|
|
+ 1267 astStmt := AST.NoNode;
|
|
|
+ 1268 IF ct #
|
|
|
+ 1269 SymTab.InvalidType THEN
|
|
|
+ 1270 IF NOT SymTab.PushClassMembers(
|
|
|
+ 1271 ct) THEN
|
|
|
+ 1272 SemError(230) END;
|
|
|
+ 1273 SymTab.PushImplClass(ct)
|
|
|
+ 1274 END; .)
|
|
|
+ 1275 ";" { MethodImpl<ct> ";" }
|
|
|
+ 1276 (. astStmt := AST.NoNode; .)
|
|
|
+ 1277 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
+ 1278 .)
|
|
|
+ 1279 [ StatSeq ] ]
|
|
|
+ 1280 "END"
|
|
|
+ 1281 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 1282 SemError(202) END;
|
|
|
+ 1283 SymTab.PopImplClass;
|
|
|
+ 1284 SymTab.PopScope;
|
|
|
+ 1285 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
+ 1286 AST.SetChild(astCls, 2, astStmt);
|
|
|
+ 1287 AST.SetChild(astCls, 3, astClsM);
|
|
|
+ 1288 astDecl := astCls; .) .
|
|
|
+ 1289 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
+ 1290 thisQ: QbeGen.QVal;
|
|
|
+ 1291 methRes: SymTab.TypeIndex; .)
|
|
|
+ 1292 = MethodHeading<pn, ct> ";"
|
|
|
+ 1293 (. IF (ct #
|
|
|
+ 1294 SymTab.InvalidType)
|
|
|
+ 1295 AND NOT SymTab.MethodExists(ct,
|
|
|
+ 1296 pn) THEN
|
|
|
+ 1297 SemError(201) END; .)
|
|
|
+ 1298 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
+ 1299 SymTab.MarkFwd;
|
|
|
+ 1300 QbeGen.AbortFunc;
|
|
|
+ 1301 Lower.ScopeLeave;
|
|
|
+ 1302 SymTab.CloseProc; .)
|
|
|
+ 1303 | (.
|
|
|
+ 1304 (* bind the receiver: bare
|
|
|
+ 1305 field names resolve
|
|
|
+ 1306 against THIS *)
|
|
|
+ 1307 QbeGen.CopyOp("@", thisQ);
|
|
|
+ 1308 QbeGen.PushWith(thisQ); .)
|
|
|
+ 1309 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
+ 1310 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
+ 1311 QbeGen.PopWith;
|
|
|
+ 1312 methRes := SymTab.CurRes();
|
|
|
+ 1313 Lower.ScopeLeave;
|
|
|
+ 1314 SymTab.CloseProc;
|
|
|
+ 1315 QbeGen.EndFunc(methRes); .) ) .
|
|
|
+ 1316 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1317 = "CONST" (. astSeq := AST.NoNode;
|
|
|
+ 1318 astTail := AST.NoNode; .)
|
|
|
+ 1319 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1320 astSeq, astTail, astDecl); .) }
|
|
|
+ 1321 (. astDecl := astSeq; .) .
|
|
|
+ 1322 ConstDecl (. VAR n: SymTab.Name;
|
|
|
+ 1323 t: SymTab.TypeIndex;
|
|
|
+ 1324 qv: QbeGen.QVal;
|
|
|
+ 1325 cls: INTEGER;
|
|
|
+ 1326 astNode: AST.Node; .)
|
|
|
+ 1327 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1328 SymTab.KindConst) THEN
|
|
|
+ 1329 SemError(200) END; .)
|
|
|
+ 1330 "="
|
|
|
+ 1331 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1332 AST.SetChild(astNode, 0,
|
|
|
+ 1333 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1334 AST.SetChild(astNode, 1, astCur);
|
|
|
+ 1335 AST.SetTy(astNode, t);
|
|
|
+ 1336 astDecl := astNode;
|
|
|
+ 1337 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
+ 1338 Lower.NoteConstVal(qv);
|
|
|
+ 1339 SymTab.SetSymType(n, t);
|
|
|
+ 1340 cls := SymTab.ClassOf(t);
|
|
|
+ 1341 IF (cls = SymTab.ClArray)
|
|
|
+ 1342 OR (cls = SymTab.ClRecord)
|
|
|
+ 1343 OR (cls = SymTab.ClClass)
|
|
|
+ 1344 OR (cls = SymTab.ClStr)
|
|
|
+ 1345 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 1346 (* an aggregate/string
|
|
|
+ 1347 constant: qv is its
|
|
|
+ 1348 descriptor address; no
|
|
|
+ 1349 scalar data *)
|
|
|
+ 1350 SymTab.SetSymVal(n, qv)
|
|
|
+ 1351 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
+ 1352 SemError(230)
|
|
|
+ 1353 ELSE
|
|
|
+ 1354 SymTab.SetSymVal(n, qv);
|
|
|
+ 1355 END; .) .
|
|
|
+ 1356 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1357 = "VAR" (. astSeq := AST.NoNode;
|
|
|
+ 1358 astTail := AST.NoNode; .)
|
|
|
+ 1359 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1360 astSeq, astTail, astDecl); .) }
|
|
|
+ 1361 (. astDecl := astSeq; .) .
|
|
|
+ 1362 VarDecl (. VAR nm: SymTab.Name;
|
|
|
+ 1363 t: SymTab.TypeIndex;
|
|
|
+ 1364 i: CARDINAL;
|
|
|
+ 1365 cls: INTEGER;
|
|
|
+ 1366 astNode, astTail: AST.Node; .)
|
|
|
+ 1367 = VarIdents ":"
|
|
|
+ 1368 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1369 astTail := astNode;
|
|
|
+ 1370 i := 0;
|
|
|
+ 1371 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1372 SymTab.PendName(i, nm);
|
|
|
+ 1373 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
+ 1374 (* chunked: a VAR list can
|
|
|
+ 1375 exceed AST.MaxChild *)
|
|
|
+ 1376 AstAppend(AST.NkBlock,
|
|
|
+ 1377 astNode, astTail,
|
|
|
+ 1378 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
+ 1379 INC(i)
|
|
|
+ 1380 END;
|
|
|
+ 1381 AST.SetTy(astNode, t);
|
|
|
+ 1382 astDecl := astNode;
|
|
|
+ 1383 cls := SymTab.ClassOf(t);
|
|
|
+ 1384 IF (t # SymTab.InvalidType)
|
|
|
+ 1385 AND NOT SymTab.IsUnresolved(t)
|
|
|
+ 1386 AND (cls # SymTab.ClInt)
|
|
|
+ 1387 AND (cls # SymTab.ClBool)
|
|
|
+ 1388 AND (cls # SymTab.ClChar)
|
|
|
+ 1389 AND (cls # SymTab.ClReal)
|
|
|
+ 1390 AND (cls # SymTab.ClArray)
|
|
|
+ 1391 AND (cls # SymTab.ClSet)
|
|
|
+ 1392 AND (cls # SymTab.ClRecord)
|
|
|
+ 1393 AND (cls # SymTab.ClPtr)
|
|
|
+ 1394 AND (cls # SymTab.ClLong)
|
|
|
+ 1395 AND (cls # SymTab.ClProc)
|
|
|
+ 1396 AND (cls # SymTab.ClUChar)
|
|
|
+ 1397 AND (cls # SymTab.ClUStr)
|
|
|
+ 1398 AND (cls # SymTab.ClEnum)
|
|
|
+ 1399 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 1400 SemError(230) END;
|
|
|
+ 1401 IF QbeGen.LocFull() THEN
|
|
|
+ 1402 SemError(233) END;
|
|
|
+ 1403 i := 0;
|
|
|
+ 1404 IF SymTab.IsUnresolved(t)
|
|
|
+ 1405 AND NOT SymTab.InProc() THEN
|
|
|
+ 1406 (* a forward-typed global:
|
|
|
+ 1407 defer emission until the
|
|
|
+ 1408 TYPE block completes *)
|
|
|
+ 1409 AST.SetOp(astNode, 1);
|
|
|
+ 1410 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1411 SymTab.PendName(i, nm);
|
|
|
+ 1412 IF nPendVar <=
|
|
|
+ 1413 HIGH(pendVarName) THEN
|
|
|
+ 1414 pendVarName[nPendVar] := nm;
|
|
|
+ 1415 pendVarT[nPendVar] := t;
|
|
|
+ 1416 INC(nPendVar)
|
|
|
+ 1417 END;
|
|
|
+ 1418 INC(i)
|
|
|
+ 1419 END
|
|
|
+ 1420 ELSE
|
|
|
+ 1421 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1422 SymTab.PendName(i, nm);
|
|
|
+ 1423 INC(i)
|
|
|
+ 1424 END
|
|
|
+ 1425 END;
|
|
|
+ 1426 (* a plain VAR list, not a
|
|
|
+ 1427 heading: the signature
|
|
|
+ 1428 result is discarded *)
|
|
|
+ 1429 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1430 END; .) .
|
|
|
+ 1431 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 1432 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1433 SymTab.KindVar) THEN
|
|
|
+ 1434 SemError(200) END; .)
|
|
|
+ 1435 { ","
|
|
|
+ 1436 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1437 SymTab.KindVar) THEN
|
|
|
+ 1438 SemError(200) END; .) } .
|
|
|
+ 1439 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 1440 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1441 SemError(200) END; .)
|
|
|
+ 1442 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1443 SemError(200) END; .) } .
|
|
|
+ 1444 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
+ 1445 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
+ 1446 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 1447 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
+ 1448 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
+ 1449 (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1450 mg: QbeGen.QVal; .)
|
|
|
+ 1451 = "PROCEDURE"
|
|
|
+ 1452 GetIdent<pn> (. IF methCls #
|
|
|
+ 1453 SymTab.InvalidType THEN
|
|
|
+ 1454 (* a method: resume the
|
|
|
+ 1455 declared symbol (reuse
|
|
|
+ 1456 its uid) *)
|
|
|
+ 1457 IF NOT SymTab.ResumeMethod(
|
|
|
+ 1458 methCls, pn) THEN
|
|
|
+ 1459 SemError(200) END
|
|
|
+ 1460 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
+ 1461 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
+ 1462 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
+ 1463 SemError(200) END
|
|
|
+ 1464 END
|
|
|
+ 1465 END;
|
|
|
+ 1466 Lower.ScopeEnter;
|
|
|
+ 1467 Lower.NoteProc(pn,
|
|
|
+ 1468 SymTab.ProcUid(pn),
|
|
|
+ 1469 SymTab.InvalidType,
|
|
|
+ 1470 SymTab.ProcDepthOf(pn),
|
|
|
+ 1471 FALSE);
|
|
|
+ 1472 QbeGen.BeginFunc("");
|
|
|
+ 1473 IF methCls #
|
|
|
+ 1474 SymTab.InvalidType THEN
|
|
|
+ 1475 (* hidden THIS receiver:
|
|
|
+ 1476 a VAR param of the
|
|
|
+ 1477 class type, pushed as
|
|
|
+ 1478 the WITH base *)
|
|
|
+ 1479 IF NOT SymTab.EnterThisParam(
|
|
|
+ 1480 methCls) THEN
|
|
|
+ 1481 SemError(200) END;
|
|
|
+ 1482 IF NOT QbeGen.FuncParam(
|
|
|
+ 1483 "THIS", TRUE,
|
|
|
+ 1484 methCls) THEN
|
|
|
+ 1485 SemError(233) END
|
|
|
+ 1486 END; .)
|
|
|
+ 1487 [ FormalParams ]
|
|
|
+ 1488 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
+ 1489 SemError(235) END;
|
|
|
+ 1490 Lower.SetProcRes(t); .) ] .
|
|
|
+ 1491 FormalParams
|
|
|
+ 1492 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 1493 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1494 nm: SymTab.Name;
|
|
|
+ 1495 i: CARDINAL;
|
|
|
+ 1496 isV: BOOLEAN; .)
|
|
|
+ 1497 = (. isV := FALSE; .)
|
|
|
+ 1498 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 1499 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
+ 1500 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1501 SymTab.PendName(i, nm);
|
|
|
+ 1502 Lower.NoteParam(nm, t, isV);
|
|
|
+ 1503 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
+ 1504 (* value open arrays are
|
|
|
+ 1505 passed as descriptor
|
|
|
+ 1506 addresses (no copy):
|
|
|
+ 1507 same representation as
|
|
|
+ 1508 VAR formals *)
|
|
|
+ 1509 IF NOT QbeGen.FuncParam(nm,
|
|
|
+ 1510 isV
|
|
|
+ 1511 OR SymTab.IsOpenArray(t),
|
|
|
+ 1512 t) THEN
|
|
|
+ 1513 SemError(233) END;
|
|
|
+ 1514 INC(i)
|
|
|
+ 1515 END;
|
|
|
+ 1516 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1517 SemError(235) END; .) .
|
|
|
+ 1518 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
+ 1519 static link gives them their parent's frame. Methods keep
|
|
|
+ 1520 parse-now/230-later. *)
|
|
|
+ 1521 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
+ 1522 astNode: AST.Node; .)
|
|
|
+ 1523 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1524 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1525 AST.SetOp(astNode, 0);
|
|
|
+ 1526 AST.SetChild(astNode, 0,
|
|
|
+ 1527 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1528 Lower.NoteProcNode(astNode); .)
|
|
|
+ 1529 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
+ 1530 astDecl := astNode;
|
|
|
+ 1531 Lower.ScopeLeave;
|
|
|
+ 1532 SymTab.MarkFwd;
|
|
|
+ 1533 SymTab.CloseProc;
|
|
|
+ 1534 QbeGen.AbortFunc; .)
|
|
|
+ 1535 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
+ 1536 astDecl := astNode;
|
|
|
+ 1537 Lower.MarkProcExternal;
|
|
|
+ 1538 Lower.ScopeLeave;
|
|
|
+ 1539 SymTab.MarkExternal("");
|
|
|
+ 1540 SymTab.CloseProc;
|
|
|
+ 1541 QbeGen.AbortFunc; .)
|
|
|
+ 1542 |
|
|
|
+ 1543 Block<pn> (. AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1544 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
+ 1545 astDecl := astNode;
|
|
|
+ 1546 Lower.ScopeLeave;
|
|
|
+ 1547 SymTab.CloseProc;
|
|
|
+ 1548 QbeGen.EndFunc(
|
|
|
+ 1549 SymTab.ProcRes(pn)); .) ) .
|
|
|
+ 1550 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
+ 1551 = (. IF twoPhaseParse AND (procNest = 0) THEN
|
|
|
+ 1552 ProbeBody(pn) END;
|
|
|
+ 1553 INC(procNest); .)
|
|
|
+ 1554 DeclSeq (. astBlkDecls := astDecl;
|
|
|
+ 1555 astStmt := AST.NoNode;
|
|
|
+ 1556 nLab := 0; nGot := 0; .)
|
|
|
+ 1557 [ "BEGIN" (. (* an empty body is still a
|
|
|
+ 1558 body: mark it so Lower
|
|
|
+ 1559 does not read it as a
|
|
|
+ 1560 definition heading *)
|
|
|
+ 1561 IF astStmt = AST.NoNode THEN
|
|
|
+ 1562 astStmt :=
|
|
|
+ 1563 AST.MakeNode(AST.NkBlock)
|
|
|
+ 1564 END; .)
|
|
|
+ 1565 [ StatSeq ] ]
|
|
|
+ 1566 "END"
|
|
|
+ 1567 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
+ 1568 SemError(202) END;
|
|
|
+ 1569 DEC(procNest);
|
|
|
+ 1570 CheckGotos; .) .
|
|
|
+ 1571 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1572 = (. astSeq := AST.NoNode;
|
|
|
+ 1573 astTail := AST.NoNode; .)
|
|
|
+ 1574 Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 1575 astSeq, astTail, astStmt); .)
|
|
|
+ 1576 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 1577 astSeq, astTail, astStmt); .) ] }
|
|
|
+ 1578 (. astStmt := astSeq; .) .
|
|
|
+ 1579 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
+ 1580 are accepted: the statement after ';' is optional. *)
|
|
|
+ 1581 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
+ 1582 = (. astStmt := AST.NoNode; .)
|
|
|
+ 1583 ( AssOrCall
|
|
|
+ 1584 | IfStat
|
|
|
+ 1585 | WhileStat
|
|
|
+ 1586 | RepeatStat
|
|
|
+ 1587 | LoopStat
|
|
|
+ 1588 | ForStat
|
|
|
+ 1589 | CaseStat
|
|
|
+ 1590 | WithStat
|
|
|
+ 1591 | ReturnStat
|
|
|
+ 1592 | HaltStat
|
|
|
+ 1593 | NewStat
|
|
|
+ 1594 | DisposeStat
|
|
|
+ 1595 | IncDecStat
|
|
|
+ 1596 | InclExclStat
|
|
|
+ 1597 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
+ 1598 SemError(230) END;
|
|
|
+ 1599 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
+ 1600 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
+ 1601 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
+ 1602 AST.SetChild(astStmt, 0,
|
|
|
+ 1603 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
+ 1604 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
+ 1605 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
+ 1606 dk: INTEGER;
|
|
|
+ 1607 qd, qe: QbeGen.QVal;
|
|
|
+ 1608 qn: SymTab.Name;
|
|
|
+ 1609 sfx, isInc: BOOLEAN;
|
|
|
+ 1610 astNode, astD: AST.Node; .)
|
|
|
+ 1611 = ( "INCL" (. isInc := TRUE; .)
|
|
|
+ 1612 | "EXCL" (. isInc := FALSE; .) )
|
|
|
+ 1613 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
+ 1614 Expr<et2, qe> ")"
|
|
|
+ 1615 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1616 IF isInc THEN
|
|
|
+ 1617 AST.SetChild(astNode, 0,
|
|
|
+ 1618 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
+ 1619 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 1620 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
+ 1621 END;
|
|
|
+ 1622 IF astD # AST.NoNode THEN
|
|
|
+ 1623 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1624 IF astCur # AST.NoNode THEN
|
|
|
+ 1625 AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 1626 astStmt := astNode; .)
|
|
|
+ 1627 (. IF (at # SymTab.InvalidType)
|
|
|
+ 1628 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
+ 1629 SemError(222)
|
|
|
+ 1630 END; .) .
|
|
|
+ 1631 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
+ 1632 integer designator. *)
|
|
|
+ 1633 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
+ 1634 dk: INTEGER;
|
|
|
+ 1635 qd, qv, qn2, qstep:
|
|
|
+ 1636 QbeGen.QVal;
|
|
|
+ 1637 qn: SymTab.Name;
|
|
|
+ 1638 sfx, isInc: BOOLEAN;
|
|
|
+ 1639 astNode, astD, astStep:
|
|
|
+ 1640 AST.Node; .)
|
|
|
+ 1641 = (. isInc := TRUE; .)
|
|
|
+ 1642 ( "INC" (. isInc := TRUE; .)
|
|
|
+ 1643 | "DEC" (. isInc := FALSE; .) )
|
|
|
+ 1644 "(" (. astStep := AST.NoNode; .)
|
|
|
+ 1645 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
+ 1646 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
+ 1647 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1648 IF isInc THEN
|
|
|
+ 1649 AST.SetChild(astNode, 0,
|
|
|
+ 1650 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
+ 1651 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 1652 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
+ 1653 END;
|
|
|
+ 1654 IF astD # AST.NoNode THEN
|
|
|
+ 1655 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1656 IF astStep # AST.NoNode THEN
|
|
|
+ 1657 AST.SetChild(astNode, 2, astStep) END;
|
|
|
+ 1658 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1659 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1660 AND (dk # SymTab.KindParam)
|
|
|
+ 1661 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1662 SemError(210)
|
|
|
+ 1663 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
+ 1664 SemError(211)
|
|
|
+ 1665 END; .) .
|
|
|
+ 1666 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
+ 1667 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
+ 1668 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
+ 1669 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1670 dk: INTEGER;
|
|
|
+ 1671 qd, qm: QbeGen.QVal;
|
|
|
+ 1672 qn: SymTab.Name;
|
|
|
+ 1673 sfx: BOOLEAN;
|
|
|
+ 1674 bt: SymTab.TypeIndex;
|
|
|
+ 1675 astNode, astD: AST.Node; .)
|
|
|
+ 1676 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 1677 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1678 AST.SetChild(astNode, 0,
|
|
|
+ 1679 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
+ 1680 IF astD # AST.NoNode THEN
|
|
|
+ 1681 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1682 astStmt := astNode; .)
|
|
|
+ 1683 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1684 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1685 AND (dk # SymTab.KindParam)
|
|
|
+ 1686 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1687 SemError(210)
|
|
|
+ 1688 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1689 SymTab.ClPtr THEN
|
|
|
+ 1690 SemError(219)
|
|
|
+ 1691 END; .) .
|
|
|
+ 1692 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1693 dk: INTEGER;
|
|
|
+ 1694 qd, qv: QbeGen.QVal;
|
|
|
+ 1695 qn: SymTab.Name;
|
|
|
+ 1696 sfx: BOOLEAN;
|
|
|
+ 1697 astNode, astD: AST.Node; .)
|
|
|
+ 1698 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 1699 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1700 AST.SetChild(astNode, 0,
|
|
|
+ 1701 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
+ 1702 IF astD # AST.NoNode THEN
|
|
|
+ 1703 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1704 astStmt := astNode; .)
|
|
|
+ 1705 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1706 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1707 AND (dk # SymTab.KindParam)
|
|
|
+ 1708 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1709 SemError(210)
|
|
|
+ 1710 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1711 SymTab.ClPtr THEN
|
|
|
+ 1712 SemError(219)
|
|
|
+ 1713 END; .) .
|
|
|
+ 1714 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
+ 1715 address; field designators resolve through both stacks. *)
|
|
|
+ 1716 WithStat (. VAR nW: CARDINAL;
|
|
|
+ 1717 astNode: AST.Node; .)
|
|
|
+ 1718 = "WITH" (. nW := 0;
|
|
|
+ 1719 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
+ 1720 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
+ 1721 "DO" (. astStmt := AST.NoNode; .)
|
|
|
+ 1722 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
+ 1723 AST.NChild(astNode), astStmt);
|
|
|
+ 1724 astStmt := astNode;
|
|
|
+ 1725 WHILE nW > 0 DO
|
|
|
+ 1726 SymTab.PopScope;
|
|
|
+ 1727 QbeGen.PopWith;
|
|
|
+ 1728 DEC(nW)
|
|
|
+ 1729 END; .) .
|
|
|
+ 1730 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
+ 1731 (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1732 dk: INTEGER;
|
|
|
+ 1733 qd, qe: QbeGen.QVal;
|
|
|
+ 1734 qn: SymTab.Name;
|
|
|
+ 1735 sfx: BOOLEAN; .)
|
|
|
+ 1736 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 1737 (. IF astCur # AST.NoNode THEN
|
|
|
+ 1738 AST.SetChild(wnode,
|
|
|
+ 1739 AST.NChild(wnode), astCur) END;
|
|
|
+ 1740 IF dt = SymTab.InvalidType THEN
|
|
|
+ 1741 ELSIF (SymTab.ClassOf(dt) #
|
|
|
+ 1742 SymTab.ClRecord)
|
|
|
+ 1743 AND (SymTab.ClassOf(dt) #
|
|
|
+ 1744 SymTab.ClClass) THEN
|
|
|
+ 1745 SemError(215)
|
|
|
+ 1746 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
+ 1747 QbeGen.PushWith(qd);
|
|
|
+ 1748 INC(nW)
|
|
|
+ 1749 END; .) .
|
|
|
+ 1750 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
+ 1751 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
+ 1752 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 1753 dk: INTEGER;
|
|
|
+ 1754 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
+ 1755 qn: SymTab.Name;
|
|
|
+ 1756 ct2, res0: SymTab.TypeIndex;
|
|
|
+ 1757 q2, mg0: QbeGen.QVal;
|
|
|
+ 1758 isR, conv, wconv: BOOLEAN;
|
|
|
+ 1759 called, sfx: BOOLEAN;
|
|
|
+ 1760 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
+ 1761 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
+ 1762 = GetIdent<n>
|
|
|
+ 1763 ( ":" (. NoteLabel(n);
|
|
|
+ 1764 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
+ 1765 AST.SetChild(astNode, 0,
|
|
|
+ 1766 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1767 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
+ 1768 AST.SetChild(astLab, 0, astNode); .)
|
|
|
+ 1769 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
+ 1770 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
+ 1771 astStmt := astLab; .)
|
|
|
+ 1772 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
+ 1773 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
+ 1774 ( ":="
|
|
|
+ 1775 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 1776 AST.NkAssign, 0, astLhs, astCur);
|
|
|
+ 1777 IF (dt # SymTab.InvalidType)
|
|
|
+ 1778 AND (dk # SymTab.KindVar)
|
|
|
+ 1779 AND (dk # SymTab.KindParam)
|
|
|
+ 1780 AND (dk # SymTab.KindField) THEN
|
|
|
1781 SemError(210)
|
|
|
- 1782 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 1783 AND (SymTab.ClassOf(dt) =
|
|
|
- 1784 SymTab.ClClass) THEN
|
|
|
- 1785 SemError(230) END;
|
|
|
- 1786 isR := (dt #
|
|
|
- 1787 SymTab.InvalidType)
|
|
|
- 1788 AND (SymTab.ClassOf(dt)
|
|
|
- 1789 = SymTab.ClReal);
|
|
|
- 1790 conv := isR
|
|
|
- 1791 AND SymTab.IsIntFamily(et);
|
|
|
- 1792 wconv := (dt #
|
|
|
- 1793 SymTab.InvalidType)
|
|
|
- 1794 AND SymTab.IsLongFamily(dt)
|
|
|
- 1795 AND SymTab.IsIntFamily(et);
|
|
|
- 1796 IF ((dk = SymTab.KindVar)
|
|
|
- 1797 OR (dk = SymTab.KindParam)
|
|
|
- 1798 OR (dk = SymTab.KindField))
|
|
|
- 1799 AND (dt # SymTab.InvalidType)
|
|
|
- 1800 AND (et # SymTab.InvalidType)
|
|
|
- 1801 AND (SymTab.ClassOf(dt) #
|
|
|
- 1802 SymTab.ClClass) THEN
|
|
|
- 1803 END; .)
|
|
|
- 1804 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
- 1805 (. astRes := AstCallNode(astLhs);
|
|
|
- 1806 sfx := FALSE; .)
|
|
|
- 1807 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
- 1808 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 1809 AST.NkAssign, 0, astRes, astCur);
|
|
|
- 1810 IF NOT sfx THEN
|
|
|
- 1811 SemError(233)
|
|
|
- 1812 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
- 1813 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
- 1814 SemError(210)
|
|
|
- 1815 END; .)
|
|
|
- 1816 | (. IF ct2 #
|
|
|
- 1817 SymTab.InvalidType THEN
|
|
|
- 1818 SemError(233) END;
|
|
|
- 1819 astStmt := astRes; .) )
|
|
|
- 1820 | (* bare `P;`: proper parameterless
|
|
|
- 1821 procedure call; anything else
|
|
|
- 1822 here is 233 (was a bare syntax
|
|
|
- 1823 error before 4.2) *)
|
|
|
- 1824 (. astStmt := AstCallNode(astLhs);
|
|
|
- 1825 IF (dk = SymTab.KindProc)
|
|
|
- 1826 AND NOT sfx THEN
|
|
|
- 1827 res0 := SymTab.ProcRes(qn);
|
|
|
- 1828 IF res0 #
|
|
|
- 1829 SymTab.InvalidType THEN
|
|
|
- 1830 SemError(233)
|
|
|
- 1831 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 1832 0 THEN
|
|
|
+ 1782 ELSIF NOT SymTab.Assignable(et,
|
|
|
+ 1783 dt) THEN
|
|
|
+ 1784 SemError(210)
|
|
|
+ 1785 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 1786 AND (SymTab.ClassOf(dt) =
|
|
|
+ 1787 SymTab.ClClass) THEN
|
|
|
+ 1788 SemError(230) END;
|
|
|
+ 1789 isR := (dt #
|
|
|
+ 1790 SymTab.InvalidType)
|
|
|
+ 1791 AND (SymTab.ClassOf(dt)
|
|
|
+ 1792 = SymTab.ClReal);
|
|
|
+ 1793 conv := isR
|
|
|
+ 1794 AND SymTab.IsIntFamily(et);
|
|
|
+ 1795 wconv := (dt #
|
|
|
+ 1796 SymTab.InvalidType)
|
|
|
+ 1797 AND SymTab.IsLongFamily(dt)
|
|
|
+ 1798 AND SymTab.IsIntFamily(et);
|
|
|
+ 1799 IF ((dk = SymTab.KindVar)
|
|
|
+ 1800 OR (dk = SymTab.KindParam)
|
|
|
+ 1801 OR (dk = SymTab.KindField))
|
|
|
+ 1802 AND (dt # SymTab.InvalidType)
|
|
|
+ 1803 AND (et # SymTab.InvalidType)
|
|
|
+ 1804 AND (SymTab.ClassOf(dt) #
|
|
|
+ 1805 SymTab.ClClass) THEN
|
|
|
+ 1806 END; .)
|
|
|
+ 1807 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
+ 1808 (. astRes := AstCallNode(astLhs);
|
|
|
+ 1809 sfx := FALSE; .)
|
|
|
+ 1810 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
+ 1811 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 1812 AST.NkAssign, 0, astRes, astCur);
|
|
|
+ 1813 IF NOT sfx THEN
|
|
|
+ 1814 SemError(233)
|
|
|
+ 1815 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
+ 1816 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
+ 1817 SemError(210)
|
|
|
+ 1818 END; .)
|
|
|
+ 1819 | (. IF ct2 #
|
|
|
+ 1820 SymTab.InvalidType THEN
|
|
|
+ 1821 SemError(233) END;
|
|
|
+ 1822 astStmt := astRes; .) )
|
|
|
+ 1823 | (* bare `P;`: proper parameterless
|
|
|
+ 1824 procedure call; anything else
|
|
|
+ 1825 here is 233 (was a bare syntax
|
|
|
+ 1826 error before 4.2) *)
|
|
|
+ 1827 (. astStmt := AstCallNode(astLhs);
|
|
|
+ 1828 IF (dk = SymTab.KindProc)
|
|
|
+ 1829 AND NOT sfx THEN
|
|
|
+ 1830 res0 := SymTab.ProcRes(qn);
|
|
|
+ 1831 IF res0 #
|
|
|
+ 1832 SymTab.InvalidType THEN
|
|
|
1833 SemError(233)
|
|
|
- 1834 END
|
|
|
- 1835 ELSE SemError(233)
|
|
|
- 1836 END; .) ) ) .
|
|
|
- 1837 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 1838 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 1839 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 1840 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 1841 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 1842 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
- 1843 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 1844 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
- 1845 vs: INTEGER;
|
|
|
- 1846 res: SymTab.TypeIndex;
|
|
|
- 1847 mg: QbeGen.QVal;
|
|
|
- 1848 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
- 1849 = "(" (. called := TRUE;
|
|
|
- 1850 ok := TRUE;
|
|
|
- 1851 ind := FALSE;
|
|
|
- 1852 isMeth := methCls #
|
|
|
- 1853 SymTab.InvalidType;
|
|
|
- 1854 IF isMeth THEN
|
|
|
- 1855 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
- 1856 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
- 1857 res := SymTab.ProcRes(pn)
|
|
|
- 1858 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 1859 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 1860 ind := TRUE;
|
|
|
- 1861 res := SymTab.ProcTypeRes(pt)
|
|
|
- 1862 ELSE SemError(233);
|
|
|
- 1863 ok := FALSE;
|
|
|
- 1864 res := SymTab.InvalidType
|
|
|
- 1865 END;
|
|
|
- 1866 i := 0; .)
|
|
|
- 1867 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
- 1868 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
- 1869 ")" (. IF ok THEN
|
|
|
- 1870 IF isMeth THEN
|
|
|
- 1871 np := SymTab.ClassMethodNPar(
|
|
|
- 1872 methCls, pn)
|
|
|
- 1873 ELSIF ind THEN
|
|
|
- 1874 np := SymTab.ProcTypeNPar(pt)
|
|
|
- 1875 ELSE np := SymTab.ProcNPar(pn)
|
|
|
- 1876 END;
|
|
|
- 1877 va := (NOT isMeth) AND (NOT ind)
|
|
|
- 1878 AND (SymTab.SymKind(pn) =
|
|
|
- 1879 SymTab.KindProc)
|
|
|
- 1880 AND SymTab.Varargs(pn);
|
|
|
- 1881 IF (i # np) AND NOT va THEN
|
|
|
- 1882 SemError(233); ok := FALSE
|
|
|
- 1883 END
|
|
|
- 1884 END;
|
|
|
- 1885 IF NOT ok THEN
|
|
|
- 1886 t := SymTab.InvalidType;
|
|
|
- 1887 QbeGen.CopyOp("0", q)
|
|
|
- 1888 ELSIF want THEN
|
|
|
- 1889 IF res =
|
|
|
- 1890 SymTab.InvalidType THEN
|
|
|
- 1891 IF NOT soft THEN SemError(233) END;
|
|
|
- 1892 t := SymTab.InvalidType;
|
|
|
- 1893 QbeGen.CopyOp("0", q)
|
|
|
- 1894 ELSE t := res;
|
|
|
- 1895 QbeGen.CopyOp("@", q)
|
|
|
- 1896 END
|
|
|
- 1897 ELSE
|
|
|
- 1898 IF res #
|
|
|
- 1899 SymTab.InvalidType THEN
|
|
|
- 1900 SemError(233)
|
|
|
- 1901 END;
|
|
|
- 1902 t := SymTab.InvalidType;
|
|
|
- 1903 QbeGen.CopyOp("0", q);
|
|
|
- 1904 END; .) .
|
|
|
- 1905 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 1906 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 1907 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 1908 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
- 1909 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 1910 qe, qa, qt: QbeGen.QVal;
|
|
|
- 1911 isV, conv, va: BOOLEAN;
|
|
|
- 1912 cl: CHAR;
|
|
|
- 1913 savedN, aj: CARDINAL;
|
|
|
- 1914 savedArgs: ARRAY [0 .. 31]
|
|
|
- 1915 OF AST.Node;
|
|
|
- 1916 astActual: AST.Node; .)
|
|
|
- 1917 = (. (* Parsing the actual can clobber
|
|
|
- 1918 the enclosing call's argument
|
|
|
- 1919 list (Factor resets astNArgs),
|
|
|
- 1920 so save/restore it. *)
|
|
|
- 1921 savedN := astNArgs; aj := 0;
|
|
|
- 1922 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 1923 savedArgs[aj] := astArgs[aj];
|
|
|
- 1924 INC(aj)
|
|
|
- 1925 END; .)
|
|
|
- 1926 Expr<at, qe> (. astActual := astCur;
|
|
|
- 1927 astNArgs := savedN; aj := 0;
|
|
|
- 1928 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 1929 astArgs[aj] := savedArgs[aj];
|
|
|
- 1930 INC(aj)
|
|
|
- 1931 END;
|
|
|
- 1932 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
- 1933 astArgs[astNArgs] := astCur;
|
|
|
- 1934 INC(astNArgs)
|
|
|
- 1935 END;
|
|
|
- 1936 va := (NOT ind)
|
|
|
- 1937 AND (methCls =
|
|
|
- 1938 SymTab.InvalidType)
|
|
|
- 1939 AND (SymTab.SymKind(pn) =
|
|
|
- 1940 SymTab.KindProc)
|
|
|
- 1941 AND SymTab.Varargs(pn);
|
|
|
- 1942 IF ind THEN
|
|
|
- 1943 ft :=
|
|
|
- 1944 SymTab.ProcTypeParamType(pt,
|
|
|
- 1945 i);
|
|
|
- 1946 isV :=
|
|
|
- 1947 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 1948 i)
|
|
|
- 1949 ELSIF methCls #
|
|
|
- 1950 SymTab.InvalidType THEN
|
|
|
- 1951 ft :=
|
|
|
- 1952 SymTab.ClassMethodParamType(
|
|
|
- 1953 methCls, pn, i);
|
|
|
- 1954 isV :=
|
|
|
- 1955 SymTab.ClassMethodParamIsVar(
|
|
|
- 1956 methCls, pn, i)
|
|
|
- 1957 ELSE
|
|
|
- 1958 ft := SymTab.ParamType(pn, i);
|
|
|
- 1959 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 1960 END;
|
|
|
- 1961 IF (at = SymTab.InvalidType) THEN
|
|
|
- 1962 ELSIF ft = SymTab.InvalidType THEN
|
|
|
- 1963 ELSIF isV THEN
|
|
|
- 1964 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 1965 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1966 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 1967 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1968 ELSIF (AST.Kind(astActual) #
|
|
|
- 1969 AST.NkDesignator)
|
|
|
- 1970 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
- 1971 SemError(233)
|
|
|
- 1972 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
- 1973 SemError(233)
|
|
|
- 1974 END
|
|
|
- 1975 ELSE
|
|
|
- 1976 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 1977 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1978 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 1979 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1980 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
- 1981 SemError(233)
|
|
|
- 1982 END
|
|
|
- 1983 END; .) .
|
|
|
- 1984 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1985 q: QbeGen.QVal;
|
|
|
- 1986 hasElse: BOOLEAN;
|
|
|
- 1987 astCond, astIf, astLast,
|
|
|
- 1988 astNode: AST.Node; .)
|
|
|
- 1989 = "IF" (. hasElse := FALSE; .)
|
|
|
- 1990 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 1991 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1992 SemError(214) END; .)
|
|
|
- 1993 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 1994 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1995 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1996 astIf := astNode;
|
|
|
- 1997 astLast := astNode; .)
|
|
|
- 1998 { "ELSIF"
|
|
|
- 1999 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2000 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2001 SemError(214) END; .)
|
|
|
- 2002 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2003 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2004 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2005 AST.SetChild(astLast, 2, astNode);
|
|
|
- 2006 astLast := astNode; .) }
|
|
|
- 2007 [ "ELSE" (. hasElse := TRUE;
|
|
|
- 2008 astStmt := AST.NoNode; .)
|
|
|
- 2009 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- 2010 "END" (. astStmt := astIf; .) .
|
|
|
- 2011 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2012 q: QbeGen.QVal;
|
|
|
- 2013 astCond, astNode: AST.Node; .)
|
|
|
- 2014 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
- 2015 Expr<t, q> (. astCond := astCur;
|
|
|
- 2016 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2017 SemError(214) END; .)
|
|
|
- 2018 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
- 2019 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2020 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2021 astStmt := astNode; .)
|
|
|
- 2022 "END" .
|
|
|
- 2023 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2024 q: QbeGen.QVal;
|
|
|
- 2025 astCond, astBody, astNode:
|
|
|
- 2026 AST.Node; .)
|
|
|
- 2027 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
- 2028 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
- 2029 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
- 2030 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
- 2031 AST.SetChild(astNode, 0, astBody);
|
|
|
- 2032 AST.SetChild(astNode, 1, astCond);
|
|
|
- 2033 astStmt := astNode;
|
|
|
- 2034 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2035 SemError(214) END; .) .
|
|
|
- 2036 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- 2037 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
- 2038 QbeGen.NewLabel(lEnd);
|
|
|
- 2039 QbeGen.PushLoop(lEnd); .)
|
|
|
- 2040 [ StatSeq ]
|
|
|
- 2041 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
- 2042 AST.SetChild(astNode, 0, astStmt);
|
|
|
- 2043 astStmt := astNode;
|
|
|
- 2044 QbeGen.PopLoop; .) .
|
|
|
- 2045 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 2046 Runtime direction would need a compare-select; the literal
|
|
|
- 2047 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 2048 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 2049 tlo, thi, tby:
|
|
|
- 2050 SymTab.TypeIndex;
|
|
|
- 2051 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 2052 QbeGen.QVal;
|
|
|
- 2053 lTop, lBody, lEnd:
|
|
|
- 2054 QbeGen.QVal;
|
|
|
- 2055 by: INTEGER;
|
|
|
- 2056 ok: BOOLEAN;
|
|
|
- 2057 astVar, astLo, astHi, astBy,
|
|
|
- 2058 astNode: AST.Node; .)
|
|
|
- 2059 = "FOR" (. by := 1; .)
|
|
|
- 2060 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
- 2061 astStmt := AST.NoNode;
|
|
|
- 2062 astBy := AST.NoNode;
|
|
|
- 2063 ok := SymTab.Lookup(lv);
|
|
|
- 2064 IF NOT ok THEN
|
|
|
- 2065 SemError(201)
|
|
|
- 2066 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 2067 SymTab.KindVar)
|
|
|
- 2068 AND (SymTab.SymKind(lv) #
|
|
|
- 2069 SymTab.KindParam) THEN
|
|
|
- 2070 SemError(220); ok := FALSE
|
|
|
- 2071 ELSIF NOT SymTab.IsIntFamily(
|
|
|
- 2072 SymTab.SymType(lv)) THEN
|
|
|
+ 1834 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 1835 0 THEN
|
|
|
+ 1836 SemError(233)
|
|
|
+ 1837 END
|
|
|
+ 1838 ELSE SemError(233)
|
|
|
+ 1839 END; .) ) ) .
|
|
|
+ 1840 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 1841 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 1842 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 1843 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 1844 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 1845 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
+ 1846 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 1847 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
+ 1848 vs: INTEGER;
|
|
|
+ 1849 res: SymTab.TypeIndex;
|
|
|
+ 1850 mg: QbeGen.QVal;
|
|
|
+ 1851 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
+ 1852 = "(" (. called := TRUE;
|
|
|
+ 1853 ok := TRUE;
|
|
|
+ 1854 ind := FALSE;
|
|
|
+ 1855 isMeth := methCls #
|
|
|
+ 1856 SymTab.InvalidType;
|
|
|
+ 1857 IF isMeth THEN
|
|
|
+ 1858 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
+ 1859 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
+ 1860 res := SymTab.ProcRes(pn)
|
|
|
+ 1861 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 1862 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 1863 ind := TRUE;
|
|
|
+ 1864 res := SymTab.ProcTypeRes(pt)
|
|
|
+ 1865 ELSE SemError(233);
|
|
|
+ 1866 ok := FALSE;
|
|
|
+ 1867 res := SymTab.InvalidType
|
|
|
+ 1868 END;
|
|
|
+ 1869 i := 0; .)
|
|
|
+ 1870 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
+ 1871 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
+ 1872 ")" (. IF ok THEN
|
|
|
+ 1873 IF isMeth THEN
|
|
|
+ 1874 np := SymTab.ClassMethodNPar(
|
|
|
+ 1875 methCls, pn)
|
|
|
+ 1876 ELSIF ind THEN
|
|
|
+ 1877 np := SymTab.ProcTypeNPar(pt)
|
|
|
+ 1878 ELSE np := SymTab.ProcNPar(pn)
|
|
|
+ 1879 END;
|
|
|
+ 1880 va := (NOT isMeth) AND (NOT ind)
|
|
|
+ 1881 AND (SymTab.SymKind(pn) =
|
|
|
+ 1882 SymTab.KindProc)
|
|
|
+ 1883 AND SymTab.Varargs(pn);
|
|
|
+ 1884 IF (i # np) AND NOT va THEN
|
|
|
+ 1885 SemError(233); ok := FALSE
|
|
|
+ 1886 END
|
|
|
+ 1887 END;
|
|
|
+ 1888 IF NOT ok THEN
|
|
|
+ 1889 t := SymTab.InvalidType;
|
|
|
+ 1890 QbeGen.CopyOp("0", q)
|
|
|
+ 1891 ELSIF want THEN
|
|
|
+ 1892 IF res =
|
|
|
+ 1893 SymTab.InvalidType THEN
|
|
|
+ 1894 IF NOT soft THEN SemError(233) END;
|
|
|
+ 1895 t := SymTab.InvalidType;
|
|
|
+ 1896 QbeGen.CopyOp("0", q)
|
|
|
+ 1897 ELSE t := res;
|
|
|
+ 1898 QbeGen.CopyOp("@", q)
|
|
|
+ 1899 END
|
|
|
+ 1900 ELSE
|
|
|
+ 1901 IF res #
|
|
|
+ 1902 SymTab.InvalidType THEN
|
|
|
+ 1903 SemError(233)
|
|
|
+ 1904 END;
|
|
|
+ 1905 t := SymTab.InvalidType;
|
|
|
+ 1906 QbeGen.CopyOp("0", q);
|
|
|
+ 1907 END; .) .
|
|
|
+ 1908 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 1909 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 1910 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 1911 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
+ 1912 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 1913 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 1914 isV, conv, va: BOOLEAN;
|
|
|
+ 1915 cl: CHAR;
|
|
|
+ 1916 savedN, aj: CARDINAL;
|
|
|
+ 1917 savedArgs: ARRAY [0 .. 31]
|
|
|
+ 1918 OF AST.Node;
|
|
|
+ 1919 astActual: AST.Node; .)
|
|
|
+ 1920 = (. (* Parsing the actual can clobber
|
|
|
+ 1921 the enclosing call's argument
|
|
|
+ 1922 list (Factor resets astNArgs),
|
|
|
+ 1923 so save/restore it. *)
|
|
|
+ 1924 savedN := astNArgs; aj := 0;
|
|
|
+ 1925 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 1926 savedArgs[aj] := astArgs[aj];
|
|
|
+ 1927 INC(aj)
|
|
|
+ 1928 END; .)
|
|
|
+ 1929 Expr<at, qe> (. astActual := astCur;
|
|
|
+ 1930 astNArgs := savedN; aj := 0;
|
|
|
+ 1931 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 1932 astArgs[aj] := savedArgs[aj];
|
|
|
+ 1933 INC(aj)
|
|
|
+ 1934 END;
|
|
|
+ 1935 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
+ 1936 astArgs[astNArgs] := astCur;
|
|
|
+ 1937 INC(astNArgs)
|
|
|
+ 1938 END;
|
|
|
+ 1939 va := (NOT ind)
|
|
|
+ 1940 AND (methCls =
|
|
|
+ 1941 SymTab.InvalidType)
|
|
|
+ 1942 AND (SymTab.SymKind(pn) =
|
|
|
+ 1943 SymTab.KindProc)
|
|
|
+ 1944 AND SymTab.Varargs(pn);
|
|
|
+ 1945 IF ind THEN
|
|
|
+ 1946 ft :=
|
|
|
+ 1947 SymTab.ProcTypeParamType(pt,
|
|
|
+ 1948 i);
|
|
|
+ 1949 isV :=
|
|
|
+ 1950 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 1951 i)
|
|
|
+ 1952 ELSIF methCls #
|
|
|
+ 1953 SymTab.InvalidType THEN
|
|
|
+ 1954 ft :=
|
|
|
+ 1955 SymTab.ClassMethodParamType(
|
|
|
+ 1956 methCls, pn, i);
|
|
|
+ 1957 isV :=
|
|
|
+ 1958 SymTab.ClassMethodParamIsVar(
|
|
|
+ 1959 methCls, pn, i)
|
|
|
+ 1960 ELSE
|
|
|
+ 1961 ft := SymTab.ParamType(pn, i);
|
|
|
+ 1962 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 1963 END;
|
|
|
+ 1964 IF (at = SymTab.InvalidType) THEN
|
|
|
+ 1965 ELSIF ft = SymTab.InvalidType THEN
|
|
|
+ 1966 ELSIF isV THEN
|
|
|
+ 1967 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 1968 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1969 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 1970 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1971 ELSIF (AST.Kind(astActual) #
|
|
|
+ 1972 AST.NkDesignator)
|
|
|
+ 1973 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
+ 1974 SemError(233)
|
|
|
+ 1975 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
+ 1976 SemError(233)
|
|
|
+ 1977 END
|
|
|
+ 1978 ELSE
|
|
|
+ 1979 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 1980 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1981 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 1982 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1983 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
+ 1984 SemError(233)
|
|
|
+ 1985 END
|
|
|
+ 1986 END; .) .
|
|
|
+ 1987 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1988 q: QbeGen.QVal;
|
|
|
+ 1989 hasElse: BOOLEAN;
|
|
|
+ 1990 astCond, astIf, astLast,
|
|
|
+ 1991 astNode: AST.Node; .)
|
|
|
+ 1992 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 1993 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 1994 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1995 SemError(214) END; .)
|
|
|
+ 1996 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 1997 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1998 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1999 astIf := astNode;
|
|
|
+ 2000 astLast := astNode; .)
|
|
|
+ 2001 { "ELSIF"
|
|
|
+ 2002 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2003 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2004 SemError(214) END; .)
|
|
|
+ 2005 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2006 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2007 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2008 AST.SetChild(astLast, 2, astNode);
|
|
|
+ 2009 astLast := astNode; .) }
|
|
|
+ 2010 [ "ELSE" (. hasElse := TRUE;
|
|
|
+ 2011 astStmt := AST.NoNode; .)
|
|
|
+ 2012 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
+ 2013 "END" (. astStmt := astIf; .) .
|
|
|
+ 2014 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2015 q: QbeGen.QVal;
|
|
|
+ 2016 astCond, astNode: AST.Node; .)
|
|
|
+ 2017 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2018 Expr<t, q> (. astCond := astCur;
|
|
|
+ 2019 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2020 SemError(214) END; .)
|
|
|
+ 2021 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ 2022 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2023 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2024 astStmt := astNode; .)
|
|
|
+ 2025 "END" .
|
|
|
+ 2026 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2027 q: QbeGen.QVal;
|
|
|
+ 2028 astCond, astBody, astNode:
|
|
|
+ 2029 AST.Node; .)
|
|
|
+ 2030 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
+ 2031 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
+ 2032 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
+ 2033 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
+ 2034 AST.SetChild(astNode, 0, astBody);
|
|
|
+ 2035 AST.SetChild(astNode, 1, astCond);
|
|
|
+ 2036 astStmt := astNode;
|
|
|
+ 2037 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2038 SemError(214) END; .) .
|
|
|
+ 2039 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ 2040 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
+ 2041 QbeGen.NewLabel(lEnd);
|
|
|
+ 2042 QbeGen.PushLoop(lEnd); .)
|
|
|
+ 2043 [ StatSeq ]
|
|
|
+ 2044 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
+ 2045 AST.SetChild(astNode, 0, astStmt);
|
|
|
+ 2046 astStmt := astNode;
|
|
|
+ 2047 QbeGen.PopLoop; .) .
|
|
|
+ 2048 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 2049 Runtime direction would need a compare-select; the literal
|
|
|
+ 2050 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 2051 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 2052 tlo, thi, tby:
|
|
|
+ 2053 SymTab.TypeIndex;
|
|
|
+ 2054 qlo, qhi, qby, qt, qk, qb:
|
|
|
+ 2055 QbeGen.QVal;
|
|
|
+ 2056 lTop, lBody, lEnd:
|
|
|
+ 2057 QbeGen.QVal;
|
|
|
+ 2058 by: INTEGER;
|
|
|
+ 2059 ok: BOOLEAN;
|
|
|
+ 2060 astVar, astLo, astHi, astBy,
|
|
|
+ 2061 astNode: AST.Node; .)
|
|
|
+ 2062 = "FOR" (. by := 1; .)
|
|
|
+ 2063 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
+ 2064 astStmt := AST.NoNode;
|
|
|
+ 2065 astBy := AST.NoNode;
|
|
|
+ 2066 ok := SymTab.Lookup(lv);
|
|
|
+ 2067 IF NOT ok THEN
|
|
|
+ 2068 SemError(201)
|
|
|
+ 2069 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 2070 SymTab.KindVar)
|
|
|
+ 2071 AND (SymTab.SymKind(lv) #
|
|
|
+ 2072 SymTab.KindParam) THEN
|
|
|
2073 SemError(220); ok := FALSE
|
|
|
- 2074 END; .)
|
|
|
- 2075 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
- 2076 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
- 2077 SemError(220); ok := FALSE
|
|
|
- 2078 END; .)
|
|
|
- 2079 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
- 2080 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
- 2081 SemError(220); ok := FALSE
|
|
|
- 2082 END; .)
|
|
|
- 2083 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
- 2084 IF (tby #
|
|
|
- 2085 SymTab.InvalidType)
|
|
|
- 2086 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 2087 SemError(220); ok := FALSE
|
|
|
- 2088 END;
|
|
|
- 2089 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 2090 SemError(230); by := 1
|
|
|
- 2091 ELSIF by = 0 THEN
|
|
|
- 2092 SemError(220); by := 1
|
|
|
- 2093 END; .) ]
|
|
|
- 2094 "DO"
|
|
|
- 2095 [ StatSeq ]
|
|
|
- 2096 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
- 2097 AST.SetChild(astNode, 0, astVar);
|
|
|
- 2098 AST.SetChild(astNode, 1, astLo);
|
|
|
- 2099 AST.SetChild(astNode, 2, astHi);
|
|
|
- 2100 AST.SetChild(astNode, 3, astBy);
|
|
|
- 2101 AST.SetChild(astNode, 4, astStmt);
|
|
|
- 2102 astStmt := astNode;
|
|
|
- 2103 .) .
|
|
|
- 2104 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 2105 qsel, lEnd: QbeGen.QVal;
|
|
|
- 2106 arm, astNode, astArms,
|
|
|
- 2107 astArmsTail: AST.Node; .)
|
|
|
- 2108 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
- 2109 AST.SetChild(astNode, 0, astCur);
|
|
|
- 2110 astArms := AST.NoNode;
|
|
|
- 2111 astArmsTail := AST.NoNode;
|
|
|
- 2112 .)
|
|
|
- 2113 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
- 2114 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
- 2115 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
- 2116 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 2117 AST.SetOp(arm, 1);
|
|
|
- 2118 AST.SetChild(arm, 0, astStmt);
|
|
|
- 2119 AstAppend(AST.NkBlock,
|
|
|
- 2120 astArms, astArmsTail, arm); .) ]
|
|
|
- 2121 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
- 2122 astStmt := astNode;
|
|
|
- 2123 .) .
|
|
|
- 2124 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 2125 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 2126 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 2127 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 2128 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2129 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- 2130 (. VAR arm: AST.Node; .)
|
|
|
- 2131 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
- 2132 CaseLabel<tsel, qsel, arm>
|
|
|
- 2133 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
- 2134 ":" (. astStmt := AST.NoNode; .)
|
|
|
- 2135 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
- 2136 astStmt);
|
|
|
- 2137 AstAppend(AST.NkBlock,
|
|
|
- 2138 arms, armsTail, arm);
|
|
|
- 2139 .) .
|
|
|
- 2140 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2141 arm: AST.Node>
|
|
|
- 2142 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 2143 q2, q3, qc, qd, qe:
|
|
|
- 2144 QbeGen.QVal;
|
|
|
- 2145 astLab: AST.Node;
|
|
|
- 2146 lNext: QbeGen.QVal; .)
|
|
|
- 2147 = Expr<t2, q2> (. astLab := astCur;
|
|
|
- 2148 IF (t2 #
|
|
|
- 2149 SymTab.InvalidType)
|
|
|
- 2150 AND (tsel #
|
|
|
- 2151 SymTab.InvalidType)
|
|
|
- 2152 AND ((SymTab.ClassOf(t2) =
|
|
|
- 2153 SymTab.ClSet)
|
|
|
- 2154 OR (SymTab.ClassOf(tsel) =
|
|
|
- 2155 SymTab.ClSet)) THEN
|
|
|
- 2156 SemError(230)
|
|
|
- 2157 ELSIF (t2 #
|
|
|
- 2158 SymTab.InvalidType)
|
|
|
- 2159 AND (tsel #
|
|
|
- 2160 SymTab.InvalidType)
|
|
|
- 2161 AND NOT SymTab.EqCheck(t2,
|
|
|
- 2162 tsel) THEN
|
|
|
- 2163 SemError(213) END;
|
|
|
- 2164 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- 2165 SemError(230)
|
|
|
- 2166 END; .)
|
|
|
- 2167 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
- 2168 AST.NkSubrange, 0, astLab, astCur);
|
|
|
- 2169 IF (t3 #
|
|
|
- 2170 SymTab.InvalidType)
|
|
|
- 2171 AND (tsel #
|
|
|
- 2172 SymTab.InvalidType)
|
|
|
- 2173 AND NOT SymTab.EqCheck(t3,
|
|
|
- 2174 tsel) THEN
|
|
|
- 2175 SemError(213) END;
|
|
|
- 2176 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- 2177 SemError(230)
|
|
|
- 2178 END; .) ]
|
|
|
- 2179 (. AST.SetChild(arm,
|
|
|
- 2180 AST.NChild(arm), astLab); .) .
|
|
|
- 2181 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2182 q, qt: QbeGen.QVal;
|
|
|
- 2183 res: SymTab.TypeIndex;
|
|
|
- 2184 hadE, conv: BOOLEAN;
|
|
|
- 2185 astVal, astNode: AST.Node; .)
|
|
|
- 2186 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
- 2187 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
- 2188 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
- 2189 IF hadE THEN
|
|
|
- 2190 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2191 END;
|
|
|
- 2192 astStmt := astNode;
|
|
|
- 2193 conv := FALSE;
|
|
|
- 2194 IF NOT SymTab.InProc() THEN
|
|
|
- 2195 SemError(232)
|
|
|
- 2196 ELSE res := SymTab.CurRes();
|
|
|
- 2197 IF NOT hadE THEN
|
|
|
- 2198 IF res #
|
|
|
- 2199 SymTab.InvalidType THEN
|
|
|
- 2200 SemError(232)
|
|
|
- 2201 END
|
|
|
- 2202 ELSIF (res =
|
|
|
- 2203 SymTab.InvalidType)
|
|
|
- 2204 OR (t #
|
|
|
- 2205 SymTab.InvalidType)
|
|
|
- 2206 AND NOT SymTab.Assignable(t,
|
|
|
- 2207 res) THEN
|
|
|
- 2208 SemError(232)
|
|
|
- 2209 END
|
|
|
- 2210 END; .) .
|
|
|
- 2211 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2212 q: QbeGen.QVal;
|
|
|
- 2213 astVal, astNode: AST.Node; .)
|
|
|
- 2214 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
- 2215 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
- 2216 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
- 2217 IF astVal # AST.NoNode THEN
|
|
|
- 2218 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2219 END;
|
|
|
- 2220 astStmt := astNode;
|
|
|
- 2221 .) .
|
|
|
- 2222 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 2223 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 2224 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 2225 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 2226 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 2227 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2228 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2229 (. VAR n: SymTab.Name; .)
|
|
|
- 2230 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
- 2231 (* The part of Design after the identifier: resolve it and walk the
|
|
|
- 2232 selectors. Split out so a statement can decide between a label
|
|
|
- 2233 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
- 2234 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2235 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2236 (. VAR fn, mal: SymTab.Name;
|
|
|
- 2237 cls: INTEGER;
|
|
|
- 2238 ic: SymTab.TypeIndex;
|
|
|
- 2239 curT, it, eT, bt:
|
|
|
- 2240 SymTab.TypeIndex;
|
|
|
- 2241 iq, ql, qlo, qhi, qe:
|
|
|
- 2242 QbeGen.QVal;
|
|
|
- 2243 lo, hi: INTEGER;
|
|
|
- 2244 fo: INTEGER;
|
|
|
- 2245 isOpen: BOOLEAN;
|
|
|
- 2246 qb, cv: QbeGen.QVal;
|
|
|
- 2247 fid, fref: INTEGER;
|
|
|
- 2248 r: BOOLEAN;
|
|
|
- 2249 astDes, astSel: AST.Node;
|
|
|
- 2250 fwd: BOOLEAN; .)
|
|
|
- 2251 = (. methCls := SymTab.InvalidType;
|
|
|
- 2252 QbeGen.CopyOp(n, qn);
|
|
|
- 2253 sfx := FALSE; fwd := FALSE;
|
|
|
- 2254 fid := 0; fref := 0;
|
|
|
- 2255 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 2256 (* a bare method name inside
|
|
|
- 2257 a CLASS IMPLEMENTATION
|
|
|
- 2258 is a sibling call on
|
|
|
- 2259 THIS *)
|
|
|
- 2260 ic := SymTab.CurImplClass();
|
|
|
- 2261 IF (ic #
|
|
|
- 2262 SymTab.InvalidType)
|
|
|
- 2263 AND SymTab.MethodExists(ic, n) THEN
|
|
|
- 2264 sfx := FALSE;
|
|
|
- 2265 QbeGen.CopyOp("@", q);
|
|
|
- 2266 methCls := ic;
|
|
|
- 2267 k := SymTab.KindProc;
|
|
|
- 2268 t := SymTab.InvalidType
|
|
|
- 2269 ELSIF SymTab.InProc() THEN
|
|
|
- 2270 (* not declared yet: a
|
|
|
- 2271 forward reference to a
|
|
|
- 2272 module-level variable
|
|
|
- 2273 declared further down. *)
|
|
|
- 2274 k := SymTab.KindVar;
|
|
|
- 2275 r := SymTab.FwdVarRef(n, k,
|
|
|
- 2276 fref, t);
|
|
|
- 2277 QbeGen.CopyOp("@", q);
|
|
|
- 2278 sfx := TRUE; fwd := TRUE
|
|
|
- 2279 ELSE
|
|
|
- 2280 SemError(201);
|
|
|
- 2281 t :=
|
|
|
- 2282 SymTab.InvalidType;
|
|
|
- 2283 k := -1;
|
|
|
- 2284 QbeGen.CopyOp("0", q)
|
|
|
- 2285 END
|
|
|
- 2286 ELSE
|
|
|
- 2287 t := SymTab.SymType(n);
|
|
|
- 2288 k := SymTab.SymKind(n);
|
|
|
- 2289 IF k = SymTab.KindConst THEN
|
|
|
- 2290 IF SymTab.Equal(n,
|
|
|
- 2291 "TRUE") THEN
|
|
|
- 2292 t := SymTab.BoolType();
|
|
|
- 2293 QbeGen.CopyOp("1", q)
|
|
|
- 2294 ELSIF SymTab.Equal(n,
|
|
|
- 2295 "FALSE") THEN
|
|
|
- 2296 t := SymTab.BoolType();
|
|
|
- 2297 QbeGen.CopyOp("0", q)
|
|
|
- 2298 ELSIF SymTab.Equal(n,
|
|
|
- 2299 "NIL") THEN
|
|
|
+ 2074 ELSIF NOT SymTab.IsIntFamily(
|
|
|
+ 2075 SymTab.SymType(lv)) THEN
|
|
|
+ 2076 SemError(220); ok := FALSE
|
|
|
+ 2077 END; .)
|
|
|
+ 2078 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
+ 2079 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 2080 SemError(220); ok := FALSE
|
|
|
+ 2081 END; .)
|
|
|
+ 2082 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
+ 2083 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
+ 2084 SemError(220); ok := FALSE
|
|
|
+ 2085 END; .)
|
|
|
+ 2086 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
+ 2087 IF (tby #
|
|
|
+ 2088 SymTab.InvalidType)
|
|
|
+ 2089 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 2090 SemError(220); ok := FALSE
|
|
|
+ 2091 END;
|
|
|
+ 2092 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 2093 SemError(230); by := 1
|
|
|
+ 2094 ELSIF by = 0 THEN
|
|
|
+ 2095 SemError(220); by := 1
|
|
|
+ 2096 END; .) ]
|
|
|
+ 2097 "DO"
|
|
|
+ 2098 [ StatSeq ]
|
|
|
+ 2099 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
+ 2100 AST.SetChild(astNode, 0, astVar);
|
|
|
+ 2101 AST.SetChild(astNode, 1, astLo);
|
|
|
+ 2102 AST.SetChild(astNode, 2, astHi);
|
|
|
+ 2103 AST.SetChild(astNode, 3, astBy);
|
|
|
+ 2104 AST.SetChild(astNode, 4, astStmt);
|
|
|
+ 2105 astStmt := astNode;
|
|
|
+ 2106 .) .
|
|
|
+ 2107 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 2108 qsel, lEnd: QbeGen.QVal;
|
|
|
+ 2109 arm, astNode, astArms,
|
|
|
+ 2110 astArmsTail: AST.Node; .)
|
|
|
+ 2111 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ 2112 AST.SetChild(astNode, 0, astCur);
|
|
|
+ 2113 astArms := AST.NoNode;
|
|
|
+ 2114 astArmsTail := AST.NoNode;
|
|
|
+ 2115 .)
|
|
|
+ 2116 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
+ 2117 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
+ 2118 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2119 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 2120 AST.SetOp(arm, 1);
|
|
|
+ 2121 AST.SetChild(arm, 0, astStmt);
|
|
|
+ 2122 AstAppend(AST.NkBlock,
|
|
|
+ 2123 astArms, astArmsTail, arm); .) ]
|
|
|
+ 2124 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
+ 2125 astStmt := astNode;
|
|
|
+ 2126 .) .
|
|
|
+ 2127 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 2128 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 2129 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 2130 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 2131 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2132 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
+ 2133 (. VAR arm: AST.Node; .)
|
|
|
+ 2134 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
+ 2135 CaseLabel<tsel, qsel, arm>
|
|
|
+ 2136 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
+ 2137 ":" (. astStmt := AST.NoNode; .)
|
|
|
+ 2138 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ 2139 astStmt);
|
|
|
+ 2140 AstAppend(AST.NkBlock,
|
|
|
+ 2141 arms, armsTail, arm);
|
|
|
+ 2142 .) .
|
|
|
+ 2143 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2144 arm: AST.Node>
|
|
|
+ 2145 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 2146 q2, q3, qc, qd, qe:
|
|
|
+ 2147 QbeGen.QVal;
|
|
|
+ 2148 astLab: AST.Node;
|
|
|
+ 2149 lNext: QbeGen.QVal; .)
|
|
|
+ 2150 = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ 2151 IF (t2 #
|
|
|
+ 2152 SymTab.InvalidType)
|
|
|
+ 2153 AND (tsel #
|
|
|
+ 2154 SymTab.InvalidType)
|
|
|
+ 2155 AND ((SymTab.ClassOf(t2) =
|
|
|
+ 2156 SymTab.ClSet)
|
|
|
+ 2157 OR (SymTab.ClassOf(tsel) =
|
|
|
+ 2158 SymTab.ClSet)) THEN
|
|
|
+ 2159 SemError(230)
|
|
|
+ 2160 ELSIF (t2 #
|
|
|
+ 2161 SymTab.InvalidType)
|
|
|
+ 2162 AND (tsel #
|
|
|
+ 2163 SymTab.InvalidType)
|
|
|
+ 2164 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 2165 tsel) THEN
|
|
|
+ 2166 SemError(213) END;
|
|
|
+ 2167 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 2168 SemError(230)
|
|
|
+ 2169 END; .)
|
|
|
+ 2170 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ 2171 AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ 2172 IF (t3 #
|
|
|
+ 2173 SymTab.InvalidType)
|
|
|
+ 2174 AND (tsel #
|
|
|
+ 2175 SymTab.InvalidType)
|
|
|
+ 2176 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 2177 tsel) THEN
|
|
|
+ 2178 SemError(213) END;
|
|
|
+ 2179 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 2180 SemError(230)
|
|
|
+ 2181 END; .) ]
|
|
|
+ 2182 (. AST.SetChild(arm,
|
|
|
+ 2183 AST.NChild(arm), astLab); .) .
|
|
|
+ 2184 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2185 q, qt: QbeGen.QVal;
|
|
|
+ 2186 res: SymTab.TypeIndex;
|
|
|
+ 2187 hadE, conv: BOOLEAN;
|
|
|
+ 2188 astVal, astNode: AST.Node; .)
|
|
|
+ 2189 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
+ 2190 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
+ 2191 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
+ 2192 IF hadE THEN
|
|
|
+ 2193 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2194 END;
|
|
|
+ 2195 astStmt := astNode;
|
|
|
+ 2196 conv := FALSE;
|
|
|
+ 2197 IF NOT SymTab.InProc() THEN
|
|
|
+ 2198 SemError(232)
|
|
|
+ 2199 ELSE res := SymTab.CurRes();
|
|
|
+ 2200 IF NOT hadE THEN
|
|
|
+ 2201 IF res #
|
|
|
+ 2202 SymTab.InvalidType THEN
|
|
|
+ 2203 SemError(232)
|
|
|
+ 2204 END
|
|
|
+ 2205 ELSIF (res =
|
|
|
+ 2206 SymTab.InvalidType)
|
|
|
+ 2207 OR (t #
|
|
|
+ 2208 SymTab.InvalidType)
|
|
|
+ 2209 AND NOT SymTab.Assignable(t,
|
|
|
+ 2210 res) THEN
|
|
|
+ 2211 SemError(232)
|
|
|
+ 2212 END
|
|
|
+ 2213 END; .) .
|
|
|
+ 2214 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2215 q: QbeGen.QVal;
|
|
|
+ 2216 astVal, astNode: AST.Node; .)
|
|
|
+ 2217 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
+ 2218 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
+ 2219 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
+ 2220 IF astVal # AST.NoNode THEN
|
|
|
+ 2221 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2222 END;
|
|
|
+ 2223 astStmt := astNode;
|
|
|
+ 2224 .) .
|
|
|
+ 2225 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 2226 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 2227 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 2228 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 2229 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 2230 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2231 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2232 (. VAR n: SymTab.Name; .)
|
|
|
+ 2233 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
+ 2234 (* The part of Design after the identifier: resolve it and walk the
|
|
|
+ 2235 selectors. Split out so a statement can decide between a label
|
|
|
+ 2236 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
+ 2237 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2238 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2239 (. VAR fn, mal: SymTab.Name;
|
|
|
+ 2240 cls: INTEGER;
|
|
|
+ 2241 ic: SymTab.TypeIndex;
|
|
|
+ 2242 curT, it, eT, bt:
|
|
|
+ 2243 SymTab.TypeIndex;
|
|
|
+ 2244 iq, ql, qlo, qhi, qe:
|
|
|
+ 2245 QbeGen.QVal;
|
|
|
+ 2246 lo, hi: INTEGER;
|
|
|
+ 2247 fo: INTEGER;
|
|
|
+ 2248 isOpen: BOOLEAN;
|
|
|
+ 2249 qb, cv: QbeGen.QVal;
|
|
|
+ 2250 fid, fref: INTEGER;
|
|
|
+ 2251 r: BOOLEAN;
|
|
|
+ 2252 astDes, astSel: AST.Node;
|
|
|
+ 2253 fwd: BOOLEAN; .)
|
|
|
+ 2254 = (. methCls := SymTab.InvalidType;
|
|
|
+ 2255 QbeGen.CopyOp(n, qn);
|
|
|
+ 2256 sfx := FALSE; fwd := FALSE;
|
|
|
+ 2257 fid := 0; fref := 0;
|
|
|
+ 2258 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 2259 (* a bare method name inside
|
|
|
+ 2260 a CLASS IMPLEMENTATION
|
|
|
+ 2261 is a sibling call on
|
|
|
+ 2262 THIS *)
|
|
|
+ 2263 ic := SymTab.CurImplClass();
|
|
|
+ 2264 IF (ic #
|
|
|
+ 2265 SymTab.InvalidType)
|
|
|
+ 2266 AND SymTab.MethodExists(ic, n) THEN
|
|
|
+ 2267 sfx := FALSE;
|
|
|
+ 2268 QbeGen.CopyOp("@", q);
|
|
|
+ 2269 methCls := ic;
|
|
|
+ 2270 k := SymTab.KindProc;
|
|
|
+ 2271 t := SymTab.InvalidType
|
|
|
+ 2272 ELSIF SymTab.InProc() THEN
|
|
|
+ 2273 (* not declared yet: a
|
|
|
+ 2274 forward reference to a
|
|
|
+ 2275 module-level variable
|
|
|
+ 2276 declared further down. *)
|
|
|
+ 2277 k := SymTab.KindVar;
|
|
|
+ 2278 r := SymTab.FwdVarRef(n, k,
|
|
|
+ 2279 fref, t);
|
|
|
+ 2280 QbeGen.CopyOp("@", q);
|
|
|
+ 2281 sfx := TRUE; fwd := TRUE
|
|
|
+ 2282 ELSE
|
|
|
+ 2283 SemError(201);
|
|
|
+ 2284 t :=
|
|
|
+ 2285 SymTab.InvalidType;
|
|
|
+ 2286 k := -1;
|
|
|
+ 2287 QbeGen.CopyOp("0", q)
|
|
|
+ 2288 END
|
|
|
+ 2289 ELSE
|
|
|
+ 2290 t := SymTab.SymType(n);
|
|
|
+ 2291 k := SymTab.SymKind(n);
|
|
|
+ 2292 IF k = SymTab.KindConst THEN
|
|
|
+ 2293 IF SymTab.Equal(n,
|
|
|
+ 2294 "TRUE") THEN
|
|
|
+ 2295 t := SymTab.BoolType();
|
|
|
+ 2296 QbeGen.CopyOp("1", q)
|
|
|
+ 2297 ELSIF SymTab.Equal(n,
|
|
|
+ 2298 "FALSE") THEN
|
|
|
+ 2299 t := SymTab.BoolType();
|
|
|
2300 QbeGen.CopyOp("0", q)
|
|
|
- 2301 ELSE
|
|
|
- 2302 cls :=
|
|
|
- 2303 SymTab.ClassOf(t);
|
|
|
- 2304 IF (t #
|
|
|
- 2305 SymTab.InvalidType)
|
|
|
- 2306 AND ((cls = SymTab.ClInt)
|
|
|
- 2307 OR (cls
|
|
|
- 2308 = SymTab.ClChar)
|
|
|
- 2309 OR (cls
|
|
|
- 2310 = SymTab.ClEnum)
|
|
|
- 2311 OR (cls
|
|
|
- 2312 = SymTab.ClReal)
|
|
|
- 2313 OR (cls
|
|
|
- 2314 = SymTab.ClLong)
|
|
|
- 2315 OR (cls
|
|
|
- 2316 = SymTab.ClNil)) THEN
|
|
|
- 2317 IF cls = SymTab.ClNil THEN
|
|
|
- 2318 QbeGen.CopyOp("0", q)
|
|
|
- 2319 ELSIF ((cls
|
|
|
- 2320 = SymTab.ClInt)
|
|
|
- 2321 OR (cls
|
|
|
- 2322 = SymTab.ClChar)
|
|
|
- 2323 OR (cls
|
|
|
- 2324 = SymTab.ClEnum)
|
|
|
- 2325 OR (cls
|
|
|
- 2326 = SymTab.ClLong))
|
|
|
- 2327 AND SymTab.GetSymVal(n, cv)
|
|
|
- 2328 AND QbeGen.IsImm(cv) THEN
|
|
|
- 2329 QbeGen.CopyOp(cv, q)
|
|
|
- 2330 ELSE
|
|
|
- 2331 QbeGen.LoadVar(n,
|
|
|
- 2332 cls = SymTab.ClReal,
|
|
|
- 2333 q)
|
|
|
- 2334 END
|
|
|
- 2335 ELSIF (cls = SymTab.ClArray)
|
|
|
- 2336 OR (cls = SymTab.ClRecord)
|
|
|
- 2337 OR (cls = SymTab.ClClass)
|
|
|
- 2338 OR (cls = SymTab.ClStr)
|
|
|
- 2339 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 2340 (* aggregate constant:
|
|
|
- 2341 its value IS the
|
|
|
- 2342 descriptor address *)
|
|
|
- 2343 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
- 2344 QbeGen.CopyOp(cv, q)
|
|
|
- 2345 ELSE
|
|
|
- 2346 QbeGen.CopyOp("0", q)
|
|
|
- 2347 END
|
|
|
- 2348 ELSE
|
|
|
- 2349 IF t #
|
|
|
- 2350 SymTab.InvalidType THEN
|
|
|
- 2351 SemError(230)
|
|
|
- 2352 END;
|
|
|
- 2353 QbeGen.CopyOp("0", q)
|
|
|
- 2354 END
|
|
|
- 2355 END
|
|
|
- 2356 ELSIF (k = SymTab.KindVar)
|
|
|
- 2357 OR (k = SymTab.KindParam) THEN
|
|
|
- 2358 cls := SymTab.ClassOf(t);
|
|
|
- 2359 IF (cls # SymTab.ClInt)
|
|
|
- 2360 AND (cls # SymTab.ClBool)
|
|
|
- 2361 AND (cls # SymTab.ClChar)
|
|
|
- 2362 AND (cls # SymTab.ClUChar)
|
|
|
- 2363 AND (cls # SymTab.ClEnum)
|
|
|
- 2364 AND (cls # SymTab.ClReal)
|
|
|
- 2365 AND (cls # SymTab.ClPtr)
|
|
|
- 2366 AND (cls # SymTab.ClProc)
|
|
|
- 2367 AND (cls # SymTab.ClLong)
|
|
|
- 2368 AND (cls # SymTab.ClArray)
|
|
|
- 2369 AND (cls # SymTab.ClSet)
|
|
|
- 2370 AND (cls # SymTab.ClRecord)
|
|
|
- 2371 AND (cls # SymTab.ClUStr)
|
|
|
- 2372 AND (cls # SymTab.ClClass) THEN
|
|
|
- 2373 SemError(230);
|
|
|
- 2374 QbeGen.CopyOp("0", q)
|
|
|
- 2375 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2376 END
|
|
|
- 2377 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 2378 IF k = SymTab.KindImport THEN
|
|
|
- 2379 SemError(230)
|
|
|
- 2380 ELSIF k =
|
|
|
- 2381 SymTab.KindProc THEN
|
|
|
- 2382 (* bare procedure name:
|
|
|
- 2383 a following ArgList
|
|
|
- 2384 makes it a call;
|
|
|
- 2385 otherwise Fact
|
|
|
- 2386 reports 230 *)
|
|
|
- 2387 ELSE
|
|
|
- 2388 IF k = SymTab.KindField THEN
|
|
|
- 2389 IF QbeGen.TopWith(qb) THEN
|
|
|
- 2390 sfx := TRUE
|
|
|
- 2391 ELSE SemError(230);
|
|
|
- 2392 QbeGen.CopyOp("0", q)
|
|
|
- 2393 END
|
|
|
- 2394 END
|
|
|
- 2395 END
|
|
|
- 2396 END
|
|
|
- 2397 END; .)
|
|
|
- 2398 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
- 2399 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 2400 IF fwd THEN AST.SetOp(astDes, 1) END;
|
|
|
- 2401 IF fwd THEN Check.NoteForward(fref, astDes) END; .)
|
|
|
- 2402 { "[" Expr<it, iq>
|
|
|
- 2403 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2404 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2405 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2406 SymTab.ClArray THEN
|
|
|
- 2407 SemError(217);
|
|
|
- 2408 t := SymTab.InvalidType
|
|
|
- 2409 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2410 AND (SymTab.ClassOf(it) #
|
|
|
- 2411 SymTab.ClChar)
|
|
|
- 2412 AND (SymTab.ClassOf(it) #
|
|
|
- 2413 SymTab.ClEnum) THEN
|
|
|
- 2414 SemError(218);
|
|
|
- 2415 t := SymTab.InvalidType
|
|
|
- 2416 ELSE
|
|
|
- 2417 eT := SymTab.ArrayElem(t);
|
|
|
- 2418 t := eT; sfx := TRUE
|
|
|
- 2419 END; .)
|
|
|
- 2420 { "," Expr<it, iq>
|
|
|
- 2421 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2422 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2423 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2424 SymTab.ClArray THEN
|
|
|
- 2425 SemError(217);
|
|
|
- 2426 t := SymTab.InvalidType
|
|
|
- 2427 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2428 AND (SymTab.ClassOf(it) #
|
|
|
- 2429 SymTab.ClChar)
|
|
|
- 2430 AND (SymTab.ClassOf(it) #
|
|
|
- 2431 SymTab.ClEnum) THEN
|
|
|
- 2432 SemError(218);
|
|
|
- 2433 t := SymTab.InvalidType
|
|
|
- 2434 ELSE
|
|
|
- 2435 eT := SymTab.ArrayElem(t);
|
|
|
- 2436 t := eT; sfx := TRUE
|
|
|
- 2437 END; .) }
|
|
|
- 2438 "]"
|
|
|
- 2439 | "." GetIdent<fn>
|
|
|
- 2440 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2441 AST.SetOp(astSel, AST.SelField);
|
|
|
- 2442 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
- 2443 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
- 2444 (* qualified L.x: materialize
|
|
|
- 2445 the export, then load it *)
|
|
|
- 2446 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 2447 fn, mal) THEN
|
|
|
- 2448 SemError(201);
|
|
|
- 2449 t := SymTab.InvalidType;
|
|
|
- 2450 QbeGen.CopyOp("0", q)
|
|
|
- 2451 ELSE
|
|
|
- 2452 QbeGen.CopyOp(mal, qn);
|
|
|
- 2453 t := SymTab.SymType(mal);
|
|
|
- 2454 k := SymTab.SymKind(mal);
|
|
|
- 2455 sfx := FALSE;
|
|
|
- 2456 IF k = SymTab.KindProc THEN
|
|
|
- 2457 (* call: ArgList supplies
|
|
|
- 2458 the value *)
|
|
|
- 2459 QbeGen.CopyOp("0", q)
|
|
|
- 2460 END
|
|
|
- 2461 END
|
|
|
- 2462 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 2463 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2464 SymTab.ClRecord)
|
|
|
- 2465 AND (SymTab.ClassOf(t) #
|
|
|
- 2466 SymTab.ClClass) THEN
|
|
|
- 2467 SemError(215);
|
|
|
- 2468 t := SymTab.InvalidType
|
|
|
- 2469 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 2470 SymTab.ClClass)
|
|
|
- 2471 AND SymTab.MethodExists(t, fn) THEN
|
|
|
- 2472 (* obj.Method: bind the
|
|
|
- 2473 method and pass obj as
|
|
|
- 2474 the hidden receiver; q
|
|
|
- 2475 already holds the
|
|
|
- 2476 object's address *)
|
|
|
- 2477 QbeGen.CopyOp(fn, n);
|
|
|
- 2478 QbeGen.CopyOp(fn, qn);
|
|
|
- 2479 methCls := t;
|
|
|
- 2480 k := SymTab.KindProc;
|
|
|
- 2481 t := SymTab.InvalidType
|
|
|
- 2482 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2483 fn) THEN
|
|
|
- 2484 SemError(216);
|
|
|
- 2485 t := SymTab.InvalidType
|
|
|
- 2486 ELSE
|
|
|
- 2487 t := SymTab.FieldType(t, fn);
|
|
|
- 2488 sfx := TRUE
|
|
|
- 2489 END; .)
|
|
|
- 2490 | "^"
|
|
|
- 2491 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2492 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2493 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2494 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2495 SymTab.ClPtr THEN
|
|
|
- 2496 SemError(219);
|
|
|
- 2497 t := SymTab.InvalidType
|
|
|
- 2498 ELSE
|
|
|
- 2499 bt := SymTab.PtrBase(t);
|
|
|
- 2500 IF bt = SymTab.InvalidType THEN
|
|
|
- 2501 ELSE
|
|
|
- 2502 t := bt;
|
|
|
- 2503 sfx := TRUE
|
|
|
- 2504 END
|
|
|
- 2505 END; .) } (. astCur := astDes; .) .
|
|
|
- 2506 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
- 2507 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
- 2508 (a value, or a descriptor address for aggregates); each component
|
|
|
- 2509 descends one level exactly like the Design components. *)
|
|
|
- 2510 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2511 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
- 2512 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
- 2513 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
- 2514 iq, ql, qlo, qhi, qe, qb:
|
|
|
- 2515 QbeGen.QVal;
|
|
|
- 2516 lo, hi, fo: INTEGER;
|
|
|
- 2517 isOpen: BOOLEAN;
|
|
|
- 2518 fname: SymTab.Name;
|
|
|
- 2519 astWrap, astSel: AST.Node; .)
|
|
|
- 2520 = "[" Expr<it, iq>
|
|
|
- 2521 (. isM := FALSE;
|
|
|
- 2522 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2523 astWrap := AST.MakeNode(
|
|
|
- 2524 AST.NkDesignator);
|
|
|
- 2525 AST.SetChild(astWrap, 0, node);
|
|
|
- 2526 node := astWrap
|
|
|
- 2527 END;
|
|
|
- 2528 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2529 AST.MakeUn(AST.NkSelector,
|
|
|
- 2530 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) # SymTab.ClChar)
|
|
|
- 2537 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
- 2538 SemError(218);
|
|
|
- 2539 t := SymTab.InvalidType
|
|
|
- 2540 ELSE
|
|
|
- 2541 eT := SymTab.ArrayElem(t);
|
|
|
- 2542 t := eT; sfx := TRUE
|
|
|
- 2543 END; .)
|
|
|
- 2544 "]"
|
|
|
- 2545 | "." GetIdent<fname>
|
|
|
- 2546 (. isM := FALSE;
|
|
|
- 2547 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2548 astWrap := AST.MakeNode(
|
|
|
- 2549 AST.NkDesignator);
|
|
|
- 2550 AST.SetChild(astWrap, 0, node);
|
|
|
- 2551 node := astWrap
|
|
|
- 2552 END;
|
|
|
- 2553 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2554 AST.MakeUn(AST.NkSelector,
|
|
|
- 2555 AST.SelField,
|
|
|
- 2556 AST.MakeLeaf(AST.NkIdent,
|
|
|
- 2557 fname))); IF t = SymTab.InvalidType THEN
|
|
|
- 2558 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2559 SymTab.ClRecord)
|
|
|
- 2560 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 2561 SemError(215);
|
|
|
- 2562 t := SymTab.InvalidType
|
|
|
- 2563 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 2564 SymTab.ClClass)
|
|
|
- 2565 AND SymTab.MethodExists(t, fname) THEN
|
|
|
- 2566 (* a method on the call result:
|
|
|
- 2567 a following ArgList makes
|
|
|
- 2568 the call *)
|
|
|
- 2569 mname := fname;
|
|
|
- 2570 methCls := t; isM := TRUE;
|
|
|
- 2571 t := SymTab.InvalidType
|
|
|
- 2572 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2573 fname) THEN
|
|
|
- 2574 SemError(216);
|
|
|
- 2575 t := SymTab.InvalidType
|
|
|
- 2576 ELSE
|
|
|
- 2577 t := SymTab.FieldType(t, fname);
|
|
|
- 2578 sfx := TRUE
|
|
|
- 2579 END; .)
|
|
|
- 2580 | "^" (. isM := FALSE;
|
|
|
- 2581 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2582 astWrap := AST.MakeNode(
|
|
|
- 2583 AST.NkDesignator);
|
|
|
- 2584 AST.SetChild(astWrap, 0, node);
|
|
|
- 2585 node := astWrap
|
|
|
- 2586 END;
|
|
|
- 2587 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2588 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2589 AST.SetChild(node,
|
|
|
- 2590 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2591 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2592 SymTab.ClPtr THEN
|
|
|
- 2593 SemError(219);
|
|
|
- 2594 t := SymTab.InvalidType
|
|
|
- 2595 ELSE
|
|
|
- 2596 bt := SymTab.PtrBase(t);
|
|
|
- 2597 IF bt # SymTab.InvalidType THEN
|
|
|
- 2598 t := bt; sfx := TRUE
|
|
|
- 2599 END
|
|
|
- 2600 END; .) .
|
|
|
- 2601 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2602 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 2603 op: INTEGER;
|
|
|
- 2604 q2, qt, wl: QbeGen.QVal;
|
|
|
- 2605 astA, astB: AST.Node;
|
|
|
- 2606 astOp: INTEGER;
|
|
|
- 2607 astMade: BOOLEAN;
|
|
|
- 2608 isR: BOOLEAN; .)
|
|
|
- 2609 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
- 2610 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 2611 (. astB := astCur; astMade := TRUE;
|
|
|
- 2612 astOp := AST.OpEq;
|
|
|
- 2613 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
- 2614 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
- 2615 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
- 2616 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
- 2617 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
- 2618 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
- 2619 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
- 2620 END;
|
|
|
- 2621 IF op = SymTab.OpIn THEN
|
|
|
- 2622 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 2623 IF (t = SymTab.InvalidType)
|
|
|
- 2624 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 2625 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 2626 ELSE
|
|
|
- 2627 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2628 END
|
|
|
- 2629 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 2630 QbeGen.CopyOp("0", q)
|
|
|
- 2631 END
|
|
|
- 2632 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 2633 IF (t = SymTab.InvalidType)
|
|
|
- 2634 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 2635 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 2636 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 2637 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 2638 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 2639 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 2640 SemError(213); t := SymTab.InvalidType;
|
|
|
- 2641 QbeGen.CopyOp("0", q)
|
|
|
- 2642 ELSE
|
|
|
- 2643 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2644 END
|
|
|
- 2645 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2646 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2647 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2648 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
- 2649 QbeGen.StrEq(op, q, q2, qt);
|
|
|
- 2650 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2651 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 2652 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 2653 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2654 ELSE
|
|
|
- 2655 t := SymTab.BoolType();
|
|
|
- 2656 QbeGen.CopyOp("@", q)
|
|
|
- 2657 END
|
|
|
- 2658 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 2659 QbeGen.CopyOp("0", q)
|
|
|
- 2660 END;
|
|
|
- 2661 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
- 2662 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
- 2663 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 2664 Rel<VAR op: INTEGER>
|
|
|
- 2665 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 2666 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 2667 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 2668 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 2669 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 2670 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 2671 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 2672 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2673 (. VAR t2, res2, lt, rt:
|
|
|
- 2674 SymTab.TypeIndex;
|
|
|
- 2675 op: INTEGER;
|
|
|
- 2676 q2, qt, wq, qf, q2a, q2b:
|
|
|
- 2677 QbeGen.QVal;
|
|
|
- 2678 neg, isR, isL, folded:
|
|
|
- 2679 BOOLEAN;
|
|
|
- 2680 fok: BOOLEAN;
|
|
|
- 2681 lw, rw, mw: CARDINAL;
|
|
|
- 2682 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 2683 astA, astB: AST.Node;
|
|
|
- 2684 astSign, astOp: INTEGER; .)
|
|
|
- 2685 = (. neg := FALSE; astSign := 0; .)
|
|
|
- 2686 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
- 2687 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
- 2688 Term<t, q> (. astA := astCur;
|
|
|
- 2689 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
- 2690 QbeGen.NegFold(q, q)
|
|
|
- 2691 END;
|
|
|
- 2692 IF astSign < 0 THEN
|
|
|
- 2693 astCur := AST.MakeUn(
|
|
|
- 2694 AST.NkUnary, AST.OpSub, astA);
|
|
|
- 2695 astA := astCur
|
|
|
- 2696 END; .)
|
|
|
- 2697 { AddOp<op>
|
|
|
- 2698 Term<t2, q2> (. astB := astCur; .)
|
|
|
- 2699 (. astOp := AST.OpAdd;
|
|
|
- 2700 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
- 2701 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
- 2702 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 2703 astCur := astA;
|
|
|
- 2704 IF op = SymTab.OpOr THEN
|
|
|
- 2705 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
- 2706 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 2707 t := SymTab.BoolType()
|
|
|
- 2708 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 2709 IF t # SymTab.InvalidType THEN
|
|
|
- 2710 QbeGen.CopyOp("@", q)
|
|
|
- 2711 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2712 END
|
|
|
- 2713 ELSIF (op = SymTab.OpAdd)
|
|
|
- 2714 AND (SymTab.UStrCompat(t, t2)
|
|
|
- 2715 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 2716 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
- 2717 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
- 2718 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
- 2719 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 2720 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
- 2721 (* UString concatenation: a UCHAR operand becomes a
|
|
|
- 2722 1-codepoint UString; the result is a descriptor in the
|
|
|
- 2723 shim's concat buffer. Work on copies so neither
|
|
|
- 2724 operand is clobbered. *)
|
|
|
- 2725 t := SymTab.NewUStr();
|
|
|
- 2726 QbeGen.CopyOp("@", q)
|
|
|
- 2727 ELSIF (op = SymTab.OpAdd)
|
|
|
- 2728 AND (SymTab.StrCompat(t, t2)
|
|
|
- 2729 OR (SymTab.IsStrType(t)
|
|
|
- 2730 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
- 2731 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
- 2732 AND SymTab.IsStrType(t2))) THEN
|
|
|
- 2733 (* string concatenation; a CHAR operand becomes a
|
|
|
- 2734 1-character string literal. When both operands are
|
|
|
- 2735 constants, fold to a single string literal so a
|
|
|
- 2736 constructor element stays compile-time. *)
|
|
|
- 2737 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
- 2738 qt, fok);
|
|
|
- 2739 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
- 2740 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2741 END;
|
|
|
- 2742 t := SymTab.NewStr()
|
|
|
- 2743 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 2744 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2745 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2746 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 2747 mw := lw;
|
|
|
- 2748 IF rw > mw THEN mw := rw END;
|
|
|
- 2749 t := SymTab.NewSet(
|
|
|
- 2750 SymTab.NewSubR(0,
|
|
|
- 2751 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 2752 QbeGen.CopyOp("@", q)
|
|
|
- 2753 ELSE
|
|
|
- 2754 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 2755 lt := t; rt := t2; t := res2
|
|
|
- 2756 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 2757 IF t # SymTab.InvalidType THEN
|
|
|
- 2758 isL := SymTab.IsLongFamily(t);
|
|
|
- 2759 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 2760 folded := FALSE;
|
|
|
- 2761 IF (NOT isL) AND (NOT isR)
|
|
|
- 2762 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 2763 IF op = SymTab.OpAdd THEN
|
|
|
- 2764 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 2765 ELSE
|
|
|
- 2766 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 2767 END
|
|
|
- 2768 END;
|
|
|
- 2769 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 2770 ELSE
|
|
|
- 2771 QbeGen.CopyOp("@", q)
|
|
|
- 2772 END
|
|
|
- 2773 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2774 END
|
|
|
- 2775 END; .) }
|
|
|
- 2776 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 2777 AddOp<VAR op: INTEGER>
|
|
|
- 2778 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 2779 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 2780 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 2781 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2782 (. VAR t2, res2, lt, rt:
|
|
|
- 2783 SymTab.TypeIndex;
|
|
|
- 2784 op: INTEGER;
|
|
|
- 2785 q2, qt, wq, qf:
|
|
|
- 2786 QbeGen.QVal;
|
|
|
- 2787 isR, isL, folded: BOOLEAN;
|
|
|
- 2788 lw, rw, mw: CARDINAL;
|
|
|
- 2789 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 2790 astA, astB: AST.Node;
|
|
|
- 2791 astOp: INTEGER; .)
|
|
|
- 2792 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
- 2793 Fact<t2, q2> (. astB := astCur; .)
|
|
|
- 2794 (. astOp := AST.OpMul;
|
|
|
- 2795 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
- 2796 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
- 2797 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
- 2798 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
- 2799 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 2800 astCur := astA;
|
|
|
- 2801 IF op = SymTab.OpAnd THEN
|
|
|
- 2802 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
- 2803 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 2804 t := SymTab.BoolType()
|
|
|
- 2805 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 2806 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
- 2807 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2808 END
|
|
|
- 2809 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 2810 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2811 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2812 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 2813 mw := lw;
|
|
|
- 2814 IF rw > mw THEN mw := rw END;
|
|
|
- 2815 t := SymTab.NewSet(
|
|
|
- 2816 SymTab.NewSubR(0,
|
|
|
- 2817 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 2818 QbeGen.CopyOp("@", q)
|
|
|
- 2819 ELSE
|
|
|
- 2820 IF SymTab.ArithCheck(t, t2,
|
|
|
- 2821 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 2822 res2) THEN
|
|
|
- 2823 lt := t; rt := t2; t := res2
|
|
|
- 2824 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 2825 IF t # SymTab.InvalidType THEN
|
|
|
- 2826 isL := SymTab.IsLongFamily(t);
|
|
|
- 2827 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 2828 folded := FALSE;
|
|
|
- 2829 IF (NOT isL) AND (NOT isR)
|
|
|
- 2830 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 2831 IF op = SymTab.OpTimes THEN
|
|
|
- 2832 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 2833 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 2834 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 2835 ELSIF op = SymTab.OpMod THEN
|
|
|
- 2836 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 2837 END
|
|
|
- 2838 END;
|
|
|
- 2839 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 2840 ELSE
|
|
|
- 2841 QbeGen.CopyOp("@", q)
|
|
|
- 2842 END
|
|
|
- 2843 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2844 END
|
|
|
- 2845 END; .) }
|
|
|
- 2846 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 2847 MulOp<VAR op: INTEGER>
|
|
|
- 2848 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 2849 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 2850 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 2851 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 2852 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
- 2853 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2854 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 2855 et, dt, t2, st, ct2, et2:
|
|
|
- 2856 SymTab.TypeIndex;
|
|
|
- 2857 dk: INTEGER;
|
|
|
- 2858 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
- 2859 QbeGen.QVal;
|
|
|
- 2860 qn, vn: SymTab.Name;
|
|
|
- 2861 vt: SymTab.TypeIndex;
|
|
|
- 2862 c1, c2: INTEGER;
|
|
|
- 2863 lo, hi: INTEGER;
|
|
|
- 2864 isMax: BOOLEAN;
|
|
|
- 2865 called, isHigh, sfx, isCh,
|
|
|
- 2866 isU, uok, isStr: BOOLEAN;
|
|
|
- 2867 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
- 2868 astD: AST.Node;
|
|
|
- 2869 astCall: BOOLEAN;
|
|
|
- 2870 astNode, astNot: AST.Node;
|
|
|
- 2871 j: CARDINAL;
|
|
|
- 2872 astArg2: AST.Node;
|
|
|
- 2873 astBrace: AST.Node;
|
|
|
- 2874 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
|
|
|
- 2875 = (. astIsLit := FALSE; .)
|
|
|
- 2876 ( integer (. LexString(s);
|
|
|
- 2877 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
- 2878 t := SymTab.IntType(); .)
|
|
|
- 2879 | charConst (. LexString(s);
|
|
|
- 2880 QbeGen.NormLit(s, q, isCh);
|
|
|
- 2881 IF twoPhase THEN
|
|
|
- 2882 astIsLit := TRUE;
|
|
|
- 2883 astCur := AST.MakeLeaf(
|
|
|
- 2884 AST.NkCharLit, s)
|
|
|
- 2885 END;
|
|
|
- 2886 t := SymTab.CharType(); .)
|
|
|
- 2887 | real (. LexString(s);
|
|
|
- 2888 QbeGen.NormReal(s, q);
|
|
|
- 2889 IF twoPhase THEN
|
|
|
- 2890 astIsLit := TRUE;
|
|
|
- 2891 astCur := AST.MakeLeaf(
|
|
|
- 2892 AST.NkRealLit, s)
|
|
|
- 2893 END;
|
|
|
- 2894 t := SymTab.RealType(); .)
|
|
|
- 2895 | string (. LexString(s);
|
|
|
- 2896 IF twoPhase THEN
|
|
|
- 2897 astIsLit := TRUE;
|
|
|
- 2898 astCur := AST.MakeLeaf(
|
|
|
- 2899 AST.NkStrLit, s)
|
|
|
- 2900 END;
|
|
|
- 2901 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 2902 t := SymTab.CharType();
|
|
|
- 2903 QbeGen.IntStr(
|
|
|
- 2904 QbeGen.CharVal(s), q)
|
|
|
- 2905 ELSE t := SymTab.NewStr();
|
|
|
- 2906 QbeGen.DeclStr(s, q);
|
|
|
- 2907 (* a literal's value IS its
|
|
|
- 2908 static descriptor address *)
|
|
|
- 2909 END; .)
|
|
|
- 2910 | ustring (. LexString(s);
|
|
|
- 2911 IF twoPhase THEN
|
|
|
- 2912 astIsLit := TRUE;
|
|
|
- 2913 astCur := AST.MakeLeaf(
|
|
|
- 2914 AST.NkStrLit, s)
|
|
|
- 2915 END;
|
|
|
- 2916 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
- 2917 uok);
|
|
|
- 2918 IF NOT uok THEN
|
|
|
- 2919 SemError(234);
|
|
|
- 2920 t := SymTab.InvalidType
|
|
|
- 2921 ELSIF isU THEN
|
|
|
- 2922 t := SymTab.UCharType();
|
|
|
- 2923 QbeGen.IntStr(ucp, q)
|
|
|
- 2924 ELSE
|
|
|
- 2925 t := SymTab.NewUStr();
|
|
|
- 2926 END; .)
|
|
|
- 2927 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
- 2928 astNArgs := 0; called := FALSE;
|
|
|
- 2929 t := dt;
|
|
|
- 2930 IF dk = SymTab.KindConst THEN
|
|
|
- 2931 QbeGen.CopyOp(qd, q)
|
|
|
- 2932 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2933 END; .)
|
|
|
- 2934 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
- 2935 astBrace := astCur; .) ]
|
|
|
- 2936 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 2937 (. astCall := TRUE;
|
|
|
- 2938 astNode := AstCallNode(astD);
|
|
|
- 2939 astRes := astNode;
|
|
|
- 2940 t := ct2;
|
|
|
- 2941 QbeGen.CopyOp(q2, q);
|
|
|
- 2942 sfx := FALSE; .)
|
|
|
- 2943 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
- 2944 [ (. astNArgs := 0; .)
|
|
|
- 2945 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 2946 (. astNode := AstCallNode(astRes);
|
|
|
- 2947 astRes := astNode;
|
|
|
- 2948 t := ct2;
|
|
|
- 2949 QbeGen.CopyOp(q2, q);
|
|
|
- 2950 sfx := FALSE; .) ] }
|
|
|
- 2951 (. IF sfx THEN
|
|
|
- 2952 IF t = SymTab.InvalidType THEN
|
|
|
- 2953 QbeGen.CopyOp("0", q)
|
|
|
- 2954 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2955 SymTab.ClRecord)
|
|
|
- 2956 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
- 2957 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
- 2958 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 2959 QbeGen.CopyOp("@", q)
|
|
|
- 2960 END
|
|
|
- 2961 END; .) ]
|
|
|
- 2962 (. IF called THEN
|
|
|
- 2963 astCur := astRes
|
|
|
- 2964 ELSIF astCall THEN
|
|
|
- 2965 astCur := astBrace
|
|
|
- 2966 ELSE astCur := astD
|
|
|
- 2967 END;
|
|
|
- 2968 astIsLit := TRUE;
|
|
|
- 2969 IF NOT called
|
|
|
- 2970 AND (dk = SymTab.KindProc) THEN
|
|
|
- 2971 (* bare zero-arg function
|
|
|
- 2972 call (parentheses may be
|
|
|
- 2973 omitted); a proper or
|
|
|
- 2974 parameterised proc here
|
|
|
- 2975 is 230 *)
|
|
|
- 2976 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 2977 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
- 2978 t := SymTab.ProcRes(qn);
|
|
|
- 2979 QbeGen.CopyOp("@", q);
|
|
|
- 2980 astCur := AST.MakeNode(AST.NkCall);
|
|
|
- 2981 AST.SetChild(astCur, 0, astD)
|
|
|
- 2982 ELSE
|
|
|
- 2983 t := SymTab.ProcTypeOf(qn);
|
|
|
- 2984 QbeGen.CopyOp("@", q)
|
|
|
- 2985 END
|
|
|
- 2986 END; .)
|
|
|
- 2987 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 2988 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- 2989 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
- 2990 isU := FALSE; .)
|
|
|
- 2991 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 2992 isStr := TRUE;
|
|
|
- 2993 isU := FALSE;
|
|
|
- 2994 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 2995 dt := SymTab.CharType();
|
|
|
- 2996 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
- 2997 qd)
|
|
|
- 2998 ELSE
|
|
|
- 2999 dt := SymTab.NewStr();
|
|
|
- 3000 QbeGen.DeclStr(s, qd);
|
|
|
- 3001 END;
|
|
|
- 3002 dk := -1;
|
|
|
- 3003 qn[0] := CHR(0); .)
|
|
|
- 3004 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3005 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
- 3006 uok);
|
|
|
- 3007 isStr := FALSE;
|
|
|
- 3008 IF NOT uok THEN
|
|
|
- 3009 SemError(234);
|
|
|
- 3010 dt := SymTab.InvalidType
|
|
|
- 3011 ELSIF isU THEN
|
|
|
- 3012 (* one codepoint: a UCHAR;
|
|
|
- 3013 LEN is 1, HIGH is 0 *)
|
|
|
- 3014 dt := SymTab.UCharType();
|
|
|
- 3015 QbeGen.IntStr(ucp, qd)
|
|
|
- 3016 ELSE
|
|
|
- 3017 dt := SymTab.NewUStr();
|
|
|
- 3018 END;
|
|
|
- 3019 dk := -1;
|
|
|
- 3020 qn[0] := CHR(0); .) )
|
|
|
- 3021 ")"
|
|
|
- 3022 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3023 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
- 3024 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
- 3025 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3026 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
- 3027 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3028 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3029 IF (dt # SymTab.InvalidType)
|
|
|
- 3030 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
- 3031 (* UString: the count is
|
|
|
- 3032 the descriptor header *)
|
|
|
- 3033 t := SymTab.IntType();
|
|
|
- 3034 QbeGen.CopyOp("@", q)
|
|
|
- 3035 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 3036 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
- 3037 (* single UCHAR codepoint *)
|
|
|
- 3038 IF isHigh THEN
|
|
|
- 3039 QbeGen.CopyOp("0", qr)
|
|
|
- 3040 ELSE
|
|
|
- 3041 QbeGen.CopyOp("1", qr)
|
|
|
- 3042 END;
|
|
|
- 3043 t := SymTab.IntType();
|
|
|
- 3044 QbeGen.CopyOp(qr, q)
|
|
|
- 3045 ELSIF isStr THEN
|
|
|
- 3046 (* fold: content length at
|
|
|
- 3047 compile time *)
|
|
|
- 3048 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3049 c1 := 1
|
|
|
- 3050 ELSE
|
|
|
- 3051 c1 :=
|
|
|
- 3052 SymTab.StrLen(s) - 2
|
|
|
- 3053 END;
|
|
|
- 3054 IF isHigh THEN
|
|
|
- 3055 DEC(c1)
|
|
|
+ 2301 ELSIF SymTab.Equal(n,
|
|
|
+ 2302 "NIL") THEN
|
|
|
+ 2303 QbeGen.CopyOp("0", q)
|
|
|
+ 2304 ELSE
|
|
|
+ 2305 cls :=
|
|
|
+ 2306 SymTab.ClassOf(t);
|
|
|
+ 2307 IF (t #
|
|
|
+ 2308 SymTab.InvalidType)
|
|
|
+ 2309 AND ((cls = SymTab.ClInt)
|
|
|
+ 2310 OR (cls
|
|
|
+ 2311 = SymTab.ClChar)
|
|
|
+ 2312 OR (cls
|
|
|
+ 2313 = SymTab.ClEnum)
|
|
|
+ 2314 OR (cls
|
|
|
+ 2315 = SymTab.ClReal)
|
|
|
+ 2316 OR (cls
|
|
|
+ 2317 = SymTab.ClLong)
|
|
|
+ 2318 OR (cls
|
|
|
+ 2319 = SymTab.ClNil)) THEN
|
|
|
+ 2320 IF cls = SymTab.ClNil THEN
|
|
|
+ 2321 QbeGen.CopyOp("0", q)
|
|
|
+ 2322 ELSIF ((cls
|
|
|
+ 2323 = SymTab.ClInt)
|
|
|
+ 2324 OR (cls
|
|
|
+ 2325 = SymTab.ClChar)
|
|
|
+ 2326 OR (cls
|
|
|
+ 2327 = SymTab.ClEnum)
|
|
|
+ 2328 OR (cls
|
|
|
+ 2329 = SymTab.ClLong))
|
|
|
+ 2330 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 2331 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 2332 QbeGen.CopyOp(cv, q)
|
|
|
+ 2333 ELSE
|
|
|
+ 2334 QbeGen.LoadVar(n,
|
|
|
+ 2335 cls = SymTab.ClReal,
|
|
|
+ 2336 q)
|
|
|
+ 2337 END
|
|
|
+ 2338 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 2339 OR (cls = SymTab.ClRecord)
|
|
|
+ 2340 OR (cls = SymTab.ClClass)
|
|
|
+ 2341 OR (cls = SymTab.ClStr)
|
|
|
+ 2342 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 2343 (* aggregate constant:
|
|
|
+ 2344 its value IS the
|
|
|
+ 2345 descriptor address *)
|
|
|
+ 2346 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ 2347 QbeGen.CopyOp(cv, q)
|
|
|
+ 2348 ELSE
|
|
|
+ 2349 QbeGen.CopyOp("0", q)
|
|
|
+ 2350 END
|
|
|
+ 2351 ELSE
|
|
|
+ 2352 IF t #
|
|
|
+ 2353 SymTab.InvalidType THEN
|
|
|
+ 2354 SemError(230)
|
|
|
+ 2355 END;
|
|
|
+ 2356 QbeGen.CopyOp("0", q)
|
|
|
+ 2357 END
|
|
|
+ 2358 END
|
|
|
+ 2359 ELSIF (k = SymTab.KindVar)
|
|
|
+ 2360 OR (k = SymTab.KindParam) THEN
|
|
|
+ 2361 cls := SymTab.ClassOf(t);
|
|
|
+ 2362 IF (cls # SymTab.ClInt)
|
|
|
+ 2363 AND (cls # SymTab.ClBool)
|
|
|
+ 2364 AND (cls # SymTab.ClChar)
|
|
|
+ 2365 AND (cls # SymTab.ClUChar)
|
|
|
+ 2366 AND (cls # SymTab.ClEnum)
|
|
|
+ 2367 AND (cls # SymTab.ClReal)
|
|
|
+ 2368 AND (cls # SymTab.ClPtr)
|
|
|
+ 2369 AND (cls # SymTab.ClProc)
|
|
|
+ 2370 AND (cls # SymTab.ClLong)
|
|
|
+ 2371 AND (cls # SymTab.ClArray)
|
|
|
+ 2372 AND (cls # SymTab.ClSet)
|
|
|
+ 2373 AND (cls # SymTab.ClRecord)
|
|
|
+ 2374 AND (cls # SymTab.ClUStr)
|
|
|
+ 2375 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 2376 SemError(230);
|
|
|
+ 2377 QbeGen.CopyOp("0", q)
|
|
|
+ 2378 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2379 END
|
|
|
+ 2380 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 2381 IF k = SymTab.KindImport THEN
|
|
|
+ 2382 SemError(230)
|
|
|
+ 2383 ELSIF k =
|
|
|
+ 2384 SymTab.KindProc THEN
|
|
|
+ 2385 (* bare procedure name:
|
|
|
+ 2386 a following ArgList
|
|
|
+ 2387 makes it a call;
|
|
|
+ 2388 otherwise Fact
|
|
|
+ 2389 reports 230 *)
|
|
|
+ 2390 ELSE
|
|
|
+ 2391 IF k = SymTab.KindField THEN
|
|
|
+ 2392 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 2393 sfx := TRUE
|
|
|
+ 2394 ELSE SemError(230);
|
|
|
+ 2395 QbeGen.CopyOp("0", q)
|
|
|
+ 2396 END
|
|
|
+ 2397 END
|
|
|
+ 2398 END
|
|
|
+ 2399 END
|
|
|
+ 2400 END; .)
|
|
|
+ 2401 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
+ 2402 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 2403 IF fwd THEN AST.SetOp(astDes, 1) END;
|
|
|
+ 2404 IF fwd THEN Check.NoteForward(fref, astDes) END; .)
|
|
|
+ 2405 { "[" Expr<it, iq>
|
|
|
+ 2406 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2407 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2408 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2409 SymTab.ClArray THEN
|
|
|
+ 2410 SemError(217);
|
|
|
+ 2411 t := SymTab.InvalidType
|
|
|
+ 2412 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2413 AND (SymTab.ClassOf(it) #
|
|
|
+ 2414 SymTab.ClChar)
|
|
|
+ 2415 AND (SymTab.ClassOf(it) #
|
|
|
+ 2416 SymTab.ClEnum) THEN
|
|
|
+ 2417 SemError(218);
|
|
|
+ 2418 t := SymTab.InvalidType
|
|
|
+ 2419 ELSE
|
|
|
+ 2420 eT := SymTab.ArrayElem(t);
|
|
|
+ 2421 t := eT; sfx := TRUE
|
|
|
+ 2422 END; .)
|
|
|
+ 2423 { "," Expr<it, iq>
|
|
|
+ 2424 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2425 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2426 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2427 SymTab.ClArray THEN
|
|
|
+ 2428 SemError(217);
|
|
|
+ 2429 t := SymTab.InvalidType
|
|
|
+ 2430 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2431 AND (SymTab.ClassOf(it) #
|
|
|
+ 2432 SymTab.ClChar)
|
|
|
+ 2433 AND (SymTab.ClassOf(it) #
|
|
|
+ 2434 SymTab.ClEnum) THEN
|
|
|
+ 2435 SemError(218);
|
|
|
+ 2436 t := SymTab.InvalidType
|
|
|
+ 2437 ELSE
|
|
|
+ 2438 eT := SymTab.ArrayElem(t);
|
|
|
+ 2439 t := eT; sfx := TRUE
|
|
|
+ 2440 END; .) }
|
|
|
+ 2441 "]"
|
|
|
+ 2442 | "." GetIdent<fn>
|
|
|
+ 2443 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2444 AST.SetOp(astSel, AST.SelField);
|
|
|
+ 2445 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
+ 2446 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
+ 2447 (* qualified L.x: materialize
|
|
|
+ 2448 the export, then load it *)
|
|
|
+ 2449 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 2450 fn, mal) THEN
|
|
|
+ 2451 SemError(201);
|
|
|
+ 2452 t := SymTab.InvalidType;
|
|
|
+ 2453 QbeGen.CopyOp("0", q)
|
|
|
+ 2454 ELSE
|
|
|
+ 2455 QbeGen.CopyOp(mal, qn);
|
|
|
+ 2456 t := SymTab.SymType(mal);
|
|
|
+ 2457 k := SymTab.SymKind(mal);
|
|
|
+ 2458 sfx := FALSE;
|
|
|
+ 2459 IF k = SymTab.KindProc THEN
|
|
|
+ 2460 (* call: ArgList supplies
|
|
|
+ 2461 the value *)
|
|
|
+ 2462 QbeGen.CopyOp("0", q)
|
|
|
+ 2463 END
|
|
|
+ 2464 END
|
|
|
+ 2465 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 2466 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2467 SymTab.ClRecord)
|
|
|
+ 2468 AND (SymTab.ClassOf(t) #
|
|
|
+ 2469 SymTab.ClClass) THEN
|
|
|
+ 2470 SemError(215);
|
|
|
+ 2471 t := SymTab.InvalidType
|
|
|
+ 2472 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 2473 SymTab.ClClass)
|
|
|
+ 2474 AND SymTab.MethodExists(t, fn) THEN
|
|
|
+ 2475 (* obj.Method: bind the
|
|
|
+ 2476 method and pass obj as
|
|
|
+ 2477 the hidden receiver; q
|
|
|
+ 2478 already holds the
|
|
|
+ 2479 object's address *)
|
|
|
+ 2480 QbeGen.CopyOp(fn, n);
|
|
|
+ 2481 QbeGen.CopyOp(fn, qn);
|
|
|
+ 2482 methCls := t;
|
|
|
+ 2483 k := SymTab.KindProc;
|
|
|
+ 2484 t := SymTab.InvalidType
|
|
|
+ 2485 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2486 fn) THEN
|
|
|
+ 2487 SemError(216);
|
|
|
+ 2488 t := SymTab.InvalidType
|
|
|
+ 2489 ELSE
|
|
|
+ 2490 t := SymTab.FieldType(t, fn);
|
|
|
+ 2491 sfx := TRUE
|
|
|
+ 2492 END; .)
|
|
|
+ 2493 | "^"
|
|
|
+ 2494 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2495 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2496 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2497 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2498 SymTab.ClPtr THEN
|
|
|
+ 2499 SemError(219);
|
|
|
+ 2500 t := SymTab.InvalidType
|
|
|
+ 2501 ELSE
|
|
|
+ 2502 bt := SymTab.PtrBase(t);
|
|
|
+ 2503 IF bt = SymTab.InvalidType THEN
|
|
|
+ 2504 ELSE
|
|
|
+ 2505 t := bt;
|
|
|
+ 2506 sfx := TRUE
|
|
|
+ 2507 END
|
|
|
+ 2508 END; .) } (. astCur := astDes; .) .
|
|
|
+ 2509 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
+ 2510 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
+ 2511 (a value, or a descriptor address for aggregates); each component
|
|
|
+ 2512 descends one level exactly like the Design components. *)
|
|
|
+ 2513 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2514 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
+ 2515 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
+ 2516 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
+ 2517 iq, ql, qlo, qhi, qe, qb:
|
|
|
+ 2518 QbeGen.QVal;
|
|
|
+ 2519 lo, hi, fo: INTEGER;
|
|
|
+ 2520 isOpen: BOOLEAN;
|
|
|
+ 2521 fname: SymTab.Name;
|
|
|
+ 2522 astWrap, astSel: AST.Node; .)
|
|
|
+ 2523 = "[" Expr<it, iq>
|
|
|
+ 2524 (. isM := FALSE;
|
|
|
+ 2525 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2526 astWrap := AST.MakeNode(
|
|
|
+ 2527 AST.NkDesignator);
|
|
|
+ 2528 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2529 node := astWrap
|
|
|
+ 2530 END;
|
|
|
+ 2531 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2532 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2533 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2534 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2535 SymTab.ClArray THEN
|
|
|
+ 2536 SemError(217);
|
|
|
+ 2537 t := SymTab.InvalidType
|
|
|
+ 2538 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2539 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
+ 2540 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
+ 2541 SemError(218);
|
|
|
+ 2542 t := SymTab.InvalidType
|
|
|
+ 2543 ELSE
|
|
|
+ 2544 eT := SymTab.ArrayElem(t);
|
|
|
+ 2545 t := eT; sfx := TRUE
|
|
|
+ 2546 END; .)
|
|
|
+ 2547 "]"
|
|
|
+ 2548 | "." GetIdent<fname>
|
|
|
+ 2549 (. isM := FALSE;
|
|
|
+ 2550 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2551 astWrap := AST.MakeNode(
|
|
|
+ 2552 AST.NkDesignator);
|
|
|
+ 2553 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2554 node := astWrap
|
|
|
+ 2555 END;
|
|
|
+ 2556 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2557 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2558 AST.SelField,
|
|
|
+ 2559 AST.MakeLeaf(AST.NkIdent,
|
|
|
+ 2560 fname))); IF t = SymTab.InvalidType THEN
|
|
|
+ 2561 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2562 SymTab.ClRecord)
|
|
|
+ 2563 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 2564 SemError(215);
|
|
|
+ 2565 t := SymTab.InvalidType
|
|
|
+ 2566 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 2567 SymTab.ClClass)
|
|
|
+ 2568 AND SymTab.MethodExists(t, fname) THEN
|
|
|
+ 2569 (* a method on the call result:
|
|
|
+ 2570 a following ArgList makes
|
|
|
+ 2571 the call *)
|
|
|
+ 2572 mname := fname;
|
|
|
+ 2573 methCls := t; isM := TRUE;
|
|
|
+ 2574 t := SymTab.InvalidType
|
|
|
+ 2575 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2576 fname) THEN
|
|
|
+ 2577 SemError(216);
|
|
|
+ 2578 t := SymTab.InvalidType
|
|
|
+ 2579 ELSE
|
|
|
+ 2580 t := SymTab.FieldType(t, fname);
|
|
|
+ 2581 sfx := TRUE
|
|
|
+ 2582 END; .)
|
|
|
+ 2583 | "^" (. isM := FALSE;
|
|
|
+ 2584 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2585 astWrap := AST.MakeNode(
|
|
|
+ 2586 AST.NkDesignator);
|
|
|
+ 2587 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2588 node := astWrap
|
|
|
+ 2589 END;
|
|
|
+ 2590 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2591 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2592 AST.SetChild(node,
|
|
|
+ 2593 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2594 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2595 SymTab.ClPtr THEN
|
|
|
+ 2596 SemError(219);
|
|
|
+ 2597 t := SymTab.InvalidType
|
|
|
+ 2598 ELSE
|
|
|
+ 2599 bt := SymTab.PtrBase(t);
|
|
|
+ 2600 IF bt # SymTab.InvalidType THEN
|
|
|
+ 2601 t := bt; sfx := TRUE
|
|
|
+ 2602 END
|
|
|
+ 2603 END; .) .
|
|
|
+ 2604 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2605 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 2606 op: INTEGER;
|
|
|
+ 2607 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 2608 astA, astB: AST.Node;
|
|
|
+ 2609 astOp: INTEGER;
|
|
|
+ 2610 astMade: BOOLEAN;
|
|
|
+ 2611 isR: BOOLEAN; .)
|
|
|
+ 2612 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
+ 2613 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 2614 (. astB := astCur; astMade := TRUE;
|
|
|
+ 2615 astOp := AST.OpEq;
|
|
|
+ 2616 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
+ 2617 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
+ 2618 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
+ 2619 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
+ 2620 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
+ 2621 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
+ 2622 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
+ 2623 END;
|
|
|
+ 2624 IF op = SymTab.OpIn THEN
|
|
|
+ 2625 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 2626 IF (t = SymTab.InvalidType)
|
|
|
+ 2627 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 2628 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 2629 ELSE
|
|
|
+ 2630 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2631 END
|
|
|
+ 2632 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 2633 QbeGen.CopyOp("0", q)
|
|
|
+ 2634 END
|
|
|
+ 2635 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 2636 IF (t = SymTab.InvalidType)
|
|
|
+ 2637 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 2638 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 2639 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 2640 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 2641 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 2642 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 2643 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 2644 QbeGen.CopyOp("0", q)
|
|
|
+ 2645 ELSE
|
|
|
+ 2646 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2647 END
|
|
|
+ 2648 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2649 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2650 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2651 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 2652 QbeGen.StrEq(op, q, q2, qt);
|
|
|
+ 2653 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2654 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 2655 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 2656 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2657 ELSE
|
|
|
+ 2658 t := SymTab.BoolType();
|
|
|
+ 2659 QbeGen.CopyOp("@", q)
|
|
|
+ 2660 END
|
|
|
+ 2661 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 2662 QbeGen.CopyOp("0", q)
|
|
|
+ 2663 END;
|
|
|
+ 2664 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
+ 2665 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
+ 2666 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 2667 Rel<VAR op: INTEGER>
|
|
|
+ 2668 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 2669 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 2670 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 2671 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 2672 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 2673 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 2674 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 2675 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2676 (. VAR t2, res2, lt, rt:
|
|
|
+ 2677 SymTab.TypeIndex;
|
|
|
+ 2678 op: INTEGER;
|
|
|
+ 2679 q2, qt, wq, qf, q2a, q2b:
|
|
|
+ 2680 QbeGen.QVal;
|
|
|
+ 2681 neg, isR, isL, folded:
|
|
|
+ 2682 BOOLEAN;
|
|
|
+ 2683 fok: BOOLEAN;
|
|
|
+ 2684 lw, rw, mw: CARDINAL;
|
|
|
+ 2685 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 2686 astA, astB: AST.Node;
|
|
|
+ 2687 astSign, astOp: INTEGER; .)
|
|
|
+ 2688 = (. neg := FALSE; astSign := 0; .)
|
|
|
+ 2689 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
+ 2690 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
+ 2691 Term<t, q> (. astA := astCur;
|
|
|
+ 2692 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
+ 2693 QbeGen.NegFold(q, q)
|
|
|
+ 2694 END;
|
|
|
+ 2695 IF astSign < 0 THEN
|
|
|
+ 2696 astCur := AST.MakeUn(
|
|
|
+ 2697 AST.NkUnary, AST.OpSub, astA);
|
|
|
+ 2698 astA := astCur
|
|
|
+ 2699 END; .)
|
|
|
+ 2700 { AddOp<op>
|
|
|
+ 2701 Term<t2, q2> (. astB := astCur; .)
|
|
|
+ 2702 (. astOp := AST.OpAdd;
|
|
|
+ 2703 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
+ 2704 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
+ 2705 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 2706 astCur := astA;
|
|
|
+ 2707 IF op = SymTab.OpOr THEN
|
|
|
+ 2708 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
+ 2709 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 2710 t := SymTab.BoolType()
|
|
|
+ 2711 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 2712 IF t # SymTab.InvalidType THEN
|
|
|
+ 2713 QbeGen.CopyOp("@", q)
|
|
|
+ 2714 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2715 END
|
|
|
+ 2716 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 2717 AND (SymTab.UStrCompat(t, t2)
|
|
|
+ 2718 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 2719 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ 2720 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ 2721 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ 2722 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 2723 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ 2724 (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 2725 1-codepoint UString; the result is a descriptor in the
|
|
|
+ 2726 shim's concat buffer. Work on copies so neither
|
|
|
+ 2727 operand is clobbered. *)
|
|
|
+ 2728 t := SymTab.NewUStr();
|
|
|
+ 2729 QbeGen.CopyOp("@", q)
|
|
|
+ 2730 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 2731 AND (SymTab.StrCompat(t, t2)
|
|
|
+ 2732 OR (SymTab.IsStrType(t)
|
|
|
+ 2733 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
+ 2734 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
+ 2735 AND SymTab.IsStrType(t2))) THEN
|
|
|
+ 2736 (* string concatenation; a CHAR operand becomes a
|
|
|
+ 2737 1-character string literal. When both operands are
|
|
|
+ 2738 constants, fold to a single string literal so a
|
|
|
+ 2739 constructor element stays compile-time. *)
|
|
|
+ 2740 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
+ 2741 qt, fok);
|
|
|
+ 2742 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
+ 2743 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2744 END;
|
|
|
+ 2745 t := SymTab.NewStr()
|
|
|
+ 2746 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 2747 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2748 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2749 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 2750 mw := lw;
|
|
|
+ 2751 IF rw > mw THEN mw := rw END;
|
|
|
+ 2752 t := SymTab.NewSet(
|
|
|
+ 2753 SymTab.NewSubR(0,
|
|
|
+ 2754 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 2755 QbeGen.CopyOp("@", q)
|
|
|
+ 2756 ELSE
|
|
|
+ 2757 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 2758 lt := t; rt := t2; t := res2
|
|
|
+ 2759 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 2760 IF t # SymTab.InvalidType THEN
|
|
|
+ 2761 isL := SymTab.IsLongFamily(t);
|
|
|
+ 2762 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 2763 folded := FALSE;
|
|
|
+ 2764 IF (NOT isL) AND (NOT isR)
|
|
|
+ 2765 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 2766 IF op = SymTab.OpAdd THEN
|
|
|
+ 2767 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 2768 ELSE
|
|
|
+ 2769 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 2770 END
|
|
|
+ 2771 END;
|
|
|
+ 2772 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 2773 ELSE
|
|
|
+ 2774 QbeGen.CopyOp("@", q)
|
|
|
+ 2775 END
|
|
|
+ 2776 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2777 END
|
|
|
+ 2778 END; .) }
|
|
|
+ 2779 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 2780 AddOp<VAR op: INTEGER>
|
|
|
+ 2781 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 2782 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 2783 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 2784 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2785 (. VAR t2, res2, lt, rt:
|
|
|
+ 2786 SymTab.TypeIndex;
|
|
|
+ 2787 op: INTEGER;
|
|
|
+ 2788 q2, qt, wq, qf:
|
|
|
+ 2789 QbeGen.QVal;
|
|
|
+ 2790 isR, isL, folded: BOOLEAN;
|
|
|
+ 2791 lw, rw, mw: CARDINAL;
|
|
|
+ 2792 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 2793 astA, astB: AST.Node;
|
|
|
+ 2794 astOp: INTEGER; .)
|
|
|
+ 2795 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
+ 2796 Fact<t2, q2> (. astB := astCur; .)
|
|
|
+ 2797 (. astOp := AST.OpMul;
|
|
|
+ 2798 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
+ 2799 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
+ 2800 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
+ 2801 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
+ 2802 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 2803 astCur := astA;
|
|
|
+ 2804 IF op = SymTab.OpAnd THEN
|
|
|
+ 2805 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
+ 2806 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 2807 t := SymTab.BoolType()
|
|
|
+ 2808 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 2809 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
+ 2810 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2811 END
|
|
|
+ 2812 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 2813 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2814 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2815 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 2816 mw := lw;
|
|
|
+ 2817 IF rw > mw THEN mw := rw END;
|
|
|
+ 2818 t := SymTab.NewSet(
|
|
|
+ 2819 SymTab.NewSubR(0,
|
|
|
+ 2820 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 2821 QbeGen.CopyOp("@", q)
|
|
|
+ 2822 ELSE
|
|
|
+ 2823 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 2824 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 2825 res2) THEN
|
|
|
+ 2826 lt := t; rt := t2; t := res2
|
|
|
+ 2827 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 2828 IF t # SymTab.InvalidType THEN
|
|
|
+ 2829 isL := SymTab.IsLongFamily(t);
|
|
|
+ 2830 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 2831 folded := FALSE;
|
|
|
+ 2832 IF (NOT isL) AND (NOT isR)
|
|
|
+ 2833 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 2834 IF op = SymTab.OpTimes THEN
|
|
|
+ 2835 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 2836 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 2837 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 2838 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 2839 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 2840 END
|
|
|
+ 2841 END;
|
|
|
+ 2842 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 2843 ELSE
|
|
|
+ 2844 QbeGen.CopyOp("@", q)
|
|
|
+ 2845 END
|
|
|
+ 2846 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2847 END
|
|
|
+ 2848 END; .) }
|
|
|
+ 2849 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 2850 MulOp<VAR op: INTEGER>
|
|
|
+ 2851 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 2852 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 2853 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 2854 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 2855 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 2856 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2857 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 2858 et, dt, t2, st, ct2, et2:
|
|
|
+ 2859 SymTab.TypeIndex;
|
|
|
+ 2860 dk: INTEGER;
|
|
|
+ 2861 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
+ 2862 QbeGen.QVal;
|
|
|
+ 2863 qn, vn: SymTab.Name;
|
|
|
+ 2864 vt: SymTab.TypeIndex;
|
|
|
+ 2865 c1, c2: INTEGER;
|
|
|
+ 2866 lo, hi: INTEGER;
|
|
|
+ 2867 isMax: BOOLEAN;
|
|
|
+ 2868 called, isHigh, sfx, isCh,
|
|
|
+ 2869 isU, uok, isStr: BOOLEAN;
|
|
|
+ 2870 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
+ 2871 astD: AST.Node;
|
|
|
+ 2872 astCall: BOOLEAN;
|
|
|
+ 2873 astNode, astNot: AST.Node;
|
|
|
+ 2874 j: CARDINAL;
|
|
|
+ 2875 astArg2: AST.Node;
|
|
|
+ 2876 astBrace: AST.Node;
|
|
|
+ 2877 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN; .)
|
|
|
+ 2878 = (. astIsLit := FALSE; .)
|
|
|
+ 2879 ( integer (. LexString(s);
|
|
|
+ 2880 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
+ 2881 t := SymTab.IntType(); .)
|
|
|
+ 2882 | charConst (. LexString(s);
|
|
|
+ 2883 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 2884 IF twoPhase THEN
|
|
|
+ 2885 astIsLit := TRUE;
|
|
|
+ 2886 astCur := AST.MakeLeaf(
|
|
|
+ 2887 AST.NkCharLit, s)
|
|
|
+ 2888 END;
|
|
|
+ 2889 t := SymTab.CharType(); .)
|
|
|
+ 2890 | real (. LexString(s);
|
|
|
+ 2891 QbeGen.NormReal(s, q);
|
|
|
+ 2892 IF twoPhase THEN
|
|
|
+ 2893 astIsLit := TRUE;
|
|
|
+ 2894 astCur := AST.MakeLeaf(
|
|
|
+ 2895 AST.NkRealLit, s)
|
|
|
+ 2896 END;
|
|
|
+ 2897 t := SymTab.RealType(); .)
|
|
|
+ 2898 | string (. LexString(s);
|
|
|
+ 2899 IF twoPhase THEN
|
|
|
+ 2900 astIsLit := TRUE;
|
|
|
+ 2901 astCur := AST.MakeLeaf(
|
|
|
+ 2902 AST.NkStrLit, s)
|
|
|
+ 2903 END;
|
|
|
+ 2904 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 2905 t := SymTab.CharType();
|
|
|
+ 2906 QbeGen.IntStr(
|
|
|
+ 2907 QbeGen.CharVal(s), q)
|
|
|
+ 2908 ELSE t := SymTab.NewStr();
|
|
|
+ 2909 QbeGen.DeclStr(s, q);
|
|
|
+ 2910 (* a literal's value IS its
|
|
|
+ 2911 static descriptor address *)
|
|
|
+ 2912 END; .)
|
|
|
+ 2913 | ustring (. LexString(s);
|
|
|
+ 2914 IF twoPhase THEN
|
|
|
+ 2915 astIsLit := TRUE;
|
|
|
+ 2916 astCur := AST.MakeLeaf(
|
|
|
+ 2917 AST.NkStrLit, s)
|
|
|
+ 2918 END;
|
|
|
+ 2919 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
+ 2920 uok);
|
|
|
+ 2921 IF NOT uok THEN
|
|
|
+ 2922 SemError(234);
|
|
|
+ 2923 t := SymTab.InvalidType
|
|
|
+ 2924 ELSIF isU THEN
|
|
|
+ 2925 t := SymTab.UCharType();
|
|
|
+ 2926 QbeGen.IntStr(ucp, q)
|
|
|
+ 2927 ELSE
|
|
|
+ 2928 t := SymTab.NewUStr();
|
|
|
+ 2929 END; .)
|
|
|
+ 2930 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
+ 2931 astNArgs := 0; called := FALSE;
|
|
|
+ 2932 t := dt;
|
|
|
+ 2933 IF dk = SymTab.KindConst THEN
|
|
|
+ 2934 QbeGen.CopyOp(qd, q)
|
|
|
+ 2935 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2936 END; .)
|
|
|
+ 2937 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
+ 2938 astBrace := astCur; .) ]
|
|
|
+ 2939 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 2940 (. astCall := TRUE;
|
|
|
+ 2941 astNode := AstCallNode(astD);
|
|
|
+ 2942 astRes := astNode;
|
|
|
+ 2943 t := ct2;
|
|
|
+ 2944 QbeGen.CopyOp(q2, q);
|
|
|
+ 2945 sfx := FALSE; .)
|
|
|
+ 2946 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
+ 2947 [ (. astNArgs := 0; .)
|
|
|
+ 2948 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 2949 (. astNode := AstCallNode(astRes);
|
|
|
+ 2950 astRes := astNode;
|
|
|
+ 2951 t := ct2;
|
|
|
+ 2952 QbeGen.CopyOp(q2, q);
|
|
|
+ 2953 sfx := FALSE; .) ] }
|
|
|
+ 2954 (. IF sfx THEN
|
|
|
+ 2955 IF t = SymTab.InvalidType THEN
|
|
|
+ 2956 QbeGen.CopyOp("0", q)
|
|
|
+ 2957 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2958 SymTab.ClRecord)
|
|
|
+ 2959 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
+ 2960 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
+ 2961 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 2962 QbeGen.CopyOp("@", q)
|
|
|
+ 2963 END
|
|
|
+ 2964 END; .) ]
|
|
|
+ 2965 (. IF called THEN
|
|
|
+ 2966 astCur := astRes
|
|
|
+ 2967 ELSIF astCall THEN
|
|
|
+ 2968 astCur := astBrace
|
|
|
+ 2969 ELSE astCur := astD
|
|
|
+ 2970 END;
|
|
|
+ 2971 astIsLit := TRUE;
|
|
|
+ 2972 IF NOT called
|
|
|
+ 2973 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 2974 (* bare zero-arg function
|
|
|
+ 2975 call (parentheses may be
|
|
|
+ 2976 omitted); a proper or
|
|
|
+ 2977 parameterised proc here
|
|
|
+ 2978 is 230 *)
|
|
|
+ 2979 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 2980 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
+ 2981 t := SymTab.ProcRes(qn);
|
|
|
+ 2982 QbeGen.CopyOp("@", q);
|
|
|
+ 2983 astCur := AST.MakeNode(AST.NkCall);
|
|
|
+ 2984 AST.SetChild(astCur, 0, astD)
|
|
|
+ 2985 ELSE
|
|
|
+ 2986 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 2987 QbeGen.CopyOp("@", q)
|
|
|
+ 2988 END
|
|
|
+ 2989 END; .)
|
|
|
+ 2990 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 2991 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 2992 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ 2993 isU := FALSE; .)
|
|
|
+ 2994 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 2995 isStr := TRUE;
|
|
|
+ 2996 isU := FALSE;
|
|
|
+ 2997 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 2998 dt := SymTab.CharType();
|
|
|
+ 2999 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
+ 3000 qd)
|
|
|
+ 3001 ELSE
|
|
|
+ 3002 dt := SymTab.NewStr();
|
|
|
+ 3003 QbeGen.DeclStr(s, qd);
|
|
|
+ 3004 END;
|
|
|
+ 3005 dk := -1;
|
|
|
+ 3006 qn[0] := CHR(0); .)
|
|
|
+ 3007 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3008 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ 3009 uok);
|
|
|
+ 3010 isStr := FALSE;
|
|
|
+ 3011 IF NOT uok THEN
|
|
|
+ 3012 SemError(234);
|
|
|
+ 3013 dt := SymTab.InvalidType
|
|
|
+ 3014 ELSIF isU THEN
|
|
|
+ 3015 (* one codepoint: a UCHAR;
|
|
|
+ 3016 LEN is 1, HIGH is 0 *)
|
|
|
+ 3017 dt := SymTab.UCharType();
|
|
|
+ 3018 QbeGen.IntStr(ucp, qd)
|
|
|
+ 3019 ELSE
|
|
|
+ 3020 dt := SymTab.NewUStr();
|
|
|
+ 3021 END;
|
|
|
+ 3022 dk := -1;
|
|
|
+ 3023 qn[0] := CHR(0); .) )
|
|
|
+ 3024 ")"
|
|
|
+ 3025 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3026 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
+ 3027 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
+ 3028 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3029 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
+ 3030 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3031 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3032 IF (dt # SymTab.InvalidType)
|
|
|
+ 3033 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ 3034 (* UString: the count is
|
|
|
+ 3035 the descriptor header *)
|
|
|
+ 3036 t := SymTab.IntType();
|
|
|
+ 3037 QbeGen.CopyOp("@", q)
|
|
|
+ 3038 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 3039 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ 3040 (* single UCHAR codepoint *)
|
|
|
+ 3041 IF isHigh THEN
|
|
|
+ 3042 QbeGen.CopyOp("0", qr)
|
|
|
+ 3043 ELSE
|
|
|
+ 3044 QbeGen.CopyOp("1", qr)
|
|
|
+ 3045 END;
|
|
|
+ 3046 t := SymTab.IntType();
|
|
|
+ 3047 QbeGen.CopyOp(qr, q)
|
|
|
+ 3048 ELSIF isStr THEN
|
|
|
+ 3049 (* fold: content length at
|
|
|
+ 3050 compile time *)
|
|
|
+ 3051 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3052 c1 := 1
|
|
|
+ 3053 ELSE
|
|
|
+ 3054 c1 :=
|
|
|
+ 3055 SymTab.StrLen(s) - 2
|
|
|
3056 END;
|
|
|
- 3057 QbeGen.IntStr(c1, qr);
|
|
|
- 3058 t := SymTab.IntType();
|
|
|
- 3059 QbeGen.CopyOp(qr, q)
|
|
|
- 3060 ELSIF dt = SymTab.InvalidType THEN
|
|
|
- 3061 t := SymTab.InvalidType;
|
|
|
- 3062 QbeGen.CopyOp("0", q)
|
|
|
- 3063 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 3064 SymTab.ClArray THEN
|
|
|
- 3065 SemError(217);
|
|
|
- 3066 t := SymTab.InvalidType;
|
|
|
- 3067 QbeGen.CopyOp("0", q)
|
|
|
- 3068 ELSE
|
|
|
- 3069 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 3070 t := SymTab.IntType();
|
|
|
- 3071 QbeGen.CopyOp("@", q)
|
|
|
- 3072 ELSE
|
|
|
- 3073 IF isHigh THEN
|
|
|
- 3074 QbeGen.IntStr(
|
|
|
- 3075 SymTab.ArrayHi(dt), qr)
|
|
|
- 3076 ELSE
|
|
|
- 3077 QbeGen.IntStr(VAL(
|
|
|
- 3078 INTEGER,
|
|
|
- 3079 SymTab.ArrayLen(dt)),
|
|
|
- 3080 qr)
|
|
|
- 3081 END;
|
|
|
- 3082 t := SymTab.IntType();
|
|
|
- 3083 QbeGen.CopyOp(qr, q)
|
|
|
- 3084 END
|
|
|
- 3085 END; .)
|
|
|
- 3086 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3087 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3088 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
- 3089 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3090 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3091 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3092 t := SymTab.InvalidType;
|
|
|
- 3093 QbeGen.CopyOp("0", q)
|
|
|
- 3094 ELSE
|
|
|
- 3095 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 3096 SymTab.ObjectSize(dt)), q);
|
|
|
- 3097 t := SymTab.IntType()
|
|
|
- 3098 END; .)
|
|
|
- 3099 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
- 3100 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
- 3101 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
- 3102 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3103 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3104 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
- 3105 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3106 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
- 3107 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3108 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3109 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3110 (* set shift/rotate: isMax
|
|
|
- 3111 doubles as "rotate" *)
|
|
|
- 3112 IF (et # SymTab.InvalidType)
|
|
|
- 3113 AND (SymTab.ClassOf(et) =
|
|
|
- 3114 SymTab.ClSet) THEN
|
|
|
- 3115 t := et;
|
|
|
- 3116 QbeGen.CopyOp("@", q)
|
|
|
- 3117 ELSE SemError(230);
|
|
|
- 3118 t := SymTab.InvalidType;
|
|
|
- 3119 QbeGen.CopyOp("0", q)
|
|
|
- 3120 END; .)
|
|
|
- 3121 | ( "MIN" (. isMax := FALSE; .)
|
|
|
- 3122 | "MAX" (. isMax := TRUE; .) )
|
|
|
- 3123 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3124 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3125 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3126 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
- 3127 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3128 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
- 3129 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3130 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3131 IF (dt # SymTab.InvalidType)
|
|
|
- 3132 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
- 3133 (* REAL/LONGREAL: the
|
|
|
- 3134 implementation bounds *)
|
|
|
- 3135 IF isMax THEN
|
|
|
- 3136 QbeGen.NormReal(
|
|
|
- 3137 "3.402823e38", q)
|
|
|
- 3138 ELSE QbeGen.NormReal(
|
|
|
- 3139 "-3.402823e38", q)
|
|
|
- 3140 END;
|
|
|
- 3141 t := SymTab.RealType()
|
|
|
- 3142 ELSIF (dt #
|
|
|
- 3143 SymTab.InvalidType)
|
|
|
- 3144 AND (SymTab.ClassOf(dt) =
|
|
|
- 3145 SymTab.ClLong) THEN
|
|
|
- 3146 IF isMax THEN
|
|
|
- 3147 QbeGen.CopyOp(
|
|
|
- 3148 "9223372036854775807", q)
|
|
|
- 3149 ELSE QbeGen.CopyOp(
|
|
|
- 3150 "-9223372036854775808", q)
|
|
|
- 3151 END;
|
|
|
- 3152 t := SymTab.LongType()
|
|
|
- 3153 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
- 3154 hi) THEN
|
|
|
- 3155 IF isMax THEN
|
|
|
- 3156 QbeGen.IntStr(hi, q)
|
|
|
- 3157 ELSE QbeGen.IntStr(lo, q)
|
|
|
- 3158 END;
|
|
|
- 3159 t := SymTab.IntType()
|
|
|
- 3160 ELSE SemError(230);
|
|
|
- 3161 t := SymTab.InvalidType;
|
|
|
- 3162 QbeGen.CopyOp("0", q)
|
|
|
- 3163 END; .)
|
|
|
- 3164 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3165 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3166 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
- 3167 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3168 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3169 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3170 t := SymTab.InvalidType;
|
|
|
- 3171 QbeGen.CopyOp("0", q)
|
|
|
- 3172 ELSE
|
|
|
- 3173 IF sfx
|
|
|
- 3174 OR (dk = SymTab.KindVar)
|
|
|
- 3175 OR (dk = SymTab.KindParam) THEN
|
|
|
- 3176 QbeGen.CopyOp("@", q)
|
|
|
- 3177 ELSE SemError(230);
|
|
|
- 3178 QbeGen.CopyOp("0", q)
|
|
|
- 3179 END;
|
|
|
- 3180 t := SymTab.AddrType()
|
|
|
- 3181 END; .)
|
|
|
- 3182 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 3183 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3184 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
- 3185 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3186 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3187 (. IF (et # SymTab.InvalidType)
|
|
|
- 3188 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3189 SemError(211) END;
|
|
|
- 3190 t := SymTab.CharType(); .)
|
|
|
- 3191 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
- 3192 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3193 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
- 3194 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3195 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3196 (. IF et # SymTab.InvalidType THEN
|
|
|
- 3197 IF (SymTab.ClassOf(et) #
|
|
|
- 3198 SymTab.ClChar)
|
|
|
- 3199 AND (SymTab.ClassOf(et) #
|
|
|
- 3200 SymTab.ClBool)
|
|
|
- 3201 AND (SymTab.ClassOf(et) #
|
|
|
- 3202 SymTab.ClEnum)
|
|
|
- 3203 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3204 SemError(211) END
|
|
|
- 3205 END;
|
|
|
- 3206 t := SymTab.IntType(); .)
|
|
|
- 3207 | "CAP" "(" Expr<et, q> ")"
|
|
|
- 3208 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3209 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
- 3210 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3211 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3212 (. QbeGen.CopyOp("@", q);
|
|
|
- 3213 t := SymTab.CharType(); .)
|
|
|
- 3214 | "UCHR" "(" Expr<et, q> ")"
|
|
|
- 3215 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3216 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
- 3217 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3218 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3219 (. (* UCHR: the UCHAR constructor.
|
|
|
- 3220 CHAR -> UCHAR (identity);
|
|
|
- 3221 INTEGER familly -> UCHAR
|
|
|
- 3222 (codepoint value). *)
|
|
|
- 3223 IF (et # SymTab.InvalidType)
|
|
|
- 3224 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
- 3225 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3226 SemError(211) END;
|
|
|
- 3227 t := SymTab.UCharType(); .)
|
|
|
- 3228 | "CHR8" "(" Expr<et, q> ")"
|
|
|
- 3229 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3230 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
- 3231 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3232 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3233 (. IF (et # SymTab.InvalidType)
|
|
|
- 3234 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3235 SemError(211) END;
|
|
|
- 3236 t := SymTab.CharType(); .)
|
|
|
- 3237 | "UORD" "(" Expr<et, q> ")"
|
|
|
- 3238 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3239 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
- 3240 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3241 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3242 (. (* UORD(u): the codepoint as a
|
|
|
- 3243 32-bit ordinal (INTEGER),
|
|
|
- 3244 cf. ORD for CHAR. *)
|
|
|
- 3245 IF (et # SymTab.InvalidType)
|
|
|
- 3246 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3247 SemError(211) END;
|
|
|
- 3248 t := SymTab.IntType(); .)
|
|
|
- 3249 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 3250 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3251 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
- 3252 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3253 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3254 (. IF (et # SymTab.InvalidType)
|
|
|
- 3255 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 3256 AND (SymTab.ClassOf(et) #
|
|
|
- 3257 SymTab.ClReal) THEN
|
|
|
- 3258 SemError(211)
|
|
|
- 3259 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3260 END;
|
|
|
- 3261 t := et; .)
|
|
|
- 3262 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
- 3263 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3264 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3265 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3266 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3267 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3268 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 3269 SemError(201);
|
|
|
- 3270 t := SymTab.InvalidType
|
|
|
- 3271 ELSE vt := SymTab.SymType(vn);
|
|
|
- 3272 IF vt = SymTab.InvalidType THEN
|
|
|
- 3273 t := SymTab.InvalidType
|
|
|
- 3274 ELSIF et =
|
|
|
- 3275 SymTab.InvalidType THEN
|
|
|
- 3276 t := vt
|
|
|
- 3277 ELSE
|
|
|
- 3278 c1 := SymTab.ClassOf(et);
|
|
|
- 3279 c2 := SymTab.ClassOf(vt);
|
|
|
- 3280 IF (c1 = SymTab.ClInt)
|
|
|
- 3281 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3282 QbeGen.WidenLong(q, qa);
|
|
|
- 3283 QbeGen.CopyOp(qa, q);
|
|
|
- 3284 t := vt
|
|
|
- 3285 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3286 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3287 QbeGen.NarrowLong(q, qa);
|
|
|
- 3288 QbeGen.CopyOp(qa, q);
|
|
|
- 3289 t := vt
|
|
|
- 3290 ELSIF (c1 = SymTab.ClInt)
|
|
|
- 3291 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3292 QbeGen.ConvIR(q, qa);
|
|
|
- 3293 QbeGen.CopyOp(qa, q);
|
|
|
- 3294 t := vt
|
|
|
- 3295 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3296 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3297 QbeGen.ConvLR(q, qa);
|
|
|
- 3298 QbeGen.CopyOp(qa, q);
|
|
|
- 3299 t := vt
|
|
|
- 3300 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3301 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3302 QbeGen.ConvRI(q, qa);
|
|
|
- 3303 QbeGen.CopyOp(qa, q);
|
|
|
- 3304 t := vt
|
|
|
- 3305 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3306 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3307 QbeGen.ConvRL(q, qa);
|
|
|
- 3308 QbeGen.CopyOp(qa, q);
|
|
|
- 3309 t := vt
|
|
|
- 3310 ELSIF ((c1 = SymTab.ClInt)
|
|
|
- 3311 OR (c1 =
|
|
|
- 3312 SymTab.ClChar)
|
|
|
- 3313 OR (c1 =
|
|
|
- 3314 SymTab.ClBool)
|
|
|
- 3315 OR (c1 =
|
|
|
- 3316 SymTab.ClEnum))
|
|
|
- 3317 AND ((c2 = SymTab.ClInt)
|
|
|
- 3318 OR (c2 =
|
|
|
- 3319 SymTab.ClChar)
|
|
|
- 3320 OR (c2 =
|
|
|
- 3321 SymTab.ClBool)
|
|
|
- 3322 OR (c2 =
|
|
|
- 3323 SymTab.ClEnum)) THEN
|
|
|
- 3324 t := vt
|
|
|
- 3325 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 3326 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 3057 IF isHigh THEN
|
|
|
+ 3058 DEC(c1)
|
|
|
+ 3059 END;
|
|
|
+ 3060 QbeGen.IntStr(c1, qr);
|
|
|
+ 3061 t := SymTab.IntType();
|
|
|
+ 3062 QbeGen.CopyOp(qr, q)
|
|
|
+ 3063 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 3064 t := SymTab.InvalidType;
|
|
|
+ 3065 QbeGen.CopyOp("0", q)
|
|
|
+ 3066 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 3067 SymTab.ClArray THEN
|
|
|
+ 3068 SemError(217);
|
|
|
+ 3069 t := SymTab.InvalidType;
|
|
|
+ 3070 QbeGen.CopyOp("0", q)
|
|
|
+ 3071 ELSE
|
|
|
+ 3072 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 3073 t := SymTab.IntType();
|
|
|
+ 3074 QbeGen.CopyOp("@", q)
|
|
|
+ 3075 ELSE
|
|
|
+ 3076 IF isHigh THEN
|
|
|
+ 3077 QbeGen.IntStr(
|
|
|
+ 3078 SymTab.ArrayHi(dt), qr)
|
|
|
+ 3079 ELSE
|
|
|
+ 3080 QbeGen.IntStr(VAL(
|
|
|
+ 3081 INTEGER,
|
|
|
+ 3082 SymTab.ArrayLen(dt)),
|
|
|
+ 3083 qr)
|
|
|
+ 3084 END;
|
|
|
+ 3085 t := SymTab.IntType();
|
|
|
+ 3086 QbeGen.CopyOp(qr, q)
|
|
|
+ 3087 END
|
|
|
+ 3088 END; .)
|
|
|
+ 3089 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3090 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3091 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
+ 3092 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3093 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3094 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3095 t := SymTab.InvalidType;
|
|
|
+ 3096 QbeGen.CopyOp("0", q)
|
|
|
+ 3097 ELSE
|
|
|
+ 3098 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 3099 SymTab.ObjectSize(dt)), q);
|
|
|
+ 3100 t := SymTab.IntType()
|
|
|
+ 3101 END; .)
|
|
|
+ 3102 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
+ 3103 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
+ 3104 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
+ 3105 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3106 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3107 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
+ 3108 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3109 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
+ 3110 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3111 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3112 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3113 (* set shift/rotate: isMax
|
|
|
+ 3114 doubles as "rotate" *)
|
|
|
+ 3115 IF (et # SymTab.InvalidType)
|
|
|
+ 3116 AND (SymTab.ClassOf(et) =
|
|
|
+ 3117 SymTab.ClSet) THEN
|
|
|
+ 3118 t := et;
|
|
|
+ 3119 QbeGen.CopyOp("@", q)
|
|
|
+ 3120 ELSE SemError(230);
|
|
|
+ 3121 t := SymTab.InvalidType;
|
|
|
+ 3122 QbeGen.CopyOp("0", q)
|
|
|
+ 3123 END; .)
|
|
|
+ 3124 | ( "MIN" (. isMax := FALSE; .)
|
|
|
+ 3125 | "MAX" (. isMax := TRUE; .) )
|
|
|
+ 3126 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3127 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3128 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3129 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
+ 3130 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3131 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
+ 3132 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3133 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3134 IF (dt # SymTab.InvalidType)
|
|
|
+ 3135 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
+ 3136 (* REAL/LONGREAL: the
|
|
|
+ 3137 implementation bounds *)
|
|
|
+ 3138 IF isMax THEN
|
|
|
+ 3139 QbeGen.NormReal(
|
|
|
+ 3140 "3.402823e38", q)
|
|
|
+ 3141 ELSE QbeGen.NormReal(
|
|
|
+ 3142 "-3.402823e38", q)
|
|
|
+ 3143 END;
|
|
|
+ 3144 t := SymTab.RealType()
|
|
|
+ 3145 ELSIF (dt #
|
|
|
+ 3146 SymTab.InvalidType)
|
|
|
+ 3147 AND (SymTab.ClassOf(dt) =
|
|
|
+ 3148 SymTab.ClLong) THEN
|
|
|
+ 3149 IF isMax THEN
|
|
|
+ 3150 QbeGen.CopyOp(
|
|
|
+ 3151 "9223372036854775807", q)
|
|
|
+ 3152 ELSE QbeGen.CopyOp(
|
|
|
+ 3153 "-9223372036854775808", q)
|
|
|
+ 3154 END;
|
|
|
+ 3155 t := SymTab.LongType()
|
|
|
+ 3156 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
+ 3157 hi) THEN
|
|
|
+ 3158 IF isMax THEN
|
|
|
+ 3159 QbeGen.IntStr(hi, q)
|
|
|
+ 3160 ELSE QbeGen.IntStr(lo, q)
|
|
|
+ 3161 END;
|
|
|
+ 3162 t := SymTab.IntType()
|
|
|
+ 3163 ELSE SemError(230);
|
|
|
+ 3164 t := SymTab.InvalidType;
|
|
|
+ 3165 QbeGen.CopyOp("0", q)
|
|
|
+ 3166 END; .)
|
|
|
+ 3167 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3168 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3169 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
+ 3170 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3171 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3172 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3173 t := SymTab.InvalidType;
|
|
|
+ 3174 QbeGen.CopyOp("0", q)
|
|
|
+ 3175 ELSE
|
|
|
+ 3176 IF sfx
|
|
|
+ 3177 OR (dk = SymTab.KindVar)
|
|
|
+ 3178 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 3179 QbeGen.CopyOp("@", q)
|
|
|
+ 3180 ELSE SemError(230);
|
|
|
+ 3181 QbeGen.CopyOp("0", q)
|
|
|
+ 3182 END;
|
|
|
+ 3183 t := SymTab.AddrType()
|
|
|
+ 3184 END; .)
|
|
|
+ 3185 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 3186 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3187 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
+ 3188 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3189 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3190 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3191 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3192 SemError(211) END;
|
|
|
+ 3193 t := SymTab.CharType(); .)
|
|
|
+ 3194 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
+ 3195 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3196 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
+ 3197 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3198 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3199 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 3200 IF (SymTab.ClassOf(et) #
|
|
|
+ 3201 SymTab.ClChar)
|
|
|
+ 3202 AND (SymTab.ClassOf(et) #
|
|
|
+ 3203 SymTab.ClBool)
|
|
|
+ 3204 AND (SymTab.ClassOf(et) #
|
|
|
+ 3205 SymTab.ClEnum)
|
|
|
+ 3206 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3207 SemError(211) END
|
|
|
+ 3208 END;
|
|
|
+ 3209 t := SymTab.IntType(); .)
|
|
|
+ 3210 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 3211 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3212 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
+ 3213 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3214 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3215 (. QbeGen.CopyOp("@", q);
|
|
|
+ 3216 t := SymTab.CharType(); .)
|
|
|
+ 3217 | "UCHR" "(" Expr<et, q> ")"
|
|
|
+ 3218 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3219 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
+ 3220 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3221 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3222 (. (* UCHR: the UCHAR constructor.
|
|
|
+ 3223 CHAR -> UCHAR (identity);
|
|
|
+ 3224 INTEGER familly -> UCHAR
|
|
|
+ 3225 (codepoint value). *)
|
|
|
+ 3226 IF (et # SymTab.InvalidType)
|
|
|
+ 3227 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
+ 3228 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3229 SemError(211) END;
|
|
|
+ 3230 t := SymTab.UCharType(); .)
|
|
|
+ 3231 | "CHR8" "(" Expr<et, q> ")"
|
|
|
+ 3232 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3233 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
+ 3234 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3235 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3236 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3237 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3238 SemError(211) END;
|
|
|
+ 3239 t := SymTab.CharType(); .)
|
|
|
+ 3240 | "UORD" "(" Expr<et, q> ")"
|
|
|
+ 3241 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3242 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
+ 3243 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3244 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3245 (. (* UORD(u): the codepoint as a
|
|
|
+ 3246 32-bit ordinal (INTEGER),
|
|
|
+ 3247 cf. ORD for CHAR. *)
|
|
|
+ 3248 IF (et # SymTab.InvalidType)
|
|
|
+ 3249 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3250 SemError(211) END;
|
|
|
+ 3251 t := SymTab.IntType(); .)
|
|
|
+ 3252 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 3253 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3254 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
+ 3255 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3256 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3257 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3258 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 3259 AND (SymTab.ClassOf(et) #
|
|
|
+ 3260 SymTab.ClReal) THEN
|
|
|
+ 3261 SemError(211)
|
|
|
+ 3262 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3263 END;
|
|
|
+ 3264 t := et; .)
|
|
|
+ 3265 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
+ 3266 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3267 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3268 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3269 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3270 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3271 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 3272 SemError(201);
|
|
|
+ 3273 t := SymTab.InvalidType
|
|
|
+ 3274 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 3275 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3276 t := SymTab.InvalidType
|
|
|
+ 3277 ELSIF et =
|
|
|
+ 3278 SymTab.InvalidType THEN
|
|
|
+ 3279 t := vt
|
|
|
+ 3280 ELSE
|
|
|
+ 3281 c1 := SymTab.ClassOf(et);
|
|
|
+ 3282 c2 := SymTab.ClassOf(vt);
|
|
|
+ 3283 IF (c1 = SymTab.ClInt)
|
|
|
+ 3284 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3285 QbeGen.WidenLong(q, qa);
|
|
|
+ 3286 QbeGen.CopyOp(qa, q);
|
|
|
+ 3287 t := vt
|
|
|
+ 3288 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3289 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3290 QbeGen.NarrowLong(q, qa);
|
|
|
+ 3291 QbeGen.CopyOp(qa, q);
|
|
|
+ 3292 t := vt
|
|
|
+ 3293 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 3294 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3295 QbeGen.ConvIR(q, qa);
|
|
|
+ 3296 QbeGen.CopyOp(qa, q);
|
|
|
+ 3297 t := vt
|
|
|
+ 3298 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3299 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3300 QbeGen.ConvLR(q, qa);
|
|
|
+ 3301 QbeGen.CopyOp(qa, q);
|
|
|
+ 3302 t := vt
|
|
|
+ 3303 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3304 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3305 QbeGen.ConvRI(q, qa);
|
|
|
+ 3306 QbeGen.CopyOp(qa, q);
|
|
|
+ 3307 t := vt
|
|
|
+ 3308 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3309 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3310 QbeGen.ConvRL(q, qa);
|
|
|
+ 3311 QbeGen.CopyOp(qa, q);
|
|
|
+ 3312 t := vt
|
|
|
+ 3313 ELSIF ((c1 = SymTab.ClInt)
|
|
|
+ 3314 OR (c1 =
|
|
|
+ 3315 SymTab.ClChar)
|
|
|
+ 3316 OR (c1 =
|
|
|
+ 3317 SymTab.ClBool)
|
|
|
+ 3318 OR (c1 =
|
|
|
+ 3319 SymTab.ClEnum))
|
|
|
+ 3320 AND ((c2 = SymTab.ClInt)
|
|
|
+ 3321 OR (c2 =
|
|
|
+ 3322 SymTab.ClChar)
|
|
|
+ 3323 OR (c2 =
|
|
|
+ 3324 SymTab.ClBool)
|
|
|
+ 3325 OR (c2 =
|
|
|
+ 3326 SymTab.ClEnum)) THEN
|
|
|
3327 t := vt
|
|
|
- 3328 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3329 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3328 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 3329 AND (c2 = SymTab.ClPtr) THEN
|
|
|
3330 t := vt
|
|
|
- 3331 ELSE SemError(230);
|
|
|
- 3332 t := SymTab.InvalidType
|
|
|
- 3333 END
|
|
|
- 3334 END
|
|
|
- 3335 END; .)
|
|
|
- 3336 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
- 3337 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
- 3338 QbeGen.CopyOp(sq, q); .)
|
|
|
- 3339 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
- 3340 IF SymTab.BoolCheck(t2) THEN
|
|
|
- 3341 t := SymTab.BoolType()
|
|
|
- 3342 ELSE SemError(212);
|
|
|
- 3343 t := SymTab.InvalidType END;
|
|
|
- 3344 IF t # SymTab.InvalidType THEN
|
|
|
- 3345 QbeGen.CopyOp("@", q)
|
|
|
- 3346 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3347 END;
|
|
|
- 3348 astIsLit := TRUE;
|
|
|
- 3349 astCur := AST.MakeUn(
|
|
|
- 3350 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
- 3351 )
|
|
|
- 3352 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
- 3353 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3354 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 3355 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 3356 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 3357 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3358 (. VAR astNode: AST.Node; .)
|
|
|
- 3359 = "{" (. t := SymTab.NewSet(
|
|
|
- 3360 SymTab.NewSubR(0, 255));
|
|
|
- 3361 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
- 3362 QbeGen.NewSetTemp(8, q);
|
|
|
- 3363 QbeGen.SetZero(q, 8); .)
|
|
|
- 3364 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
- 3365 "}" (. astCur := astNode; .) .
|
|
|
- 3366 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
- 3367 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
- 3368 declared type sets the width (set) or element type (array). *)
|
|
|
- 3369 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3370 (. VAR nw: CARDINAL;
|
|
|
- 3371 astNode, astTail: AST.Node;
|
|
|
- 3372 savedCls: INTEGER; .)
|
|
|
- 3373 = "{" (. savedCls := braceCls;
|
|
|
- 3374 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
- 3375 AST.SetTy(astNode, vt);
|
|
|
- 3376 astTail := astNode;
|
|
|
- 3377 IF vt = SymTab.InvalidType THEN
|
|
|
- 3378 braceCls := -1
|
|
|
- 3379 ELSE braceCls :=
|
|
|
- 3380 SymTab.ClassOf(vt)
|
|
|
- 3381 END;
|
|
|
- 3382 IF braceCls = SymTab.ClSet THEN
|
|
|
- 3383 IF vt = SymTab.InvalidType THEN
|
|
|
- 3384 nw := 8
|
|
|
- 3385 ELSE nw := SymTab.SetWords(vt);
|
|
|
- 3386 IF nw = 0 THEN nw := 8 END
|
|
|
- 3387 END;
|
|
|
- 3388 QbeGen.NewSetTemp(nw, q);
|
|
|
- 3389 QbeGen.SetZero(q, nw)
|
|
|
- 3390 ELSIF (braceCls =
|
|
|
- 3391 SymTab.ClArray)
|
|
|
- 3392 OR (braceCls =
|
|
|
- 3393 SymTab.ClRecord)
|
|
|
- 3394 OR (braceCls =
|
|
|
- 3395 SymTab.ClClass) THEN
|
|
|
- 3396 QbeGen.CtorBegin(vt)
|
|
|
- 3397 ELSE
|
|
|
- 3398 IF vt # SymTab.InvalidType THEN
|
|
|
- 3399 SemError(230) END;
|
|
|
- 3400 braceCls := -1
|
|
|
- 3401 END; .)
|
|
|
- 3402 [ BraceElem<vt, q, astNode, astTail>
|
|
|
- 3403 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
- 3404 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
- 3405 OR (braceCls =
|
|
|
- 3406 SymTab.ClRecord)
|
|
|
- 3407 OR (braceCls =
|
|
|
- 3408 SymTab.ClClass) THEN
|
|
|
- 3409 QbeGen.CtorEnd(q)
|
|
|
- 3410 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
- 3411 QbeGen.CopyOp("0", q)
|
|
|
- 3412 END;
|
|
|
- 3413 braceCls := savedCls; .)
|
|
|
- 3414 (. astCur := astNode; .) .
|
|
|
- 3415 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
- 3416 VAR node, tail: AST.Node>
|
|
|
- 3417 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3418 qe, q2: QbeGen.QVal;
|
|
|
- 3419 v, v2, reps, k: INTEGER;
|
|
|
- 3420 elem: SymTab.TypeIndex;
|
|
|
- 3421 lo: INTEGER;
|
|
|
- 3422 span: CARDINAL;
|
|
|
- 3423 cl, cl2: INTEGER;
|
|
|
- 3424 hasR, hasB: BOOLEAN;
|
|
|
- 3425 astEl: AST.Node; .)
|
|
|
- 3426 = (. hasR := FALSE; hasB := FALSE;
|
|
|
- 3427 reps := 1; .)
|
|
|
- 3428 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3429 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3430 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3431 hasR := TRUE; .) ]
|
|
|
- 3432 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
- 3433 (. IF braceCls = SymTab.ClSet THEN
|
|
|
- 3434 IF hasB THEN SemError(230) END;
|
|
|
- 3435 lo := SymTab.SetBaseLo(vt);
|
|
|
- 3436 span := SymTab.SetCount(vt);
|
|
|
- 3437 IF (et = SymTab.InvalidType)
|
|
|
- 3438 OR (hasR AND (et2 =
|
|
|
- 3439 SymTab.InvalidType)) THEN
|
|
|
- 3440 ELSE cl :=
|
|
|
- 3441 SymTab.ClassOf(et);
|
|
|
- 3442 IF hasR THEN
|
|
|
- 3443 cl2 :=
|
|
|
- 3444 SymTab.ClassOf(et2)
|
|
|
- 3445 ELSE cl2 := SymTab.ClInt
|
|
|
- 3446 END;
|
|
|
- 3447 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3448 OR (hasR AND NOT
|
|
|
- 3449 SymTab.SetElemClassOk(cl2))
|
|
|
- 3450 THEN
|
|
|
- 3451 SemError(222)
|
|
|
- 3452 ELSIF hasR
|
|
|
- 3453 AND SymTab.ConstInt(qe, v)
|
|
|
- 3454 AND SymTab.ConstInt(q2,
|
|
|
- 3455 v2)
|
|
|
- 3456 AND ((v < lo)
|
|
|
- 3457 OR (v2 < lo)
|
|
|
- 3458 OR (v >= lo +
|
|
|
- 3459 VAL(INTEGER, span))
|
|
|
- 3460 OR (v2 >= lo +
|
|
|
- 3461 VAL(INTEGER, span))
|
|
|
- 3462 OR (v > v2)) THEN
|
|
|
- 3463 SemError(222)
|
|
|
- 3464 ELSIF hasR THEN
|
|
|
- 3465 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3466 lo, span)
|
|
|
- 3467 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3468 v)
|
|
|
- 3469 AND ((v < lo)
|
|
|
- 3470 OR (v >= lo +
|
|
|
- 3471 VAL(INTEGER,
|
|
|
- 3472 span))) THEN
|
|
|
- 3473 SemError(222)
|
|
|
- 3474 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3475 lo, span)
|
|
|
- 3476 END
|
|
|
- 3477 END
|
|
|
- 3478 ELSIF (braceCls = SymTab.ClArray)
|
|
|
- 3479 OR (braceCls =
|
|
|
- 3480 SymTab.ClRecord)
|
|
|
- 3481 OR (braceCls =
|
|
|
- 3482 SymTab.ClClass) THEN
|
|
|
- 3483 IF hasR THEN SemError(230) END;
|
|
|
- 3484 reps := 1;
|
|
|
- 3485 IF hasB THEN
|
|
|
- 3486 IF SymTab.ConstInt(q2, v2)
|
|
|
- 3487 AND (v2 >= 1) THEN
|
|
|
- 3488 reps := v2
|
|
|
- 3489 ELSE SemError(230)
|
|
|
- 3490 END
|
|
|
- 3491 END;
|
|
|
- 3492 k := 0;
|
|
|
- 3493 WHILE k < reps DO
|
|
|
- 3494 QbeGen.CtorElem(qe);
|
|
|
- 3495 INC(k)
|
|
|
- 3496 END
|
|
|
- 3497 END; .)
|
|
|
- 3498 (. (* the BY form repeats the
|
|
|
- 3499 element; keep the AST in
|
|
|
- 3500 step with CtorElem *)
|
|
|
- 3501 k := 0;
|
|
|
- 3502 WHILE k < reps DO
|
|
|
- 3503 AstAppend(AST.NkBlock,
|
|
|
- 3504 node, tail, astEl);
|
|
|
- 3505 INC(k)
|
|
|
- 3506 END; .) .
|
|
|
- 3507 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3508 qe, q2: QbeGen.QVal;
|
|
|
- 3509 v, v2: INTEGER;
|
|
|
- 3510 lo: INTEGER;
|
|
|
- 3511 span: CARDINAL;
|
|
|
- 3512 cl, cl2: INTEGER;
|
|
|
- 3513 hasR: BOOLEAN;
|
|
|
- 3514 astEl: AST.Node; .)
|
|
|
- 3515 = (. hasR := FALSE; .)
|
|
|
- 3516 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3517 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3518 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3519 hasR := TRUE; .) ]
|
|
|
- 3520 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 3521 span := SymTab.SetCount(st);
|
|
|
- 3522 IF (et = SymTab.InvalidType)
|
|
|
- 3523 OR (hasR AND (et2 =
|
|
|
- 3524 SymTab.InvalidType)) THEN
|
|
|
- 3525 ELSE cl :=
|
|
|
- 3526 SymTab.ClassOf(et);
|
|
|
- 3527 IF hasR THEN
|
|
|
- 3528 cl2 :=
|
|
|
- 3529 SymTab.ClassOf(et2)
|
|
|
- 3530 ELSE cl2 := SymTab.ClInt
|
|
|
- 3531 END;
|
|
|
- 3532 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3533 OR (hasR AND NOT
|
|
|
- 3534 SymTab.SetElemClassOk(cl2))
|
|
|
- 3535 THEN
|
|
|
- 3536 SemError(222)
|
|
|
- 3537 ELSIF hasR
|
|
|
- 3538 AND SymTab.ConstInt(qe, v)
|
|
|
- 3539 AND SymTab.ConstInt(q2,
|
|
|
- 3540 v2)
|
|
|
- 3541 AND ((v < lo)
|
|
|
- 3542 OR (v2 < lo)
|
|
|
- 3543 OR (v >= lo +
|
|
|
- 3544 VAL(INTEGER, span))
|
|
|
- 3545 OR (v2 >= lo +
|
|
|
- 3546 VAL(INTEGER, span))
|
|
|
- 3547 OR (v > v2)) THEN
|
|
|
- 3548 SemError(222)
|
|
|
- 3549 ELSIF hasR THEN
|
|
|
- 3550 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3551 lo, span)
|
|
|
- 3552 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3553 v)
|
|
|
- 3554 AND ((v < lo)
|
|
|
- 3555 OR (v >= lo +
|
|
|
- 3556 VAL(INTEGER,
|
|
|
- 3557 span))) THEN
|
|
|
- 3558 SemError(222)
|
|
|
- 3559 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3560 lo, span)
|
|
|
- 3561 END
|
|
|
- 3562 END; .)
|
|
|
- 3563 (. AST.SetChild(node,
|
|
|
- 3564 AST.NChild(node), astEl); .) .
|
|
|
- 3565 GetIdent<VAR n: SymTab.Name>
|
|
|
- 3566 = ident (. LexName(n); .) .
|
|
|
- 3567
|
|
|
- 3568 END M2.
|
|
|
+ 3331 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3332 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3333 t := vt
|
|
|
+ 3334 ELSE SemError(230);
|
|
|
+ 3335 t := SymTab.InvalidType
|
|
|
+ 3336 END
|
|
|
+ 3337 END
|
|
|
+ 3338 END; .)
|
|
|
+ 3339 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
+ 3340 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
+ 3341 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 3342 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
+ 3343 IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 3344 t := SymTab.BoolType()
|
|
|
+ 3345 ELSE SemError(212);
|
|
|
+ 3346 t := SymTab.InvalidType END;
|
|
|
+ 3347 IF t # SymTab.InvalidType THEN
|
|
|
+ 3348 QbeGen.CopyOp("@", q)
|
|
|
+ 3349 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3350 END;
|
|
|
+ 3351 astIsLit := TRUE;
|
|
|
+ 3352 astCur := AST.MakeUn(
|
|
|
+ 3353 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
+ 3354 )
|
|
|
+ 3355 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
+ 3356 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3357 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 3358 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 3359 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 3360 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3361 (. VAR astNode: AST.Node; .)
|
|
|
+ 3362 = "{" (. t := SymTab.NewSet(
|
|
|
+ 3363 SymTab.NewSubR(0, 255));
|
|
|
+ 3364 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
+ 3365 QbeGen.NewSetTemp(8, q);
|
|
|
+ 3366 QbeGen.SetZero(q, 8); .)
|
|
|
+ 3367 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
+ 3368 "}" (. astCur := astNode; .) .
|
|
|
+ 3369 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ 3370 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ 3371 declared type sets the width (set) or element type (array). *)
|
|
|
+ 3372 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3373 (. VAR nw: CARDINAL;
|
|
|
+ 3374 astNode, astTail: AST.Node;
|
|
|
+ 3375 savedCls: INTEGER; .)
|
|
|
+ 3376 = "{" (. savedCls := braceCls;
|
|
|
+ 3377 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
+ 3378 AST.SetTy(astNode, vt);
|
|
|
+ 3379 astTail := astNode;
|
|
|
+ 3380 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3381 braceCls := -1
|
|
|
+ 3382 ELSE braceCls :=
|
|
|
+ 3383 SymTab.ClassOf(vt)
|
|
|
+ 3384 END;
|
|
|
+ 3385 IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3386 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3387 nw := 8
|
|
|
+ 3388 ELSE nw := SymTab.SetWords(vt);
|
|
|
+ 3389 IF nw = 0 THEN nw := 8 END
|
|
|
+ 3390 END;
|
|
|
+ 3391 QbeGen.NewSetTemp(nw, q);
|
|
|
+ 3392 QbeGen.SetZero(q, nw)
|
|
|
+ 3393 ELSIF (braceCls =
|
|
|
+ 3394 SymTab.ClArray)
|
|
|
+ 3395 OR (braceCls =
|
|
|
+ 3396 SymTab.ClRecord)
|
|
|
+ 3397 OR (braceCls =
|
|
|
+ 3398 SymTab.ClClass) THEN
|
|
|
+ 3399 QbeGen.CtorBegin(vt)
|
|
|
+ 3400 ELSE
|
|
|
+ 3401 IF vt # SymTab.InvalidType THEN
|
|
|
+ 3402 SemError(230) END;
|
|
|
+ 3403 braceCls := -1
|
|
|
+ 3404 END; .)
|
|
|
+ 3405 [ BraceElem<vt, q, astNode, astTail>
|
|
|
+ 3406 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
+ 3407 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
+ 3408 OR (braceCls =
|
|
|
+ 3409 SymTab.ClRecord)
|
|
|
+ 3410 OR (braceCls =
|
|
|
+ 3411 SymTab.ClClass) THEN
|
|
|
+ 3412 QbeGen.CtorEnd(q)
|
|
|
+ 3413 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ 3414 QbeGen.CopyOp("0", q)
|
|
|
+ 3415 END;
|
|
|
+ 3416 braceCls := savedCls; .)
|
|
|
+ 3417 (. astCur := astNode; .) .
|
|
|
+ 3418 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
+ 3419 VAR node, tail: AST.Node>
|
|
|
+ 3420 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3421 qe, q2: QbeGen.QVal;
|
|
|
+ 3422 v, v2, reps, k: INTEGER;
|
|
|
+ 3423 elem: SymTab.TypeIndex;
|
|
|
+ 3424 lo: INTEGER;
|
|
|
+ 3425 span: CARDINAL;
|
|
|
+ 3426 cl, cl2: INTEGER;
|
|
|
+ 3427 hasR, hasB: BOOLEAN;
|
|
|
+ 3428 astEl: AST.Node; .)
|
|
|
+ 3429 = (. hasR := FALSE; hasB := FALSE;
|
|
|
+ 3430 reps := 1; .)
|
|
|
+ 3431 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3432 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3433 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3434 hasR := TRUE; .) ]
|
|
|
+ 3435 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ 3436 (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3437 IF hasB THEN SemError(230) END;
|
|
|
+ 3438 lo := SymTab.SetBaseLo(vt);
|
|
|
+ 3439 span := SymTab.SetCount(vt);
|
|
|
+ 3440 IF (et = SymTab.InvalidType)
|
|
|
+ 3441 OR (hasR AND (et2 =
|
|
|
+ 3442 SymTab.InvalidType)) THEN
|
|
|
+ 3443 ELSE cl :=
|
|
|
+ 3444 SymTab.ClassOf(et);
|
|
|
+ 3445 IF hasR THEN
|
|
|
+ 3446 cl2 :=
|
|
|
+ 3447 SymTab.ClassOf(et2)
|
|
|
+ 3448 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3449 END;
|
|
|
+ 3450 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3451 OR (hasR AND NOT
|
|
|
+ 3452 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3453 THEN
|
|
|
+ 3454 SemError(222)
|
|
|
+ 3455 ELSIF hasR
|
|
|
+ 3456 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3457 AND SymTab.ConstInt(q2,
|
|
|
+ 3458 v2)
|
|
|
+ 3459 AND ((v < lo)
|
|
|
+ 3460 OR (v2 < lo)
|
|
|
+ 3461 OR (v >= lo +
|
|
|
+ 3462 VAL(INTEGER, span))
|
|
|
+ 3463 OR (v2 >= lo +
|
|
|
+ 3464 VAL(INTEGER, span))
|
|
|
+ 3465 OR (v > v2)) THEN
|
|
|
+ 3466 SemError(222)
|
|
|
+ 3467 ELSIF hasR THEN
|
|
|
+ 3468 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3469 lo, span)
|
|
|
+ 3470 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3471 v)
|
|
|
+ 3472 AND ((v < lo)
|
|
|
+ 3473 OR (v >= lo +
|
|
|
+ 3474 VAL(INTEGER,
|
|
|
+ 3475 span))) THEN
|
|
|
+ 3476 SemError(222)
|
|
|
+ 3477 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3478 lo, span)
|
|
|
+ 3479 END
|
|
|
+ 3480 END
|
|
|
+ 3481 ELSIF (braceCls = SymTab.ClArray)
|
|
|
+ 3482 OR (braceCls =
|
|
|
+ 3483 SymTab.ClRecord)
|
|
|
+ 3484 OR (braceCls =
|
|
|
+ 3485 SymTab.ClClass) THEN
|
|
|
+ 3486 IF hasR THEN SemError(230) END;
|
|
|
+ 3487 reps := 1;
|
|
|
+ 3488 IF hasB THEN
|
|
|
+ 3489 IF SymTab.ConstInt(q2, v2)
|
|
|
+ 3490 AND (v2 >= 1) THEN
|
|
|
+ 3491 reps := v2
|
|
|
+ 3492 ELSE SemError(230)
|
|
|
+ 3493 END
|
|
|
+ 3494 END;
|
|
|
+ 3495 k := 0;
|
|
|
+ 3496 WHILE k < reps DO
|
|
|
+ 3497 QbeGen.CtorElem(qe);
|
|
|
+ 3498 INC(k)
|
|
|
+ 3499 END
|
|
|
+ 3500 END; .)
|
|
|
+ 3501 (. (* the BY form repeats the
|
|
|
+ 3502 element; keep the AST in
|
|
|
+ 3503 step with CtorElem *)
|
|
|
+ 3504 k := 0;
|
|
|
+ 3505 WHILE k < reps DO
|
|
|
+ 3506 AstAppend(AST.NkBlock,
|
|
|
+ 3507 node, tail, astEl);
|
|
|
+ 3508 INC(k)
|
|
|
+ 3509 END; .) .
|
|
|
+ 3510 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3511 qe, q2: QbeGen.QVal;
|
|
|
+ 3512 v, v2: INTEGER;
|
|
|
+ 3513 lo: INTEGER;
|
|
|
+ 3514 span: CARDINAL;
|
|
|
+ 3515 cl, cl2: INTEGER;
|
|
|
+ 3516 hasR: BOOLEAN;
|
|
|
+ 3517 astEl: AST.Node; .)
|
|
|
+ 3518 = (. hasR := FALSE; .)
|
|
|
+ 3519 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3520 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3521 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3522 hasR := TRUE; .) ]
|
|
|
+ 3523 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 3524 span := SymTab.SetCount(st);
|
|
|
+ 3525 IF (et = SymTab.InvalidType)
|
|
|
+ 3526 OR (hasR AND (et2 =
|
|
|
+ 3527 SymTab.InvalidType)) THEN
|
|
|
+ 3528 ELSE cl :=
|
|
|
+ 3529 SymTab.ClassOf(et);
|
|
|
+ 3530 IF hasR THEN
|
|
|
+ 3531 cl2 :=
|
|
|
+ 3532 SymTab.ClassOf(et2)
|
|
|
+ 3533 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3534 END;
|
|
|
+ 3535 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3536 OR (hasR AND NOT
|
|
|
+ 3537 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3538 THEN
|
|
|
+ 3539 SemError(222)
|
|
|
+ 3540 ELSIF hasR
|
|
|
+ 3541 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3542 AND SymTab.ConstInt(q2,
|
|
|
+ 3543 v2)
|
|
|
+ 3544 AND ((v < lo)
|
|
|
+ 3545 OR (v2 < lo)
|
|
|
+ 3546 OR (v >= lo +
|
|
|
+ 3547 VAL(INTEGER, span))
|
|
|
+ 3548 OR (v2 >= lo +
|
|
|
+ 3549 VAL(INTEGER, span))
|
|
|
+ 3550 OR (v > v2)) THEN
|
|
|
+ 3551 SemError(222)
|
|
|
+ 3552 ELSIF hasR THEN
|
|
|
+ 3553 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3554 lo, span)
|
|
|
+ 3555 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3556 v)
|
|
|
+ 3557 AND ((v < lo)
|
|
|
+ 3558 OR (v >= lo +
|
|
|
+ 3559 VAL(INTEGER,
|
|
|
+ 3560 span))) THEN
|
|
|
+ 3561 SemError(222)
|
|
|
+ 3562 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3563 lo, span)
|
|
|
+ 3564 END
|
|
|
+ 3565 END; .)
|
|
|
+ 3566 (. AST.SetChild(node,
|
|
|
+ 3567 AST.NChild(node), astEl); .) .
|
|
|
+ 3568 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 3569 = ident (. LexName(n); .) .
|
|
|
+ 3570
|
|
|
+ 3571 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|