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