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