|
|
@@ -94,2097 +94,2107 @@ Listing:
|
|
|
77 [ ( "E" | "e" ) [ "+" | "-" ] digit { digit } ] .
|
|
|
78 string = "'" { noQuote1 } "'"
|
|
|
79 | '"' { noQuote2 } '"' .
|
|
|
- 80
|
|
|
- 81 PRODUCTIONS
|
|
|
- 82 M2
|
|
|
- 83 = Unit "." .
|
|
|
- 84 (* Units: program modules compile fully; DEFINITION and
|
|
|
- 85 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
- 86 (each ends with one 230); same for nested local modules. *)
|
|
|
- 87 Unit
|
|
|
- 88 = DefUnit
|
|
|
- 89 | ImplUnit
|
|
|
- 90 | ProgModule .
|
|
|
- 91 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
- 92 and one program (last) into one image. Units share the symbol
|
|
|
- 93 table; imports materialize exported names. *)
|
|
|
- 94 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
- 95 = "DEFINITION" "MODULE"
|
|
|
- 96 GetIdent<m1> (. IF NOT SymTab.BeginDef(m1) THEN
|
|
|
- 97 SemError(200) END;
|
|
|
- 98 QbeGen.SetModule(m1); .)
|
|
|
- 99 ";"
|
|
|
- 100 { Import }
|
|
|
- 101 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
- 102 | ProcHeading<pn> ";" (. SymTab.CloseProc;
|
|
|
- 103 QbeGen.AbortFunc; .) }
|
|
|
- 104 "END"
|
|
|
- 105 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 106 SemError(202) END;
|
|
|
- 107 SymTab.EndUnit; .) .
|
|
|
- 108 ImplUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
- 109 = "IMPLEMENTATION" "MODULE"
|
|
|
- 110 GetIdent<m1> (. IF NOT SymTab.BeginImpl(m1) THEN
|
|
|
- 111 SemError(201) END;
|
|
|
- 112 QbeGen.SetModule(m1); .)
|
|
|
- 113 ";"
|
|
|
- 114 { Import }
|
|
|
- 115 DeclSeq
|
|
|
- 116 [ "BEGIN" (. QbeGen.BeginInit(m1); .)
|
|
|
- 117 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
- 118 "END"
|
|
|
- 119 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 120 SemError(202) END;
|
|
|
- 121 SymTab.EndUnit; .) .
|
|
|
- 122 ProgModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
- 123 = "MODULE"
|
|
|
- 124 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
- 125 SemError(200) END;
|
|
|
- 126 QbeGen.SetModule(m1); .)
|
|
|
- 127 [ Priority ]
|
|
|
- 128 ";"
|
|
|
- 129 { Import }
|
|
|
- 130 DeclSeq
|
|
|
- 131 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
- 132 [ StatSeq ] ]
|
|
|
- 133 "END"
|
|
|
- 134 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 135 SemError(202) END;
|
|
|
- 136 QbeGen.EndModule(m1);
|
|
|
- 137 SymTab.EndUnit; .) .
|
|
|
- 138 DeclSeq
|
|
|
- 139 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
- 140 | NestedModule ";" | ClassItem ";" } .
|
|
|
- 141 (* Local module, Wirth form. Parses + checks fully (own scope);
|
|
|
- 142 lowering waits for step 4, marked by one 230 at END. *)
|
|
|
- 143 NestedModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
- 144 = "MODULE"
|
|
|
- 145 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
- 146 SymTab.KindModule) THEN
|
|
|
- 147 SemError(200) END;
|
|
|
- 148 SymTab.PushScope; .)
|
|
|
- 149 [ Priority ]
|
|
|
- 150 ";"
|
|
|
- 151 { Import }
|
|
|
- 152 [ Export ]
|
|
|
- 153 DeclSeq
|
|
|
- 154 [ "BEGIN"
|
|
|
- 155 [ StatSeq ] ]
|
|
|
- 156 "END"
|
|
|
- 157 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
- 158 SemError(202) END;
|
|
|
- 159 SymTab.PopScope;
|
|
|
- 160 SemError(230); .) .
|
|
|
- 161 Priority
|
|
|
- 162 = "[" integer "]" (. SemError(230); .) .
|
|
|
- 163 Export (. VAR nm: SymTab.Name; .)
|
|
|
- 164 = "EXPORT" (* names wire up in step 4 *)
|
|
|
- 165 [ "QUALIFIED" ]
|
|
|
- 166 GetIdent<nm>
|
|
|
- 167 { "," GetIdent<nm> }
|
|
|
- 168 ";" .
|
|
|
- 169 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
- 170 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
- 171 materializes on first use (Design). *)
|
|
|
- 172 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
- 173 import lines don't fail); a known module's missing export is
|
|
|
- 174 201. *)
|
|
|
- 175 Import (. VAR n: SymTab.Name; .)
|
|
|
- 176 = "FROM"
|
|
|
- 177 GetIdent<n>
|
|
|
- 178 "IMPORT"
|
|
|
- 179 ImpList<n> ";"
|
|
|
- 180 | "IMPORT"
|
|
|
- 181 ImpModList ";" .
|
|
|
- 182 ImpList<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
- 183 = ImpName<mod>
|
|
|
- 184 { "," ImpName<mod> } .
|
|
|
- 185 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
- 186 accepted and ignored: the built-in applies regardless. *)
|
|
|
- 187 ImpName<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
- 188 = GetIdent<n> (. IF SymTab.ModKnown(mod)
|
|
|
- 189 AND NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
- 190 SemError(201) END; .)
|
|
|
- 191 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
- 192 | "CHR" | "ORD" | "VAL" | "ABS" | "INC" | "DEC" ) .
|
|
|
- 193 ImpModList (. VAR n: SymTab.Name; .)
|
|
|
- 194 = GetIdent<n>
|
|
|
- 195 { "," GetIdent<n> } .
|
|
|
- 196 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
- 197 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
- 198 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
- 199 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
- 200 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
- 201 TypeBlock<isDef: BOOLEAN>
|
|
|
- 202 = "TYPE" (. SymTab.BeginTypeBlock; .)
|
|
|
- 203 { TypeItem<isDef> ";" | ClassItem ";" }
|
|
|
- 204 (. SymTab.EndTypeBlock; .) .
|
|
|
- 205 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
- 206 t, op: SymTab.TypeIndex; .)
|
|
|
- 207 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
- 208 IF op = SymTab.InvalidType THEN
|
|
|
- 209 IF NOT SymTab.Enter(n,
|
|
|
- 210 SymTab.KindType) THEN
|
|
|
- 211 SemError(200) END
|
|
|
- 212 END; .)
|
|
|
- 213 ( "=" Type<t, FALSE> (. IF op # SymTab.InvalidType THEN
|
|
|
- 214 SymTab.SetTarget(op, t)
|
|
|
- 215 ELSE SymTab.SetSymType(n, t)
|
|
|
- 216 END; .)
|
|
|
- 217 | (. IF op # SymTab.InvalidType THEN
|
|
|
- 218 (* stays opaque *)
|
|
|
- 219 ELSIF NOT isDef THEN
|
|
|
- 220 SemError(231)
|
|
|
- 221 ELSE SymTab.SetSymType(n,
|
|
|
- 222 SymTab.NewAlias()) END; .) ) .
|
|
|
- 223 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 224 = TypeIdent<t>
|
|
|
- 225 | Subrange<t>
|
|
|
- 226 | Enum<t>
|
|
|
- 227 | ArrayType<t, allowOpen>
|
|
|
- 228 | SetType<t>
|
|
|
- 229 | RecordType<t>
|
|
|
- 230 | PointerType<t>
|
|
|
- 231 | ProcType<t> .
|
|
|
- 232 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
- 233 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
- 234 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
- 235 are code pointers; params are collected into the descriptor. *)
|
|
|
- 236 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
- 237 isV: BOOLEAN; .)
|
|
|
- 238 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
- 239 t := SymTab.NewProcType(res); .)
|
|
|
- 240 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
- 241 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
- 242 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
- 243 isV: BOOLEAN;
|
|
|
- 244 cnt, k: CARDINAL;
|
|
|
- 245 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
- 246 = (. isV := FALSE; cnt := 0; .)
|
|
|
- 247 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 248 GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
- 249 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
- 250 ( ":" Type<pt, FALSE> (. k := 0;
|
|
|
- 251 WHILE k < cnt DO
|
|
|
- 252 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
- 253 INC(k)
|
|
|
- 254 END; .)
|
|
|
- 255 | (. (* type-only parameter list:
|
|
|
- 256 each name is a type (GNU
|
|
|
- 257 shorthand used by the
|
|
|
- 258 Coco/R scanner frame) *)
|
|
|
- 259 k := 0;
|
|
|
- 260 WHILE k < cnt DO
|
|
|
- 261 IF SymTab.Lookup(names[k])
|
|
|
- 262 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
- 263 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
- 264 pt := SymTab.SymType(names[k])
|
|
|
- 265 ELSE SemError(201);
|
|
|
- 266 pt := SymTab.InvalidType
|
|
|
- 267 END;
|
|
|
- 268 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
- 269 INC(k)
|
|
|
- 270 END; .) ) .
|
|
|
- 271 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
- 272 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
- 273 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
- 274 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
- 275 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
- 276 (. VAR elem: SymTab.TypeIndex;
|
|
|
- 277 ok: BOOLEAN; .)
|
|
|
- 278 = "ARRAY"
|
|
|
- 279 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
- 280 SemError(230) END;
|
|
|
- 281 t := SymTab.NewOpenArray(elem); .)
|
|
|
- 282 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
- 283 BoundPair<ok>
|
|
|
- 284 { "," BoundPair<ok> }
|
|
|
- 285 "]" "OF" Type<elem, FALSE>
|
|
|
- 286 (. IF ok THEN
|
|
|
- 287 t := SymTab.NestArray(elem)
|
|
|
- 288 ELSE t := SymTab.InvalidType
|
|
|
- 289 END; .) ) .
|
|
|
- 290 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 291 qlo, qhi: QbeGen.QVal;
|
|
|
- 292 lo, hi: INTEGER;
|
|
|
- 293 cl, cl2: INTEGER; .)
|
|
|
- 294 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 295 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 296 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 297 ok := FALSE
|
|
|
- 298 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
- 299 cl2 := SymTab.ClassOf(thi);
|
|
|
- 300 IF ((cl # SymTab.ClInt)
|
|
|
- 301 AND (cl # SymTab.ClChar))
|
|
|
- 302 OR ((cl2 # SymTab.ClInt)
|
|
|
- 303 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
- 304 SemError(230); ok := FALSE
|
|
|
- 305 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 306 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 307 OR (lo > hi) THEN
|
|
|
- 308 SemError(230); ok := FALSE
|
|
|
- 309 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
- 310 SemError(230); ok := FALSE
|
|
|
- 311 END;
|
|
|
- 312 END; .) .
|
|
|
- 313 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
- 314 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
- 315 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
- 316 comparison across suitable bases are lenient (masks over min
|
|
|
- 317 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
- 318 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
- 319 blo, bhi, bspan: INTEGER;
|
|
|
- 320 bcls: INTEGER; .)
|
|
|
- 321 = "SET" "OF" Type<base, FALSE>
|
|
|
- 322 (. IF base = SymTab.InvalidType THEN
|
|
|
- 323 t := SymTab.InvalidType
|
|
|
- 324 ELSE bcls :=
|
|
|
- 325 SymTab.ClassOf(base);
|
|
|
- 326 IF bcls = SymTab.ClBool THEN
|
|
|
- 327 blo := 0; bspan := 2
|
|
|
- 328 ELSIF bcls = SymTab.ClChar THEN
|
|
|
- 329 blo := 0; bspan := 256
|
|
|
- 330 ELSIF SymTab.SubBounds(base,
|
|
|
- 331 blo, bhi) THEN
|
|
|
- 332 bspan := bhi - blo + 1
|
|
|
- 333 ELSE bspan := 0 END;
|
|
|
- 334 IF (bspan <= 0)
|
|
|
- 335 OR (bspan > 256) THEN
|
|
|
- 336 SemError(230);
|
|
|
- 337 t := SymTab.InvalidType
|
|
|
- 338 ELSE t := SymTab.NewSet(base)
|
|
|
- 339 END
|
|
|
- 340 END; .) .
|
|
|
- 341 (* Records: flat blobs; array fields are pointers to static
|
|
|
- 342 descriptors (locked amendment), nested records inline. Field
|
|
|
- 343 offsets static and declaration-ordered. *)
|
|
|
- 344 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex; .)
|
|
|
- 345 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
- 346 [ RecField<t> { ";" [ RecField<t> ] } ]
|
|
|
- 347 "END" .
|
|
|
- 348 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 349 t2: SymTab.TypeIndex; .)
|
|
|
- 350 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
- 351 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
- 352 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 353 n) THEN
|
|
|
- 354 SemError(200) END; .)
|
|
|
- 355 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 356 n) THEN
|
|
|
- 357 SemError(200) END; .) } .
|
|
|
- 358 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
- 359 k: INTEGER;
|
|
|
- 360 dotted: BOOLEAN; .)
|
|
|
- 361 = GetIdent<n> (. dotted := FALSE;
|
|
|
- 362 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 363 k := -1;
|
|
|
- 364 t := SymTab.ForwardType(n);
|
|
|
- 365 IF t = SymTab.InvalidType THEN
|
|
|
- 366 SemError(201)
|
|
|
- 367 END
|
|
|
- 368 ELSE k := SymTab.SymKind(n);
|
|
|
- 369 IF (k = SymTab.KindType)
|
|
|
- 370 OR (k = SymTab.KindPredef) THEN
|
|
|
- 371 t := SymTab.SymType(n)
|
|
|
- 372 ELSE t := SymTab.InvalidType
|
|
|
- 373 END
|
|
|
- 374 END; .)
|
|
|
- 375 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
- 376 IF k = SymTab.KindModule THEN
|
|
|
- 377 t := SymTab.QualType(n, qid);
|
|
|
- 378 IF t = SymTab.InvalidType THEN
|
|
|
- 379 SemError(201)
|
|
|
- 380 END
|
|
|
- 381 ELSE SemError(221);
|
|
|
- 382 t := SymTab.InvalidType
|
|
|
- 383 END; .) ]
|
|
|
- 384 (. IF NOT dotted THEN
|
|
|
- 385 IF (k = SymTab.KindModule)
|
|
|
- 386 OR ((k # SymTab.KindType)
|
|
|
- 387 AND (k # SymTab.KindPredef)
|
|
|
- 388 AND (k # SymTab.KindImport)
|
|
|
- 389 AND (k # -1)) THEN
|
|
|
- 390 SemError(221)
|
|
|
- 391 END
|
|
|
- 392 END; .) .
|
|
|
- 393 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 394 qlo, qhi: QbeGen.QVal;
|
|
|
- 395 lo, hi: INTEGER; .)
|
|
|
- 396 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 397 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 398 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 399 t := SymTab.InvalidType
|
|
|
- 400 ELSIF (SymTab.ClassOf(tlo) #
|
|
|
- 401 SymTab.ClInt)
|
|
|
- 402 OR (SymTab.ClassOf(thi) #
|
|
|
- 403 SymTab.ClInt) THEN
|
|
|
- 404 SemError(230);
|
|
|
- 405 t := SymTab.InvalidType
|
|
|
- 406 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 407 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 408 OR (lo > hi) THEN
|
|
|
- 409 SemError(230);
|
|
|
- 410 t := SymTab.InvalidType
|
|
|
- 411 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
- 412 END; .)
|
|
|
- 413 "]" .
|
|
|
- 414 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
- 415 = "(" (. t := SymTab.NewEnum(); .)
|
|
|
- 416 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 417 SymTab.KindConst) THEN
|
|
|
- 418 SemError(200) END;
|
|
|
- 419 SymTab.SetSymType(n, t); .)
|
|
|
- 420 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 421 SymTab.KindConst) THEN
|
|
|
- 422 SemError(200) END;
|
|
|
- 423 SymTab.SetSymType(n, t); .) }
|
|
|
- 424 ")" .
|
|
|
- 425 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
- 426 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
- 427 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
- 428 class/impl block. Methods end with ";" per the Table example
|
|
|
- 429 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
- 430 (* Single CLASS item in both loops: separating declaration from
|
|
|
- 431 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
- 432 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
- 433 The second token decides after CLASS is consumed. A misplaced
|
|
|
- 434 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
- 435 whole unit ends 230 until lowering). *)
|
|
|
- 436 ClassItem
|
|
|
- 437 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
- 438 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
- 439 ct: SymTab.TypeIndex; .)
|
|
|
- 440 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
- 441 SymTab.KindType) THEN
|
|
|
- 442 SemError(200) END;
|
|
|
- 443 ct := SymTab.NewClass();
|
|
|
- 444 SymTab.SetSymType(cn, ct);
|
|
|
- 445 SymTab.PushClassScope(ct); .)
|
|
|
- 446 [ Parents<ct> ]
|
|
|
- 447 ";"
|
|
|
- 448 { ClassField<ct> ";" }
|
|
|
- 449 { MethodHeading<pn> ";" (. SymTab.CloseProc;
|
|
|
- 450 QbeGen.AbortFunc; .) }
|
|
|
- 451 "END"
|
|
|
- 452 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 453 SemError(202) END;
|
|
|
- 454 SymTab.PopScope;
|
|
|
- 455 SemError(230); .) .
|
|
|
- 456 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
- 457 = "(" Parent1<ct>
|
|
|
- 458 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
- 459 ")" .
|
|
|
- 460 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
- 461 pt: SymTab.TypeIndex; .)
|
|
|
- 462 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
- 463 SemError(201)
|
|
|
- 464 ELSE pt := SymTab.SymType(p);
|
|
|
- 465 IF SymTab.ClassOf(pt) #
|
|
|
- 466 SymTab.ClClass THEN
|
|
|
- 467 SemError(230)
|
|
|
- 468 ELSE SymTab.SetParent(ct, pt)
|
|
|
- 469 END
|
|
|
- 470 END; .) .
|
|
|
- 471 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
- 472 t: SymTab.TypeIndex; .)
|
|
|
- 473 = GetIdent<n>
|
|
|
- 474 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
- 475 SymTab.KindConst) THEN
|
|
|
- 476 SemError(200) END;
|
|
|
- 477 IF SymTab.Lookup(rhs) THEN
|
|
|
- 478 SymTab.SetSymType(n,
|
|
|
- 479 SymTab.SymType(rhs))
|
|
|
- 480 END; .)
|
|
|
- 481 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 482 n) THEN
|
|
|
- 483 SemError(200) END; .)
|
|
|
- 484 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 485 n) THEN
|
|
|
- 486 SemError(200) END; .) }
|
|
|
- 487 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
- 488 MethodHeading<VAR pn: SymTab.Name> (. VAR wantVirt: BOOLEAN; .)
|
|
|
- 489 = (. wantVirt := FALSE; .)
|
|
|
- 490 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
- 491 ProcHeading<pn> (. IF wantVirt THEN
|
|
|
- 492 SymTab.MarkVirtual END; .) .
|
|
|
- 493 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
- 494 ct: SymTab.TypeIndex; .)
|
|
|
- 495 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
- 496 SemError(201);
|
|
|
- 497 ct := SymTab.InvalidType
|
|
|
- 498 ELSE ct := SymTab.SymType(cn);
|
|
|
- 499 IF SymTab.ClassOf(ct) #
|
|
|
- 500 SymTab.ClClass THEN
|
|
|
- 501 SemError(230);
|
|
|
- 502 ct := SymTab.InvalidType
|
|
|
- 503 END
|
|
|
- 504 END;
|
|
|
- 505 IF ct #
|
|
|
- 506 SymTab.InvalidType THEN
|
|
|
- 507 IF NOT SymTab.PushClassMembers(
|
|
|
- 508 ct) THEN
|
|
|
- 509 SemError(230) END
|
|
|
- 510 END; .)
|
|
|
- 511 ";" { MethodImpl<ct> ";" }
|
|
|
- 512 [ "BEGIN"
|
|
|
- 513 [ StatSeq ] ]
|
|
|
- 514 "END"
|
|
|
- 515 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 516 SemError(202) END;
|
|
|
- 517 SymTab.PopScope;
|
|
|
- 518 SemError(230); .) .
|
|
|
- 519 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name; .)
|
|
|
- 520 = (. QbeGen.SetNoEmit(TRUE); .)
|
|
|
- 521 MethodHeading<pn> ";"
|
|
|
- 522 (. IF (ct #
|
|
|
- 523 SymTab.InvalidType)
|
|
|
- 524 AND NOT SymTab.MethodExists(ct,
|
|
|
- 525 pn) THEN
|
|
|
- 526 SemError(201) END; .)
|
|
|
- 527 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
- 528 SymTab.CloseProc; .)
|
|
|
- 529 | Block<pn> (. SymTab.CloseProc; .) )
|
|
|
- 530 (. QbeGen.AbortFunc;
|
|
|
- 531 QbeGen.SetNoEmit(FALSE);
|
|
|
- 532 SemError(230); .) .
|
|
|
- 533 ConstBlock
|
|
|
- 534 = "CONST" { ConstDecl ";" } .
|
|
|
- 535 ConstDecl (. VAR n: SymTab.Name;
|
|
|
- 536 t: SymTab.TypeIndex;
|
|
|
- 537 qv: QbeGen.QVal;
|
|
|
- 538 cls: INTEGER; .)
|
|
|
- 539 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 540 SymTab.KindConst) THEN
|
|
|
- 541 SemError(200) END; .)
|
|
|
- 542 "="
|
|
|
- 543 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
- 544 cls := SymTab.ClassOf(t);
|
|
|
- 545 IF cls = SymTab.ClStr THEN
|
|
|
- 546 SemError(230)
|
|
|
- 547 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
- 548 SemError(230) END;
|
|
|
- 549 SymTab.SetSymVal(n, qv);
|
|
|
- 550 QbeGen.DeclConst(n, qv, t); .) .
|
|
|
- 551 VarBlock
|
|
|
- 552 = "VAR" { VarDecl ";" } .
|
|
|
- 553 VarDecl (. VAR nm: SymTab.Name;
|
|
|
- 554 t: SymTab.TypeIndex;
|
|
|
- 555 i: CARDINAL;
|
|
|
- 556 cls: INTEGER; .)
|
|
|
- 557 = VarIdents ":"
|
|
|
- 558 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
|
|
|
- 559 IF (t # SymTab.InvalidType)
|
|
|
- 560 AND (cls # SymTab.ClInt)
|
|
|
- 561 AND (cls # SymTab.ClBool)
|
|
|
- 562 AND (cls # SymTab.ClChar)
|
|
|
- 563 AND (cls # SymTab.ClReal)
|
|
|
- 564 AND (cls # SymTab.ClArray)
|
|
|
- 565 AND (cls # SymTab.ClSet)
|
|
|
- 566 AND (cls # SymTab.ClRecord)
|
|
|
- 567 AND (cls # SymTab.ClPtr)
|
|
|
- 568 AND (cls # SymTab.ClLong)
|
|
|
- 569 AND (cls # SymTab.ClProc) THEN
|
|
|
- 570 SemError(230) END;
|
|
|
- 571 IF QbeGen.LocFull() THEN
|
|
|
- 572 SemError(233) END;
|
|
|
- 573 i := 0;
|
|
|
- 574 WHILE i < SymTab.PendCount() DO
|
|
|
- 575 SymTab.PendName(i, nm);
|
|
|
- 576 QbeGen.DeclVar(nm, t);
|
|
|
- 577 INC(i)
|
|
|
- 578 END;
|
|
|
- 579 SymTab.FixPending(t); .) .
|
|
|
- 580 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 581 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 582 SymTab.KindVar) THEN
|
|
|
- 583 SemError(200) END; .)
|
|
|
- 584 { ","
|
|
|
- 585 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 586 SymTab.KindVar) THEN
|
|
|
- 587 SemError(200) END; .) } .
|
|
|
- 588 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 589 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 590 SemError(200) END; .)
|
|
|
- 591 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 592 SemError(200) END; .) } .
|
|
|
- 593 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
- 594 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
- 595 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 596 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
- 597 ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex;
|
|
|
- 598 mg: QbeGen.QVal; .)
|
|
|
- 599 = "PROCEDURE"
|
|
|
- 600 GetIdent<pn> (. IF NOT SymTab.EnterProc(pn) THEN
|
|
|
- 601 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
- 602 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
- 603 SemError(200) END
|
|
|
- 604 END
|
|
|
- 605 END;
|
|
|
- 606 QbeGen.Mangled(pn,
|
|
|
- 607 SymTab.ProcUid(pn), mg);
|
|
|
- 608 QbeGen.BeginFunc(mg); .)
|
|
|
- 609 [ FormalParams ]
|
|
|
- 610 [ ":" TypeIdent<t> (. SymTab.SetProcRes(t);
|
|
|
- 611 QbeGen.SetFuncRes(t);
|
|
|
- 612 IF (t #
|
|
|
- 613 SymTab.InvalidType)
|
|
|
- 614 AND ((SymTab.ClassOf(t)
|
|
|
- 615 = SymTab.ClArray)
|
|
|
- 616 OR (SymTab.ClassOf(t)
|
|
|
- 617 = SymTab.ClRecord)
|
|
|
+ 80 charConst = digit { digit } ( "C" | "c" ) .
|
|
|
+ 81
|
|
|
+ 82 PRODUCTIONS
|
|
|
+ 83 M2
|
|
|
+ 84 = Unit "." .
|
|
|
+ 85 (* Units: program modules compile fully; DEFINITION and
|
|
|
+ 86 IMPLEMENTATION modules parse + check now but lower in step 4
|
|
|
+ 87 (each ends with one 230); same for nested local modules. *)
|
|
|
+ 88 Unit
|
|
|
+ 89 = DefUnit
|
|
|
+ 90 | ImplUnit
|
|
|
+ 91 | ProgModule .
|
|
|
+ 92 (* Step 4.3: one session compiles DEFINITION, its IMPLEMENTATION
|
|
|
+ 93 and one program (last) into one image. Units share the symbol
|
|
|
+ 94 table; imports materialize exported names. *)
|
|
|
+ 95 DefUnit (. VAR m1, m2, pn: SymTab.Name; .)
|
|
|
+ 96 = "DEFINITION" "MODULE"
|
|
|
+ 97 GetIdent<m1> (. IF NOT SymTab.BeginDef(m1) THEN
|
|
|
+ 98 SemError(200) END;
|
|
|
+ 99 QbeGen.SetModule(m1); .)
|
|
|
+ 100 ";"
|
|
|
+ 101 { Import }
|
|
|
+ 102 { ConstBlock | TypeBlock<TRUE> | VarBlock
|
|
|
+ 103 | ProcHeading<pn> ";" (. SymTab.CloseProc;
|
|
|
+ 104 QbeGen.AbortFunc; .) }
|
|
|
+ 105 "END"
|
|
|
+ 106 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 107 SemError(202) END;
|
|
|
+ 108 SymTab.EndUnit; .) .
|
|
|
+ 109 ImplUnit (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ 110 = "IMPLEMENTATION" "MODULE"
|
|
|
+ 111 GetIdent<m1> (. IF NOT SymTab.BeginImpl(m1) THEN
|
|
|
+ 112 SemError(201) END;
|
|
|
+ 113 QbeGen.SetModule(m1); .)
|
|
|
+ 114 ";"
|
|
|
+ 115 { Import }
|
|
|
+ 116 DeclSeq
|
|
|
+ 117 [ "BEGIN" (. QbeGen.BeginInit(m1); .)
|
|
|
+ 118 [ StatSeq ] (. QbeGen.EndInit; .) ]
|
|
|
+ 119 "END"
|
|
|
+ 120 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 121 SemError(202) END;
|
|
|
+ 122 SymTab.EndUnit; .) .
|
|
|
+ 123 ProgModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ 124 = "MODULE"
|
|
|
+ 125 GetIdent<m1> (. IF NOT SymTab.BeginProg(m1) THEN
|
|
|
+ 126 SemError(200) END;
|
|
|
+ 127 QbeGen.SetModule(m1); .)
|
|
|
+ 128 [ Priority ]
|
|
|
+ 129 ";"
|
|
|
+ 130 { Import }
|
|
|
+ 131 DeclSeq
|
|
|
+ 132 [ "BEGIN" (. QbeGen.BeginBody; .)
|
|
|
+ 133 [ StatSeq ] ]
|
|
|
+ 134 "END"
|
|
|
+ 135 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 136 SemError(202) END;
|
|
|
+ 137 QbeGen.EndModule(m1);
|
|
|
+ 138 SymTab.EndUnit; .) .
|
|
|
+ 139 DeclSeq
|
|
|
+ 140 = { ConstBlock | TypeBlock<FALSE> | VarBlock | ProcDecl ";"
|
|
|
+ 141 | NestedModule ";" | ClassItem ";" } .
|
|
|
+ 142 (* Local module, Wirth form. Parses + checks fully (own scope);
|
|
|
+ 143 lowering waits for step 4, marked by one 230 at END. *)
|
|
|
+ 144 NestedModule (. VAR m1, m2: SymTab.Name; .)
|
|
|
+ 145 = "MODULE"
|
|
|
+ 146 GetIdent<m1> (. IF NOT SymTab.Enter(m1,
|
|
|
+ 147 SymTab.KindModule) THEN
|
|
|
+ 148 SemError(200) END;
|
|
|
+ 149 SymTab.PushScope; .)
|
|
|
+ 150 [ Priority ]
|
|
|
+ 151 ";"
|
|
|
+ 152 { Import }
|
|
|
+ 153 [ Export ]
|
|
|
+ 154 DeclSeq
|
|
|
+ 155 [ "BEGIN"
|
|
|
+ 156 [ StatSeq ] ]
|
|
|
+ 157 "END"
|
|
|
+ 158 GetIdent<m2> (. IF NOT SymTab.Equal(m1, m2) THEN
|
|
|
+ 159 SemError(202) END;
|
|
|
+ 160 SymTab.PopScope;
|
|
|
+ 161 SemError(230); .) .
|
|
|
+ 162 Priority
|
|
|
+ 163 = "[" integer "]" (. SemError(230); .) .
|
|
|
+ 164 Export (. VAR nm: SymTab.Name; .)
|
|
|
+ 165 = "EXPORT" (* names wire up in step 4 *)
|
|
|
+ 166 [ "QUALIFIED" ]
|
|
|
+ 167 GetIdent<nm>
|
|
|
+ 168 { "," GetIdent<nm> }
|
|
|
+ 169 ";" .
|
|
|
+ 170 (* Imports (4.3): FROM materializes the names (unqualified use);
|
|
|
+ 171 plain IMPORT only demands the module exists — qualified `L.x`
|
|
|
+ 172 materializes on first use (Design). *)
|
|
|
+ 173 (* Unknown modules stay unchecked stubs (legacy, so hand-written
|
|
|
+ 174 import lines don't fail); a known module's missing export is
|
|
|
+ 175 201. *)
|
|
|
+ 176 Import (. VAR n: SymTab.Name; .)
|
|
|
+ 177 = "FROM"
|
|
|
+ 178 GetIdent<n>
|
|
|
+ 179 "IMPORT"
|
|
|
+ 180 ImpList<n> ";"
|
|
|
+ 181 | "IMPORT"
|
|
|
+ 182 ImpModList ";" .
|
|
|
+ 183 ImpList<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
+ 184 = ImpName<mod>
|
|
|
+ 185 { "," ImpName<mod> } .
|
|
|
+ 186 (* Pervasive built-ins imported from SYSTEM (e.g. TSIZE) are
|
|
|
+ 187 accepted and ignored: the built-in applies regardless. *)
|
|
|
+ 188 ImpName<mod: SymTab.Name> (. VAR n: SymTab.Name; .)
|
|
|
+ 189 = GetIdent<n> (. IF SymTab.ModKnown(mod)
|
|
|
+ 190 AND NOT SymTab.ImportFrom(mod, n) THEN
|
|
|
+ 191 SemError(201) END; .)
|
|
|
+ 192 | ( "TSIZE" | "SIZE" | "ADR" | "HIGH" | "LEN"
|
|
|
+ 193 | "CHR" | "ORD" | "ORDL" | "VAL" | "ABS" | "CAP"
|
|
|
+ 194 | "INC" | "DEC" ) .
|
|
|
+ 195 ImpModList (. VAR n: SymTab.Name; .)
|
|
|
+ 196 = GetIdent<n>
|
|
|
+ 197 { "," GetIdent<n> } .
|
|
|
+ 198 (* Opaque TYPE declarations (definition modules). The targetless
|
|
|
+ 199 alias resolves to InvalidType until step 4 completes it. *)
|
|
|
+ 200 (* Scalar-phase TYPEs: named types, integer subranges, enumerations.
|
|
|
+ 201 Opaque "TYPE T;" needs isDef (definition units); elsewhere 231.
|
|
|
+ 202 Composite forms (ARRAY/RECORD/SET/POINTER) arrive with step 3. *)
|
|
|
+ 203 TypeBlock<isDef: BOOLEAN>
|
|
|
+ 204 = "TYPE" (. SymTab.BeginTypeBlock; .)
|
|
|
+ 205 { TypeItem<isDef> ";" | ClassItem ";" }
|
|
|
+ 206 (. SymTab.EndTypeBlock; .) .
|
|
|
+ 207 TypeItem<isDef: BOOLEAN> (. VAR n: SymTab.Name;
|
|
|
+ 208 t, op: SymTab.TypeIndex; .)
|
|
|
+ 209 = GetIdent<n> (. op := SymTab.OpaqueBase(n);
|
|
|
+ 210 IF op = SymTab.InvalidType THEN
|
|
|
+ 211 IF NOT SymTab.Enter(n,
|
|
|
+ 212 SymTab.KindType) THEN
|
|
|
+ 213 SemError(200) END
|
|
|
+ 214 END; .)
|
|
|
+ 215 ( "=" Type<t, FALSE> (. IF op # SymTab.InvalidType THEN
|
|
|
+ 216 SymTab.SetTarget(op, t)
|
|
|
+ 217 ELSE SymTab.SetSymType(n, t)
|
|
|
+ 218 END; .)
|
|
|
+ 219 | (. IF op # SymTab.InvalidType THEN
|
|
|
+ 220 (* stays opaque *)
|
|
|
+ 221 ELSIF NOT isDef THEN
|
|
|
+ 222 SemError(231)
|
|
|
+ 223 ELSE SymTab.SetSymType(n,
|
|
|
+ 224 SymTab.NewAlias()) END; .) ) .
|
|
|
+ 225 Type<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 226 = TypeIdent<t>
|
|
|
+ 227 | Subrange<t>
|
|
|
+ 228 | Enum<t>
|
|
|
+ 229 | ArrayType<t, allowOpen>
|
|
|
+ 230 | SetType<t>
|
|
|
+ 231 | RecordType<t>
|
|
|
+ 232 | PointerType<t>
|
|
|
+ 233 | ProcType<t> .
|
|
|
+ 234 PointerType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex; .)
|
|
|
+ 235 = "POINTER" "TO" Type<base, FALSE>(. t := SymTab.NewPtr(base); .) .
|
|
|
+ 236 (* Procedure types (step 8.5): PROCEDURE (params): result. Values
|
|
|
+ 237 are code pointers; params are collected into the descriptor. *)
|
|
|
+ 238 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
+ 239 isV: BOOLEAN; .)
|
|
|
+ 240 = "PROCEDURE" (. res := SymTab.InvalidType;
|
|
|
+ 241 t := SymTab.NewProcType(res); .)
|
|
|
+ 242 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
+ 243 [ ":" TypeIdent<res> (. SymTab.SetProcTypeRes(t, res); .) ] .
|
|
|
+ 244 ProcTypeSection<t: SymTab.TypeIndex> (. VAR pt: SymTab.TypeIndex;
|
|
|
+ 245 isV: BOOLEAN;
|
|
|
+ 246 cnt, k: CARDINAL;
|
|
|
+ 247 names: ARRAY [0 .. 15] OF SymTab.Name; .)
|
|
|
+ 248 = (. isV := FALSE; cnt := 0; .)
|
|
|
+ 249 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 250 GetIdent<names[cnt]> (. INC(cnt); .)
|
|
|
+ 251 { "," GetIdent<names[cnt]> (. INC(cnt); .) }
|
|
|
+ 252 ( ":" Type<pt, FALSE> (. k := 0;
|
|
|
+ 253 WHILE k < cnt DO
|
|
|
+ 254 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
+ 255 INC(k)
|
|
|
+ 256 END; .)
|
|
|
+ 257 | (. (* type-only parameter list:
|
|
|
+ 258 each name is a type (GNU
|
|
|
+ 259 shorthand used by the
|
|
|
+ 260 Coco/R scanner frame) *)
|
|
|
+ 261 k := 0;
|
|
|
+ 262 WHILE k < cnt DO
|
|
|
+ 263 IF SymTab.Lookup(names[k])
|
|
|
+ 264 AND ((SymTab.SymKind(names[k]) = SymTab.KindType)
|
|
|
+ 265 OR (SymTab.SymKind(names[k]) = SymTab.KindPredef)) THEN
|
|
|
+ 266 pt := SymTab.SymType(names[k])
|
|
|
+ 267 ELSE SemError(201);
|
|
|
+ 268 pt := SymTab.InvalidType
|
|
|
+ 269 END;
|
|
|
+ 270 SymTab.ProcTypeAdd(t, isV, pt);
|
|
|
+ 271 INC(k)
|
|
|
+ 272 END; .) ) .
|
|
|
+ 273 (* Arrays: "OF" without bounds is an open formal (allowed only
|
|
|
+ 274 where allowOpen); "[lo..hi, ...]" nests bounded levels inside
|
|
|
+ 275 out. Bounds are folded literals (int/char); anything else 230.
|
|
|
+ 276 Bare-type indices ("ARRAY Color OF") wait for enum ordinals. *)
|
|
|
+ 277 ArrayType<VAR t: SymTab.TypeIndex; allowOpen: BOOLEAN>
|
|
|
+ 278 (. VAR elem: SymTab.TypeIndex;
|
|
|
+ 279 ok: BOOLEAN; .)
|
|
|
+ 280 = "ARRAY"
|
|
|
+ 281 ( "OF" Type<elem, FALSE> (. IF NOT allowOpen THEN
|
|
|
+ 282 SemError(230) END;
|
|
|
+ 283 t := SymTab.NewOpenArray(elem); .)
|
|
|
+ 284 | "[" (. SymTab.BoundBegin; ok := TRUE; .)
|
|
|
+ 285 BoundPair<ok>
|
|
|
+ 286 { "," BoundPair<ok> }
|
|
|
+ 287 "]" "OF" Type<elem, FALSE>
|
|
|
+ 288 (. IF ok THEN
|
|
|
+ 289 t := SymTab.NestArray(elem)
|
|
|
+ 290 ELSE t := SymTab.InvalidType
|
|
|
+ 291 END; .) ) .
|
|
|
+ 292 BoundPair<VAR ok: BOOLEAN> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 293 qlo, qhi: QbeGen.QVal;
|
|
|
+ 294 lo, hi: INTEGER;
|
|
|
+ 295 cl, cl2: INTEGER; .)
|
|
|
+ 296 = Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 297 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 298 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 299 ok := FALSE
|
|
|
+ 300 ELSE cl := SymTab.ClassOf(tlo);
|
|
|
+ 301 cl2 := SymTab.ClassOf(thi);
|
|
|
+ 302 IF ((cl # SymTab.ClInt)
|
|
|
+ 303 AND (cl # SymTab.ClChar))
|
|
|
+ 304 OR ((cl2 # SymTab.ClInt)
|
|
|
+ 305 AND (cl2 # SymTab.ClChar)) THEN
|
|
|
+ 306 SemError(230); ok := FALSE
|
|
|
+ 307 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 308 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 309 OR (lo > hi) THEN
|
|
|
+ 310 SemError(230); ok := FALSE
|
|
|
+ 311 ELSIF NOT SymTab.BoundAdd(lo, hi) THEN
|
|
|
+ 312 SemError(230); ok := FALSE
|
|
|
+ 313 END;
|
|
|
+ 314 END; .) .
|
|
|
+ 315 (* Sets: multi-word masks over bases ≤ 256 values (bool, char,
|
|
|
+ 316 bounded subranges; enums wait for ordinals, INTEGER is
|
|
|
+ 317 unbounded). Literals are SET OF [0..255]; assignment and
|
|
|
+ 318 comparison across suitable bases are lenient (masks over min
|
|
|
+ 319 words + zero-check extras), out-of-span literals are 222. *)
|
|
|
+ 320 SetType<VAR t: SymTab.TypeIndex> (. VAR base: SymTab.TypeIndex;
|
|
|
+ 321 blo, bhi, bspan: INTEGER;
|
|
|
+ 322 bcls: INTEGER; .)
|
|
|
+ 323 = "SET" "OF" Type<base, FALSE>
|
|
|
+ 324 (. IF base = SymTab.InvalidType THEN
|
|
|
+ 325 t := SymTab.InvalidType
|
|
|
+ 326 ELSE bcls :=
|
|
|
+ 327 SymTab.ClassOf(base);
|
|
|
+ 328 IF bcls = SymTab.ClBool THEN
|
|
|
+ 329 blo := 0; bspan := 2
|
|
|
+ 330 ELSIF bcls = SymTab.ClChar THEN
|
|
|
+ 331 blo := 0; bspan := 256
|
|
|
+ 332 ELSIF SymTab.SubBounds(base,
|
|
|
+ 333 blo, bhi) THEN
|
|
|
+ 334 bspan := bhi - blo + 1
|
|
|
+ 335 ELSE bspan := 0 END;
|
|
|
+ 336 IF (bspan <= 0)
|
|
|
+ 337 OR (bspan > 256) THEN
|
|
|
+ 338 SemError(230);
|
|
|
+ 339 t := SymTab.InvalidType
|
|
|
+ 340 ELSE t := SymTab.NewSet(base)
|
|
|
+ 341 END
|
|
|
+ 342 END; .) .
|
|
|
+ 343 (* Records: flat blobs; array fields are pointers to static
|
|
|
+ 344 descriptors (locked amendment), nested records inline. Field
|
|
|
+ 345 offsets static and declaration-ordered. *)
|
|
|
+ 346 RecordType<VAR t: SymTab.TypeIndex> (. VAR t2: SymTab.TypeIndex; .)
|
|
|
+ 347 = "RECORD" (. t := SymTab.NewRecord(); .)
|
|
|
+ 348 [ RecField<t> { ";" [ RecField<t> ] } ]
|
|
|
+ 349 "END" .
|
|
|
+ 350 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 351 t2: SymTab.TypeIndex; .)
|
|
|
+ 352 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
+ 353 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ 354 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 355 n) THEN
|
|
|
+ 356 SemError(200) END; .)
|
|
|
+ 357 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 358 n) THEN
|
|
|
+ 359 SemError(200) END; .) } .
|
|
|
+ 360 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
+ 361 k: INTEGER;
|
|
|
+ 362 dotted: BOOLEAN; .)
|
|
|
+ 363 = GetIdent<n> (. dotted := FALSE;
|
|
|
+ 364 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 365 k := -1;
|
|
|
+ 366 t := SymTab.ForwardType(n);
|
|
|
+ 367 IF t = SymTab.InvalidType THEN
|
|
|
+ 368 SemError(201)
|
|
|
+ 369 END
|
|
|
+ 370 ELSE k := SymTab.SymKind(n);
|
|
|
+ 371 IF (k = SymTab.KindType)
|
|
|
+ 372 OR (k = SymTab.KindPredef) THEN
|
|
|
+ 373 t := SymTab.SymType(n)
|
|
|
+ 374 ELSE t := SymTab.InvalidType
|
|
|
+ 375 END
|
|
|
+ 376 END; .)
|
|
|
+ 377 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
+ 378 IF k = SymTab.KindModule THEN
|
|
|
+ 379 t := SymTab.QualType(n, qid);
|
|
|
+ 380 IF t = SymTab.InvalidType THEN
|
|
|
+ 381 SemError(201)
|
|
|
+ 382 END
|
|
|
+ 383 ELSE SemError(221);
|
|
|
+ 384 t := SymTab.InvalidType
|
|
|
+ 385 END; .) ]
|
|
|
+ 386 (. IF NOT dotted THEN
|
|
|
+ 387 IF (k = SymTab.KindModule)
|
|
|
+ 388 OR ((k # SymTab.KindType)
|
|
|
+ 389 AND (k # SymTab.KindPredef)
|
|
|
+ 390 AND (k # SymTab.KindImport)
|
|
|
+ 391 AND (k # -1)) THEN
|
|
|
+ 392 SemError(221)
|
|
|
+ 393 END
|
|
|
+ 394 END; .) .
|
|
|
+ 395 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 396 qlo, qhi: QbeGen.QVal;
|
|
|
+ 397 lo, hi: INTEGER; .)
|
|
|
+ 398 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 399 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 400 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 401 t := SymTab.InvalidType
|
|
|
+ 402 ELSIF (SymTab.ClassOf(tlo) #
|
|
|
+ 403 SymTab.ClInt)
|
|
|
+ 404 OR (SymTab.ClassOf(thi) #
|
|
|
+ 405 SymTab.ClInt) THEN
|
|
|
+ 406 SemError(230);
|
|
|
+ 407 t := SymTab.InvalidType
|
|
|
+ 408 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 409 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 410 OR (lo > hi) THEN
|
|
|
+ 411 SemError(230);
|
|
|
+ 412 t := SymTab.InvalidType
|
|
|
+ 413 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
+ 414 END; .)
|
|
|
+ 415 "]" .
|
|
|
+ 416 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ 417 = "(" (. t := SymTab.NewEnum(); .)
|
|
|
+ 418 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 419 SymTab.KindConst) THEN
|
|
|
+ 420 SemError(200) END;
|
|
|
+ 421 SymTab.SetSymType(n, t); .)
|
|
|
+ 422 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 423 SymTab.KindConst) THEN
|
|
|
+ 424 SemError(200) END;
|
|
|
+ 425 SymTab.SetSymType(n, t); .) }
|
|
|
+ 426 ")" .
|
|
|
+ 427 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
+ 428 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
+ 429 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
+ 430 class/impl block. Methods end with ";" per the Table example
|
|
|
+ 431 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
+ 432 (* Single CLASS item in both loops: separating declaration from
|
|
|
+ 433 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
+ 434 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
+ 435 The second token decides after CLASS is consumed. A misplaced
|
|
|
+ 436 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
+ 437 whole unit ends 230 until lowering). *)
|
|
|
+ 438 ClassItem
|
|
|
+ 439 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
+ 440 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
+ 441 ct: SymTab.TypeIndex; .)
|
|
|
+ 442 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
+ 443 SymTab.KindType) THEN
|
|
|
+ 444 SemError(200) END;
|
|
|
+ 445 ct := SymTab.NewClass();
|
|
|
+ 446 SymTab.SetSymType(cn, ct);
|
|
|
+ 447 SymTab.PushClassScope(ct); .)
|
|
|
+ 448 [ Parents<ct> ]
|
|
|
+ 449 ";"
|
|
|
+ 450 { ClassField<ct> ";" }
|
|
|
+ 451 { MethodHeading<pn> ";" (. SymTab.CloseProc;
|
|
|
+ 452 QbeGen.AbortFunc; .) }
|
|
|
+ 453 "END"
|
|
|
+ 454 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 455 SemError(202) END;
|
|
|
+ 456 SymTab.PopScope;
|
|
|
+ 457 SemError(230); .) .
|
|
|
+ 458 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
+ 459 = "(" Parent1<ct>
|
|
|
+ 460 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
+ 461 ")" .
|
|
|
+ 462 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
+ 463 pt: SymTab.TypeIndex; .)
|
|
|
+ 464 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
+ 465 SemError(201)
|
|
|
+ 466 ELSE pt := SymTab.SymType(p);
|
|
|
+ 467 IF SymTab.ClassOf(pt) #
|
|
|
+ 468 SymTab.ClClass THEN
|
|
|
+ 469 SemError(230)
|
|
|
+ 470 ELSE SymTab.SetParent(ct, pt)
|
|
|
+ 471 END
|
|
|
+ 472 END; .) .
|
|
|
+ 473 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
+ 474 t: SymTab.TypeIndex; .)
|
|
|
+ 475 = GetIdent<n>
|
|
|
+ 476 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
+ 477 SymTab.KindConst) THEN
|
|
|
+ 478 SemError(200) END;
|
|
|
+ 479 IF SymTab.Lookup(rhs) THEN
|
|
|
+ 480 SymTab.SetSymType(n,
|
|
|
+ 481 SymTab.SymType(rhs))
|
|
|
+ 482 END; .)
|
|
|
+ 483 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 484 n) THEN
|
|
|
+ 485 SemError(200) END; .)
|
|
|
+ 486 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 487 n) THEN
|
|
|
+ 488 SemError(200) END; .) }
|
|
|
+ 489 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t); .) ) .
|
|
|
+ 490 MethodHeading<VAR pn: SymTab.Name> (. VAR wantVirt: BOOLEAN; .)
|
|
|
+ 491 = (. wantVirt := FALSE; .)
|
|
|
+ 492 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
+ 493 ProcHeading<pn> (. IF wantVirt THEN
|
|
|
+ 494 SymTab.MarkVirtual END; .) .
|
|
|
+ 495 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
+ 496 ct: SymTab.TypeIndex; .)
|
|
|
+ 497 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
+ 498 SemError(201);
|
|
|
+ 499 ct := SymTab.InvalidType
|
|
|
+ 500 ELSE ct := SymTab.SymType(cn);
|
|
|
+ 501 IF SymTab.ClassOf(ct) #
|
|
|
+ 502 SymTab.ClClass THEN
|
|
|
+ 503 SemError(230);
|
|
|
+ 504 ct := SymTab.InvalidType
|
|
|
+ 505 END
|
|
|
+ 506 END;
|
|
|
+ 507 IF ct #
|
|
|
+ 508 SymTab.InvalidType THEN
|
|
|
+ 509 IF NOT SymTab.PushClassMembers(
|
|
|
+ 510 ct) THEN
|
|
|
+ 511 SemError(230) END
|
|
|
+ 512 END; .)
|
|
|
+ 513 ";" { MethodImpl<ct> ";" }
|
|
|
+ 514 [ "BEGIN"
|
|
|
+ 515 [ StatSeq ] ]
|
|
|
+ 516 "END"
|
|
|
+ 517 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 518 SemError(202) END;
|
|
|
+ 519 SymTab.PopScope;
|
|
|
+ 520 SemError(230); .) .
|
|
|
+ 521 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name; .)
|
|
|
+ 522 = (. QbeGen.SetNoEmit(TRUE); .)
|
|
|
+ 523 MethodHeading<pn> ";"
|
|
|
+ 524 (. IF (ct #
|
|
|
+ 525 SymTab.InvalidType)
|
|
|
+ 526 AND NOT SymTab.MethodExists(ct,
|
|
|
+ 527 pn) THEN
|
|
|
+ 528 SemError(201) END; .)
|
|
|
+ 529 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
+ 530 SymTab.CloseProc; .)
|
|
|
+ 531 | Block<pn> (. SymTab.CloseProc; .) )
|
|
|
+ 532 (. QbeGen.AbortFunc;
|
|
|
+ 533 QbeGen.SetNoEmit(FALSE);
|
|
|
+ 534 SemError(230); .) .
|
|
|
+ 535 ConstBlock
|
|
|
+ 536 = "CONST" { ConstDecl ";" } .
|
|
|
+ 537 ConstDecl (. VAR n: SymTab.Name;
|
|
|
+ 538 t: SymTab.TypeIndex;
|
|
|
+ 539 qv: QbeGen.QVal;
|
|
|
+ 540 cls: INTEGER; .)
|
|
|
+ 541 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 542 SymTab.KindConst) THEN
|
|
|
+ 543 SemError(200) END; .)
|
|
|
+ 544 "="
|
|
|
+ 545 Expr<t, qv> (. SymTab.SetSymType(n, t);
|
|
|
+ 546 cls := SymTab.ClassOf(t);
|
|
|
+ 547 IF cls = SymTab.ClStr THEN
|
|
|
+ 548 SemError(230)
|
|
|
+ 549 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
+ 550 SemError(230) END;
|
|
|
+ 551 SymTab.SetSymVal(n, qv);
|
|
|
+ 552 QbeGen.DeclConst(n, qv, t); .) .
|
|
|
+ 553 VarBlock
|
|
|
+ 554 = "VAR" { VarDecl ";" } .
|
|
|
+ 555 VarDecl (. VAR nm: SymTab.Name;
|
|
|
+ 556 t: SymTab.TypeIndex;
|
|
|
+ 557 i: CARDINAL;
|
|
|
+ 558 cls: INTEGER; .)
|
|
|
+ 559 = VarIdents ":"
|
|
|
+ 560 Type<t, FALSE> (. cls := SymTab.ClassOf(t);
|
|
|
+ 561 IF (t # SymTab.InvalidType)
|
|
|
+ 562 AND (cls # SymTab.ClInt)
|
|
|
+ 563 AND (cls # SymTab.ClBool)
|
|
|
+ 564 AND (cls # SymTab.ClChar)
|
|
|
+ 565 AND (cls # SymTab.ClReal)
|
|
|
+ 566 AND (cls # SymTab.ClArray)
|
|
|
+ 567 AND (cls # SymTab.ClSet)
|
|
|
+ 568 AND (cls # SymTab.ClRecord)
|
|
|
+ 569 AND (cls # SymTab.ClPtr)
|
|
|
+ 570 AND (cls # SymTab.ClLong)
|
|
|
+ 571 AND (cls # SymTab.ClProc) THEN
|
|
|
+ 572 SemError(230) END;
|
|
|
+ 573 IF QbeGen.LocFull() THEN
|
|
|
+ 574 SemError(233) END;
|
|
|
+ 575 i := 0;
|
|
|
+ 576 WHILE i < SymTab.PendCount() DO
|
|
|
+ 577 SymTab.PendName(i, nm);
|
|
|
+ 578 QbeGen.DeclVar(nm, t);
|
|
|
+ 579 INC(i)
|
|
|
+ 580 END;
|
|
|
+ 581 SymTab.FixPending(t); .) .
|
|
|
+ 582 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 583 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 584 SymTab.KindVar) THEN
|
|
|
+ 585 SemError(200) END; .)
|
|
|
+ 586 { ","
|
|
|
+ 587 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 588 SymTab.KindVar) THEN
|
|
|
+ 589 SemError(200) END; .) } .
|
|
|
+ 590 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 591 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 592 SemError(200) END; .)
|
|
|
+ 593 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 594 SemError(200) END; .) } .
|
|
|
+ 595 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
+ 596 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
+ 597 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 598 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
+ 599 ProcHeading<VAR pn: SymTab.Name> (. VAR t: SymTab.TypeIndex;
|
|
|
+ 600 mg: QbeGen.QVal; .)
|
|
|
+ 601 = "PROCEDURE"
|
|
|
+ 602 GetIdent<pn> (. IF NOT SymTab.EnterProc(pn) THEN
|
|
|
+ 603 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
+ 604 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
+ 605 SemError(200) END
|
|
|
+ 606 END
|
|
|
+ 607 END;
|
|
|
+ 608 QbeGen.Mangled(pn,
|
|
|
+ 609 SymTab.ProcUid(pn), mg);
|
|
|
+ 610 QbeGen.BeginFunc(mg); .)
|
|
|
+ 611 [ FormalParams ]
|
|
|
+ 612 [ ":" TypeIdent<t> (. SymTab.SetProcRes(t);
|
|
|
+ 613 QbeGen.SetFuncRes(t);
|
|
|
+ 614 IF (t #
|
|
|
+ 615 SymTab.InvalidType)
|
|
|
+ 616 AND ((SymTab.ClassOf(t)
|
|
|
+ 617 = SymTab.ClArray)
|
|
|
618 OR (SymTab.ClassOf(t)
|
|
|
- 619 = SymTab.ClSet)
|
|
|
+ 619 = SymTab.ClRecord)
|
|
|
620 OR (SymTab.ClassOf(t)
|
|
|
- 621 = SymTab.ClClass)) THEN
|
|
|
- 622 SemError(230) END; .) ] .
|
|
|
- 623 FormalParams
|
|
|
- 624 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 625 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 626 nm: SymTab.Name;
|
|
|
- 627 i: CARDINAL;
|
|
|
- 628 isV: BOOLEAN; .)
|
|
|
- 629 = (. isV := FALSE; .)
|
|
|
- 630 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 631 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
- 632 WHILE i < SymTab.PendCount() DO
|
|
|
- 633 SymTab.PendName(i, nm);
|
|
|
- 634 (* value open arrays are
|
|
|
- 635 passed as descriptor
|
|
|
- 636 addresses (no copy):
|
|
|
- 637 same representation as
|
|
|
- 638 VAR formals *)
|
|
|
- 639 IF NOT QbeGen.FuncParam(nm,
|
|
|
- 640 isV
|
|
|
- 641 OR SymTab.IsOpenArray(t),
|
|
|
- 642 t) THEN
|
|
|
- 643 SemError(233) END;
|
|
|
- 644 INC(i)
|
|
|
- 645 END;
|
|
|
- 646 SymTab.FixPending(t); .) .
|
|
|
- 647 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
- 648 static link gives them their parent's frame. Methods keep
|
|
|
- 649 parse-now/230-later. *)
|
|
|
- 650 ProcDecl (. VAR pn: SymTab.Name; .)
|
|
|
- 651 = ProcHeading<pn> ";"
|
|
|
- 652 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
- 653 SymTab.CloseProc;
|
|
|
- 654 QbeGen.AbortFunc; .)
|
|
|
- 655 | "EXTERNAL" (. SymTab.MarkExternal("");
|
|
|
- 656 SymTab.CloseProc;
|
|
|
- 657 QbeGen.AbortFunc; .)
|
|
|
- 658 | (. QbeGen.EndFuncHeader; .)
|
|
|
- 659 Block<pn> (. SymTab.CloseProc;
|
|
|
- 660 QbeGen.EndFunc(
|
|
|
- 661 SymTab.ProcRes(pn)); .) ) .
|
|
|
- 662 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
- 663 = DeclSeq
|
|
|
- 664 [ "BEGIN"
|
|
|
- 665 [ StatSeq ] ]
|
|
|
- 666 "END"
|
|
|
- 667 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
- 668 SemError(202) END; .) .
|
|
|
- 669 StatSeq
|
|
|
- 670 = Statement { ";" [ Statement ] } .
|
|
|
- 671 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
- 672 are accepted: the statement after ';' is optional. *)
|
|
|
- 673 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
- 674 = AssOrCall
|
|
|
- 675 | IfStat
|
|
|
- 676 | WhileStat
|
|
|
- 677 | RepeatStat
|
|
|
- 678 | LoopStat
|
|
|
- 679 | ForStat
|
|
|
- 680 | CaseStat
|
|
|
- 681 | WithStat
|
|
|
- 682 | ReturnStat
|
|
|
- 683 | NewStat
|
|
|
- 684 | DisposeStat
|
|
|
- 685 | IncDecStat
|
|
|
- 686 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
- 687 QbeGen.Jmp(lx)
|
|
|
- 688 ELSE SemError(230) END; .) .
|
|
|
- 689 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
- 690 integer designator. *)
|
|
|
- 691 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
- 692 dk: INTEGER;
|
|
|
- 693 qd, qv, qn2, qstep:
|
|
|
- 694 QbeGen.QVal;
|
|
|
- 695 qn: SymTab.Name;
|
|
|
- 696 sfx, isInc: BOOLEAN; .)
|
|
|
- 697 = (. isInc := TRUE; .)
|
|
|
- 698 ( "INC" (. isInc := TRUE; .)
|
|
|
- 699 | "DEC" (. isInc := FALSE; .) )
|
|
|
- 700 "(" (. QbeGen.CopyOp("1", qstep); .)
|
|
|
- 701 Design<dt, dk, qd, qn, sfx>
|
|
|
- 702 [ "," Expr<et2, qstep> ]
|
|
|
- 703 ")" (. IF dt = SymTab.InvalidType THEN
|
|
|
- 704 ELSIF (dk # SymTab.KindVar)
|
|
|
- 705 AND (dk # SymTab.KindParam)
|
|
|
- 706 AND (dk # SymTab.KindField) THEN
|
|
|
- 707 SemError(210)
|
|
|
- 708 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
- 709 SemError(211)
|
|
|
- 710 ELSE
|
|
|
- 711 IF sfx
|
|
|
- 712 OR (dk = SymTab.KindField) THEN
|
|
|
- 713 QbeGen.ElemLoad(qd, dt, qv)
|
|
|
- 714 ELSE QbeGen.LoadVar(qn,
|
|
|
- 715 FALSE, qv)
|
|
|
- 716 END;
|
|
|
- 717 QbeGen.NewTemp(qn2);
|
|
|
- 718 IF isInc THEN
|
|
|
- 719 QbeGen.Op3("add", qn2, qv,
|
|
|
- 720 qstep, FALSE)
|
|
|
- 721 ELSE QbeGen.Op3("sub", qn2, qv,
|
|
|
+ 621 = SymTab.ClSet)
|
|
|
+ 622 OR (SymTab.ClassOf(t)
|
|
|
+ 623 = SymTab.ClClass)) THEN
|
|
|
+ 624 SemError(230) END; .) ] .
|
|
|
+ 625 FormalParams
|
|
|
+ 626 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 627 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 628 nm: SymTab.Name;
|
|
|
+ 629 i: CARDINAL;
|
|
|
+ 630 isV: BOOLEAN; .)
|
|
|
+ 631 = (. isV := FALSE; .)
|
|
|
+ 632 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 633 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
+ 634 WHILE i < SymTab.PendCount() DO
|
|
|
+ 635 SymTab.PendName(i, nm);
|
|
|
+ 636 (* value open arrays are
|
|
|
+ 637 passed as descriptor
|
|
|
+ 638 addresses (no copy):
|
|
|
+ 639 same representation as
|
|
|
+ 640 VAR formals *)
|
|
|
+ 641 IF NOT QbeGen.FuncParam(nm,
|
|
|
+ 642 isV
|
|
|
+ 643 OR SymTab.IsOpenArray(t),
|
|
|
+ 644 t) THEN
|
|
|
+ 645 SemError(233) END;
|
|
|
+ 646 INC(i)
|
|
|
+ 647 END;
|
|
|
+ 648 SymTab.FixPending(t); .) .
|
|
|
+ 649 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
+ 650 static link gives them their parent's frame. Methods keep
|
|
|
+ 651 parse-now/230-later. *)
|
|
|
+ 652 ProcDecl (. VAR pn: SymTab.Name; .)
|
|
|
+ 653 = ProcHeading<pn> ";"
|
|
|
+ 654 ( "FORWARD" (. SymTab.MarkFwd;
|
|
|
+ 655 SymTab.CloseProc;
|
|
|
+ 656 QbeGen.AbortFunc; .)
|
|
|
+ 657 | "EXTERNAL" (. SymTab.MarkExternal("");
|
|
|
+ 658 SymTab.CloseProc;
|
|
|
+ 659 QbeGen.AbortFunc; .)
|
|
|
+ 660 | (. QbeGen.EndFuncHeader; .)
|
|
|
+ 661 Block<pn> (. SymTab.CloseProc;
|
|
|
+ 662 QbeGen.EndFunc(
|
|
|
+ 663 SymTab.ProcRes(pn)); .) ) .
|
|
|
+ 664 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
+ 665 = DeclSeq
|
|
|
+ 666 [ "BEGIN"
|
|
|
+ 667 [ StatSeq ] ]
|
|
|
+ 668 "END"
|
|
|
+ 669 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
+ 670 SemError(202) END; .) .
|
|
|
+ 671 StatSeq
|
|
|
+ 672 = Statement { ";" [ Statement ] } .
|
|
|
+ 673 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
+ 674 are accepted: the statement after ';' is optional. *)
|
|
|
+ 675 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
+ 676 = AssOrCall
|
|
|
+ 677 | IfStat
|
|
|
+ 678 | WhileStat
|
|
|
+ 679 | RepeatStat
|
|
|
+ 680 | LoopStat
|
|
|
+ 681 | ForStat
|
|
|
+ 682 | CaseStat
|
|
|
+ 683 | WithStat
|
|
|
+ 684 | ReturnStat
|
|
|
+ 685 | NewStat
|
|
|
+ 686 | DisposeStat
|
|
|
+ 687 | IncDecStat
|
|
|
+ 688 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
+ 689 QbeGen.Jmp(lx)
|
|
|
+ 690 ELSE SemError(230) END; .) .
|
|
|
+ 691 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
+ 692 integer designator. *)
|
|
|
+ 693 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
+ 694 dk: INTEGER;
|
|
|
+ 695 qd, qv, qn2, qstep:
|
|
|
+ 696 QbeGen.QVal;
|
|
|
+ 697 qn: SymTab.Name;
|
|
|
+ 698 sfx, isInc: BOOLEAN; .)
|
|
|
+ 699 = (. isInc := TRUE; .)
|
|
|
+ 700 ( "INC" (. isInc := TRUE; .)
|
|
|
+ 701 | "DEC" (. isInc := FALSE; .) )
|
|
|
+ 702 "(" (. QbeGen.CopyOp("1", qstep); .)
|
|
|
+ 703 Design<dt, dk, qd, qn, sfx>
|
|
|
+ 704 [ "," Expr<et2, qstep> ]
|
|
|
+ 705 ")" (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 706 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 707 AND (dk # SymTab.KindParam)
|
|
|
+ 708 AND (dk # SymTab.KindField) THEN
|
|
|
+ 709 SemError(210)
|
|
|
+ 710 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
+ 711 SemError(211)
|
|
|
+ 712 ELSE
|
|
|
+ 713 IF sfx
|
|
|
+ 714 OR (dk = SymTab.KindField) THEN
|
|
|
+ 715 QbeGen.ElemLoad(qd, dt, qv)
|
|
|
+ 716 ELSE QbeGen.LoadVar(qn,
|
|
|
+ 717 FALSE, qv)
|
|
|
+ 718 END;
|
|
|
+ 719 QbeGen.NewTemp(qn2);
|
|
|
+ 720 IF isInc THEN
|
|
|
+ 721 QbeGen.Op3("add", qn2, qv,
|
|
|
722 qstep, FALSE)
|
|
|
- 723 END;
|
|
|
- 724 IF sfx
|
|
|
- 725 OR (dk = SymTab.KindField) THEN
|
|
|
- 726 QbeGen.ElemStore(qd, qn2,
|
|
|
- 727 dt)
|
|
|
- 728 ELSE QbeGen.StoreVar(qn,
|
|
|
- 729 qn2, FALSE)
|
|
|
- 730 END
|
|
|
- 731 END; .) .
|
|
|
- 732 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
- 733 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
- 734 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
- 735 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 736 dk: INTEGER;
|
|
|
- 737 qd, qm: QbeGen.QVal;
|
|
|
- 738 qn: SymTab.Name;
|
|
|
- 739 sfx: BOOLEAN;
|
|
|
- 740 bt: SymTab.TypeIndex; .)
|
|
|
- 741 = "NEW" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 742 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 743 ELSIF (dk # SymTab.KindVar)
|
|
|
- 744 AND (dk # SymTab.KindParam)
|
|
|
- 745 AND (dk # SymTab.KindField) THEN
|
|
|
- 746 SemError(210)
|
|
|
- 747 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 748 SymTab.ClPtr THEN
|
|
|
- 749 SemError(219)
|
|
|
- 750 ELSE bt := SymTab.PtrBase(dt);
|
|
|
- 751 IF bt #
|
|
|
- 752 SymTab.InvalidType THEN
|
|
|
- 753 QbeGen.NewHeap(bt, qm);
|
|
|
- 754 QbeGen.InitHeap(qm, bt);
|
|
|
- 755 IF sfx
|
|
|
- 756 OR (dk =
|
|
|
- 757 SymTab.KindField) THEN
|
|
|
- 758 QbeGen.ElemStore(qd, qm,
|
|
|
- 759 dt)
|
|
|
- 760 ELSE QbeGen.StorePtr(qn,
|
|
|
- 761 qm)
|
|
|
- 762 END
|
|
|
- 763 END
|
|
|
- 764 END; .) .
|
|
|
- 765 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 766 dk: INTEGER;
|
|
|
- 767 qd, qv: QbeGen.QVal;
|
|
|
- 768 qn: SymTab.Name;
|
|
|
- 769 sfx: BOOLEAN; .)
|
|
|
- 770 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 771 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 772 ELSIF (dk # SymTab.KindVar)
|
|
|
- 773 AND (dk # SymTab.KindParam)
|
|
|
- 774 AND (dk # SymTab.KindField) THEN
|
|
|
- 775 SemError(210)
|
|
|
- 776 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 777 SymTab.ClPtr THEN
|
|
|
- 778 SemError(219)
|
|
|
- 779 ELSE
|
|
|
- 780 IF sfx
|
|
|
- 781 OR (dk =
|
|
|
- 782 SymTab.KindField) THEN
|
|
|
- 783 QbeGen.ElemLoad(qd, dt,
|
|
|
- 784 qv)
|
|
|
- 785 ELSE QbeGen.LoadPtr(qn, qv)
|
|
|
- 786 END;
|
|
|
- 787 QbeGen.FreeHeap(qv);
|
|
|
- 788 IF sfx
|
|
|
- 789 OR (dk =
|
|
|
- 790 SymTab.KindField) THEN
|
|
|
- 791 QbeGen.ElemStore(qd, "0",
|
|
|
- 792 dt)
|
|
|
- 793 ELSE QbeGen.StorePtr(qn,
|
|
|
- 794 "0")
|
|
|
- 795 END
|
|
|
- 796 END; .) .
|
|
|
- 797 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
- 798 address; field designators resolve through both stacks. *)
|
|
|
- 799 WithStat (. VAR nW: CARDINAL; .)
|
|
|
- 800 = "WITH" (. nW := 0; .)
|
|
|
- 801 WithItem<nW> { "," WithItem<nW> }
|
|
|
- 802 "DO" StatSeq "END"
|
|
|
- 803 (. WHILE nW > 0 DO
|
|
|
- 804 SymTab.PopScope;
|
|
|
- 805 QbeGen.PopWith;
|
|
|
- 806 DEC(nW)
|
|
|
- 807 END; .) .
|
|
|
- 808 WithItem<VAR nW: CARDINAL> (. VAR dt: SymTab.TypeIndex;
|
|
|
- 809 dk: INTEGER;
|
|
|
- 810 qd, qe: QbeGen.QVal;
|
|
|
- 811 qn: SymTab.Name;
|
|
|
- 812 sfx: BOOLEAN; .)
|
|
|
- 813 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 814 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 815 ELSIF (SymTab.ClassOf(dt) #
|
|
|
- 816 SymTab.ClRecord)
|
|
|
- 817 AND (SymTab.ClassOf(dt) #
|
|
|
- 818 SymTab.ClClass) THEN
|
|
|
- 819 SemError(215)
|
|
|
- 820 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
- 821 QbeGen.PushWith(qd);
|
|
|
- 822 INC(nW)
|
|
|
- 823 END; .) .
|
|
|
- 824 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
- 825 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
- 826 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 827 dk: INTEGER;
|
|
|
- 828 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
- 829 qn: SymTab.Name;
|
|
|
- 830 ct2, res0: SymTab.TypeIndex;
|
|
|
- 831 q2, mg0: QbeGen.QVal;
|
|
|
- 832 isR, conv, wconv: BOOLEAN;
|
|
|
- 833 called, sfx: BOOLEAN; .)
|
|
|
- 834 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 835 ( ":="
|
|
|
- 836 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
- 837 AND (dk # SymTab.KindVar)
|
|
|
- 838 AND (dk # SymTab.KindParam)
|
|
|
- 839 AND (dk # SymTab.KindField) THEN
|
|
|
- 840 SemError(210)
|
|
|
- 841 ELSIF NOT SymTab.Assignable(et,
|
|
|
- 842 dt) THEN
|
|
|
- 843 SemError(210)
|
|
|
- 844 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 845 AND (SymTab.ClassOf(dt) =
|
|
|
- 846 SymTab.ClClass) THEN
|
|
|
- 847 SemError(230) END;
|
|
|
- 848 isR := (dt #
|
|
|
- 849 SymTab.InvalidType)
|
|
|
- 850 AND (SymTab.ClassOf(dt)
|
|
|
- 851 = SymTab.ClReal);
|
|
|
- 852 conv := isR
|
|
|
- 853 AND SymTab.IsIntFamily(et);
|
|
|
- 854 wconv := (dt #
|
|
|
- 855 SymTab.InvalidType)
|
|
|
- 856 AND SymTab.IsLongFamily(dt)
|
|
|
- 857 AND SymTab.IsIntFamily(et);
|
|
|
- 858 IF ((dk = SymTab.KindVar)
|
|
|
- 859 OR (dk = SymTab.KindParam)
|
|
|
- 860 OR (dk = SymTab.KindField))
|
|
|
- 861 AND (dt # SymTab.InvalidType)
|
|
|
- 862 AND (et # SymTab.InvalidType)
|
|
|
- 863 AND (SymTab.ClassOf(dt) #
|
|
|
- 864 SymTab.ClClass) THEN
|
|
|
- 865 IF sfx
|
|
|
- 866 OR (dk = SymTab.KindField) THEN
|
|
|
- 867 IF SymTab.ClassOf(dt) =
|
|
|
- 868 SymTab.ClArray THEN
|
|
|
- 869 QbeGen.CopyArray(qd, qe,
|
|
|
- 870 dt)
|
|
|
- 871 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 872 SymTab.ClSet THEN
|
|
|
- 873 QbeGen.CopySet(qd, qe,
|
|
|
- 874 SymTab.SetWords(dt),
|
|
|
- 875 SymTab.SetWords(et))
|
|
|
- 876 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 877 SymTab.ClRecord THEN
|
|
|
- 878 QbeGen.CopyRecord(qd, qe,
|
|
|
- 879 dt)
|
|
|
- 880 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
- 881 IF wconv THEN
|
|
|
- 882 QbeGen.WidenLong(qe, ql);
|
|
|
- 883 QbeGen.ElemStore(qd, ql,
|
|
|
- 884 dt)
|
|
|
- 885 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
- 886 dt)
|
|
|
- 887 END
|
|
|
- 888 ELSIF conv THEN
|
|
|
- 889 QbeGen.ConvIR(qe, qt);
|
|
|
- 890 QbeGen.ElemStore(qd, qt,
|
|
|
- 891 dt)
|
|
|
- 892 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
- 893 dt)
|
|
|
- 894 END
|
|
|
- 895 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 896 SymTab.ClArray THEN
|
|
|
- 897 QbeGen.CopyArray(qd, qe, dt)
|
|
|
- 898 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 899 SymTab.ClSet THEN
|
|
|
- 900 QbeGen.CopySet(qd, qe,
|
|
|
- 901 SymTab.SetWords(dt),
|
|
|
- 902 SymTab.SetWords(et))
|
|
|
- 903 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 904 SymTab.ClRecord THEN
|
|
|
- 905 QbeGen.CopyRecord(qd, qe, dt)
|
|
|
- 906 ELSIF (SymTab.ClassOf(dt) =
|
|
|
- 907 SymTab.ClPtr)
|
|
|
- 908 OR (SymTab.ClassOf(dt) =
|
|
|
- 909 SymTab.ClProc) THEN
|
|
|
- 910 QbeGen.StorePtr(qn, qe)
|
|
|
- 911 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
- 912 IF wconv THEN
|
|
|
- 913 QbeGen.WidenLong(qe, ql);
|
|
|
- 914 QbeGen.StoreLong(qn, ql)
|
|
|
- 915 ELSE QbeGen.StoreLong(qn, qe)
|
|
|
- 916 END
|
|
|
- 917 ELSIF conv THEN
|
|
|
- 918 QbeGen.ConvIR(qe, qt);
|
|
|
- 919 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
- 920 ELSE
|
|
|
- 921 QbeGen.StoreVar(qn, qe, isR)
|
|
|
- 922 END
|
|
|
- 923 END; .)
|
|
|
- 924 | ArgList<qn, dt, qd, FALSE, ct2, q2, called>
|
|
|
- 925 | (* bare `P;`: proper parameterless
|
|
|
- 926 procedure call; anything else
|
|
|
- 927 here is 233 (was a bare syntax
|
|
|
- 928 error before 4.2) *)
|
|
|
- 929 (. IF (dk = SymTab.KindProc)
|
|
|
- 930 AND NOT sfx THEN
|
|
|
- 931 res0 := SymTab.ProcRes(qn);
|
|
|
- 932 IF res0 #
|
|
|
- 933 SymTab.InvalidType THEN
|
|
|
- 934 SemError(233)
|
|
|
- 935 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 936 0 THEN
|
|
|
- 937 SemError(233)
|
|
|
- 938 ELSE QbeGen.Mangled(qn,
|
|
|
- 939 SymTab.ProcUid(qn), mg0);
|
|
|
- 940 QbeGen.CallBegin(mg0,
|
|
|
- 941 res0,
|
|
|
- 942 SymTab.ProcDepthOf(qn),
|
|
|
- 943 SymTab.IsExternal(qn));
|
|
|
- 944 QbeGen.CallEnd(FALSE, q2)
|
|
|
- 945 END
|
|
|
- 946 ELSE SemError(233)
|
|
|
- 947 END; .) ) .
|
|
|
- 948 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 949 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 950 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 951 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 952 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 953 want: BOOLEAN;
|
|
|
- 954 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 955 VAR called: BOOLEAN> (. VAR i: CARDINAL;
|
|
|
- 956 res: SymTab.TypeIndex;
|
|
|
- 957 mg: QbeGen.QVal;
|
|
|
- 958 ok, ind: BOOLEAN; .)
|
|
|
- 959 = "(" (. called := TRUE;
|
|
|
- 960 ok := TRUE;
|
|
|
- 961 ind := FALSE;
|
|
|
- 962 IF SymTab.SymKind(pn) =
|
|
|
- 963 SymTab.KindProc THEN
|
|
|
- 964 res := SymTab.ProcRes(pn);
|
|
|
- 965 QbeGen.Mangled(pn,
|
|
|
- 966 SymTab.ProcUid(pn), mg);
|
|
|
- 967 QbeGen.CallBegin(mg, res,
|
|
|
- 968 SymTab.ProcDepthOf(pn),
|
|
|
- 969 SymTab.IsExternal(pn))
|
|
|
- 970 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 971 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 972 ind := TRUE;
|
|
|
- 973 res :=
|
|
|
- 974 SymTab.ProcTypeRes(pt);
|
|
|
- 975 QbeGen.CallBeginInd(callee,
|
|
|
- 976 res, FALSE)
|
|
|
- 977 ELSE SemError(233);
|
|
|
- 978 ok := FALSE;
|
|
|
- 979 res := SymTab.InvalidType
|
|
|
- 980 END;
|
|
|
- 981 i := 0; .)
|
|
|
- 982 [ ActParam<pn, pt, ind, i> (. INC(i); .)
|
|
|
- 983 { "," ActParam<pn, pt, ind, i> (. INC(i); .) } ]
|
|
|
- 984 ")" (. IF ok THEN
|
|
|
- 985 IF ind THEN
|
|
|
- 986 IF i #
|
|
|
- 987 SymTab.ProcTypeNPar(pt) THEN
|
|
|
- 988 SemError(233); ok := FALSE
|
|
|
- 989 END
|
|
|
- 990 ELSIF i #
|
|
|
- 991 SymTab.ProcNPar(pn) THEN
|
|
|
- 992 SemError(233); ok := FALSE
|
|
|
- 993 END
|
|
|
- 994 END;
|
|
|
- 995 IF NOT ok THEN
|
|
|
- 996 t := SymTab.InvalidType;
|
|
|
- 997 QbeGen.CopyOp("0", q)
|
|
|
- 998 ELSIF want THEN
|
|
|
- 999 IF res =
|
|
|
- 1000 SymTab.InvalidType THEN
|
|
|
- 1001 SemError(233);
|
|
|
- 1002 t := SymTab.InvalidType;
|
|
|
- 1003 QbeGen.CopyOp("0", q)
|
|
|
- 1004 ELSE t := res;
|
|
|
- 1005 QbeGen.CallEnd(TRUE, q)
|
|
|
- 1006 END
|
|
|
- 1007 ELSE
|
|
|
- 1008 IF res #
|
|
|
- 1009 SymTab.InvalidType THEN
|
|
|
- 1010 SemError(233)
|
|
|
- 1011 END;
|
|
|
- 1012 t := SymTab.InvalidType;
|
|
|
- 1013 QbeGen.CopyOp("0", q);
|
|
|
- 1014 QbeGen.CallEnd(FALSE, q)
|
|
|
- 1015 END; .) .
|
|
|
- 1016 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 1017 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 1018 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 1019 i: CARDINAL> (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 1020 qe, qa, qt: QbeGen.QVal;
|
|
|
- 1021 isV, conv: BOOLEAN; .)
|
|
|
- 1022 = Expr<at, qe> (. IF ind THEN
|
|
|
- 1023 ft :=
|
|
|
- 1024 SymTab.ProcTypeParamType(pt,
|
|
|
- 1025 i);
|
|
|
- 1026 isV :=
|
|
|
- 1027 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 1028 i)
|
|
|
- 1029 ELSE
|
|
|
- 1030 ft := SymTab.ParamType(pn, i);
|
|
|
- 1031 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 1032 END;
|
|
|
- 1033 IF (at = SymTab.InvalidType)
|
|
|
- 1034 OR (ft =
|
|
|
- 1035 SymTab.InvalidType) THEN
|
|
|
- 1036 ELSIF isV THEN
|
|
|
- 1037 IF NOT QbeGen.AddrOfVal(qe,
|
|
|
- 1038 qa) THEN
|
|
|
- 1039 SemError(233)
|
|
|
- 1040 ELSIF NOT SymTab.VarParamOk(at,
|
|
|
- 1041 ft) THEN
|
|
|
- 1042 SemError(233)
|
|
|
- 1043 ELSIF NOT QbeGen.CallArg(qa,
|
|
|
- 1044 "l") THEN
|
|
|
- 1045 SemError(233)
|
|
|
- 1046 END
|
|
|
- 1047 ELSE
|
|
|
- 1048 IF (SymTab.ClassOf(at)
|
|
|
- 1049 = SymTab.ClChar)
|
|
|
- 1050 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1051 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
- 1052 = SymTab.ClChar)
|
|
|
- 1053 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1054 (* 1-char string
|
|
|
- 1055 literal passed to
|
|
|
- 1056 ARRAY OF CHAR *)
|
|
|
- 1057 QbeGen.DeclCharStr(qe,
|
|
|
- 1058 qa);
|
|
|
- 1059 IF NOT QbeGen.CallArg(qa,
|
|
|
- 1060 "l") THEN
|
|
|
- 1061 SemError(233)
|
|
|
- 1062 END
|
|
|
- 1063 ELSIF NOT SymTab.Assignable(at,
|
|
|
- 1064 ft) THEN
|
|
|
- 1065 SemError(233)
|
|
|
- 1066 ELSE
|
|
|
- 1067 conv := (SymTab.ClassOf(
|
|
|
- 1068 ft) = SymTab.ClReal)
|
|
|
- 1069 AND SymTab.IsIntFamily(at);
|
|
|
- 1070 IF conv THEN
|
|
|
- 1071 QbeGen.ConvIR(qe, qt);
|
|
|
- 1072 IF NOT QbeGen.CallArg(qt,
|
|
|
- 1073 "d") THEN
|
|
|
- 1074 SemError(233)
|
|
|
- 1075 END
|
|
|
- 1076 ELSIF NOT QbeGen.CallArg(qe,
|
|
|
- 1077 QbeGen.ArgClass(ft)) THEN
|
|
|
- 1078 SemError(233)
|
|
|
- 1079 END
|
|
|
- 1080 END
|
|
|
- 1081 END; .) .
|
|
|
- 1082 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1083 q, lThen, lElse, lEnd:
|
|
|
- 1084 QbeGen.QVal;
|
|
|
- 1085 hasElse: BOOLEAN; .)
|
|
|
- 1086 = "IF" (. hasElse := FALSE; .)
|
|
|
- 1087 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1088 SemError(214) END;
|
|
|
- 1089 QbeGen.NewLabel(lThen);
|
|
|
- 1090 QbeGen.NewLabel(lElse);
|
|
|
- 1091 QbeGen.NewLabel(lEnd);
|
|
|
- 1092 QbeGen.Jnz(q, lThen, lElse);
|
|
|
- 1093 QbeGen.EmitLabel(lThen); .)
|
|
|
- 1094 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .)
|
|
|
- 1095 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
- 1096 QbeGen.NewLabel(lElse); .)
|
|
|
- 1097 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1098 SemError(214) END;
|
|
|
- 1099 QbeGen.NewLabel(lThen);
|
|
|
- 1100 QbeGen.Jnz(q, lThen, lElse);
|
|
|
- 1101 QbeGen.EmitLabel(lThen); .)
|
|
|
- 1102 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .) }
|
|
|
- 1103 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
- 1104 hasElse := TRUE; .)
|
|
|
- 1105 StatSeq ]
|
|
|
- 1106 "END" (. IF hasElse THEN
|
|
|
- 1107 QbeGen.EmitLabel(lEnd)
|
|
|
- 1108 ELSE QbeGen.EmitLabel(lElse);
|
|
|
+ 723 ELSE QbeGen.Op3("sub", qn2, qv,
|
|
|
+ 724 qstep, FALSE)
|
|
|
+ 725 END;
|
|
|
+ 726 IF sfx
|
|
|
+ 727 OR (dk = SymTab.KindField) THEN
|
|
|
+ 728 QbeGen.ElemStore(qd, qn2,
|
|
|
+ 729 dt)
|
|
|
+ 730 ELSE QbeGen.StoreVar(qn,
|
|
|
+ 731 qn2, FALSE)
|
|
|
+ 732 END
|
|
|
+ 733 END; .) .
|
|
|
+ 734 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
+ 735 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
+ 736 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
+ 737 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 738 dk: INTEGER;
|
|
|
+ 739 qd, qm: QbeGen.QVal;
|
|
|
+ 740 qn: SymTab.Name;
|
|
|
+ 741 sfx: BOOLEAN;
|
|
|
+ 742 bt: SymTab.TypeIndex; .)
|
|
|
+ 743 = "NEW" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 744 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 745 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 746 AND (dk # SymTab.KindParam)
|
|
|
+ 747 AND (dk # SymTab.KindField) THEN
|
|
|
+ 748 SemError(210)
|
|
|
+ 749 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 750 SymTab.ClPtr THEN
|
|
|
+ 751 SemError(219)
|
|
|
+ 752 ELSE bt := SymTab.PtrBase(dt);
|
|
|
+ 753 IF bt #
|
|
|
+ 754 SymTab.InvalidType THEN
|
|
|
+ 755 QbeGen.NewHeap(bt, qm);
|
|
|
+ 756 QbeGen.InitHeap(qm, bt);
|
|
|
+ 757 IF sfx
|
|
|
+ 758 OR (dk =
|
|
|
+ 759 SymTab.KindField) THEN
|
|
|
+ 760 QbeGen.ElemStore(qd, qm,
|
|
|
+ 761 dt)
|
|
|
+ 762 ELSE QbeGen.StorePtr(qn,
|
|
|
+ 763 qm)
|
|
|
+ 764 END
|
|
|
+ 765 END
|
|
|
+ 766 END; .) .
|
|
|
+ 767 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 768 dk: INTEGER;
|
|
|
+ 769 qd, qv: QbeGen.QVal;
|
|
|
+ 770 qn: SymTab.Name;
|
|
|
+ 771 sfx: BOOLEAN; .)
|
|
|
+ 772 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 773 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 774 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 775 AND (dk # SymTab.KindParam)
|
|
|
+ 776 AND (dk # SymTab.KindField) THEN
|
|
|
+ 777 SemError(210)
|
|
|
+ 778 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 779 SymTab.ClPtr THEN
|
|
|
+ 780 SemError(219)
|
|
|
+ 781 ELSE
|
|
|
+ 782 IF sfx
|
|
|
+ 783 OR (dk =
|
|
|
+ 784 SymTab.KindField) THEN
|
|
|
+ 785 QbeGen.ElemLoad(qd, dt,
|
|
|
+ 786 qv)
|
|
|
+ 787 ELSE QbeGen.LoadPtr(qn, qv)
|
|
|
+ 788 END;
|
|
|
+ 789 QbeGen.FreeHeap(qv);
|
|
|
+ 790 IF sfx
|
|
|
+ 791 OR (dk =
|
|
|
+ 792 SymTab.KindField) THEN
|
|
|
+ 793 QbeGen.ElemStore(qd, "0",
|
|
|
+ 794 dt)
|
|
|
+ 795 ELSE QbeGen.StorePtr(qn,
|
|
|
+ 796 "0")
|
|
|
+ 797 END
|
|
|
+ 798 END; .) .
|
|
|
+ 799 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
+ 800 address; field designators resolve through both stacks. *)
|
|
|
+ 801 WithStat (. VAR nW: CARDINAL; .)
|
|
|
+ 802 = "WITH" (. nW := 0; .)
|
|
|
+ 803 WithItem<nW> { "," WithItem<nW> }
|
|
|
+ 804 "DO" [ StatSeq ] "END"
|
|
|
+ 805 (. WHILE nW > 0 DO
|
|
|
+ 806 SymTab.PopScope;
|
|
|
+ 807 QbeGen.PopWith;
|
|
|
+ 808 DEC(nW)
|
|
|
+ 809 END; .) .
|
|
|
+ 810 WithItem<VAR nW: CARDINAL> (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 811 dk: INTEGER;
|
|
|
+ 812 qd, qe: QbeGen.QVal;
|
|
|
+ 813 qn: SymTab.Name;
|
|
|
+ 814 sfx: BOOLEAN; .)
|
|
|
+ 815 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 816 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 817 ELSIF (SymTab.ClassOf(dt) #
|
|
|
+ 818 SymTab.ClRecord)
|
|
|
+ 819 AND (SymTab.ClassOf(dt) #
|
|
|
+ 820 SymTab.ClClass) THEN
|
|
|
+ 821 SemError(215)
|
|
|
+ 822 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
+ 823 QbeGen.PushWith(qd);
|
|
|
+ 824 INC(nW)
|
|
|
+ 825 END; .) .
|
|
|
+ 826 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
+ 827 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
+ 828 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 829 dk: INTEGER;
|
|
|
+ 830 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
+ 831 qn: SymTab.Name;
|
|
|
+ 832 ct2, res0: SymTab.TypeIndex;
|
|
|
+ 833 q2, mg0: QbeGen.QVal;
|
|
|
+ 834 isR, conv, wconv: BOOLEAN;
|
|
|
+ 835 called, sfx: BOOLEAN; .)
|
|
|
+ 836 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 837 ( ":="
|
|
|
+ 838 Expr<et, qe> (. IF (dt # SymTab.InvalidType)
|
|
|
+ 839 AND (dk # SymTab.KindVar)
|
|
|
+ 840 AND (dk # SymTab.KindParam)
|
|
|
+ 841 AND (dk # SymTab.KindField) THEN
|
|
|
+ 842 SemError(210)
|
|
|
+ 843 ELSIF NOT SymTab.Assignable(et,
|
|
|
+ 844 dt) THEN
|
|
|
+ 845 SemError(210)
|
|
|
+ 846 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 847 AND (SymTab.ClassOf(dt) =
|
|
|
+ 848 SymTab.ClClass) THEN
|
|
|
+ 849 SemError(230) END;
|
|
|
+ 850 isR := (dt #
|
|
|
+ 851 SymTab.InvalidType)
|
|
|
+ 852 AND (SymTab.ClassOf(dt)
|
|
|
+ 853 = SymTab.ClReal);
|
|
|
+ 854 conv := isR
|
|
|
+ 855 AND SymTab.IsIntFamily(et);
|
|
|
+ 856 wconv := (dt #
|
|
|
+ 857 SymTab.InvalidType)
|
|
|
+ 858 AND SymTab.IsLongFamily(dt)
|
|
|
+ 859 AND SymTab.IsIntFamily(et);
|
|
|
+ 860 IF ((dk = SymTab.KindVar)
|
|
|
+ 861 OR (dk = SymTab.KindParam)
|
|
|
+ 862 OR (dk = SymTab.KindField))
|
|
|
+ 863 AND (dt # SymTab.InvalidType)
|
|
|
+ 864 AND (et # SymTab.InvalidType)
|
|
|
+ 865 AND (SymTab.ClassOf(dt) #
|
|
|
+ 866 SymTab.ClClass) THEN
|
|
|
+ 867 IF sfx
|
|
|
+ 868 OR (dk = SymTab.KindField) THEN
|
|
|
+ 869 IF SymTab.ClassOf(dt) =
|
|
|
+ 870 SymTab.ClArray THEN
|
|
|
+ 871 QbeGen.CopyArray(qd, qe,
|
|
|
+ 872 dt)
|
|
|
+ 873 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 874 SymTab.ClSet THEN
|
|
|
+ 875 QbeGen.CopySet(qd, qe,
|
|
|
+ 876 SymTab.SetWords(dt),
|
|
|
+ 877 SymTab.SetWords(et))
|
|
|
+ 878 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 879 SymTab.ClRecord THEN
|
|
|
+ 880 QbeGen.CopyRecord(qd, qe,
|
|
|
+ 881 dt)
|
|
|
+ 882 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
+ 883 IF wconv THEN
|
|
|
+ 884 QbeGen.WidenLong(qe, ql);
|
|
|
+ 885 QbeGen.ElemStore(qd, ql,
|
|
|
+ 886 dt)
|
|
|
+ 887 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
+ 888 dt)
|
|
|
+ 889 END
|
|
|
+ 890 ELSIF conv THEN
|
|
|
+ 891 QbeGen.ConvIR(qe, qt);
|
|
|
+ 892 QbeGen.ElemStore(qd, qt,
|
|
|
+ 893 dt)
|
|
|
+ 894 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
+ 895 dt)
|
|
|
+ 896 END
|
|
|
+ 897 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 898 SymTab.ClArray THEN
|
|
|
+ 899 QbeGen.CopyArray(qd, qe, dt)
|
|
|
+ 900 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 901 SymTab.ClSet THEN
|
|
|
+ 902 QbeGen.CopySet(qd, qe,
|
|
|
+ 903 SymTab.SetWords(dt),
|
|
|
+ 904 SymTab.SetWords(et))
|
|
|
+ 905 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 906 SymTab.ClRecord THEN
|
|
|
+ 907 QbeGen.CopyRecord(qd, qe, dt)
|
|
|
+ 908 ELSIF (SymTab.ClassOf(dt) =
|
|
|
+ 909 SymTab.ClPtr)
|
|
|
+ 910 OR (SymTab.ClassOf(dt) =
|
|
|
+ 911 SymTab.ClProc) THEN
|
|
|
+ 912 QbeGen.StorePtr(qn, qe)
|
|
|
+ 913 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
+ 914 IF wconv THEN
|
|
|
+ 915 QbeGen.WidenLong(qe, ql);
|
|
|
+ 916 QbeGen.StoreLong(qn, ql)
|
|
|
+ 917 ELSE QbeGen.StoreLong(qn, qe)
|
|
|
+ 918 END
|
|
|
+ 919 ELSIF conv THEN
|
|
|
+ 920 QbeGen.ConvIR(qe, qt);
|
|
|
+ 921 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
+ 922 ELSE
|
|
|
+ 923 QbeGen.StoreVar(qn, qe, isR)
|
|
|
+ 924 END
|
|
|
+ 925 END; .)
|
|
|
+ 926 | ArgList<qn, dt, qd, FALSE, ct2, q2, called>
|
|
|
+ 927 | (* bare `P;`: proper parameterless
|
|
|
+ 928 procedure call; anything else
|
|
|
+ 929 here is 233 (was a bare syntax
|
|
|
+ 930 error before 4.2) *)
|
|
|
+ 931 (. IF (dk = SymTab.KindProc)
|
|
|
+ 932 AND NOT sfx THEN
|
|
|
+ 933 res0 := SymTab.ProcRes(qn);
|
|
|
+ 934 IF res0 #
|
|
|
+ 935 SymTab.InvalidType THEN
|
|
|
+ 936 SemError(233)
|
|
|
+ 937 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 938 0 THEN
|
|
|
+ 939 SemError(233)
|
|
|
+ 940 ELSE QbeGen.Mangled(qn,
|
|
|
+ 941 SymTab.ProcUid(qn), mg0);
|
|
|
+ 942 QbeGen.CallBegin(mg0,
|
|
|
+ 943 res0,
|
|
|
+ 944 SymTab.ProcDepthOf(qn),
|
|
|
+ 945 SymTab.IsExternal(qn));
|
|
|
+ 946 QbeGen.CallEnd(FALSE, q2)
|
|
|
+ 947 END
|
|
|
+ 948 ELSE SemError(233)
|
|
|
+ 949 END; .) ) .
|
|
|
+ 950 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 951 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 952 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 953 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 954 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 955 want: BOOLEAN;
|
|
|
+ 956 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 957 VAR called: BOOLEAN> (. VAR i: CARDINAL;
|
|
|
+ 958 res: SymTab.TypeIndex;
|
|
|
+ 959 mg: QbeGen.QVal;
|
|
|
+ 960 ok, ind: BOOLEAN; .)
|
|
|
+ 961 = "(" (. called := TRUE;
|
|
|
+ 962 ok := TRUE;
|
|
|
+ 963 ind := FALSE;
|
|
|
+ 964 IF SymTab.SymKind(pn) =
|
|
|
+ 965 SymTab.KindProc THEN
|
|
|
+ 966 res := SymTab.ProcRes(pn);
|
|
|
+ 967 QbeGen.Mangled(pn,
|
|
|
+ 968 SymTab.ProcUid(pn), mg);
|
|
|
+ 969 QbeGen.CallBegin(mg, res,
|
|
|
+ 970 SymTab.ProcDepthOf(pn),
|
|
|
+ 971 SymTab.IsExternal(pn))
|
|
|
+ 972 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 973 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 974 ind := TRUE;
|
|
|
+ 975 res :=
|
|
|
+ 976 SymTab.ProcTypeRes(pt);
|
|
|
+ 977 QbeGen.CallBeginInd(callee,
|
|
|
+ 978 res, FALSE)
|
|
|
+ 979 ELSE SemError(233);
|
|
|
+ 980 ok := FALSE;
|
|
|
+ 981 res := SymTab.InvalidType
|
|
|
+ 982 END;
|
|
|
+ 983 i := 0; .)
|
|
|
+ 984 [ ActParam<pn, pt, ind, i> (. INC(i); .)
|
|
|
+ 985 { "," ActParam<pn, pt, ind, i> (. INC(i); .) } ]
|
|
|
+ 986 ")" (. IF ok THEN
|
|
|
+ 987 IF ind THEN
|
|
|
+ 988 IF i #
|
|
|
+ 989 SymTab.ProcTypeNPar(pt) THEN
|
|
|
+ 990 SemError(233); ok := FALSE
|
|
|
+ 991 END
|
|
|
+ 992 ELSIF i #
|
|
|
+ 993 SymTab.ProcNPar(pn) THEN
|
|
|
+ 994 SemError(233); ok := FALSE
|
|
|
+ 995 END
|
|
|
+ 996 END;
|
|
|
+ 997 IF NOT ok THEN
|
|
|
+ 998 t := SymTab.InvalidType;
|
|
|
+ 999 QbeGen.CopyOp("0", q)
|
|
|
+ 1000 ELSIF want THEN
|
|
|
+ 1001 IF res =
|
|
|
+ 1002 SymTab.InvalidType THEN
|
|
|
+ 1003 SemError(233);
|
|
|
+ 1004 t := SymTab.InvalidType;
|
|
|
+ 1005 QbeGen.CopyOp("0", q)
|
|
|
+ 1006 ELSE t := res;
|
|
|
+ 1007 QbeGen.CallEnd(TRUE, q)
|
|
|
+ 1008 END
|
|
|
+ 1009 ELSE
|
|
|
+ 1010 IF res #
|
|
|
+ 1011 SymTab.InvalidType THEN
|
|
|
+ 1012 SemError(233)
|
|
|
+ 1013 END;
|
|
|
+ 1014 t := SymTab.InvalidType;
|
|
|
+ 1015 QbeGen.CopyOp("0", q);
|
|
|
+ 1016 QbeGen.CallEnd(FALSE, q)
|
|
|
+ 1017 END; .) .
|
|
|
+ 1018 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 1019 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 1020 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 1021 i: CARDINAL> (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 1022 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 1023 isV, conv: BOOLEAN; .)
|
|
|
+ 1024 = Expr<at, qe> (. IF ind THEN
|
|
|
+ 1025 ft :=
|
|
|
+ 1026 SymTab.ProcTypeParamType(pt,
|
|
|
+ 1027 i);
|
|
|
+ 1028 isV :=
|
|
|
+ 1029 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 1030 i)
|
|
|
+ 1031 ELSE
|
|
|
+ 1032 ft := SymTab.ParamType(pn, i);
|
|
|
+ 1033 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 1034 END;
|
|
|
+ 1035 IF (at = SymTab.InvalidType)
|
|
|
+ 1036 OR (ft =
|
|
|
+ 1037 SymTab.InvalidType) THEN
|
|
|
+ 1038 ELSIF isV THEN
|
|
|
+ 1039 IF NOT QbeGen.AddrOfVal(qe,
|
|
|
+ 1040 qa) THEN
|
|
|
+ 1041 SemError(233)
|
|
|
+ 1042 ELSIF NOT SymTab.VarParamOk(at,
|
|
|
+ 1043 ft) THEN
|
|
|
+ 1044 SemError(233)
|
|
|
+ 1045 ELSIF NOT QbeGen.CallArg(qa,
|
|
|
+ 1046 "l") THEN
|
|
|
+ 1047 SemError(233)
|
|
|
+ 1048 END
|
|
|
+ 1049 ELSE
|
|
|
+ 1050 IF (SymTab.ClassOf(at)
|
|
|
+ 1051 = SymTab.ClChar)
|
|
|
+ 1052 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1053 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
+ 1054 = SymTab.ClChar)
|
|
|
+ 1055 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1056 (* 1-char string
|
|
|
+ 1057 literal passed to
|
|
|
+ 1058 ARRAY OF CHAR *)
|
|
|
+ 1059 QbeGen.DeclCharStr(qe,
|
|
|
+ 1060 qa);
|
|
|
+ 1061 IF NOT QbeGen.CallArg(qa,
|
|
|
+ 1062 "l") THEN
|
|
|
+ 1063 SemError(233)
|
|
|
+ 1064 END
|
|
|
+ 1065 ELSIF NOT SymTab.Assignable(at,
|
|
|
+ 1066 ft) THEN
|
|
|
+ 1067 SemError(233)
|
|
|
+ 1068 ELSE
|
|
|
+ 1069 conv := (SymTab.ClassOf(
|
|
|
+ 1070 ft) = SymTab.ClReal)
|
|
|
+ 1071 AND SymTab.IsIntFamily(at);
|
|
|
+ 1072 IF conv THEN
|
|
|
+ 1073 QbeGen.ConvIR(qe, qt);
|
|
|
+ 1074 IF NOT QbeGen.CallArg(qt,
|
|
|
+ 1075 "d") THEN
|
|
|
+ 1076 SemError(233)
|
|
|
+ 1077 END
|
|
|
+ 1078 ELSIF NOT QbeGen.CallArg(qe,
|
|
|
+ 1079 QbeGen.ArgClass(ft)) THEN
|
|
|
+ 1080 SemError(233)
|
|
|
+ 1081 END
|
|
|
+ 1082 END
|
|
|
+ 1083 END; .) .
|
|
|
+ 1084 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1085 q, lThen, lElse, lEnd:
|
|
|
+ 1086 QbeGen.QVal;
|
|
|
+ 1087 hasElse: BOOLEAN; .)
|
|
|
+ 1088 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 1089 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1090 SemError(214) END;
|
|
|
+ 1091 QbeGen.NewLabel(lThen);
|
|
|
+ 1092 QbeGen.NewLabel(lElse);
|
|
|
+ 1093 QbeGen.NewLabel(lEnd);
|
|
|
+ 1094 QbeGen.Jnz(q, lThen, lElse);
|
|
|
+ 1095 QbeGen.EmitLabel(lThen); .)
|
|
|
+ 1096 "THEN" [ StatSeq ] (. QbeGen.Jmp(lEnd); .)
|
|
|
+ 1097 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
+ 1098 QbeGen.NewLabel(lElse); .)
|
|
|
+ 1099 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1100 SemError(214) END;
|
|
|
+ 1101 QbeGen.NewLabel(lThen);
|
|
|
+ 1102 QbeGen.Jnz(q, lThen, lElse);
|
|
|
+ 1103 QbeGen.EmitLabel(lThen); .)
|
|
|
+ 1104 "THEN" StatSeq (. QbeGen.Jmp(lEnd); .) }
|
|
|
+ 1105 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
+ 1106 hasElse := TRUE; .)
|
|
|
+ 1107 [ StatSeq ] ]
|
|
|
+ 1108 "END" (. IF hasElse THEN
|
|
|
1109 QbeGen.EmitLabel(lEnd)
|
|
|
- 1110 END; .) .
|
|
|
- 1111 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1112 q, lTop, lBody, lEnd:
|
|
|
- 1113 QbeGen.QVal; .)
|
|
|
- 1114 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
- 1115 QbeGen.NewLabel(lBody);
|
|
|
- 1116 QbeGen.NewLabel(lEnd);
|
|
|
- 1117 QbeGen.EmitLabel(lTop); .)
|
|
|
- 1118 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1119 SemError(214) END;
|
|
|
- 1120 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
- 1121 QbeGen.EmitLabel(lBody); .)
|
|
|
- 1122 "DO" StatSeq (. QbeGen.Jmp(lTop); .)
|
|
|
- 1123 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1124 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1125 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
- 1126 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
- 1127 QbeGen.NewLabel(lEnd);
|
|
|
- 1128 QbeGen.EmitLabel(lTop); .)
|
|
|
- 1129 StatSeq
|
|
|
- 1130 "UNTIL" Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1131 SemError(214) END;
|
|
|
- 1132 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
- 1133 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1134 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
- 1135 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
- 1136 QbeGen.NewLabel(lEnd);
|
|
|
- 1137 QbeGen.PushLoop(lEnd);
|
|
|
- 1138 QbeGen.EmitLabel(lTop); .)
|
|
|
- 1139 StatSeq
|
|
|
- 1140 "END" (. QbeGen.Jmp(lTop);
|
|
|
- 1141 QbeGen.PopLoop;
|
|
|
- 1142 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1143 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 1144 Runtime direction would need a compare-select; the literal
|
|
|
- 1145 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 1146 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 1147 tlo, thi, tby:
|
|
|
- 1148 SymTab.TypeIndex;
|
|
|
- 1149 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 1150 QbeGen.QVal;
|
|
|
- 1151 lTop, lBody, lEnd:
|
|
|
+ 1110 ELSE QbeGen.EmitLabel(lElse);
|
|
|
+ 1111 QbeGen.EmitLabel(lEnd)
|
|
|
+ 1112 END; .) .
|
|
|
+ 1113 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1114 q, lTop, lBody, lEnd:
|
|
|
+ 1115 QbeGen.QVal; .)
|
|
|
+ 1116 = "WHILE" (. QbeGen.NewLabel(lTop);
|
|
|
+ 1117 QbeGen.NewLabel(lBody);
|
|
|
+ 1118 QbeGen.NewLabel(lEnd);
|
|
|
+ 1119 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 1120 Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1121 SemError(214) END;
|
|
|
+ 1122 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
+ 1123 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 1124 "DO" [ StatSeq ] (. QbeGen.Jmp(lTop); .)
|
|
|
+ 1125 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1126 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1127 q, lTop, lEnd: QbeGen.QVal; .)
|
|
|
+ 1128 = "REPEAT" (. QbeGen.NewLabel(lTop);
|
|
|
+ 1129 QbeGen.NewLabel(lEnd);
|
|
|
+ 1130 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 1131 [ StatSeq ]
|
|
|
+ 1132 "UNTIL" Expr<t, q> (. IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1133 SemError(214) END;
|
|
|
+ 1134 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
+ 1135 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1136 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; .)
|
|
|
+ 1137 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
+ 1138 QbeGen.NewLabel(lEnd);
|
|
|
+ 1139 QbeGen.PushLoop(lEnd);
|
|
|
+ 1140 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 1141 [ StatSeq ]
|
|
|
+ 1142 "END" (. QbeGen.Jmp(lTop);
|
|
|
+ 1143 QbeGen.PopLoop;
|
|
|
+ 1144 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1145 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 1146 Runtime direction would need a compare-select; the literal
|
|
|
+ 1147 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 1148 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 1149 tlo, thi, tby:
|
|
|
+ 1150 SymTab.TypeIndex;
|
|
|
+ 1151 qlo, qhi, qby, qt, qk, qb:
|
|
|
1152 QbeGen.QVal;
|
|
|
- 1153 by: INTEGER;
|
|
|
- 1154 ok: BOOLEAN; .)
|
|
|
- 1155 = "FOR" (. by := 1; .)
|
|
|
- 1156 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
- 1157 IF NOT ok THEN
|
|
|
- 1158 SemError(201)
|
|
|
- 1159 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 1160 SymTab.KindVar)
|
|
|
- 1161 AND (SymTab.SymKind(lv) #
|
|
|
- 1162 SymTab.KindParam) THEN
|
|
|
- 1163 SemError(220); ok := FALSE
|
|
|
- 1164 ELSIF NOT SymTab.IsIntFamily(
|
|
|
- 1165 SymTab.SymType(lv)) THEN
|
|
|
- 1166 SemError(220); ok := FALSE
|
|
|
- 1167 END; .)
|
|
|
- 1168 ":=" Expr<tlo, qlo> (. IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
- 1169 SemError(220); ok := FALSE
|
|
|
- 1170 END; .)
|
|
|
- 1171 "TO" Expr<thi, qhi> (. IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
- 1172 SemError(220); ok := FALSE
|
|
|
- 1173 END; .)
|
|
|
- 1174 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
- 1175 SymTab.InvalidType)
|
|
|
- 1176 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 1177 SemError(220); ok := FALSE
|
|
|
- 1178 END;
|
|
|
- 1179 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 1180 SemError(230); by := 1
|
|
|
- 1181 ELSIF by = 0 THEN
|
|
|
- 1182 SemError(220); by := 1
|
|
|
- 1183 END; .) ]
|
|
|
- 1184 "DO" (. IF ok THEN
|
|
|
- 1185 QbeGen.StoreVar(lv, qlo,
|
|
|
- 1186 FALSE) END;
|
|
|
- 1187 QbeGen.NewLabel(lTop);
|
|
|
- 1188 QbeGen.NewLabel(lBody);
|
|
|
- 1189 QbeGen.NewLabel(lEnd);
|
|
|
- 1190 QbeGen.EmitLabel(lTop);
|
|
|
- 1191 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
- 1192 QbeGen.NewTemp(qk);
|
|
|
- 1193 IF by > 0 THEN
|
|
|
- 1194 QbeGen.Op3("cslew", qk,
|
|
|
- 1195 qt, qhi, FALSE)
|
|
|
- 1196 ELSE QbeGen.Op3("csgew", qk,
|
|
|
- 1197 qt, qhi, FALSE)
|
|
|
- 1198 END;
|
|
|
- 1199 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
- 1200 QbeGen.EmitLabel(lBody); .)
|
|
|
- 1201 StatSeq
|
|
|
- 1202 "END" (. IF ok THEN
|
|
|
- 1203 QbeGen.LoadVar(lv, FALSE,
|
|
|
- 1204 qt);
|
|
|
- 1205 QbeGen.IntStr(by, qb);
|
|
|
- 1206 QbeGen.NewTemp(qk);
|
|
|
- 1207 QbeGen.Op3("add", qk,
|
|
|
- 1208 qt, qb, FALSE);
|
|
|
- 1209 QbeGen.StoreVar(lv, qk,
|
|
|
- 1210 FALSE) END;
|
|
|
- 1211 QbeGen.Jmp(lTop);
|
|
|
- 1212 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1213 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 1214 qsel, lEnd: QbeGen.QVal; .)
|
|
|
- 1215 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
- 1216 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
- 1217 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
- 1218 [ "ELSE" StatSeq ]
|
|
|
- 1219 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1220 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 1221 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 1222 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 1223 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 1224 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 1225 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
- 1226 = (. QbeGen.NewLabel(lBody);
|
|
|
- 1227 QbeGen.NewLabel(lAfter); .)
|
|
|
- 1228 CaseLabel<tsel, qsel, lBody>
|
|
|
- 1229 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
- 1230 ":" (. QbeGen.Jmp(lAfter);
|
|
|
- 1231 QbeGen.EmitLabel(lBody); .)
|
|
|
- 1232 StatSeq (. QbeGen.Jmp(lEnd);
|
|
|
- 1233 QbeGen.EmitLabel(lAfter); .) .
|
|
|
- 1234 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 1235 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 1236 q2, q3, qc, qd, qe:
|
|
|
- 1237 QbeGen.QVal;
|
|
|
- 1238 lNext: QbeGen.QVal; .)
|
|
|
- 1239 = Expr<t2, q2> (. IF (t2 #
|
|
|
- 1240 SymTab.InvalidType)
|
|
|
- 1241 AND (tsel #
|
|
|
- 1242 SymTab.InvalidType)
|
|
|
- 1243 AND ((SymTab.ClassOf(t2) =
|
|
|
- 1244 SymTab.ClSet)
|
|
|
- 1245 OR (SymTab.ClassOf(tsel) =
|
|
|
- 1246 SymTab.ClSet)) THEN
|
|
|
- 1247 SemError(230)
|
|
|
- 1248 ELSIF (t2 #
|
|
|
- 1249 SymTab.InvalidType)
|
|
|
- 1250 AND (tsel #
|
|
|
- 1251 SymTab.InvalidType)
|
|
|
- 1252 AND NOT SymTab.EqCheck(t2,
|
|
|
- 1253 tsel) THEN
|
|
|
- 1254 SemError(213) END;
|
|
|
- 1255 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- 1256 SemError(230);
|
|
|
- 1257 QbeGen.CopyOp("0", q2)
|
|
|
- 1258 END;
|
|
|
- 1259 QbeGen.NewLabel(lNext);
|
|
|
- 1260 QbeGen.Cmp(SymTab.OpEq,
|
|
|
- 1261 qsel, q2, qc, FALSE);
|
|
|
- 1262 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
- 1263 QbeGen.EmitLabel(lNext); .)
|
|
|
- 1264 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
- 1265 SymTab.InvalidType)
|
|
|
- 1266 AND (tsel #
|
|
|
- 1267 SymTab.InvalidType)
|
|
|
- 1268 AND NOT SymTab.EqCheck(t3,
|
|
|
- 1269 tsel) THEN
|
|
|
- 1270 SemError(213) END;
|
|
|
- 1271 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- 1272 SemError(230);
|
|
|
- 1273 QbeGen.CopyOp("0", q3)
|
|
|
- 1274 END;
|
|
|
- 1275 QbeGen.Cmp(SymTab.OpGe,
|
|
|
- 1276 qsel, q2, qc, FALSE);
|
|
|
- 1277 QbeGen.Cmp(SymTab.OpLe,
|
|
|
- 1278 qsel, q3, qd, FALSE);
|
|
|
- 1279 QbeGen.NewTemp(qe);
|
|
|
- 1280 QbeGen.Op3("and", qe, qc, qd,
|
|
|
- 1281 FALSE);
|
|
|
- 1282 QbeGen.NewLabel(lNext);
|
|
|
- 1283 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
- 1284 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
- 1285 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1286 q, qt: QbeGen.QVal;
|
|
|
- 1287 res: SymTab.TypeIndex;
|
|
|
- 1288 hadE, conv: BOOLEAN; .)
|
|
|
- 1289 = "RETURN" (. hadE := FALSE; .)
|
|
|
- 1290 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
- 1291 (. conv := FALSE;
|
|
|
- 1292 IF NOT SymTab.InProc() THEN
|
|
|
- 1293 SemError(232)
|
|
|
- 1294 ELSE res := SymTab.CurRes();
|
|
|
- 1295 IF NOT hadE THEN
|
|
|
- 1296 IF res #
|
|
|
- 1297 SymTab.InvalidType THEN
|
|
|
- 1298 SemError(232)
|
|
|
- 1299 ELSE QbeGen.EmitRet(q,
|
|
|
- 1300 FALSE)
|
|
|
- 1301 END
|
|
|
- 1302 ELSIF (res =
|
|
|
- 1303 SymTab.InvalidType)
|
|
|
- 1304 OR (t #
|
|
|
+ 1153 lTop, lBody, lEnd:
|
|
|
+ 1154 QbeGen.QVal;
|
|
|
+ 1155 by: INTEGER;
|
|
|
+ 1156 ok: BOOLEAN; .)
|
|
|
+ 1157 = "FOR" (. by := 1; .)
|
|
|
+ 1158 GetIdent<lv> (. ok := SymTab.Lookup(lv);
|
|
|
+ 1159 IF NOT ok THEN
|
|
|
+ 1160 SemError(201)
|
|
|
+ 1161 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 1162 SymTab.KindVar)
|
|
|
+ 1163 AND (SymTab.SymKind(lv) #
|
|
|
+ 1164 SymTab.KindParam) THEN
|
|
|
+ 1165 SemError(220); ok := FALSE
|
|
|
+ 1166 ELSIF NOT SymTab.IsIntFamily(
|
|
|
+ 1167 SymTab.SymType(lv)) THEN
|
|
|
+ 1168 SemError(220); ok := FALSE
|
|
|
+ 1169 END; .)
|
|
|
+ 1170 ":=" Expr<tlo, qlo> (. IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 1171 SemError(220); ok := FALSE
|
|
|
+ 1172 END; .)
|
|
|
+ 1173 "TO" Expr<thi, qhi> (. IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
+ 1174 SemError(220); ok := FALSE
|
|
|
+ 1175 END; .)
|
|
|
+ 1176 [ "BY" Expr<tby, qby> (. IF (tby #
|
|
|
+ 1177 SymTab.InvalidType)
|
|
|
+ 1178 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 1179 SemError(220); ok := FALSE
|
|
|
+ 1180 END;
|
|
|
+ 1181 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 1182 SemError(230); by := 1
|
|
|
+ 1183 ELSIF by = 0 THEN
|
|
|
+ 1184 SemError(220); by := 1
|
|
|
+ 1185 END; .) ]
|
|
|
+ 1186 "DO" (. IF ok THEN
|
|
|
+ 1187 QbeGen.StoreVar(lv, qlo,
|
|
|
+ 1188 FALSE) END;
|
|
|
+ 1189 QbeGen.NewLabel(lTop);
|
|
|
+ 1190 QbeGen.NewLabel(lBody);
|
|
|
+ 1191 QbeGen.NewLabel(lEnd);
|
|
|
+ 1192 QbeGen.EmitLabel(lTop);
|
|
|
+ 1193 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
+ 1194 QbeGen.NewTemp(qk);
|
|
|
+ 1195 IF by > 0 THEN
|
|
|
+ 1196 QbeGen.Op3("cslew", qk,
|
|
|
+ 1197 qt, qhi, FALSE)
|
|
|
+ 1198 ELSE QbeGen.Op3("csgew", qk,
|
|
|
+ 1199 qt, qhi, FALSE)
|
|
|
+ 1200 END;
|
|
|
+ 1201 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
+ 1202 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 1203 [ StatSeq ]
|
|
|
+ 1204 "END" (. IF ok THEN
|
|
|
+ 1205 QbeGen.LoadVar(lv, FALSE,
|
|
|
+ 1206 qt);
|
|
|
+ 1207 QbeGen.IntStr(by, qb);
|
|
|
+ 1208 QbeGen.NewTemp(qk);
|
|
|
+ 1209 QbeGen.Op3("add", qk,
|
|
|
+ 1210 qt, qb, FALSE);
|
|
|
+ 1211 QbeGen.StoreVar(lv, qk,
|
|
|
+ 1212 FALSE) END;
|
|
|
+ 1213 QbeGen.Jmp(lTop);
|
|
|
+ 1214 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1215 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 1216 qsel, lEnd: QbeGen.QVal; .)
|
|
|
+ 1217 = "CASE" Expr<tsel, qsel> (. QbeGen.NewLabel(lEnd); .)
|
|
|
+ 1218 "OF" CaseAlt<tsel, qsel, lEnd>
|
|
|
+ 1219 { "|" CaseAlt<tsel, qsel, lEnd> }
|
|
|
+ 1220 [ "ELSE" [ StatSeq ] ]
|
|
|
+ 1221 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1222 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 1223 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 1224 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 1225 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 1226 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 1227 lEnd: QbeGen.QVal> (. VAR lBody, lAfter: QbeGen.QVal; .)
|
|
|
+ 1228 = (. QbeGen.NewLabel(lBody);
|
|
|
+ 1229 QbeGen.NewLabel(lAfter); .)
|
|
|
+ 1230 CaseLabel<tsel, qsel, lBody>
|
|
|
+ 1231 { "," CaseLabel<tsel, qsel, lBody> }
|
|
|
+ 1232 ":" (. QbeGen.Jmp(lAfter);
|
|
|
+ 1233 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 1234 [ StatSeq ] (. QbeGen.Jmp(lEnd);
|
|
|
+ 1235 QbeGen.EmitLabel(lAfter); .) .
|
|
|
+ 1236 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 1237 lBody: QbeGen.QVal> (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 1238 q2, q3, qc, qd, qe:
|
|
|
+ 1239 QbeGen.QVal;
|
|
|
+ 1240 lNext: QbeGen.QVal; .)
|
|
|
+ 1241 = Expr<t2, q2> (. IF (t2 #
|
|
|
+ 1242 SymTab.InvalidType)
|
|
|
+ 1243 AND (tsel #
|
|
|
+ 1244 SymTab.InvalidType)
|
|
|
+ 1245 AND ((SymTab.ClassOf(t2) =
|
|
|
+ 1246 SymTab.ClSet)
|
|
|
+ 1247 OR (SymTab.ClassOf(tsel) =
|
|
|
+ 1248 SymTab.ClSet)) THEN
|
|
|
+ 1249 SemError(230)
|
|
|
+ 1250 ELSIF (t2 #
|
|
|
+ 1251 SymTab.InvalidType)
|
|
|
+ 1252 AND (tsel #
|
|
|
+ 1253 SymTab.InvalidType)
|
|
|
+ 1254 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 1255 tsel) THEN
|
|
|
+ 1256 SemError(213) END;
|
|
|
+ 1257 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 1258 SemError(230);
|
|
|
+ 1259 QbeGen.CopyOp("0", q2)
|
|
|
+ 1260 END;
|
|
|
+ 1261 QbeGen.NewLabel(lNext);
|
|
|
+ 1262 QbeGen.Cmp(SymTab.OpEq,
|
|
|
+ 1263 qsel, q2, qc, FALSE);
|
|
|
+ 1264 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
+ 1265 QbeGen.EmitLabel(lNext); .)
|
|
|
+ 1266 [ ".." Expr<t3, q3> (. IF (t3 #
|
|
|
+ 1267 SymTab.InvalidType)
|
|
|
+ 1268 AND (tsel #
|
|
|
+ 1269 SymTab.InvalidType)
|
|
|
+ 1270 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 1271 tsel) THEN
|
|
|
+ 1272 SemError(213) END;
|
|
|
+ 1273 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 1274 SemError(230);
|
|
|
+ 1275 QbeGen.CopyOp("0", q3)
|
|
|
+ 1276 END;
|
|
|
+ 1277 QbeGen.Cmp(SymTab.OpGe,
|
|
|
+ 1278 qsel, q2, qc, FALSE);
|
|
|
+ 1279 QbeGen.Cmp(SymTab.OpLe,
|
|
|
+ 1280 qsel, q3, qd, FALSE);
|
|
|
+ 1281 QbeGen.NewTemp(qe);
|
|
|
+ 1282 QbeGen.Op3("and", qe, qc, qd,
|
|
|
+ 1283 FALSE);
|
|
|
+ 1284 QbeGen.NewLabel(lNext);
|
|
|
+ 1285 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
+ 1286 QbeGen.EmitLabel(lNext); .) ] .
|
|
|
+ 1287 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1288 q, qt: QbeGen.QVal;
|
|
|
+ 1289 res: SymTab.TypeIndex;
|
|
|
+ 1290 hadE, conv: BOOLEAN; .)
|
|
|
+ 1291 = "RETURN" (. hadE := FALSE; .)
|
|
|
+ 1292 [ Expr<t, q> (. hadE := TRUE; .) ]
|
|
|
+ 1293 (. conv := FALSE;
|
|
|
+ 1294 IF NOT SymTab.InProc() THEN
|
|
|
+ 1295 SemError(232)
|
|
|
+ 1296 ELSE res := SymTab.CurRes();
|
|
|
+ 1297 IF NOT hadE THEN
|
|
|
+ 1298 IF res #
|
|
|
+ 1299 SymTab.InvalidType THEN
|
|
|
+ 1300 SemError(232)
|
|
|
+ 1301 ELSE QbeGen.EmitRet(q,
|
|
|
+ 1302 FALSE)
|
|
|
+ 1303 END
|
|
|
+ 1304 ELSIF (res =
|
|
|
1305 SymTab.InvalidType)
|
|
|
- 1306 AND NOT SymTab.Assignable(t,
|
|
|
- 1307 res) THEN
|
|
|
- 1308 SemError(232)
|
|
|
- 1309 ELSE
|
|
|
- 1310 conv := (SymTab.ClassOf(
|
|
|
- 1311 res) = SymTab.ClReal)
|
|
|
- 1312 AND SymTab.IsIntFamily(t);
|
|
|
- 1313 IF conv THEN
|
|
|
- 1314 QbeGen.ConvIR(q, qt);
|
|
|
- 1315 QbeGen.EmitRet(qt, TRUE)
|
|
|
- 1316 ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
- 1317 END
|
|
|
- 1318 END
|
|
|
- 1319 END; .) .
|
|
|
- 1320 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 1321 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 1322 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 1323 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 1324 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 1325 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 1326 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 1327 (. VAR n, fn, mal: SymTab.Name;
|
|
|
- 1328 cls: INTEGER;
|
|
|
- 1329 curT, it, eT, bt:
|
|
|
- 1330 SymTab.TypeIndex;
|
|
|
- 1331 iq, ql, qlo, qhi, qe:
|
|
|
- 1332 QbeGen.QVal;
|
|
|
- 1333 lo, hi: INTEGER;
|
|
|
- 1334 fo: INTEGER;
|
|
|
- 1335 isOpen: BOOLEAN;
|
|
|
- 1336 qb, cv: QbeGen.QVal; .)
|
|
|
- 1337 = GetIdent<n> (. QbeGen.CopyOp(n, qn);
|
|
|
- 1338 sfx := FALSE;
|
|
|
- 1339 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 1340 SemError(201);
|
|
|
- 1341 t := SymTab.InvalidType;
|
|
|
- 1342 k := -1;
|
|
|
- 1343 QbeGen.CopyOp("0", q)
|
|
|
- 1344 ELSE
|
|
|
- 1345 t := SymTab.SymType(n);
|
|
|
- 1346 k := SymTab.SymKind(n);
|
|
|
- 1347 IF k = SymTab.KindConst THEN
|
|
|
- 1348 IF SymTab.Equal(n,
|
|
|
- 1349 "TRUE") THEN
|
|
|
- 1350 t := SymTab.BoolType();
|
|
|
- 1351 QbeGen.CopyOp("1", q)
|
|
|
- 1352 ELSIF SymTab.Equal(n,
|
|
|
- 1353 "FALSE") THEN
|
|
|
- 1354 t := SymTab.BoolType();
|
|
|
- 1355 QbeGen.CopyOp("0", q)
|
|
|
- 1356 ELSIF SymTab.Equal(n,
|
|
|
- 1357 "NIL") THEN
|
|
|
- 1358 QbeGen.CopyOp("0", q)
|
|
|
- 1359 ELSE
|
|
|
- 1360 cls :=
|
|
|
- 1361 SymTab.ClassOf(t);
|
|
|
- 1362 IF (t #
|
|
|
- 1363 SymTab.InvalidType)
|
|
|
- 1364 AND ((cls = SymTab.ClInt)
|
|
|
- 1365 OR (cls
|
|
|
- 1366 = SymTab.ClChar)
|
|
|
+ 1306 OR (t #
|
|
|
+ 1307 SymTab.InvalidType)
|
|
|
+ 1308 AND NOT SymTab.Assignable(t,
|
|
|
+ 1309 res) THEN
|
|
|
+ 1310 SemError(232)
|
|
|
+ 1311 ELSE
|
|
|
+ 1312 conv := (SymTab.ClassOf(
|
|
|
+ 1313 res) = SymTab.ClReal)
|
|
|
+ 1314 AND SymTab.IsIntFamily(t);
|
|
|
+ 1315 IF conv THEN
|
|
|
+ 1316 QbeGen.ConvIR(q, qt);
|
|
|
+ 1317 QbeGen.EmitRet(qt, TRUE)
|
|
|
+ 1318 ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
+ 1319 END
|
|
|
+ 1320 END
|
|
|
+ 1321 END; .) .
|
|
|
+ 1322 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 1323 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 1324 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 1325 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 1326 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 1327 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 1328 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 1329 (. VAR n, fn, mal: SymTab.Name;
|
|
|
+ 1330 cls: INTEGER;
|
|
|
+ 1331 curT, it, eT, bt:
|
|
|
+ 1332 SymTab.TypeIndex;
|
|
|
+ 1333 iq, ql, qlo, qhi, qe:
|
|
|
+ 1334 QbeGen.QVal;
|
|
|
+ 1335 lo, hi: INTEGER;
|
|
|
+ 1336 fo: INTEGER;
|
|
|
+ 1337 isOpen: BOOLEAN;
|
|
|
+ 1338 qb, cv: QbeGen.QVal; .)
|
|
|
+ 1339 = GetIdent<n> (. QbeGen.CopyOp(n, qn);
|
|
|
+ 1340 sfx := FALSE;
|
|
|
+ 1341 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 1342 SemError(201);
|
|
|
+ 1343 t := SymTab.InvalidType;
|
|
|
+ 1344 k := -1;
|
|
|
+ 1345 QbeGen.CopyOp("0", q)
|
|
|
+ 1346 ELSE
|
|
|
+ 1347 t := SymTab.SymType(n);
|
|
|
+ 1348 k := SymTab.SymKind(n);
|
|
|
+ 1349 IF k = SymTab.KindConst THEN
|
|
|
+ 1350 IF SymTab.Equal(n,
|
|
|
+ 1351 "TRUE") THEN
|
|
|
+ 1352 t := SymTab.BoolType();
|
|
|
+ 1353 QbeGen.CopyOp("1", q)
|
|
|
+ 1354 ELSIF SymTab.Equal(n,
|
|
|
+ 1355 "FALSE") THEN
|
|
|
+ 1356 t := SymTab.BoolType();
|
|
|
+ 1357 QbeGen.CopyOp("0", q)
|
|
|
+ 1358 ELSIF SymTab.Equal(n,
|
|
|
+ 1359 "NIL") THEN
|
|
|
+ 1360 QbeGen.CopyOp("0", q)
|
|
|
+ 1361 ELSE
|
|
|
+ 1362 cls :=
|
|
|
+ 1363 SymTab.ClassOf(t);
|
|
|
+ 1364 IF (t #
|
|
|
+ 1365 SymTab.InvalidType)
|
|
|
+ 1366 AND ((cls = SymTab.ClInt)
|
|
|
1367 OR (cls
|
|
|
- 1368 = SymTab.ClReal)
|
|
|
+ 1368 = SymTab.ClChar)
|
|
|
1369 OR (cls
|
|
|
- 1370 = SymTab.ClNil)) THEN
|
|
|
- 1371 IF cls = SymTab.ClNil THEN
|
|
|
- 1372 QbeGen.CopyOp("0", q)
|
|
|
- 1373 ELSIF ((cls
|
|
|
- 1374 = SymTab.ClInt)
|
|
|
- 1375 OR (cls
|
|
|
- 1376 = SymTab.ClChar))
|
|
|
- 1377 AND SymTab.GetSymVal(n, cv)
|
|
|
- 1378 AND QbeGen.IsImm(cv) THEN
|
|
|
- 1379 QbeGen.CopyOp(cv, q)
|
|
|
- 1380 ELSE
|
|
|
- 1381 QbeGen.LoadVar(n,
|
|
|
- 1382 cls = SymTab.ClReal,
|
|
|
- 1383 q)
|
|
|
- 1384 END
|
|
|
- 1385 ELSE
|
|
|
- 1386 IF t #
|
|
|
- 1387 SymTab.InvalidType THEN
|
|
|
- 1388 SemError(230)
|
|
|
- 1389 END;
|
|
|
- 1390 QbeGen.CopyOp("0", q)
|
|
|
- 1391 END
|
|
|
- 1392 END
|
|
|
- 1393 ELSIF (k = SymTab.KindVar)
|
|
|
- 1394 OR (k = SymTab.KindParam) THEN
|
|
|
- 1395 cls :=
|
|
|
- 1396 SymTab.ClassOf(t);
|
|
|
- 1397 IF (cls = SymTab.ClInt)
|
|
|
- 1398 OR (cls = SymTab.ClBool)
|
|
|
- 1399 OR (cls = SymTab.ClChar)
|
|
|
- 1400 OR (cls
|
|
|
- 1401 = SymTab.ClReal) THEN
|
|
|
- 1402 QbeGen.LoadVar(n,
|
|
|
- 1403 cls = SymTab.ClReal, q)
|
|
|
- 1404 ELSIF (cls = SymTab.ClPtr)
|
|
|
- 1405 OR (cls = SymTab.ClProc) THEN
|
|
|
- 1406 QbeGen.LoadPtr(n, q)
|
|
|
- 1407 ELSIF cls = SymTab.ClLong THEN
|
|
|
- 1408 QbeGen.LoadLong(n, q)
|
|
|
- 1409 ELSIF (cls
|
|
|
- 1410 = SymTab.ClArray)
|
|
|
- 1411 OR (cls
|
|
|
- 1412 = SymTab.ClSet)
|
|
|
+ 1370 = SymTab.ClReal)
|
|
|
+ 1371 OR (cls
|
|
|
+ 1372 = SymTab.ClNil)) THEN
|
|
|
+ 1373 IF cls = SymTab.ClNil THEN
|
|
|
+ 1374 QbeGen.CopyOp("0", q)
|
|
|
+ 1375 ELSIF ((cls
|
|
|
+ 1376 = SymTab.ClInt)
|
|
|
+ 1377 OR (cls
|
|
|
+ 1378 = SymTab.ClChar))
|
|
|
+ 1379 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 1380 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 1381 QbeGen.CopyOp(cv, q)
|
|
|
+ 1382 ELSE
|
|
|
+ 1383 QbeGen.LoadVar(n,
|
|
|
+ 1384 cls = SymTab.ClReal,
|
|
|
+ 1385 q)
|
|
|
+ 1386 END
|
|
|
+ 1387 ELSE
|
|
|
+ 1388 IF t #
|
|
|
+ 1389 SymTab.InvalidType THEN
|
|
|
+ 1390 SemError(230)
|
|
|
+ 1391 END;
|
|
|
+ 1392 QbeGen.CopyOp("0", q)
|
|
|
+ 1393 END
|
|
|
+ 1394 END
|
|
|
+ 1395 ELSIF (k = SymTab.KindVar)
|
|
|
+ 1396 OR (k = SymTab.KindParam) THEN
|
|
|
+ 1397 cls :=
|
|
|
+ 1398 SymTab.ClassOf(t);
|
|
|
+ 1399 IF (cls = SymTab.ClInt)
|
|
|
+ 1400 OR (cls = SymTab.ClBool)
|
|
|
+ 1401 OR (cls = SymTab.ClChar)
|
|
|
+ 1402 OR (cls
|
|
|
+ 1403 = SymTab.ClReal) THEN
|
|
|
+ 1404 QbeGen.LoadVar(n,
|
|
|
+ 1405 cls = SymTab.ClReal, q)
|
|
|
+ 1406 ELSIF (cls = SymTab.ClPtr)
|
|
|
+ 1407 OR (cls = SymTab.ClProc) THEN
|
|
|
+ 1408 QbeGen.LoadPtr(n, q)
|
|
|
+ 1409 ELSIF cls = SymTab.ClLong THEN
|
|
|
+ 1410 QbeGen.LoadLong(n, q)
|
|
|
+ 1411 ELSIF (cls
|
|
|
+ 1412 = SymTab.ClArray)
|
|
|
1413 OR (cls
|
|
|
- 1414 = SymTab.ClRecord)
|
|
|
+ 1414 = SymTab.ClSet)
|
|
|
1415 OR (cls
|
|
|
- 1416 = SymTab.ClClass) THEN
|
|
|
- 1417 QbeGen.AddrOf(n, q)
|
|
|
- 1418 ELSE SemError(230);
|
|
|
- 1419 QbeGen.CopyOp("0", q)
|
|
|
- 1420 END
|
|
|
- 1421 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 1422 IF k = SymTab.KindImport THEN
|
|
|
- 1423 SemError(230)
|
|
|
- 1424 ELSIF k =
|
|
|
- 1425 SymTab.KindProc THEN
|
|
|
- 1426 (* bare procedure name:
|
|
|
- 1427 a following ArgList
|
|
|
- 1428 makes it a call;
|
|
|
- 1429 otherwise Fact
|
|
|
- 1430 reports 230 *)
|
|
|
- 1431 ELSE
|
|
|
- 1432 IF k = SymTab.KindField THEN
|
|
|
- 1433 IF QbeGen.TopWith(qb) THEN
|
|
|
- 1434 fo :=
|
|
|
- 1435 SymTab.FieldOffset(
|
|
|
- 1436 SymTab.FieldOwner(n),
|
|
|
- 1437 n);
|
|
|
- 1438 QbeGen.FieldAddr(qb,
|
|
|
- 1439 fo, q);
|
|
|
- 1440 sfx := TRUE
|
|
|
- 1441 ELSE SemError(230);
|
|
|
- 1442 QbeGen.CopyOp("0", q)
|
|
|
- 1443 END
|
|
|
- 1444 END
|
|
|
- 1445 END
|
|
|
- 1446 END
|
|
|
- 1447 END; .)
|
|
|
- 1448 { "[" Expr<it, iq>
|
|
|
- 1449 (. IF t = SymTab.InvalidType THEN
|
|
|
- 1450 ELSIF SymTab.ClassOf(t) #
|
|
|
- 1451 SymTab.ClArray THEN
|
|
|
- 1452 SemError(217);
|
|
|
- 1453 t := SymTab.InvalidType
|
|
|
- 1454 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 1455 AND (SymTab.ClassOf(it) #
|
|
|
- 1456 SymTab.ClChar) THEN
|
|
|
- 1457 SemError(218);
|
|
|
- 1458 t := SymTab.InvalidType
|
|
|
- 1459 ELSE
|
|
|
- 1460 QbeGen.WidenIndex(iq, ql);
|
|
|
- 1461 isOpen :=
|
|
|
- 1462 SymTab.IsOpenArray(t);
|
|
|
- 1463 IF isOpen THEN
|
|
|
- 1464 QbeGen.CopyOp("0", qlo);
|
|
|
- 1465 QbeGen.OpenHi(q, qhi)
|
|
|
- 1466 ELSE
|
|
|
- 1467 lo := SymTab.ArrayLo(t);
|
|
|
- 1468 hi := SymTab.ArrayHi(t);
|
|
|
- 1469 QbeGen.IntStr(lo, qlo);
|
|
|
- 1470 QbeGen.IntStr(hi, qhi)
|
|
|
- 1471 END;
|
|
|
- 1472 QbeGen.CheckRange(ql, qlo,
|
|
|
- 1473 qhi);
|
|
|
- 1474 eT := SymTab.ArrayElem(t);
|
|
|
- 1475 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 1476 t, qe);
|
|
|
- 1477 IF SymTab.ClassOf(eT) =
|
|
|
- 1478 SymTab.ClArray THEN
|
|
|
- 1479 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 1480 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 1481 END;
|
|
|
- 1482 t := eT; sfx := TRUE
|
|
|
- 1483 END; .)
|
|
|
- 1484 { "," Expr<it, iq>
|
|
|
- 1485 (. IF t = SymTab.InvalidType THEN
|
|
|
- 1486 ELSIF SymTab.ClassOf(t) #
|
|
|
- 1487 SymTab.ClArray THEN
|
|
|
- 1488 SemError(217);
|
|
|
- 1489 t := SymTab.InvalidType
|
|
|
- 1490 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 1491 AND (SymTab.ClassOf(it) #
|
|
|
- 1492 SymTab.ClChar) THEN
|
|
|
- 1493 SemError(218);
|
|
|
- 1494 t := SymTab.InvalidType
|
|
|
- 1495 ELSE
|
|
|
- 1496 QbeGen.WidenIndex(iq, ql);
|
|
|
- 1497 isOpen :=
|
|
|
- 1498 SymTab.IsOpenArray(t);
|
|
|
- 1499 IF isOpen THEN
|
|
|
- 1500 QbeGen.CopyOp("0", qlo);
|
|
|
- 1501 QbeGen.OpenHi(q, qhi)
|
|
|
- 1502 ELSE
|
|
|
- 1503 lo := SymTab.ArrayLo(t);
|
|
|
- 1504 hi := SymTab.ArrayHi(t);
|
|
|
- 1505 QbeGen.IntStr(lo, qlo);
|
|
|
- 1506 QbeGen.IntStr(hi, qhi)
|
|
|
- 1507 END;
|
|
|
- 1508 QbeGen.CheckRange(ql, qlo,
|
|
|
- 1509 qhi);
|
|
|
- 1510 eT := SymTab.ArrayElem(t);
|
|
|
- 1511 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 1512 t, qe);
|
|
|
- 1513 IF SymTab.ClassOf(eT) =
|
|
|
- 1514 SymTab.ClArray THEN
|
|
|
- 1515 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 1516 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 1517 END;
|
|
|
- 1518 t := eT; sfx := TRUE
|
|
|
- 1519 END; .) }
|
|
|
- 1520 "]"
|
|
|
- 1521 | "." GetIdent<fn>
|
|
|
- 1522 (. IF k = SymTab.KindModule THEN
|
|
|
- 1523 (* qualified L.x: materialize
|
|
|
- 1524 the export, then load it *)
|
|
|
- 1525 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 1526 fn, mal) THEN
|
|
|
- 1527 SemError(201);
|
|
|
- 1528 t := SymTab.InvalidType;
|
|
|
- 1529 QbeGen.CopyOp("0", q)
|
|
|
- 1530 ELSE
|
|
|
- 1531 QbeGen.CopyOp(mal, qn);
|
|
|
- 1532 t := SymTab.SymType(mal);
|
|
|
- 1533 k := SymTab.SymKind(mal);
|
|
|
- 1534 sfx := FALSE;
|
|
|
- 1535 IF k = SymTab.KindProc THEN
|
|
|
- 1536 (* call: ArgList supplies
|
|
|
- 1537 the value *)
|
|
|
- 1538 QbeGen.CopyOp("0", q)
|
|
|
- 1539 ELSIF NOT QbeGen.LoadDesignator(
|
|
|
- 1540 mal, t, k, q) THEN
|
|
|
- 1541 SemError(230);
|
|
|
- 1542 QbeGen.CopyOp("0", q)
|
|
|
- 1543 END
|
|
|
- 1544 END
|
|
|
- 1545 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 1546 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 1547 SymTab.ClRecord)
|
|
|
- 1548 AND (SymTab.ClassOf(t) #
|
|
|
- 1549 SymTab.ClClass) THEN
|
|
|
- 1550 SemError(215);
|
|
|
- 1551 t := SymTab.InvalidType
|
|
|
- 1552 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 1553 fn) THEN
|
|
|
- 1554 SemError(216);
|
|
|
- 1555 t := SymTab.InvalidType
|
|
|
- 1556 ELSE
|
|
|
- 1557 fo := SymTab.FieldOffset(t,
|
|
|
- 1558 fn);
|
|
|
- 1559 t := SymTab.FieldType(t, fn);
|
|
|
- 1560 QbeGen.FieldAddr(q, fo, qe);
|
|
|
- 1561 IF SymTab.ClassOf(t) =
|
|
|
- 1562 SymTab.ClArray THEN
|
|
|
- 1563 QbeGen.ElemLoad(qe, t, q)
|
|
|
- 1564 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 1565 END;
|
|
|
- 1566 sfx := TRUE
|
|
|
- 1567 END; .)
|
|
|
- 1568 | "^"
|
|
|
- 1569 (. IF t = SymTab.InvalidType THEN
|
|
|
- 1570 ELSIF SymTab.ClassOf(t) #
|
|
|
- 1571 SymTab.ClPtr THEN
|
|
|
- 1572 SemError(219);
|
|
|
- 1573 t := SymTab.InvalidType
|
|
|
- 1574 ELSE
|
|
|
- 1575 bt := SymTab.PtrBase(t);
|
|
|
- 1576 IF bt = SymTab.InvalidType THEN
|
|
|
- 1577 ELSE
|
|
|
- 1578 IF sfx THEN
|
|
|
- 1579 QbeGen.ElemLoad(q, t,
|
|
|
- 1580 qb);
|
|
|
- 1581 QbeGen.CopyOp(qb, q)
|
|
|
- 1582 END;
|
|
|
- 1583 t := bt;
|
|
|
- 1584 IF (SymTab.ClassOf(bt) =
|
|
|
- 1585 SymTab.ClInt)
|
|
|
- 1586 OR (SymTab.ClassOf(bt) =
|
|
|
- 1587 SymTab.ClBool)
|
|
|
+ 1416 = SymTab.ClRecord)
|
|
|
+ 1417 OR (cls
|
|
|
+ 1418 = SymTab.ClClass) THEN
|
|
|
+ 1419 QbeGen.AddrOf(n, q)
|
|
|
+ 1420 ELSE SemError(230);
|
|
|
+ 1421 QbeGen.CopyOp("0", q)
|
|
|
+ 1422 END
|
|
|
+ 1423 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 1424 IF k = SymTab.KindImport THEN
|
|
|
+ 1425 SemError(230)
|
|
|
+ 1426 ELSIF k =
|
|
|
+ 1427 SymTab.KindProc THEN
|
|
|
+ 1428 (* bare procedure name:
|
|
|
+ 1429 a following ArgList
|
|
|
+ 1430 makes it a call;
|
|
|
+ 1431 otherwise Fact
|
|
|
+ 1432 reports 230 *)
|
|
|
+ 1433 ELSE
|
|
|
+ 1434 IF k = SymTab.KindField THEN
|
|
|
+ 1435 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 1436 fo :=
|
|
|
+ 1437 SymTab.FieldOffset(
|
|
|
+ 1438 SymTab.FieldOwner(n),
|
|
|
+ 1439 n);
|
|
|
+ 1440 QbeGen.FieldAddr(qb,
|
|
|
+ 1441 fo, q);
|
|
|
+ 1442 sfx := TRUE
|
|
|
+ 1443 ELSE SemError(230);
|
|
|
+ 1444 QbeGen.CopyOp("0", q)
|
|
|
+ 1445 END
|
|
|
+ 1446 END
|
|
|
+ 1447 END
|
|
|
+ 1448 END
|
|
|
+ 1449 END; .)
|
|
|
+ 1450 { "[" Expr<it, iq>
|
|
|
+ 1451 (. IF t = SymTab.InvalidType THEN
|
|
|
+ 1452 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 1453 SymTab.ClArray THEN
|
|
|
+ 1454 SemError(217);
|
|
|
+ 1455 t := SymTab.InvalidType
|
|
|
+ 1456 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 1457 AND (SymTab.ClassOf(it) #
|
|
|
+ 1458 SymTab.ClChar) THEN
|
|
|
+ 1459 SemError(218);
|
|
|
+ 1460 t := SymTab.InvalidType
|
|
|
+ 1461 ELSE
|
|
|
+ 1462 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 1463 isOpen :=
|
|
|
+ 1464 SymTab.IsOpenArray(t);
|
|
|
+ 1465 IF isOpen THEN
|
|
|
+ 1466 QbeGen.CopyOp("0", qlo);
|
|
|
+ 1467 QbeGen.OpenHi(q, qhi)
|
|
|
+ 1468 ELSE
|
|
|
+ 1469 lo := SymTab.ArrayLo(t);
|
|
|
+ 1470 hi := SymTab.ArrayHi(t);
|
|
|
+ 1471 QbeGen.IntStr(lo, qlo);
|
|
|
+ 1472 QbeGen.IntStr(hi, qhi)
|
|
|
+ 1473 END;
|
|
|
+ 1474 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 1475 qhi);
|
|
|
+ 1476 eT := SymTab.ArrayElem(t);
|
|
|
+ 1477 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 1478 t, qe);
|
|
|
+ 1479 IF SymTab.ClassOf(eT) =
|
|
|
+ 1480 SymTab.ClArray THEN
|
|
|
+ 1481 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 1482 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 1483 END;
|
|
|
+ 1484 t := eT; sfx := TRUE
|
|
|
+ 1485 END; .)
|
|
|
+ 1486 { "," Expr<it, iq>
|
|
|
+ 1487 (. IF t = SymTab.InvalidType THEN
|
|
|
+ 1488 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 1489 SymTab.ClArray THEN
|
|
|
+ 1490 SemError(217);
|
|
|
+ 1491 t := SymTab.InvalidType
|
|
|
+ 1492 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 1493 AND (SymTab.ClassOf(it) #
|
|
|
+ 1494 SymTab.ClChar) THEN
|
|
|
+ 1495 SemError(218);
|
|
|
+ 1496 t := SymTab.InvalidType
|
|
|
+ 1497 ELSE
|
|
|
+ 1498 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 1499 isOpen :=
|
|
|
+ 1500 SymTab.IsOpenArray(t);
|
|
|
+ 1501 IF isOpen THEN
|
|
|
+ 1502 QbeGen.CopyOp("0", qlo);
|
|
|
+ 1503 QbeGen.OpenHi(q, qhi)
|
|
|
+ 1504 ELSE
|
|
|
+ 1505 lo := SymTab.ArrayLo(t);
|
|
|
+ 1506 hi := SymTab.ArrayHi(t);
|
|
|
+ 1507 QbeGen.IntStr(lo, qlo);
|
|
|
+ 1508 QbeGen.IntStr(hi, qhi)
|
|
|
+ 1509 END;
|
|
|
+ 1510 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 1511 qhi);
|
|
|
+ 1512 eT := SymTab.ArrayElem(t);
|
|
|
+ 1513 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 1514 t, qe);
|
|
|
+ 1515 IF SymTab.ClassOf(eT) =
|
|
|
+ 1516 SymTab.ClArray THEN
|
|
|
+ 1517 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 1518 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 1519 END;
|
|
|
+ 1520 t := eT; sfx := TRUE
|
|
|
+ 1521 END; .) }
|
|
|
+ 1522 "]"
|
|
|
+ 1523 | "." GetIdent<fn>
|
|
|
+ 1524 (. IF k = SymTab.KindModule THEN
|
|
|
+ 1525 (* qualified L.x: materialize
|
|
|
+ 1526 the export, then load it *)
|
|
|
+ 1527 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 1528 fn, mal) THEN
|
|
|
+ 1529 SemError(201);
|
|
|
+ 1530 t := SymTab.InvalidType;
|
|
|
+ 1531 QbeGen.CopyOp("0", q)
|
|
|
+ 1532 ELSE
|
|
|
+ 1533 QbeGen.CopyOp(mal, qn);
|
|
|
+ 1534 t := SymTab.SymType(mal);
|
|
|
+ 1535 k := SymTab.SymKind(mal);
|
|
|
+ 1536 sfx := FALSE;
|
|
|
+ 1537 IF k = SymTab.KindProc THEN
|
|
|
+ 1538 (* call: ArgList supplies
|
|
|
+ 1539 the value *)
|
|
|
+ 1540 QbeGen.CopyOp("0", q)
|
|
|
+ 1541 ELSIF NOT QbeGen.LoadDesignator(
|
|
|
+ 1542 mal, t, k, q) THEN
|
|
|
+ 1543 SemError(230);
|
|
|
+ 1544 QbeGen.CopyOp("0", q)
|
|
|
+ 1545 END
|
|
|
+ 1546 END
|
|
|
+ 1547 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 1548 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 1549 SymTab.ClRecord)
|
|
|
+ 1550 AND (SymTab.ClassOf(t) #
|
|
|
+ 1551 SymTab.ClClass) THEN
|
|
|
+ 1552 SemError(215);
|
|
|
+ 1553 t := SymTab.InvalidType
|
|
|
+ 1554 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 1555 fn) THEN
|
|
|
+ 1556 SemError(216);
|
|
|
+ 1557 t := SymTab.InvalidType
|
|
|
+ 1558 ELSE
|
|
|
+ 1559 fo := SymTab.FieldOffset(t,
|
|
|
+ 1560 fn);
|
|
|
+ 1561 t := SymTab.FieldType(t, fn);
|
|
|
+ 1562 QbeGen.FieldAddr(q, fo, qe);
|
|
|
+ 1563 IF SymTab.ClassOf(t) =
|
|
|
+ 1564 SymTab.ClArray THEN
|
|
|
+ 1565 QbeGen.ElemLoad(qe, t, q)
|
|
|
+ 1566 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 1567 END;
|
|
|
+ 1568 sfx := TRUE
|
|
|
+ 1569 END; .)
|
|
|
+ 1570 | "^"
|
|
|
+ 1571 (. IF t = SymTab.InvalidType THEN
|
|
|
+ 1572 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 1573 SymTab.ClPtr THEN
|
|
|
+ 1574 SemError(219);
|
|
|
+ 1575 t := SymTab.InvalidType
|
|
|
+ 1576 ELSE
|
|
|
+ 1577 bt := SymTab.PtrBase(t);
|
|
|
+ 1578 IF bt = SymTab.InvalidType THEN
|
|
|
+ 1579 ELSE
|
|
|
+ 1580 IF sfx THEN
|
|
|
+ 1581 QbeGen.ElemLoad(q, t,
|
|
|
+ 1582 qb);
|
|
|
+ 1583 QbeGen.CopyOp(qb, q)
|
|
|
+ 1584 END;
|
|
|
+ 1585 t := bt;
|
|
|
+ 1586 IF (SymTab.ClassOf(bt) =
|
|
|
+ 1587 SymTab.ClInt)
|
|
|
1588 OR (SymTab.ClassOf(bt) =
|
|
|
- 1589 SymTab.ClChar)
|
|
|
+ 1589 SymTab.ClBool)
|
|
|
1590 OR (SymTab.ClassOf(bt) =
|
|
|
- 1591 SymTab.ClReal) THEN
|
|
|
- 1592 sfx := TRUE
|
|
|
- 1593 ELSE sfx := FALSE
|
|
|
- 1594 END
|
|
|
- 1595 END
|
|
|
- 1596 END; .) } .
|
|
|
- 1597 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1598 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 1599 op: INTEGER;
|
|
|
- 1600 q2, qt, wl: QbeGen.QVal;
|
|
|
- 1601 isR: BOOLEAN; .)
|
|
|
- 1602 = SimExpr<t, q>
|
|
|
- 1603 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 1604 (. IF op = SymTab.OpIn THEN
|
|
|
- 1605 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 1606 IF (t = SymTab.InvalidType)
|
|
|
- 1607 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 1608 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 1609 ELSE
|
|
|
- 1610 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
- 1611 SymTab.SetCount(t2), qt);
|
|
|
- 1612 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 1613 END
|
|
|
- 1614 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 1615 QbeGen.CopyOp("0", q)
|
|
|
- 1616 END
|
|
|
- 1617 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 1618 IF (t = SymTab.InvalidType)
|
|
|
- 1619 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 1620 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 1621 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 1622 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 1623 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 1624 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 1625 SemError(213); t := SymTab.InvalidType;
|
|
|
- 1626 QbeGen.CopyOp("0", q)
|
|
|
- 1627 ELSE
|
|
|
- 1628 QbeGen.CmpL(op, q, q2, qt);
|
|
|
- 1629 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 1630 END
|
|
|
- 1631 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 1632 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 1633 QbeGen.CmpSet(op, q, q2,
|
|
|
- 1634 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
- 1635 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 1636 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 1637 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 1638 IF SymTab.IsIntFamily(t) THEN
|
|
|
- 1639 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
|
|
|
- 1640 END;
|
|
|
- 1641 IF SymTab.IsIntFamily(t2) THEN
|
|
|
- 1642 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
|
|
|
- 1643 END;
|
|
|
- 1644 QbeGen.CmpLong(op, q, q2, qt);
|
|
|
- 1645 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 1646 ELSE
|
|
|
- 1647 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 1648 t := SymTab.BoolType();
|
|
|
- 1649 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
- 1650 QbeGen.CopyOp(qt, q)
|
|
|
- 1651 END
|
|
|
- 1652 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 1653 QbeGen.CopyOp("0", q)
|
|
|
- 1654 END; .) ] .
|
|
|
- 1655 Rel<VAR op: INTEGER>
|
|
|
- 1656 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 1657 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 1658 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 1659 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 1660 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 1661 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 1662 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 1663 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1664 (. VAR t2, res2, lt, rt:
|
|
|
- 1665 SymTab.TypeIndex;
|
|
|
- 1666 op: INTEGER;
|
|
|
- 1667 q2, qt, wq, qf:
|
|
|
- 1668 QbeGen.QVal;
|
|
|
- 1669 neg, isR, isL, folded:
|
|
|
- 1670 BOOLEAN;
|
|
|
- 1671 lw, rw, mw: CARDINAL; .)
|
|
|
- 1672 = (. neg := FALSE; .)
|
|
|
- 1673 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
- 1674 Term<t, q> (. IF neg THEN
|
|
|
- 1675 IF QbeGen.IsImm(q) THEN
|
|
|
- 1676 QbeGen.NegFold(q, q)
|
|
|
- 1677 ELSE QbeGen.NewTemp(qt);
|
|
|
- 1678 QbeGen.NegQ(q, qt,
|
|
|
- 1679 SymTab.ClassOf(t)
|
|
|
- 1680 = SymTab.ClReal);
|
|
|
- 1681 QbeGen.CopyOp(qt, q)
|
|
|
- 1682 END
|
|
|
- 1683 END; .)
|
|
|
- 1684 { AddOp<op> Term<t2, q2>
|
|
|
- 1685 (. IF op = SymTab.OpOr THEN
|
|
|
- 1686 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 1687 t := SymTab.BoolType()
|
|
|
- 1688 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 1689 IF t # SymTab.InvalidType THEN
|
|
|
- 1690 QbeGen.NewTemp(qt);
|
|
|
- 1691 QbeGen.Op3("or", qt, q, q2, FALSE);
|
|
|
- 1692 QbeGen.CopyOp(qt, q)
|
|
|
- 1693 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1694 END
|
|
|
- 1695 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 1696 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 1697 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 1698 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 1699 mw := lw;
|
|
|
- 1700 IF rw > mw THEN mw := rw END;
|
|
|
- 1701 IF op = SymTab.OpAdd THEN
|
|
|
- 1702 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
- 1703 ELSE
|
|
|
- 1704 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
- 1705 END;
|
|
|
- 1706 t := SymTab.NewSet(
|
|
|
- 1707 SymTab.NewSubR(0,
|
|
|
- 1708 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 1709 QbeGen.CopyOp(qt, q)
|
|
|
- 1710 ELSE
|
|
|
- 1711 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 1712 lt := t; rt := t2; t := res2
|
|
|
- 1713 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 1714 IF t # SymTab.InvalidType THEN
|
|
|
- 1715 isL := SymTab.IsLongFamily(t);
|
|
|
- 1716 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 1717 folded := FALSE;
|
|
|
- 1718 IF (NOT isL) AND (NOT isR)
|
|
|
- 1719 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 1720 IF op = SymTab.OpAdd THEN
|
|
|
- 1721 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 1722 ELSE
|
|
|
- 1723 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 1724 END
|
|
|
- 1725 END;
|
|
|
- 1726 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 1727 ELSE
|
|
|
- 1728 IF isL THEN
|
|
|
- 1729 IF SymTab.IsIntFamily(lt) THEN
|
|
|
- 1730 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
- 1731 END;
|
|
|
- 1732 IF SymTab.IsIntFamily(rt) THEN
|
|
|
- 1733 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
- 1734 END;
|
|
|
- 1735 QbeGen.NewTemp(qt);
|
|
|
- 1736 IF op = SymTab.OpAdd THEN
|
|
|
- 1737 QbeGen.Op3L("add", qt, q, q2)
|
|
|
- 1738 ELSE
|
|
|
- 1739 QbeGen.Op3L("sub", qt, q, q2)
|
|
|
- 1740 END
|
|
|
- 1741 ELSE
|
|
|
- 1742 QbeGen.NewTemp(qt);
|
|
|
- 1743 IF op = SymTab.OpAdd THEN
|
|
|
- 1744 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
- 1745 ELSE
|
|
|
- 1746 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
- 1747 END
|
|
|
- 1748 END;
|
|
|
- 1749 QbeGen.CopyOp(qt, q)
|
|
|
- 1750 END
|
|
|
- 1751 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1752 END
|
|
|
- 1753 END; .) } .
|
|
|
- 1754 AddOp<VAR op: INTEGER>
|
|
|
- 1755 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 1756 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 1757 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 1758 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1759 (. VAR t2, res2, lt, rt:
|
|
|
- 1760 SymTab.TypeIndex;
|
|
|
- 1761 op: INTEGER;
|
|
|
- 1762 q2, qt, wq, qf:
|
|
|
- 1763 QbeGen.QVal;
|
|
|
- 1764 isR, isL, folded: BOOLEAN;
|
|
|
- 1765 lw, rw, mw: CARDINAL; .)
|
|
|
- 1766 = Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
|
- 1767 (. IF op = SymTab.OpAnd THEN
|
|
|
- 1768 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 1769 t := SymTab.BoolType()
|
|
|
- 1770 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 1771 IF t # SymTab.InvalidType THEN
|
|
|
- 1772 QbeGen.NewTemp(qt);
|
|
|
- 1773 QbeGen.Op3("and", qt, q, q2, FALSE);
|
|
|
- 1774 QbeGen.CopyOp(qt, q)
|
|
|
- 1775 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1776 END
|
|
|
- 1777 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 1778 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 1779 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 1780 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 1781 mw := lw;
|
|
|
- 1782 IF rw > mw THEN mw := rw END;
|
|
|
- 1783 IF op = SymTab.OpTimes THEN
|
|
|
- 1784 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
- 1785 ELSE
|
|
|
- 1786 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
- 1787 END;
|
|
|
- 1788 t := SymTab.NewSet(
|
|
|
- 1789 SymTab.NewSubR(0,
|
|
|
- 1790 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 1791 QbeGen.CopyOp(qt, q)
|
|
|
- 1792 ELSE
|
|
|
- 1793 IF SymTab.ArithCheck(t, t2,
|
|
|
- 1794 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 1795 res2) THEN
|
|
|
- 1796 lt := t; rt := t2; t := res2
|
|
|
- 1797 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 1798 IF t # SymTab.InvalidType THEN
|
|
|
- 1799 isL := SymTab.IsLongFamily(t);
|
|
|
- 1800 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 1801 folded := FALSE;
|
|
|
- 1802 IF (NOT isL) AND (NOT isR)
|
|
|
- 1803 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 1804 IF op = SymTab.OpTimes THEN
|
|
|
- 1805 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 1806 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 1807 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 1808 ELSIF op = SymTab.OpMod THEN
|
|
|
- 1809 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 1810 END
|
|
|
- 1811 END;
|
|
|
- 1812 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 1813 ELSE
|
|
|
- 1814 IF isL THEN
|
|
|
- 1815 IF SymTab.IsIntFamily(lt) THEN
|
|
|
- 1816 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
- 1817 END;
|
|
|
- 1818 IF SymTab.IsIntFamily(rt) THEN
|
|
|
- 1819 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
- 1820 END;
|
|
|
- 1821 QbeGen.NewTemp(qt);
|
|
|
- 1822 IF op = SymTab.OpTimes THEN
|
|
|
- 1823 QbeGen.Op3L("mul", qt, q, q2)
|
|
|
- 1824 ELSIF (op = SymTab.OpDiv)
|
|
|
- 1825 OR (op = SymTab.OpSlash) THEN
|
|
|
- 1826 QbeGen.Op3L("div", qt, q, q2)
|
|
|
- 1827 ELSE
|
|
|
- 1828 QbeGen.Op3L("rem", qt, q, q2)
|
|
|
- 1829 END
|
|
|
- 1830 ELSE
|
|
|
- 1831 QbeGen.NewTemp(qt);
|
|
|
- 1832 IF op = SymTab.OpTimes THEN
|
|
|
- 1833 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
- 1834 ELSIF (op = SymTab.OpDiv)
|
|
|
- 1835 OR (op = SymTab.OpSlash) THEN
|
|
|
- 1836 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
- 1837 ELSE
|
|
|
- 1838 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
- 1839 END
|
|
|
- 1840 END;
|
|
|
- 1841 QbeGen.CopyOp(qt, q)
|
|
|
- 1842 END
|
|
|
- 1843 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 1844 END
|
|
|
- 1845 END; .) } .
|
|
|
- 1846 MulOp<VAR op: INTEGER>
|
|
|
- 1847 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 1848 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 1849 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 1850 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 1851 | "AND" (. op := SymTab.OpAnd; .) .
|
|
|
- 1852 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1853 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 1854 et, dt, t2, st, ct2:
|
|
|
- 1855 SymTab.TypeIndex;
|
|
|
- 1856 dk: INTEGER;
|
|
|
- 1857 qd, q2, sq, qa, qm0, qr:
|
|
|
- 1858 QbeGen.QVal;
|
|
|
- 1859 qn, vn: SymTab.Name;
|
|
|
- 1860 vt: SymTab.TypeIndex;
|
|
|
- 1861 c1, c2: INTEGER;
|
|
|
- 1862 called, isHigh, sfx:
|
|
|
- 1863 BOOLEAN; .)
|
|
|
- 1864 = integer (. LexString(s);
|
|
|
- 1865 QbeGen.NormInt(s, q);
|
|
|
- 1866 t := SymTab.IntType(); .)
|
|
|
- 1867 | real (. LexString(s);
|
|
|
- 1868 QbeGen.NormReal(s, q);
|
|
|
- 1869 t := SymTab.RealType(); .)
|
|
|
- 1870 | string (. LexString(s);
|
|
|
- 1871 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 1872 t := SymTab.CharType();
|
|
|
- 1873 QbeGen.IntStr(
|
|
|
- 1874 QbeGen.CharVal(s), q)
|
|
|
- 1875 ELSE t := SymTab.NewStr();
|
|
|
- 1876 QbeGen.DeclStr(s, q);
|
|
|
- 1877 (* a literal's value IS its
|
|
|
- 1878 static descriptor address *)
|
|
|
- 1879 QbeGen.NoteAddr(q, q)
|
|
|
- 1880 END; .)
|
|
|
- 1881 | Design<dt, dk, qd, qn, sfx> (. called := FALSE;
|
|
|
- 1882 t := dt;
|
|
|
- 1883 IF sfx THEN
|
|
|
- 1884 IF dt =
|
|
|
- 1885 SymTab.InvalidType THEN
|
|
|
- 1886 QbeGen.CopyOp("0", q)
|
|
|
- 1887 ELSIF (SymTab.ClassOf(dt) =
|
|
|
- 1888 SymTab.ClRecord)
|
|
|
- 1889 OR (SymTab.ClassOf(dt) =
|
|
|
- 1890 SymTab.ClSet)
|
|
|
- 1891 OR (SymTab.ClassOf(dt) =
|
|
|
- 1892 SymTab.ClArray)
|
|
|
- 1893 OR (SymTab.ClassOf(dt) =
|
|
|
- 1894 SymTab.ClClass) THEN
|
|
|
- 1895 QbeGen.CopyOp(qd, q)
|
|
|
- 1896 ELSE QbeGen.ElemLoad(qd, dt,
|
|
|
- 1897 q)
|
|
|
- 1898 END
|
|
|
- 1899 ELSE QbeGen.CopyOp(qd, q)
|
|
|
- 1900 END;
|
|
|
- 1901 IF (dk = SymTab.KindVar)
|
|
|
- 1902 OR (dk = SymTab.KindParam)
|
|
|
- 1903 OR (dk =
|
|
|
- 1904 SymTab.KindField) THEN
|
|
|
- 1905 IF sfx THEN
|
|
|
- 1906 QbeGen.NoteAddr(q, qd)
|
|
|
- 1907 ELSE
|
|
|
- 1908 QbeGen.AddrOf(qn, qa);
|
|
|
- 1909 QbeGen.NoteAddr(q, qa)
|
|
|
- 1910 END
|
|
|
- 1911 ELSIF sfx
|
|
|
- 1912 AND (dt #
|
|
|
- 1913 SymTab.InvalidType)
|
|
|
- 1914 AND ((SymTab.ClassOf(dt) =
|
|
|
- 1915 SymTab.ClArray)
|
|
|
- 1916 OR (SymTab.ClassOf(dt) =
|
|
|
- 1917 SymTab.ClSet)
|
|
|
- 1918 OR (SymTab.ClassOf(dt) =
|
|
|
- 1919 SymTab.ClRecord)) THEN
|
|
|
- 1920 QbeGen.NoteAddr(qd, qd)
|
|
|
- 1921 END; .)
|
|
|
- 1922 [ ArgList<qn, dt, qd, TRUE, ct2, q2, called>
|
|
|
- 1923 (. t := ct2;
|
|
|
- 1924 QbeGen.CopyOp(q2, q); .) ]
|
|
|
- 1925 (. IF NOT called
|
|
|
- 1926 AND (dk = SymTab.KindProc) THEN
|
|
|
- 1927 (* bare zero-arg function
|
|
|
- 1928 call (parentheses may be
|
|
|
- 1929 omitted); a proper or
|
|
|
- 1930 parameterised proc here
|
|
|
- 1931 is 230 *)
|
|
|
- 1932 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 1933 AND (SymTab.ProcRes(qn) #
|
|
|
- 1934 SymTab.InvalidType) THEN
|
|
|
- 1935 QbeGen.Mangled(qn,
|
|
|
- 1936 SymTab.ProcUid(qn), qm0);
|
|
|
- 1937 QbeGen.CallBegin(qm0,
|
|
|
- 1938 SymTab.ProcRes(qn),
|
|
|
- 1939 SymTab.ProcDepthOf(qn),
|
|
|
- 1940 SymTab.IsExternal(qn));
|
|
|
- 1941 QbeGen.CallEnd(TRUE, q);
|
|
|
- 1942 t := SymTab.ProcRes(qn)
|
|
|
- 1943 ELSE
|
|
|
- 1944 (* procedure used as a
|
|
|
- 1945 value (assign to a
|
|
|
- 1946 procedure variable):
|
|
|
- 1947 its code address *)
|
|
|
- 1948 t := SymTab.ProcTypeOf(qn);
|
|
|
- 1949 QbeGen.Mangled(qn,
|
|
|
- 1950 SymTab.ProcUid(qn), qm0);
|
|
|
- 1951 QbeGen.ProcAddr(qm0, q)
|
|
|
- 1952 END
|
|
|
- 1953 END; .)
|
|
|
- 1954 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 1955 | "LEN" (. isHigh := FALSE; .) )
|
|
|
- 1956 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 1957 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1958 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1959 SymTab.ClArray THEN
|
|
|
- 1960 SemError(217);
|
|
|
- 1961 t := SymTab.InvalidType;
|
|
|
- 1962 QbeGen.CopyOp("0", q)
|
|
|
- 1963 ELSE
|
|
|
- 1964 IF isHigh THEN
|
|
|
- 1965 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 1966 QbeGen.OpenHi(qd, qr)
|
|
|
- 1967 ELSE
|
|
|
- 1968 QbeGen.IntStr(
|
|
|
- 1969 SymTab.ArrayHi(dt), qr)
|
|
|
- 1970 END
|
|
|
- 1971 ELSE
|
|
|
- 1972 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 1973 QbeGen.LoadCount(qd, qr)
|
|
|
- 1974 ELSE
|
|
|
- 1975 QbeGen.IntStr(VAL(
|
|
|
- 1976 INTEGER,
|
|
|
- 1977 SymTab.ArrayLen(dt)),
|
|
|
- 1978 qr)
|
|
|
- 1979 END
|
|
|
- 1980 END;
|
|
|
- 1981 t := SymTab.IntType();
|
|
|
- 1982 QbeGen.CopyOp(qr, q)
|
|
|
- 1983 END; .)
|
|
|
- 1984 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 1985 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1986 t := SymTab.InvalidType;
|
|
|
- 1987 QbeGen.CopyOp("0", q)
|
|
|
- 1988 ELSE
|
|
|
- 1989 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 1990 SymTab.ObjectSize(dt)), q);
|
|
|
- 1991 t := SymTab.IntType()
|
|
|
- 1992 END; .)
|
|
|
- 1993 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 1994 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1995 t := SymTab.InvalidType;
|
|
|
- 1996 QbeGen.CopyOp("0", q)
|
|
|
- 1997 ELSE
|
|
|
- 1998 IF sfx THEN
|
|
|
- 1999 QbeGen.CopyOp(qd, q)
|
|
|
- 2000 ELSIF (dk = SymTab.KindVar)
|
|
|
- 2001 OR (dk = SymTab.KindParam) THEN
|
|
|
- 2002 QbeGen.AddrOf(qn, q)
|
|
|
- 2003 ELSE SemError(230);
|
|
|
- 2004 QbeGen.CopyOp("0", q)
|
|
|
- 2005 END;
|
|
|
- 2006 t := SymTab.AddrType()
|
|
|
- 2007 END; .)
|
|
|
- 2008 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 2009 (. IF (et # SymTab.InvalidType)
|
|
|
- 2010 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 2011 SemError(211) END;
|
|
|
- 2012 t := SymTab.CharType(); .)
|
|
|
- 2013 | "ORD" "(" Expr<et, q> ")"
|
|
|
- 2014 (. IF et # SymTab.InvalidType THEN
|
|
|
- 2015 IF (SymTab.ClassOf(et) #
|
|
|
- 2016 SymTab.ClChar)
|
|
|
- 2017 AND (SymTab.ClassOf(et) #
|
|
|
- 2018 SymTab.ClBool)
|
|
|
- 2019 AND (SymTab.ClassOf(et) #
|
|
|
- 2020 SymTab.ClEnum)
|
|
|
- 2021 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 2022 SemError(211) END
|
|
|
- 2023 END;
|
|
|
- 2024 t := SymTab.IntType(); .)
|
|
|
- 2025 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 2026 (. IF (et # SymTab.InvalidType)
|
|
|
- 2027 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 2028 AND (SymTab.ClassOf(et) #
|
|
|
- 2029 SymTab.ClReal) THEN
|
|
|
- 2030 SemError(211)
|
|
|
- 2031 ELSE QbeGen.AbsQ(q, qa,
|
|
|
- 2032 SymTab.ClassOf(et) =
|
|
|
- 2033 SymTab.ClReal)
|
|
|
- 2034 END;
|
|
|
- 2035 t := et; .)
|
|
|
- 2036 | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
|
|
|
- 2037 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 2038 SemError(201);
|
|
|
- 2039 t := SymTab.InvalidType
|
|
|
- 2040 ELSE vt := SymTab.SymType(vn);
|
|
|
- 2041 IF vt = SymTab.InvalidType THEN
|
|
|
- 2042 t := SymTab.InvalidType
|
|
|
- 2043 ELSIF et =
|
|
|
- 2044 SymTab.InvalidType THEN
|
|
|
- 2045 t := vt
|
|
|
- 2046 ELSE
|
|
|
- 2047 c1 := SymTab.ClassOf(et);
|
|
|
- 2048 c2 := SymTab.ClassOf(vt);
|
|
|
- 2049 IF ((c1 = SymTab.ClInt)
|
|
|
- 2050 OR (c1 =
|
|
|
- 2051 SymTab.ClChar)
|
|
|
- 2052 OR (c1 =
|
|
|
- 2053 SymTab.ClBool)
|
|
|
- 2054 OR (c1 =
|
|
|
- 2055 SymTab.ClEnum))
|
|
|
- 2056 AND ((c2 = SymTab.ClInt)
|
|
|
- 2057 OR (c2 =
|
|
|
- 2058 SymTab.ClChar)
|
|
|
- 2059 OR (c2 =
|
|
|
- 2060 SymTab.ClBool)
|
|
|
- 2061 OR (c2 =
|
|
|
- 2062 SymTab.ClEnum)) THEN
|
|
|
- 2063 t := vt
|
|
|
- 2064 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 2065 AND (c2 = SymTab.ClPtr) THEN
|
|
|
- 2066 t := vt
|
|
|
- 2067 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 2068 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 2069 t := vt
|
|
|
- 2070 ELSE SemError(230);
|
|
|
- 2071 t := SymTab.InvalidType
|
|
|
- 2072 END
|
|
|
- 2073 END
|
|
|
- 2074 END; .)
|
|
|
- 2075 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
- 2076 | SetLit<st, sq> (. t := st;
|
|
|
- 2077 QbeGen.CopyOp(sq, q); .)
|
|
|
- 2078 | "NOT" Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
- 2079 t := SymTab.BoolType()
|
|
|
- 2080 ELSE SemError(212);
|
|
|
- 2081 t := SymTab.InvalidType END;
|
|
|
- 2082 IF t # SymTab.InvalidType THEN
|
|
|
- 2083 QbeGen.NotQ(q2, q)
|
|
|
- 2084 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2085 END; .) .
|
|
|
- 2086 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 2087 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 2088 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 2089 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2090 = "{" (. t := SymTab.NewSet(
|
|
|
- 2091 SymTab.NewSubR(0, 255));
|
|
|
- 2092 QbeGen.NewSetTemp(8, q);
|
|
|
- 2093 QbeGen.SetZero(q, 8); .)
|
|
|
- 2094 [ SetElem<t, q> { "," SetElem<t, q> } ]
|
|
|
- 2095 "}" .
|
|
|
- 2096 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 2097 qe, q2: QbeGen.QVal;
|
|
|
- 2098 v, v2: INTEGER;
|
|
|
- 2099 lo: INTEGER;
|
|
|
- 2100 span: CARDINAL;
|
|
|
- 2101 cl, cl2: INTEGER;
|
|
|
- 2102 hasR: BOOLEAN; .)
|
|
|
- 2103 = (. hasR := FALSE; .)
|
|
|
- 2104 Expr<et, qe>
|
|
|
- 2105 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
- 2106 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 2107 span := SymTab.SetCount(st);
|
|
|
- 2108 IF (et = SymTab.InvalidType)
|
|
|
- 2109 OR (hasR AND (et2 =
|
|
|
- 2110 SymTab.InvalidType)) THEN
|
|
|
- 2111 ELSE cl :=
|
|
|
- 2112 SymTab.ClassOf(et);
|
|
|
- 2113 IF hasR THEN
|
|
|
- 2114 cl2 :=
|
|
|
- 2115 SymTab.ClassOf(et2)
|
|
|
- 2116 ELSE cl2 := SymTab.ClInt
|
|
|
- 2117 END;
|
|
|
- 2118 IF ((cl # SymTab.ClInt)
|
|
|
- 2119 AND (cl # SymTab.ClChar)
|
|
|
- 2120 AND (cl # SymTab.ClBool))
|
|
|
- 2121 OR (hasR AND
|
|
|
- 2122 ((cl2
|
|
|
- 2123 # SymTab.ClInt)
|
|
|
- 2124 AND (cl2
|
|
|
- 2125 # SymTab.ClChar)
|
|
|
- 2126 AND (cl2
|
|
|
- 2127 # SymTab.ClBool))) THEN
|
|
|
- 2128 SemError(222)
|
|
|
- 2129 ELSIF hasR
|
|
|
- 2130 AND SymTab.ConstInt(qe, v)
|
|
|
- 2131 AND SymTab.ConstInt(q2,
|
|
|
- 2132 v2)
|
|
|
- 2133 AND ((v < lo)
|
|
|
- 2134 OR (v2 < lo)
|
|
|
- 2135 OR (v >= lo +
|
|
|
- 2136 VAL(INTEGER, span))
|
|
|
- 2137 OR (v2 >= lo +
|
|
|
- 2138 VAL(INTEGER, span))
|
|
|
- 2139 OR (v > v2)) THEN
|
|
|
- 2140 SemError(222)
|
|
|
- 2141 ELSIF hasR THEN
|
|
|
- 2142 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 2143 lo, span)
|
|
|
- 2144 ELSIF SymTab.ConstInt(qe,
|
|
|
- 2145 v)
|
|
|
- 2146 AND ((v < lo)
|
|
|
- 2147 OR (v >= lo +
|
|
|
- 2148 VAL(INTEGER,
|
|
|
- 2149 span))) THEN
|
|
|
- 2150 SemError(222)
|
|
|
- 2151 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 2152 lo, span)
|
|
|
- 2153 END
|
|
|
- 2154 END; .) .
|
|
|
- 2155 GetIdent<VAR n: SymTab.Name>
|
|
|
- 2156 = ident (. LexName(n); .) .
|
|
|
- 2157
|
|
|
- 2158 END M2.
|
|
|
+ 1591 SymTab.ClChar)
|
|
|
+ 1592 OR (SymTab.ClassOf(bt) =
|
|
|
+ 1593 SymTab.ClReal) THEN
|
|
|
+ 1594 sfx := TRUE
|
|
|
+ 1595 ELSE sfx := FALSE
|
|
|
+ 1596 END
|
|
|
+ 1597 END
|
|
|
+ 1598 END; .) } .
|
|
|
+ 1599 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1600 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 1601 op: INTEGER;
|
|
|
+ 1602 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 1603 isR: BOOLEAN; .)
|
|
|
+ 1604 = SimExpr<t, q>
|
|
|
+ 1605 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 1606 (. IF op = SymTab.OpIn THEN
|
|
|
+ 1607 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 1608 IF (t = SymTab.InvalidType)
|
|
|
+ 1609 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 1610 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 1611 ELSE
|
|
|
+ 1612 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
+ 1613 SymTab.SetCount(t2), qt);
|
|
|
+ 1614 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 1615 END
|
|
|
+ 1616 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 1617 QbeGen.CopyOp("0", q)
|
|
|
+ 1618 END
|
|
|
+ 1619 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 1620 IF (t = SymTab.InvalidType)
|
|
|
+ 1621 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 1622 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 1623 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 1624 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 1625 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 1626 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 1627 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 1628 QbeGen.CopyOp("0", q)
|
|
|
+ 1629 ELSE
|
|
|
+ 1630 QbeGen.CmpL(op, q, q2, qt);
|
|
|
+ 1631 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 1632 END
|
|
|
+ 1633 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 1634 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 1635 QbeGen.CmpSet(op, q, q2,
|
|
|
+ 1636 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
+ 1637 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 1638 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 1639 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 1640 IF SymTab.IsIntFamily(t) THEN
|
|
|
+ 1641 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
|
|
|
+ 1642 END;
|
|
|
+ 1643 IF SymTab.IsIntFamily(t2) THEN
|
|
|
+ 1644 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
|
|
|
+ 1645 END;
|
|
|
+ 1646 QbeGen.CmpLong(op, q, q2, qt);
|
|
|
+ 1647 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 1648 ELSE
|
|
|
+ 1649 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 1650 t := SymTab.BoolType();
|
|
|
+ 1651 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
+ 1652 QbeGen.CopyOp(qt, q)
|
|
|
+ 1653 END
|
|
|
+ 1654 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 1655 QbeGen.CopyOp("0", q)
|
|
|
+ 1656 END; .) ] .
|
|
|
+ 1657 Rel<VAR op: INTEGER>
|
|
|
+ 1658 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 1659 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 1660 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 1661 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 1662 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 1663 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 1664 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 1665 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1666 (. VAR t2, res2, lt, rt:
|
|
|
+ 1667 SymTab.TypeIndex;
|
|
|
+ 1668 op: INTEGER;
|
|
|
+ 1669 q2, qt, wq, qf:
|
|
|
+ 1670 QbeGen.QVal;
|
|
|
+ 1671 neg, isR, isL, folded:
|
|
|
+ 1672 BOOLEAN;
|
|
|
+ 1673 lw, rw, mw: CARDINAL; .)
|
|
|
+ 1674 = (. neg := FALSE; .)
|
|
|
+ 1675 [ "+" | "-" (. neg := TRUE; .) ]
|
|
|
+ 1676 Term<t, q> (. IF neg THEN
|
|
|
+ 1677 IF QbeGen.IsImm(q) THEN
|
|
|
+ 1678 QbeGen.NegFold(q, q)
|
|
|
+ 1679 ELSE QbeGen.NewTemp(qt);
|
|
|
+ 1680 QbeGen.NegQ(q, qt,
|
|
|
+ 1681 SymTab.ClassOf(t)
|
|
|
+ 1682 = SymTab.ClReal);
|
|
|
+ 1683 QbeGen.CopyOp(qt, q)
|
|
|
+ 1684 END
|
|
|
+ 1685 END; .)
|
|
|
+ 1686 { AddOp<op> Term<t2, q2>
|
|
|
+ 1687 (. IF op = SymTab.OpOr THEN
|
|
|
+ 1688 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 1689 t := SymTab.BoolType()
|
|
|
+ 1690 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 1691 IF t # SymTab.InvalidType THEN
|
|
|
+ 1692 QbeGen.NewTemp(qt);
|
|
|
+ 1693 QbeGen.Op3("or", qt, q, q2, FALSE);
|
|
|
+ 1694 QbeGen.CopyOp(qt, q)
|
|
|
+ 1695 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1696 END
|
|
|
+ 1697 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 1698 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 1699 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 1700 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 1701 mw := lw;
|
|
|
+ 1702 IF rw > mw THEN mw := rw END;
|
|
|
+ 1703 IF op = SymTab.OpAdd THEN
|
|
|
+ 1704 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
+ 1705 ELSE
|
|
|
+ 1706 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
+ 1707 END;
|
|
|
+ 1708 t := SymTab.NewSet(
|
|
|
+ 1709 SymTab.NewSubR(0,
|
|
|
+ 1710 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 1711 QbeGen.CopyOp(qt, q)
|
|
|
+ 1712 ELSE
|
|
|
+ 1713 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 1714 lt := t; rt := t2; t := res2
|
|
|
+ 1715 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 1716 IF t # SymTab.InvalidType THEN
|
|
|
+ 1717 isL := SymTab.IsLongFamily(t);
|
|
|
+ 1718 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 1719 folded := FALSE;
|
|
|
+ 1720 IF (NOT isL) AND (NOT isR)
|
|
|
+ 1721 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 1722 IF op = SymTab.OpAdd THEN
|
|
|
+ 1723 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 1724 ELSE
|
|
|
+ 1725 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 1726 END
|
|
|
+ 1727 END;
|
|
|
+ 1728 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 1729 ELSE
|
|
|
+ 1730 IF isL THEN
|
|
|
+ 1731 IF SymTab.IsIntFamily(lt) THEN
|
|
|
+ 1732 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
+ 1733 END;
|
|
|
+ 1734 IF SymTab.IsIntFamily(rt) THEN
|
|
|
+ 1735 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
+ 1736 END;
|
|
|
+ 1737 QbeGen.NewTemp(qt);
|
|
|
+ 1738 IF op = SymTab.OpAdd THEN
|
|
|
+ 1739 QbeGen.Op3L("add", qt, q, q2)
|
|
|
+ 1740 ELSE
|
|
|
+ 1741 QbeGen.Op3L("sub", qt, q, q2)
|
|
|
+ 1742 END
|
|
|
+ 1743 ELSE
|
|
|
+ 1744 QbeGen.NewTemp(qt);
|
|
|
+ 1745 IF op = SymTab.OpAdd THEN
|
|
|
+ 1746 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
+ 1747 ELSE
|
|
|
+ 1748 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
+ 1749 END
|
|
|
+ 1750 END;
|
|
|
+ 1751 QbeGen.CopyOp(qt, q)
|
|
|
+ 1752 END
|
|
|
+ 1753 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1754 END
|
|
|
+ 1755 END; .) } .
|
|
|
+ 1756 AddOp<VAR op: INTEGER>
|
|
|
+ 1757 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 1758 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 1759 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 1760 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1761 (. VAR t2, res2, lt, rt:
|
|
|
+ 1762 SymTab.TypeIndex;
|
|
|
+ 1763 op: INTEGER;
|
|
|
+ 1764 q2, qt, wq, qf:
|
|
|
+ 1765 QbeGen.QVal;
|
|
|
+ 1766 isR, isL, folded: BOOLEAN;
|
|
|
+ 1767 lw, rw, mw: CARDINAL; .)
|
|
|
+ 1768 = Fact<t, q> { MulOp<op> Fact<t2, q2>
|
|
|
+ 1769 (. IF op = SymTab.OpAnd THEN
|
|
|
+ 1770 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 1771 t := SymTab.BoolType()
|
|
|
+ 1772 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 1773 IF t # SymTab.InvalidType THEN
|
|
|
+ 1774 QbeGen.NewTemp(qt);
|
|
|
+ 1775 QbeGen.Op3("and", qt, q, q2, FALSE);
|
|
|
+ 1776 QbeGen.CopyOp(qt, q)
|
|
|
+ 1777 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1778 END
|
|
|
+ 1779 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 1780 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 1781 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 1782 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 1783 mw := lw;
|
|
|
+ 1784 IF rw > mw THEN mw := rw END;
|
|
|
+ 1785 IF op = SymTab.OpTimes THEN
|
|
|
+ 1786 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
+ 1787 ELSE
|
|
|
+ 1788 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
+ 1789 END;
|
|
|
+ 1790 t := SymTab.NewSet(
|
|
|
+ 1791 SymTab.NewSubR(0,
|
|
|
+ 1792 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 1793 QbeGen.CopyOp(qt, q)
|
|
|
+ 1794 ELSE
|
|
|
+ 1795 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 1796 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 1797 res2) THEN
|
|
|
+ 1798 lt := t; rt := t2; t := res2
|
|
|
+ 1799 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 1800 IF t # SymTab.InvalidType THEN
|
|
|
+ 1801 isL := SymTab.IsLongFamily(t);
|
|
|
+ 1802 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 1803 folded := FALSE;
|
|
|
+ 1804 IF (NOT isL) AND (NOT isR)
|
|
|
+ 1805 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 1806 IF op = SymTab.OpTimes THEN
|
|
|
+ 1807 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 1808 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 1809 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 1810 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 1811 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 1812 END
|
|
|
+ 1813 END;
|
|
|
+ 1814 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 1815 ELSE
|
|
|
+ 1816 IF isL THEN
|
|
|
+ 1817 IF SymTab.IsIntFamily(lt) THEN
|
|
|
+ 1818 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
+ 1819 END;
|
|
|
+ 1820 IF SymTab.IsIntFamily(rt) THEN
|
|
|
+ 1821 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
+ 1822 END;
|
|
|
+ 1823 QbeGen.NewTemp(qt);
|
|
|
+ 1824 IF op = SymTab.OpTimes THEN
|
|
|
+ 1825 QbeGen.Op3L("mul", qt, q, q2)
|
|
|
+ 1826 ELSIF (op = SymTab.OpDiv)
|
|
|
+ 1827 OR (op = SymTab.OpSlash) THEN
|
|
|
+ 1828 QbeGen.Op3L("div", qt, q, q2)
|
|
|
+ 1829 ELSE
|
|
|
+ 1830 QbeGen.Op3L("rem", qt, q, q2)
|
|
|
+ 1831 END
|
|
|
+ 1832 ELSE
|
|
|
+ 1833 QbeGen.NewTemp(qt);
|
|
|
+ 1834 IF op = SymTab.OpTimes THEN
|
|
|
+ 1835 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
+ 1836 ELSIF (op = SymTab.OpDiv)
|
|
|
+ 1837 OR (op = SymTab.OpSlash) THEN
|
|
|
+ 1838 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
+ 1839 ELSE
|
|
|
+ 1840 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
+ 1841 END
|
|
|
+ 1842 END;
|
|
|
+ 1843 QbeGen.CopyOp(qt, q)
|
|
|
+ 1844 END
|
|
|
+ 1845 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 1846 END
|
|
|
+ 1847 END; .) } .
|
|
|
+ 1848 MulOp<VAR op: INTEGER>
|
|
|
+ 1849 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 1850 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 1851 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 1852 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 1853 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 1854 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1855 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 1856 et, dt, t2, st, ct2:
|
|
|
+ 1857 SymTab.TypeIndex;
|
|
|
+ 1858 dk: INTEGER;
|
|
|
+ 1859 qd, q2, sq, qa, qm0, qr:
|
|
|
+ 1860 QbeGen.QVal;
|
|
|
+ 1861 qn, vn: SymTab.Name;
|
|
|
+ 1862 vt: SymTab.TypeIndex;
|
|
|
+ 1863 c1, c2: INTEGER;
|
|
|
+ 1864 called, isHigh, sfx, isCh:
|
|
|
+ 1865 BOOLEAN; .)
|
|
|
+ 1866 = integer (. LexString(s);
|
|
|
+ 1867 QbeGen.NormInt(s, q);
|
|
|
+ 1868 t := SymTab.IntType(); .)
|
|
|
+ 1869 | charConst (. LexString(s);
|
|
|
+ 1870 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 1871 t := SymTab.CharType(); .)
|
|
|
+ 1872 | real (. LexString(s);
|
|
|
+ 1873 QbeGen.NormReal(s, q);
|
|
|
+ 1874 t := SymTab.RealType(); .)
|
|
|
+ 1875 | string (. LexString(s);
|
|
|
+ 1876 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 1877 t := SymTab.CharType();
|
|
|
+ 1878 QbeGen.IntStr(
|
|
|
+ 1879 QbeGen.CharVal(s), q)
|
|
|
+ 1880 ELSE t := SymTab.NewStr();
|
|
|
+ 1881 QbeGen.DeclStr(s, q);
|
|
|
+ 1882 (* a literal's value IS its
|
|
|
+ 1883 static descriptor address *)
|
|
|
+ 1884 QbeGen.NoteAddr(q, q)
|
|
|
+ 1885 END; .)
|
|
|
+ 1886 | Design<dt, dk, qd, qn, sfx> (. called := FALSE;
|
|
|
+ 1887 t := dt;
|
|
|
+ 1888 IF sfx THEN
|
|
|
+ 1889 IF dt =
|
|
|
+ 1890 SymTab.InvalidType THEN
|
|
|
+ 1891 QbeGen.CopyOp("0", q)
|
|
|
+ 1892 ELSIF (SymTab.ClassOf(dt) =
|
|
|
+ 1893 SymTab.ClRecord)
|
|
|
+ 1894 OR (SymTab.ClassOf(dt) =
|
|
|
+ 1895 SymTab.ClSet)
|
|
|
+ 1896 OR (SymTab.ClassOf(dt) =
|
|
|
+ 1897 SymTab.ClArray)
|
|
|
+ 1898 OR (SymTab.ClassOf(dt) =
|
|
|
+ 1899 SymTab.ClClass) THEN
|
|
|
+ 1900 QbeGen.CopyOp(qd, q)
|
|
|
+ 1901 ELSE QbeGen.ElemLoad(qd, dt,
|
|
|
+ 1902 q)
|
|
|
+ 1903 END
|
|
|
+ 1904 ELSE QbeGen.CopyOp(qd, q)
|
|
|
+ 1905 END;
|
|
|
+ 1906 IF (dk = SymTab.KindVar)
|
|
|
+ 1907 OR (dk = SymTab.KindParam)
|
|
|
+ 1908 OR (dk =
|
|
|
+ 1909 SymTab.KindField) THEN
|
|
|
+ 1910 IF sfx THEN
|
|
|
+ 1911 QbeGen.NoteAddr(q, qd)
|
|
|
+ 1912 ELSE
|
|
|
+ 1913 QbeGen.AddrOf(qn, qa);
|
|
|
+ 1914 QbeGen.NoteAddr(q, qa)
|
|
|
+ 1915 END
|
|
|
+ 1916 ELSIF sfx
|
|
|
+ 1917 AND (dt #
|
|
|
+ 1918 SymTab.InvalidType)
|
|
|
+ 1919 AND ((SymTab.ClassOf(dt) =
|
|
|
+ 1920 SymTab.ClArray)
|
|
|
+ 1921 OR (SymTab.ClassOf(dt) =
|
|
|
+ 1922 SymTab.ClSet)
|
|
|
+ 1923 OR (SymTab.ClassOf(dt) =
|
|
|
+ 1924 SymTab.ClRecord)) THEN
|
|
|
+ 1925 QbeGen.NoteAddr(qd, qd)
|
|
|
+ 1926 END; .)
|
|
|
+ 1927 [ ArgList<qn, dt, qd, TRUE, ct2, q2, called>
|
|
|
+ 1928 (. t := ct2;
|
|
|
+ 1929 QbeGen.CopyOp(q2, q); .) ]
|
|
|
+ 1930 (. IF NOT called
|
|
|
+ 1931 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 1932 (* bare zero-arg function
|
|
|
+ 1933 call (parentheses may be
|
|
|
+ 1934 omitted); a proper or
|
|
|
+ 1935 parameterised proc here
|
|
|
+ 1936 is 230 *)
|
|
|
+ 1937 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 1938 AND (SymTab.ProcRes(qn) #
|
|
|
+ 1939 SymTab.InvalidType) THEN
|
|
|
+ 1940 QbeGen.Mangled(qn,
|
|
|
+ 1941 SymTab.ProcUid(qn), qm0);
|
|
|
+ 1942 QbeGen.CallBegin(qm0,
|
|
|
+ 1943 SymTab.ProcRes(qn),
|
|
|
+ 1944 SymTab.ProcDepthOf(qn),
|
|
|
+ 1945 SymTab.IsExternal(qn));
|
|
|
+ 1946 QbeGen.CallEnd(TRUE, q);
|
|
|
+ 1947 t := SymTab.ProcRes(qn)
|
|
|
+ 1948 ELSE
|
|
|
+ 1949 (* procedure used as a
|
|
|
+ 1950 value (assign to a
|
|
|
+ 1951 procedure variable):
|
|
|
+ 1952 its code address *)
|
|
|
+ 1953 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 1954 QbeGen.Mangled(qn,
|
|
|
+ 1955 SymTab.ProcUid(qn), qm0);
|
|
|
+ 1956 QbeGen.ProcAddr(qm0, q)
|
|
|
+ 1957 END
|
|
|
+ 1958 END; .)
|
|
|
+ 1959 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 1960 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 1961 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 1962 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1963 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1964 SymTab.ClArray THEN
|
|
|
+ 1965 SemError(217);
|
|
|
+ 1966 t := SymTab.InvalidType;
|
|
|
+ 1967 QbeGen.CopyOp("0", q)
|
|
|
+ 1968 ELSE
|
|
|
+ 1969 IF isHigh THEN
|
|
|
+ 1970 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 1971 QbeGen.OpenHi(qd, qr)
|
|
|
+ 1972 ELSE
|
|
|
+ 1973 QbeGen.IntStr(
|
|
|
+ 1974 SymTab.ArrayHi(dt), qr)
|
|
|
+ 1975 END
|
|
|
+ 1976 ELSE
|
|
|
+ 1977 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 1978 QbeGen.LoadCount(qd, qr)
|
|
|
+ 1979 ELSE
|
|
|
+ 1980 QbeGen.IntStr(VAL(
|
|
|
+ 1981 INTEGER,
|
|
|
+ 1982 SymTab.ArrayLen(dt)),
|
|
|
+ 1983 qr)
|
|
|
+ 1984 END
|
|
|
+ 1985 END;
|
|
|
+ 1986 t := SymTab.IntType();
|
|
|
+ 1987 QbeGen.CopyOp(qr, q)
|
|
|
+ 1988 END; .)
|
|
|
+ 1989 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 1990 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1991 t := SymTab.InvalidType;
|
|
|
+ 1992 QbeGen.CopyOp("0", q)
|
|
|
+ 1993 ELSE
|
|
|
+ 1994 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 1995 SymTab.ObjectSize(dt)), q);
|
|
|
+ 1996 t := SymTab.IntType()
|
|
|
+ 1997 END; .)
|
|
|
+ 1998 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 1999 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2000 t := SymTab.InvalidType;
|
|
|
+ 2001 QbeGen.CopyOp("0", q)
|
|
|
+ 2002 ELSE
|
|
|
+ 2003 IF sfx THEN
|
|
|
+ 2004 QbeGen.CopyOp(qd, q)
|
|
|
+ 2005 ELSIF (dk = SymTab.KindVar)
|
|
|
+ 2006 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 2007 QbeGen.AddrOf(qn, q)
|
|
|
+ 2008 ELSE SemError(230);
|
|
|
+ 2009 QbeGen.CopyOp("0", q)
|
|
|
+ 2010 END;
|
|
|
+ 2011 t := SymTab.AddrType()
|
|
|
+ 2012 END; .)
|
|
|
+ 2013 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 2014 (. IF (et # SymTab.InvalidType)
|
|
|
+ 2015 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 2016 SemError(211) END;
|
|
|
+ 2017 t := SymTab.CharType(); .)
|
|
|
+ 2018 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
+ 2019 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 2020 IF (SymTab.ClassOf(et) #
|
|
|
+ 2021 SymTab.ClChar)
|
|
|
+ 2022 AND (SymTab.ClassOf(et) #
|
|
|
+ 2023 SymTab.ClBool)
|
|
|
+ 2024 AND (SymTab.ClassOf(et) #
|
|
|
+ 2025 SymTab.ClEnum)
|
|
|
+ 2026 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 2027 SemError(211) END
|
|
|
+ 2028 END;
|
|
|
+ 2029 t := SymTab.IntType(); .)
|
|
|
+ 2030 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 2031 (. QbeGen.CapQ(q, qa);
|
|
|
+ 2032 QbeGen.CopyOp(qa, q);
|
|
|
+ 2033 t := SymTab.CharType(); .)
|
|
|
+ 2034 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 2035 (. IF (et # SymTab.InvalidType)
|
|
|
+ 2036 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 2037 AND (SymTab.ClassOf(et) #
|
|
|
+ 2038 SymTab.ClReal) THEN
|
|
|
+ 2039 SemError(211)
|
|
|
+ 2040 ELSE QbeGen.AbsQ(q, qa,
|
|
|
+ 2041 SymTab.ClassOf(et) =
|
|
|
+ 2042 SymTab.ClReal);
|
|
|
+ 2043 QbeGen.CopyOp(qa, q)
|
|
|
+ 2044 END;
|
|
|
+ 2045 t := et; .)
|
|
|
+ 2046 | "VAL" "(" GetIdent<vn> "," Expr<et, q> ")"
|
|
|
+ 2047 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 2048 SemError(201);
|
|
|
+ 2049 t := SymTab.InvalidType
|
|
|
+ 2050 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 2051 IF vt = SymTab.InvalidType THEN
|
|
|
+ 2052 t := SymTab.InvalidType
|
|
|
+ 2053 ELSIF et =
|
|
|
+ 2054 SymTab.InvalidType THEN
|
|
|
+ 2055 t := vt
|
|
|
+ 2056 ELSE
|
|
|
+ 2057 c1 := SymTab.ClassOf(et);
|
|
|
+ 2058 c2 := SymTab.ClassOf(vt);
|
|
|
+ 2059 IF ((c1 = SymTab.ClInt)
|
|
|
+ 2060 OR (c1 =
|
|
|
+ 2061 SymTab.ClChar)
|
|
|
+ 2062 OR (c1 =
|
|
|
+ 2063 SymTab.ClBool)
|
|
|
+ 2064 OR (c1 =
|
|
|
+ 2065 SymTab.ClEnum))
|
|
|
+ 2066 AND ((c2 = SymTab.ClInt)
|
|
|
+ 2067 OR (c2 =
|
|
|
+ 2068 SymTab.ClChar)
|
|
|
+ 2069 OR (c2 =
|
|
|
+ 2070 SymTab.ClBool)
|
|
|
+ 2071 OR (c2 =
|
|
|
+ 2072 SymTab.ClEnum)) THEN
|
|
|
+ 2073 t := vt
|
|
|
+ 2074 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 2075 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 2076 t := vt
|
|
|
+ 2077 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 2078 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 2079 t := vt
|
|
|
+ 2080 ELSE SemError(230);
|
|
|
+ 2081 t := SymTab.InvalidType
|
|
|
+ 2082 END
|
|
|
+ 2083 END
|
|
|
+ 2084 END; .)
|
|
|
+ 2085 | "(" Expr<et, q> ")" (. t := et; .)
|
|
|
+ 2086 | SetLit<st, sq> (. t := st;
|
|
|
+ 2087 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 2088 | ( "NOT" | "~" ) Fact<t2, q2> (. IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 2089 t := SymTab.BoolType()
|
|
|
+ 2090 ELSE SemError(212);
|
|
|
+ 2091 t := SymTab.InvalidType END;
|
|
|
+ 2092 IF t # SymTab.InvalidType THEN
|
|
|
+ 2093 QbeGen.NotQ(q2, q)
|
|
|
+ 2094 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2095 END; .) .
|
|
|
+ 2096 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 2097 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 2098 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 2099 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2100 = "{" (. t := SymTab.NewSet(
|
|
|
+ 2101 SymTab.NewSubR(0, 255));
|
|
|
+ 2102 QbeGen.NewSetTemp(8, q);
|
|
|
+ 2103 QbeGen.SetZero(q, 8); .)
|
|
|
+ 2104 [ SetElem<t, q> { "," SetElem<t, q> } ]
|
|
|
+ 2105 "}" .
|
|
|
+ 2106 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 2107 qe, q2: QbeGen.QVal;
|
|
|
+ 2108 v, v2: INTEGER;
|
|
|
+ 2109 lo: INTEGER;
|
|
|
+ 2110 span: CARDINAL;
|
|
|
+ 2111 cl, cl2: INTEGER;
|
|
|
+ 2112 hasR: BOOLEAN; .)
|
|
|
+ 2113 = (. hasR := FALSE; .)
|
|
|
+ 2114 Expr<et, qe>
|
|
|
+ 2115 [ ".." Expr<et2, q2> (. hasR := TRUE; .) ]
|
|
|
+ 2116 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 2117 span := SymTab.SetCount(st);
|
|
|
+ 2118 IF (et = SymTab.InvalidType)
|
|
|
+ 2119 OR (hasR AND (et2 =
|
|
|
+ 2120 SymTab.InvalidType)) THEN
|
|
|
+ 2121 ELSE cl :=
|
|
|
+ 2122 SymTab.ClassOf(et);
|
|
|
+ 2123 IF hasR THEN
|
|
|
+ 2124 cl2 :=
|
|
|
+ 2125 SymTab.ClassOf(et2)
|
|
|
+ 2126 ELSE cl2 := SymTab.ClInt
|
|
|
+ 2127 END;
|
|
|
+ 2128 IF ((cl # SymTab.ClInt)
|
|
|
+ 2129 AND (cl # SymTab.ClChar)
|
|
|
+ 2130 AND (cl # SymTab.ClBool))
|
|
|
+ 2131 OR (hasR AND
|
|
|
+ 2132 ((cl2
|
|
|
+ 2133 # SymTab.ClInt)
|
|
|
+ 2134 AND (cl2
|
|
|
+ 2135 # SymTab.ClChar)
|
|
|
+ 2136 AND (cl2
|
|
|
+ 2137 # SymTab.ClBool))) THEN
|
|
|
+ 2138 SemError(222)
|
|
|
+ 2139 ELSIF hasR
|
|
|
+ 2140 AND SymTab.ConstInt(qe, v)
|
|
|
+ 2141 AND SymTab.ConstInt(q2,
|
|
|
+ 2142 v2)
|
|
|
+ 2143 AND ((v < lo)
|
|
|
+ 2144 OR (v2 < lo)
|
|
|
+ 2145 OR (v >= lo +
|
|
|
+ 2146 VAL(INTEGER, span))
|
|
|
+ 2147 OR (v2 >= lo +
|
|
|
+ 2148 VAL(INTEGER, span))
|
|
|
+ 2149 OR (v > v2)) THEN
|
|
|
+ 2150 SemError(222)
|
|
|
+ 2151 ELSIF hasR THEN
|
|
|
+ 2152 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 2153 lo, span)
|
|
|
+ 2154 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 2155 v)
|
|
|
+ 2156 AND ((v < lo)
|
|
|
+ 2157 OR (v >= lo +
|
|
|
+ 2158 VAL(INTEGER,
|
|
|
+ 2159 span))) THEN
|
|
|
+ 2160 SemError(222)
|
|
|
+ 2161 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 2162 lo, span)
|
|
|
+ 2163 END
|
|
|
+ 2164 END; .) .
|
|
|
+ 2165 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 2166 = ident (. LexName(n); .) .
|
|
|
+ 2167
|
|
|
+ 2168 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|
|
|
|
|
|
Statistics:
|
|
|
|
|
|
- nr of terminals: 87 (limit 400)
|
|
|
+ nr of terminals: 93 (limit 400)
|
|
|
nr of non-terminals: 77 (limit 210)
|
|
|
- nr of pragmas: 0 (limit 413)
|
|
|
- nr of symbolnodes: 164 (limit 500)
|
|
|
- nr of graphnodes: 804 (limit 1500)
|
|
|
- nr of conditionsets: 8 (limit 100)
|
|
|
- nr of charactersets: 11 (limit 250)
|
|
|
+ nr of pragmas: 0 (limit 407)
|
|
|
+ nr of symbolnodes: 170 (limit 500)
|
|
|
+ nr of graphnodes: 838 (limit 1500)
|
|
|
+ nr of conditionsets: 9 (limit 100)
|
|
|
+ nr of charactersets: 12 (limit 250)
|
|
|
|
|
|
|