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