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