|
|
@@ -6,12 +6,14 @@ Grammar Tests:
|
|
|
|
|
|
Deletable symbols:
|
|
|
DesignTail
|
|
|
+ RecFieldList
|
|
|
DeclSeq
|
|
|
Undefined nonterminals: -- none --
|
|
|
Unreachable nonterminals: -- none --
|
|
|
Circular derivations: -- none --
|
|
|
Underivable nonterminals: -- none --
|
|
|
LL(1) conditions:
|
|
|
+ LL(1) error in RecFieldList: "ELSE" is the start & successor of a deletable structure
|
|
|
LL(1) error in ProcTypeSection: ident is the start of several alternatives.
|
|
|
LL(1) error in TypeBlock: "CLASS" is the start & successor of a deletable structure
|
|
|
|
|
|
@@ -1248,7 +1250,7 @@ Listing:
|
|
|
1229 are code pointers; params are collected into the descriptor. *)
|
|
|
1230 ProcType<VAR t: SymTab.TypeIndex> (. VAR res, pt: SymTab.TypeIndex;
|
|
|
1231 isV: BOOLEAN; .)
|
|
|
- 1232 = "PROCEDURE" (. allowFwdType := FALSE;
|
|
|
+ 1232 = ( "PROCEDURE" | "PROC" ) (. allowFwdType := FALSE;
|
|
|
1233 res := SymTab.InvalidType;
|
|
|
1234 t := SymTab.NewProcType(res); .)
|
|
|
1235 [ "(" [ ProcTypeSection<t> { ";" ProcTypeSection<t> } ] ")" ]
|
|
|
@@ -1421,2741 +1423,2760 @@ Listing:
|
|
|
1402 RecItem<rec: SymTab.TypeIndex> (. VAR tt: SymTab.TypeIndex; .)
|
|
|
1403 = RecField<rec>
|
|
|
1404 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
- 1405 (* A variant part: CASE tag : Type OF variants. The layout overlays
|
|
|
- 1406 every branch from the tag slot (see SymTab.ComputeOffsets). *)
|
|
|
+ 1405 (* A variant part: CASE [tag] : Type OF variants. gm2 extensions:
|
|
|
+ 1406 an untagged inner CASE (no tag field), empty arms and ELSE arms. *)
|
|
|
1407 CaseField<rec: SymTab.TypeIndex> (. VAR tagT: SymTab.TypeIndex;
|
|
|
- 1408 tagN: SymTab.Name; .)
|
|
|
- 1409 = "CASE" (. SymTab.ResetFields(rec); .)
|
|
|
- 1410 GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1411 tagN) THEN
|
|
|
- 1412 SemError(200) END; .)
|
|
|
- 1413 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
- 1414 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
- 1415 SemError(224)
|
|
|
- 1416 END;
|
|
|
- 1417 SymTab.FixPendingF(rec, tagT);
|
|
|
- 1418 SymTab.SetVariantTag(rec, tagN); .)
|
|
|
- 1419 "OF"
|
|
|
- 1420 RecFieldList<rec>
|
|
|
- 1421 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
- 1422 RecFieldList<rec> }
|
|
|
- 1423 "END" .
|
|
|
- 1424 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
- 1425 lv1, lv2: QbeGen.QVal; .)
|
|
|
- 1426 = VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] ":"
|
|
|
- 1427 RecField<rec> { ";" [ RecField<rec> ] } .
|
|
|
- 1428 (* Variant case label: a constant (or a constant range). Values are
|
|
|
- 1429 not interpreted (the layout overlays regardless). *)
|
|
|
- 1430 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 1431 (. VAR lname: SymTab.Name; .)
|
|
|
- 1432 = ( ident (. LexName(lname);
|
|
|
- 1433 QbeGen.CopyOp("0", q);
|
|
|
- 1434 t := SymTab.IntType(); .)
|
|
|
- 1435 | integer (. LexString(lname);
|
|
|
- 1436 QbeGen.CopyOp("0", q);
|
|
|
- 1437 t := SymTab.IntType(); .)
|
|
|
- 1438 | charConst (. LexString(lname);
|
|
|
- 1439 QbeGen.CopyOp("0", q);
|
|
|
- 1440 t := SymTab.CharType(); .) ) .
|
|
|
- 1441 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 1442 t2: SymTab.TypeIndex; .)
|
|
|
- 1443 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
- 1444 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
- 1445 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1446 n) THEN
|
|
|
- 1447 SemError(200) END; .)
|
|
|
- 1448 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
- 1449 n) THEN
|
|
|
- 1450 SemError(200) END; .) } .
|
|
|
- 1451 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
- 1452 k: INTEGER;
|
|
|
- 1453 dotted: BOOLEAN; .)
|
|
|
- 1454 = GetIdent<n> (. dotted := FALSE;
|
|
|
- 1455 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 1456 (* declaration before use: an
|
|
|
- 1457 undeclared type is 201,
|
|
|
- 1458 except as a POINTER's base
|
|
|
- 1459 (allowFwdType) *)
|
|
|
- 1460 k := -1;
|
|
|
- 1461 IF allowFwdType THEN
|
|
|
- 1462 t := SymTab.ForwardType(n)
|
|
|
- 1463 ELSE t := SymTab.InvalidType
|
|
|
- 1464 END;
|
|
|
- 1465 IF t = SymTab.InvalidType THEN
|
|
|
- 1466 SemError(201)
|
|
|
- 1467 END
|
|
|
- 1468 ELSE k := SymTab.SymKind(n);
|
|
|
- 1469 IF (k = SymTab.KindType)
|
|
|
- 1470 OR (k = SymTab.KindPredef) THEN
|
|
|
- 1471 t := SymTab.SymType(n)
|
|
|
- 1472 ELSE t := SymTab.InvalidType
|
|
|
- 1473 END
|
|
|
- 1474 END; .)
|
|
|
- 1475 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
- 1476 IF k = SymTab.KindModule THEN
|
|
|
- 1477 t := SymTab.QualType(n, qid);
|
|
|
- 1478 IF t = SymTab.InvalidType THEN
|
|
|
- 1479 SemError(201)
|
|
|
- 1480 END
|
|
|
- 1481 ELSE SemError(221);
|
|
|
- 1482 t := SymTab.InvalidType
|
|
|
- 1483 END; .) ]
|
|
|
- 1484 (. IF NOT dotted THEN
|
|
|
- 1485 IF (k = SymTab.KindModule)
|
|
|
- 1486 OR ((k # SymTab.KindType)
|
|
|
- 1487 AND (k # SymTab.KindPredef)
|
|
|
- 1488 AND (k # SymTab.KindImport)
|
|
|
- 1489 AND (k # -1)) THEN
|
|
|
- 1490 SemError(221)
|
|
|
- 1491 END
|
|
|
- 1492 END; .) .
|
|
|
- 1493 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
- 1494 qlo, qhi: QbeGen.QVal;
|
|
|
- 1495 lo, hi: INTEGER; .)
|
|
|
- 1496 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
- 1497 (. IF (tlo = SymTab.InvalidType)
|
|
|
- 1498 OR (thi = SymTab.InvalidType) THEN
|
|
|
- 1499 t := SymTab.InvalidType
|
|
|
- 1500 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
- 1501 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
- 1502 SemError(230);
|
|
|
- 1503 t := SymTab.InvalidType
|
|
|
- 1504 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
- 1505 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
- 1506 OR (lo > hi) THEN
|
|
|
- 1507 SemError(230);
|
|
|
- 1508 t := SymTab.InvalidType
|
|
|
- 1509 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
- 1510 END; .)
|
|
|
- 1511 "]" .
|
|
|
- 1512 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
- 1513 ord: INTEGER;
|
|
|
- 1514 qv: QbeGen.QVal; .)
|
|
|
- 1515 = "(" (. t := SymTab.NewEnum();
|
|
|
- 1516 ord := 0; .)
|
|
|
- 1517 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1518 SymTab.KindConst) THEN
|
|
|
- 1519 SemError(200) END;
|
|
|
- 1520 SymTab.SetSymType(n, t);
|
|
|
- 1521 QbeGen.IntStr(ord, qv);
|
|
|
- 1522 SymTab.SetSymVal(n, qv);
|
|
|
- 1523 SymTab.NoteEnumLit(t, n);
|
|
|
- 1524 Lower.NoteVar(n,
|
|
|
- 1525 SymTab.KindConst, t);
|
|
|
- 1526 Lower.NoteConstVal(qv);
|
|
|
- 1527 INC(ord); .)
|
|
|
- 1528 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1529 SymTab.KindConst) THEN
|
|
|
- 1530 SemError(200) END;
|
|
|
- 1531 SymTab.SetSymType(n, t);
|
|
|
- 1532 QbeGen.IntStr(ord, qv);
|
|
|
- 1533 SymTab.SetSymVal(n, qv);
|
|
|
- 1534 SymTab.NoteEnumLit(t, n);
|
|
|
- 1535 Lower.NoteVar(n,
|
|
|
- 1536 SymTab.KindConst, t);
|
|
|
- 1537 Lower.NoteConstVal(qv);
|
|
|
- 1538 INC(ord); .) }
|
|
|
- 1539 ")" (. SymTab.SetEnumCount(t,
|
|
|
- 1540 VAL(CARDINAL, ord)); .) .
|
|
|
- 1541 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
- 1542 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
- 1543 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
- 1544 class/impl block. Methods end with ";" per the Table example
|
|
|
- 1545 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
- 1546 (* Single CLASS item in both loops: separating declaration from
|
|
|
- 1547 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
- 1548 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
- 1549 The second token decides after CLASS is consumed. A misplaced
|
|
|
- 1550 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
- 1551 whole unit ends 230 until lowering). *)
|
|
|
- 1552 ClassItem
|
|
|
- 1553 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
- 1554 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
- 1555 ct: SymTab.TypeIndex; .)
|
|
|
- 1556 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
- 1557 SymTab.KindType) THEN
|
|
|
- 1558 SemError(200) END;
|
|
|
- 1559 ct := SymTab.NewClass();
|
|
|
- 1560 SymTab.SetSymType(cn, ct);
|
|
|
- 1561 SymTab.PushClassScope(ct);
|
|
|
- 1562 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
- 1563 AST.SetChild(astCls, 0,
|
|
|
- 1564 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
- 1565 astClsP := AST.NoNode;
|
|
|
- 1566 astClsPTail := AST.NoNode;
|
|
|
- 1567 astClsF := AST.NoNode;
|
|
|
- 1568 astClsFTail := AST.NoNode;
|
|
|
- 1569 astClsM := AST.NoNode;
|
|
|
- 1570 astClsMTail := AST.NoNode; .)
|
|
|
- 1571 [ Parents<ct> ]
|
|
|
- 1572 ";"
|
|
|
- 1573 { ClassField<ct> ";" }
|
|
|
- 1574 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1575 (. Lower.ScopeLeave;
|
|
|
- 1576 SymTab.CloseProc;
|
|
|
- 1577 QbeGen.AbortFunc; .) }
|
|
|
- 1578 "END"
|
|
|
- 1579 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 1580 SemError(202) END;
|
|
|
- 1581 SymTab.LayoutClass(ct);
|
|
|
- 1582 SymTab.PopScope;
|
|
|
- 1583 AST.SetChild(astCls, 1, astClsP);
|
|
|
- 1584 AST.SetChild(astCls, 2, astClsF);
|
|
|
- 1585 AST.SetChild(astCls, 3, astClsM);
|
|
|
- 1586 astDecl := astCls; .) .
|
|
|
- 1587 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
- 1588 = "(" Parent1<ct>
|
|
|
- 1589 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
- 1590 ")" .
|
|
|
- 1591 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
- 1592 pt: SymTab.TypeIndex; .)
|
|
|
- 1593 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
- 1594 SemError(201)
|
|
|
- 1595 ELSE pt := SymTab.SymType(p);
|
|
|
- 1596 IF SymTab.ClassOf(pt) #
|
|
|
- 1597 SymTab.ClClass THEN
|
|
|
- 1598 SemError(230)
|
|
|
- 1599 ELSE SymTab.SetParent(ct, pt)
|
|
|
- 1600 END
|
|
|
- 1601 END;
|
|
|
- 1602 AstAppend(AST.NkFieldDecl,
|
|
|
- 1603 astClsP, astClsPTail,
|
|
|
- 1604 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
- 1605 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
- 1606 t: SymTab.TypeIndex;
|
|
|
- 1607 astNode: AST.Node; .)
|
|
|
- 1608 = GetIdent<n>
|
|
|
- 1609 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
- 1610 SymTab.KindConst) THEN
|
|
|
- 1611 SemError(200) END;
|
|
|
- 1612 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1613 AST.SetChild(astNode, 0,
|
|
|
- 1614 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1615 AST.SetChild(astNode, 1,
|
|
|
- 1616 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
+ 1408 tagN: SymTab.Name;
|
|
|
+ 1409 tagged: BOOLEAN; .)
|
|
|
+ 1410 = "CASE" (. SymTab.ResetFields(rec);
|
|
|
+ 1411 tagged := FALSE; .)
|
|
|
+ 1412 [ GetIdent<tagN> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1413 tagN) THEN
|
|
|
+ 1414 SemError(200) END;
|
|
|
+ 1415 tagged := TRUE; .) ]
|
|
|
+ 1416 ":" Type<tagT, FALSE> (. IF (tagT # SymTab.InvalidType)
|
|
|
+ 1417 AND NOT SymTab.IsOrdinal(tagT) THEN
|
|
|
+ 1418 SemError(224)
|
|
|
+ 1419 END;
|
|
|
+ 1420 IF tagged THEN
|
|
|
+ 1421 SymTab.FixPendingF(rec, tagT);
|
|
|
+ 1422 SymTab.SetVariantTag(rec, tagN)
|
|
|
+ 1423 END; .)
|
|
|
+ 1424 "OF"
|
|
|
+ 1425 RecFieldList<rec>
|
|
|
+ 1426 { "|" (. SymTab.ResetFields(rec); .)
|
|
|
+ 1427 RecFieldList<rec> }
|
|
|
+ 1428 [ "ELSE" ]
|
|
|
+ 1429 "END" .
|
|
|
+ 1430 (* A variant branch: `labels : fields` (fields and their trailing ";"
|
|
|
+ 1431 optional, gm2), `ELSE`, or empty (the extra "|" separators gm2
|
|
|
+ 1432 tolerates). A branch may itself contain a nested variant CASE. *)
|
|
|
+ 1433 RecFieldList<rec: SymTab.TypeIndex> (. VAR lt, lq: SymTab.TypeIndex;
|
|
|
+ 1434 lv1, lv2: QbeGen.QVal; .)
|
|
|
+ 1435 = [ ( VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ]
|
|
|
+ 1436 { "," VarLabel<lt, lv1> [ ".." VarLabel<lq, lv2> ] }
|
|
|
+ 1437 ":"
|
|
|
+ 1438 [ ArmField<rec> { ";" [ ArmField<rec> ] } ]
|
|
|
+ 1439 | "ELSE" ) ] .
|
|
|
+ 1440 ArmField<rec: SymTab.TypeIndex>
|
|
|
+ 1441 = RecField<rec>
|
|
|
+ 1442 | CaseField<rec> (. SymTab.MarkVariant(rec); .) .
|
|
|
+ 1443 (* Variant case label: a constant (or a constant range). Values are
|
|
|
+ 1444 not interpreted (the layout overlays regardless). *)
|
|
|
+ 1445 VarLabel<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 1446 (. VAR lname: SymTab.Name; .)
|
|
|
+ 1447 = ( ident (. LexName(lname);
|
|
|
+ 1448 QbeGen.CopyOp("0", q);
|
|
|
+ 1449 t := SymTab.IntType(); .)
|
|
|
+ 1450 | integer (. LexString(lname);
|
|
|
+ 1451 QbeGen.CopyOp("0", q);
|
|
|
+ 1452 t := SymTab.IntType(); .)
|
|
|
+ 1453 | charConst (. LexString(lname);
|
|
|
+ 1454 QbeGen.CopyOp("0", q);
|
|
|
+ 1455 t := SymTab.CharType(); .) ) .
|
|
|
+ 1456 RecField<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 1457 t2: SymTab.TypeIndex; .)
|
|
|
+ 1458 = RecIdents<rec> ":" Type<t2, FALSE>(. SymTab.FixPendingF(rec, t2); .) .
|
|
|
+ 1459 RecIdents<rec: SymTab.TypeIndex> (. VAR n: SymTab.Name; .)
|
|
|
+ 1460 = GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1461 n) THEN
|
|
|
+ 1462 SemError(200) END; .)
|
|
|
+ 1463 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(rec,
|
|
|
+ 1464 n) THEN
|
|
|
+ 1465 SemError(200) END; .) } .
|
|
|
+ 1466 TypeIdent<VAR t: SymTab.TypeIndex> (. VAR n, qid: SymTab.Name;
|
|
|
+ 1467 k: INTEGER;
|
|
|
+ 1468 dotted: BOOLEAN; .)
|
|
|
+ 1469 = GetIdent<n> (. dotted := FALSE;
|
|
|
+ 1470 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 1471 (* declaration before use: an
|
|
|
+ 1472 undeclared type is 201,
|
|
|
+ 1473 except as a POINTER's base
|
|
|
+ 1474 (allowFwdType) *)
|
|
|
+ 1475 k := -1;
|
|
|
+ 1476 IF allowFwdType THEN
|
|
|
+ 1477 t := SymTab.ForwardType(n)
|
|
|
+ 1478 ELSE t := SymTab.InvalidType
|
|
|
+ 1479 END;
|
|
|
+ 1480 IF t = SymTab.InvalidType THEN
|
|
|
+ 1481 SemError(201)
|
|
|
+ 1482 END
|
|
|
+ 1483 ELSE k := SymTab.SymKind(n);
|
|
|
+ 1484 IF (k = SymTab.KindType)
|
|
|
+ 1485 OR (k = SymTab.KindPredef) THEN
|
|
|
+ 1486 t := SymTab.SymType(n)
|
|
|
+ 1487 ELSE t := SymTab.InvalidType
|
|
|
+ 1488 END
|
|
|
+ 1489 END; .)
|
|
|
+ 1490 [ "." GetIdent<qid> (. dotted := TRUE;
|
|
|
+ 1491 IF k = SymTab.KindModule THEN
|
|
|
+ 1492 t := SymTab.QualType(n, qid);
|
|
|
+ 1493 IF t = SymTab.InvalidType THEN
|
|
|
+ 1494 SemError(201)
|
|
|
+ 1495 END
|
|
|
+ 1496 ELSE SemError(221);
|
|
|
+ 1497 t := SymTab.InvalidType
|
|
|
+ 1498 END; .) ]
|
|
|
+ 1499 (. IF NOT dotted THEN
|
|
|
+ 1500 IF (k = SymTab.KindModule)
|
|
|
+ 1501 OR ((k # SymTab.KindType)
|
|
|
+ 1502 AND (k # SymTab.KindPredef)
|
|
|
+ 1503 AND (k # SymTab.KindImport)
|
|
|
+ 1504 AND (k # -1)) THEN
|
|
|
+ 1505 SemError(221)
|
|
|
+ 1506 END
|
|
|
+ 1507 END; .) .
|
|
|
+ 1508 Subrange<VAR t: SymTab.TypeIndex> (. VAR tlo, thi: SymTab.TypeIndex;
|
|
|
+ 1509 qlo, qhi: QbeGen.QVal;
|
|
|
+ 1510 lo, hi: INTEGER; .)
|
|
|
+ 1511 = "[" Expr<tlo, qlo> ".." Expr<thi, qhi>
|
|
|
+ 1512 (. IF (tlo = SymTab.InvalidType)
|
|
|
+ 1513 OR (thi = SymTab.InvalidType) THEN
|
|
|
+ 1514 t := SymTab.InvalidType
|
|
|
+ 1515 ELSIF NOT SymTab.IsOrdinal(tlo)
|
|
|
+ 1516 OR NOT SymTab.IsOrdinal(thi) THEN
|
|
|
+ 1517 SemError(230);
|
|
|
+ 1518 t := SymTab.InvalidType
|
|
|
+ 1519 ELSIF NOT SymTab.ConstInt(qlo, lo)
|
|
|
+ 1520 OR NOT SymTab.ConstInt(qhi, hi)
|
|
|
+ 1521 OR (lo > hi) THEN
|
|
|
+ 1522 SemError(230);
|
|
|
+ 1523 t := SymTab.InvalidType
|
|
|
+ 1524 ELSE t := SymTab.NewSubR(lo, hi)
|
|
|
+ 1525 END; .)
|
|
|
+ 1526 "]" .
|
|
|
+ 1527 Enum<VAR t: SymTab.TypeIndex> (. VAR n: SymTab.Name;
|
|
|
+ 1528 ord: INTEGER;
|
|
|
+ 1529 qv: QbeGen.QVal; .)
|
|
|
+ 1530 = "(" (. t := SymTab.NewEnum();
|
|
|
+ 1531 ord := 0; .)
|
|
|
+ 1532 GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1533 SymTab.KindConst) THEN
|
|
|
+ 1534 SemError(200) END;
|
|
|
+ 1535 SymTab.SetSymType(n, t);
|
|
|
+ 1536 QbeGen.IntStr(ord, qv);
|
|
|
+ 1537 SymTab.SetSymVal(n, qv);
|
|
|
+ 1538 SymTab.NoteEnumLit(t, n);
|
|
|
+ 1539 Lower.NoteVar(n,
|
|
|
+ 1540 SymTab.KindConst, t);
|
|
|
+ 1541 Lower.NoteConstVal(qv);
|
|
|
+ 1542 INC(ord); .)
|
|
|
+ 1543 { "," GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1544 SymTab.KindConst) THEN
|
|
|
+ 1545 SemError(200) END;
|
|
|
+ 1546 SymTab.SetSymType(n, t);
|
|
|
+ 1547 QbeGen.IntStr(ord, qv);
|
|
|
+ 1548 SymTab.SetSymVal(n, qv);
|
|
|
+ 1549 SymTab.NoteEnumLit(t, n);
|
|
|
+ 1550 Lower.NoteVar(n,
|
|
|
+ 1551 SymTab.KindConst, t);
|
|
|
+ 1552 Lower.NoteConstVal(qv);
|
|
|
+ 1553 INC(ord); .) }
|
|
|
+ 1554 ")" (. SymTab.SetEnumCount(t,
|
|
|
+ 1555 VAL(CARDINAL, ord)); .) .
|
|
|
+ 1556 (* Clarion-form classes (docs/OOP.txt): declaration + single
|
|
|
+ 1557 inheritance + IMPLEMENTATION blocks. Scopes and member checks
|
|
|
+ 1558 now; lowering (vtable, dispatch, THIS) later — one 230 per
|
|
|
+ 1559 class/impl block. Methods end with ";" per the Table example
|
|
|
+ 1560 (not "," as in the sketch). No underscores in identifiers. *)
|
|
|
+ 1561 (* Single CLASS item in both loops: separating declaration from
|
|
|
+ 1562 IMPLEMENTATION at the loop level needs 2-token lookahead
|
|
|
+ 1563 (CLASS ident vs CLASS IMPLEMENTATION), which LL(1) cannot do.
|
|
|
+ 1564 The second token decides after CLASS is consumed. A misplaced
|
|
|
+ 1565 CLASS IMPLEMENTATION inside TYPE still parses (harmless: the
|
|
|
+ 1566 whole unit ends 230 until lowering). *)
|
|
|
+ 1567 ClassItem
|
|
|
+ 1568 = "CLASS" ( "IMPLEMENTATION" ClassImplRest | ClassRest ) .
|
|
|
+ 1569 ClassRest (. VAR cn, m2, pn: SymTab.Name;
|
|
|
+ 1570 ct: SymTab.TypeIndex; .)
|
|
|
+ 1571 = GetIdent<cn> (. IF NOT SymTab.Enter(cn,
|
|
|
+ 1572 SymTab.KindType) THEN
|
|
|
+ 1573 SemError(200) END;
|
|
|
+ 1574 ct := SymTab.NewClass();
|
|
|
+ 1575 SymTab.SetSymType(cn, ct);
|
|
|
+ 1576 SymTab.PushClassScope(ct);
|
|
|
+ 1577 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ 1578 AST.SetChild(astCls, 0,
|
|
|
+ 1579 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ 1580 astClsP := AST.NoNode;
|
|
|
+ 1581 astClsPTail := AST.NoNode;
|
|
|
+ 1582 astClsF := AST.NoNode;
|
|
|
+ 1583 astClsFTail := AST.NoNode;
|
|
|
+ 1584 astClsM := AST.NoNode;
|
|
|
+ 1585 astClsMTail := AST.NoNode; .)
|
|
|
+ 1586 [ Parents<ct> ]
|
|
|
+ 1587 ";"
|
|
|
+ 1588 { ClassField<ct> ";" }
|
|
|
+ 1589 { MethodHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1590 (. Lower.ScopeLeave;
|
|
|
+ 1591 SymTab.CloseProc;
|
|
|
+ 1592 QbeGen.AbortFunc; .) }
|
|
|
+ 1593 "END"
|
|
|
+ 1594 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 1595 SemError(202) END;
|
|
|
+ 1596 SymTab.LayoutClass(ct);
|
|
|
+ 1597 SymTab.PopScope;
|
|
|
+ 1598 AST.SetChild(astCls, 1, astClsP);
|
|
|
+ 1599 AST.SetChild(astCls, 2, astClsF);
|
|
|
+ 1600 AST.SetChild(astCls, 3, astClsM);
|
|
|
+ 1601 astDecl := astCls; .) .
|
|
|
+ 1602 Parents<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name; .)
|
|
|
+ 1603 = "(" Parent1<ct>
|
|
|
+ 1604 { "," GetIdent<p> (. SemError(230); .) }
|
|
|
+ 1605 ")" .
|
|
|
+ 1606 Parent1<ct: SymTab.TypeIndex> (. VAR p: SymTab.Name;
|
|
|
+ 1607 pt: SymTab.TypeIndex; .)
|
|
|
+ 1608 = GetIdent<p> (. IF NOT SymTab.Lookup(p) THEN
|
|
|
+ 1609 SemError(201)
|
|
|
+ 1610 ELSE pt := SymTab.SymType(p);
|
|
|
+ 1611 IF SymTab.ClassOf(pt) #
|
|
|
+ 1612 SymTab.ClClass THEN
|
|
|
+ 1613 SemError(230)
|
|
|
+ 1614 ELSE SymTab.SetParent(ct, pt)
|
|
|
+ 1615 END
|
|
|
+ 1616 END;
|
|
|
1617 AstAppend(AST.NkFieldDecl,
|
|
|
- 1618 astClsF, astClsFTail, astNode);
|
|
|
- 1619 IF SymTab.Lookup(rhs) THEN
|
|
|
- 1620 SymTab.SetSymType(n,
|
|
|
- 1621 SymTab.SymType(rhs))
|
|
|
- 1622 END; .)
|
|
|
- 1623 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 1624 n) THEN
|
|
|
- 1625 SemError(200) END;
|
|
|
- 1626 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1627 AST.SetChild(astNode, 0,
|
|
|
- 1628 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 1629 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
- 1630 n) THEN
|
|
|
- 1631 SemError(200) END;
|
|
|
- 1632 AST.SetChild(astNode,
|
|
|
- 1633 AST.NChild(astNode),
|
|
|
- 1634 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
- 1635 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
- 1636 AST.SetTy(astNode, t);
|
|
|
- 1637 AstAppend(AST.NkFieldDecl,
|
|
|
- 1638 astClsF, astClsFTail, astNode); .) ) .
|
|
|
- 1639 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
- 1640 (. VAR wantVirt: BOOLEAN; .)
|
|
|
- 1641 = (. wantVirt := FALSE; .)
|
|
|
- 1642 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
- 1643 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
- 1644 SymTab.MarkVirtual END;
|
|
|
- 1645 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1646 AST.SetChild(astMethod, 0,
|
|
|
- 1647 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1648 IF wantVirt THEN
|
|
|
- 1649 AST.SetOp(astMethod, 3)
|
|
|
- 1650 ELSE AST.SetOp(astMethod, 0)
|
|
|
- 1651 END;
|
|
|
+ 1618 astClsP, astClsPTail,
|
|
|
+ 1619 AST.MakeLeaf(AST.NkIdent, p)); .) .
|
|
|
+ 1620 ClassField<ct: SymTab.TypeIndex> (. VAR n, rhs: SymTab.Name;
|
|
|
+ 1621 t: SymTab.TypeIndex;
|
|
|
+ 1622 astNode: AST.Node; .)
|
|
|
+ 1623 = GetIdent<n>
|
|
|
+ 1624 ( "=" GetIdent<rhs> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1625 SymTab.KindConst) THEN
|
|
|
+ 1626 SemError(200) END;
|
|
|
+ 1627 astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1628 AST.SetChild(astNode, 0,
|
|
|
+ 1629 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1630 AST.SetChild(astNode, 1,
|
|
|
+ 1631 AST.MakeLeaf(AST.NkIdent, rhs));
|
|
|
+ 1632 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1633 astClsF, astClsFTail, astNode);
|
|
|
+ 1634 IF SymTab.Lookup(rhs) THEN
|
|
|
+ 1635 SymTab.SetSymType(n,
|
|
|
+ 1636 SymTab.SymType(rhs))
|
|
|
+ 1637 END; .)
|
|
|
+ 1638 | (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 1639 n) THEN
|
|
|
+ 1640 SemError(200) END;
|
|
|
+ 1641 astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1642 AST.SetChild(astNode, 0,
|
|
|
+ 1643 AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 1644 { "," GetIdent<n> (. IF NOT SymTab.FieldPending(ct,
|
|
|
+ 1645 n) THEN
|
|
|
+ 1646 SemError(200) END;
|
|
|
+ 1647 AST.SetChild(astNode,
|
|
|
+ 1648 AST.NChild(astNode),
|
|
|
+ 1649 AST.MakeLeaf(AST.NkIdent, n)); .) }
|
|
|
+ 1650 ":" Type<t, FALSE> (. SymTab.FixPendingF(ct, t);
|
|
|
+ 1651 AST.SetTy(astNode, t);
|
|
|
1652 AstAppend(AST.NkFieldDecl,
|
|
|
- 1653 astClsM, astClsMTail, astMethod); .) .
|
|
|
- 1654 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
- 1655 ct: SymTab.TypeIndex; .)
|
|
|
- 1656 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
- 1657 SemError(201);
|
|
|
- 1658 ct := SymTab.InvalidType
|
|
|
- 1659 ELSE ct := SymTab.SymType(cn);
|
|
|
- 1660 IF SymTab.ClassOf(ct) #
|
|
|
- 1661 SymTab.ClClass THEN
|
|
|
- 1662 SemError(230);
|
|
|
- 1663 ct := SymTab.InvalidType
|
|
|
- 1664 END
|
|
|
- 1665 END;
|
|
|
- 1666 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
- 1667 AST.SetOp(astCls, 1);
|
|
|
- 1668 AST.SetChild(astCls, 0,
|
|
|
- 1669 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
- 1670 astClsM := AST.NoNode;
|
|
|
- 1671 astClsMTail := AST.NoNode;
|
|
|
- 1672 astStmt := AST.NoNode;
|
|
|
- 1673 IF ct #
|
|
|
- 1674 SymTab.InvalidType THEN
|
|
|
- 1675 IF NOT SymTab.PushClassMembers(
|
|
|
- 1676 ct) THEN
|
|
|
- 1677 SemError(230) END;
|
|
|
- 1678 SymTab.PushImplClass(ct)
|
|
|
- 1679 END; .)
|
|
|
- 1680 ";" { MethodImpl<ct> ";" }
|
|
|
- 1681 (. astStmt := AST.NoNode; .)
|
|
|
- 1682 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
- 1683 .)
|
|
|
- 1684 [ StatSeq ] ]
|
|
|
- 1685 "END"
|
|
|
- 1686 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
- 1687 SemError(202) END;
|
|
|
- 1688 SymTab.PopImplClass;
|
|
|
- 1689 SymTab.PopScope;
|
|
|
- 1690 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
- 1691 AST.SetChild(astCls, 2, astStmt);
|
|
|
- 1692 AST.SetChild(astCls, 3, astClsM);
|
|
|
- 1693 astDecl := astCls; .) .
|
|
|
- 1694 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
- 1695 thisQ: QbeGen.QVal;
|
|
|
- 1696 methRes: SymTab.TypeIndex; .)
|
|
|
- 1697 = MethodHeading<pn, ct> ";"
|
|
|
- 1698 (. IF (ct #
|
|
|
- 1699 SymTab.InvalidType)
|
|
|
- 1700 AND NOT SymTab.MethodExists(ct,
|
|
|
- 1701 pn) THEN
|
|
|
- 1702 SemError(201) END; .)
|
|
|
- 1703 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
- 1704 SymTab.MarkFwd;
|
|
|
- 1705 QbeGen.AbortFunc;
|
|
|
- 1706 Lower.ScopeLeave;
|
|
|
- 1707 SymTab.CloseProc; .)
|
|
|
- 1708 | (.
|
|
|
- 1709 (* bind the receiver: bare
|
|
|
- 1710 field names resolve
|
|
|
- 1711 against THIS *)
|
|
|
- 1712 QbeGen.CopyOp("@", thisQ);
|
|
|
- 1713 QbeGen.PushWith(thisQ); .)
|
|
|
- 1714 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
- 1715 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
- 1716 QbeGen.PopWith;
|
|
|
- 1717 methRes := SymTab.CurRes();
|
|
|
- 1718 Lower.ScopeLeave;
|
|
|
- 1719 SymTab.CloseProc;
|
|
|
- 1720 QbeGen.EndFunc(methRes); .) ) .
|
|
|
- 1721 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1722 = "CONST" (. astSeq := AST.NoNode;
|
|
|
- 1723 astTail := AST.NoNode; .)
|
|
|
- 1724 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1725 astSeq, astTail, astDecl); .) }
|
|
|
- 1726 (. astDecl := astSeq; .) .
|
|
|
- 1727 ConstDecl (. VAR n: SymTab.Name;
|
|
|
- 1728 t: SymTab.TypeIndex;
|
|
|
- 1729 qv: QbeGen.QVal;
|
|
|
- 1730 cls: INTEGER;
|
|
|
- 1731 mk: ARRAY [0 .. 15] OF CARDINAL;
|
|
|
- 1732 mw: CARDINAL;
|
|
|
- 1733 mlo: INTEGER;
|
|
|
- 1734 astNode: AST.Node; .)
|
|
|
- 1735 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1736 SymTab.KindConst) THEN
|
|
|
- 1737 SemError(200) END; .)
|
|
|
- 1738 "="
|
|
|
- 1739 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1740 AST.SetChild(astNode, 0,
|
|
|
- 1741 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1742 AST.SetChild(astNode, 1, astCur);
|
|
|
- 1743 AST.SetTy(astNode, t);
|
|
|
- 1744 astDecl := astNode;
|
|
|
- 1745 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
- 1746 Lower.NoteConstVal(qv);
|
|
|
- 1747 SymTab.SetSymType(n, t);
|
|
|
- 1748 cls := SymTab.ClassOf(t);
|
|
|
- 1749 IF cls = SymTab.ClSet THEN
|
|
|
- 1750 (* a SET CONST needs static
|
|
|
- 1751 data: fold its mask now
|
|
|
- 1752 (the grammar sees the
|
|
|
- 1753 element values) and let
|
|
|
- 1754 Lower re-emit it *)
|
|
|
- 1755 IF Lower.SetConstMaskOf(
|
|
|
- 1756 AST.Child(astNode, 1),
|
|
|
- 1757 mk, mw, mlo) THEN
|
|
|
- 1758 Lower.NoteSetMask(n, mk, mw,
|
|
|
- 1759 mlo);
|
|
|
- 1760 SymTab.SetSymVal(n, qv)
|
|
|
- 1761 ELSE
|
|
|
- 1762 SemError(230)
|
|
|
- 1763 END
|
|
|
- 1764 ELSIF (cls = SymTab.ClArray)
|
|
|
- 1765 OR (cls = SymTab.ClRecord)
|
|
|
- 1766 OR (cls = SymTab.ClClass)
|
|
|
- 1767 OR (cls = SymTab.ClStr)
|
|
|
- 1768 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 1769 (* an aggregate/string
|
|
|
- 1770 constant: qv is its
|
|
|
- 1771 descriptor address; no
|
|
|
- 1772 scalar data *)
|
|
|
- 1773 SymTab.SetSymVal(n, qv)
|
|
|
- 1774 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
- 1775 SemError(230)
|
|
|
- 1776 ELSE
|
|
|
- 1777 SymTab.SetSymVal(n, qv);
|
|
|
- 1778 END; .) .
|
|
|
- 1779 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1780 = "VAR" (. astSeq := AST.NoNode;
|
|
|
- 1781 astTail := AST.NoNode; .)
|
|
|
- 1782 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1783 astSeq, astTail, astDecl); .) }
|
|
|
- 1784 (. astDecl := astSeq; .) .
|
|
|
- 1785 VarDecl (. VAR nm: SymTab.Name;
|
|
|
- 1786 t: SymTab.TypeIndex;
|
|
|
- 1787 i: CARDINAL;
|
|
|
- 1788 cls: INTEGER;
|
|
|
- 1789 astNode, astTail: AST.Node; .)
|
|
|
- 1790 = VarIdents ":"
|
|
|
- 1791 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1792 astTail := astNode;
|
|
|
- 1793 i := 0;
|
|
|
- 1794 WHILE i < SymTab.PendCount() DO
|
|
|
- 1795 SymTab.PendName(i, nm);
|
|
|
- 1796 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
- 1797 (* chunked: a VAR list can
|
|
|
- 1798 exceed AST.MaxChild *)
|
|
|
- 1799 AstAppend(AST.NkBlock,
|
|
|
- 1800 astNode, astTail,
|
|
|
- 1801 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
- 1802 INC(i)
|
|
|
- 1803 END;
|
|
|
- 1804 AST.SetTy(astNode, t);
|
|
|
- 1805 astDecl := astNode;
|
|
|
- 1806 cls := SymTab.ClassOf(t);
|
|
|
- 1807 IF (t # SymTab.InvalidType)
|
|
|
- 1808 AND NOT SymTab.IsUnresolved(t)
|
|
|
- 1809 AND (cls # SymTab.ClInt)
|
|
|
- 1810 AND (cls # SymTab.ClBool)
|
|
|
- 1811 AND (cls # SymTab.ClChar)
|
|
|
- 1812 AND (cls # SymTab.ClReal)
|
|
|
- 1813 AND (cls # SymTab.ClArray)
|
|
|
- 1814 AND (cls # SymTab.ClSet)
|
|
|
- 1815 AND (cls # SymTab.ClRecord)
|
|
|
- 1816 AND (cls # SymTab.ClPtr)
|
|
|
- 1817 AND (cls # SymTab.ClLong)
|
|
|
- 1818 AND (cls # SymTab.ClProc)
|
|
|
- 1819 AND (cls # SymTab.ClUChar)
|
|
|
- 1820 AND (cls # SymTab.ClUStr)
|
|
|
- 1821 AND (cls # SymTab.ClEnum)
|
|
|
- 1822 AND (cls # SymTab.ClClass) THEN
|
|
|
- 1823 SemError(230) END;
|
|
|
- 1824 IF QbeGen.LocFull() THEN
|
|
|
- 1825 SemError(233) END;
|
|
|
- 1826 i := 0;
|
|
|
- 1827 IF SymTab.IsUnresolved(t)
|
|
|
- 1828 AND NOT SymTab.InProc() THEN
|
|
|
- 1829 (* a forward-typed global:
|
|
|
- 1830 defer emission until the
|
|
|
- 1831 TYPE block completes *)
|
|
|
- 1832 AST.SetOp(astNode, 1);
|
|
|
- 1833 WHILE i < SymTab.PendCount() DO
|
|
|
- 1834 SymTab.PendName(i, nm);
|
|
|
- 1835 IF nPendVar <=
|
|
|
- 1836 HIGH(pendVarName) THEN
|
|
|
- 1837 pendVarName[nPendVar] := nm;
|
|
|
- 1838 pendVarT[nPendVar] := t;
|
|
|
- 1839 INC(nPendVar)
|
|
|
- 1840 END;
|
|
|
- 1841 INC(i)
|
|
|
- 1842 END
|
|
|
- 1843 ELSE
|
|
|
- 1844 WHILE i < SymTab.PendCount() DO
|
|
|
- 1845 SymTab.PendName(i, nm);
|
|
|
- 1846 INC(i)
|
|
|
- 1847 END
|
|
|
- 1848 END;
|
|
|
- 1849 (* a plain VAR list, not a
|
|
|
- 1850 heading: the signature
|
|
|
- 1851 result is discarded *)
|
|
|
- 1852 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1853 END; .) .
|
|
|
- 1854 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 1855 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1856 SymTab.KindVar) THEN
|
|
|
- 1857 SemError(200) END; .)
|
|
|
- 1858 { ","
|
|
|
- 1859 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1860 SymTab.KindVar) THEN
|
|
|
- 1861 SemError(200) END; .) } .
|
|
|
- 1862 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 1863 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1864 SemError(200) END; .)
|
|
|
- 1865 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1866 SemError(200) END; .) } .
|
|
|
- 1867 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
- 1868 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
- 1869 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 1870 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
- 1871 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
- 1872 (. VAR t: SymTab.TypeIndex;
|
|
|
- 1873 mg: QbeGen.QVal; .)
|
|
|
- 1874 = "PROCEDURE"
|
|
|
- 1875 GetIdent<pn> (. IF methCls #
|
|
|
- 1876 SymTab.InvalidType THEN
|
|
|
- 1877 (* a method: resume the
|
|
|
- 1878 declared symbol (reuse
|
|
|
- 1879 its uid) *)
|
|
|
- 1880 IF NOT SymTab.ResumeMethod(
|
|
|
- 1881 methCls, pn) THEN
|
|
|
- 1882 SemError(200) END
|
|
|
- 1883 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
- 1884 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
- 1885 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
- 1886 SemError(200) END
|
|
|
- 1887 END
|
|
|
- 1888 END;
|
|
|
- 1889 Lower.ScopeEnter;
|
|
|
- 1890 Lower.NoteProc(pn,
|
|
|
- 1891 SymTab.ProcUid(pn),
|
|
|
- 1892 SymTab.InvalidType,
|
|
|
- 1893 SymTab.ProcDepthOf(pn),
|
|
|
- 1894 FALSE);
|
|
|
- 1895 QbeGen.BeginFunc("");
|
|
|
- 1896 IF methCls #
|
|
|
- 1897 SymTab.InvalidType THEN
|
|
|
- 1898 (* hidden THIS receiver:
|
|
|
- 1899 a VAR param of the
|
|
|
- 1900 class type, pushed as
|
|
|
- 1901 the WITH base *)
|
|
|
- 1902 IF NOT SymTab.EnterThisParam(
|
|
|
- 1903 methCls) THEN
|
|
|
- 1904 SemError(200) END;
|
|
|
- 1905 IF NOT QbeGen.FuncParam(
|
|
|
- 1906 "THIS", TRUE,
|
|
|
- 1907 methCls) THEN
|
|
|
- 1908 SemError(233) END
|
|
|
- 1909 END; .)
|
|
|
- 1910 [ FormalParams ]
|
|
|
- 1911 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
- 1912 SemError(235) END;
|
|
|
- 1913 Lower.SetProcRes(t); .) ] .
|
|
|
- 1914 FormalParams
|
|
|
- 1915 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 1916 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 1917 nm: SymTab.Name;
|
|
|
- 1918 i: CARDINAL;
|
|
|
- 1919 isV: BOOLEAN; .)
|
|
|
- 1920 = (. isV := FALSE; .)
|
|
|
- 1921 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 1922 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
- 1923 WHILE i < SymTab.PendCount() DO
|
|
|
- 1924 SymTab.PendName(i, nm);
|
|
|
- 1925 Lower.NoteParam(nm, t, isV);
|
|
|
- 1926 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
- 1927 (* value open arrays are
|
|
|
- 1928 passed as descriptor
|
|
|
- 1929 addresses (no copy):
|
|
|
- 1930 same representation as
|
|
|
- 1931 VAR formals *)
|
|
|
- 1932 IF NOT QbeGen.FuncParam(nm,
|
|
|
- 1933 isV
|
|
|
- 1934 OR SymTab.IsOpenArray(t),
|
|
|
- 1935 t) THEN
|
|
|
- 1936 SemError(233) END;
|
|
|
- 1937 INC(i)
|
|
|
- 1938 END;
|
|
|
- 1939 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1940 SemError(235) END; .) .
|
|
|
- 1941 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
- 1942 static link gives them their parent's frame. Methods keep
|
|
|
- 1943 parse-now/230-later. *)
|
|
|
- 1944 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
- 1945 astNode: AST.Node; .)
|
|
|
- 1946 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1947 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1948 AST.SetOp(astNode, 0);
|
|
|
- 1949 AST.SetChild(astNode, 0,
|
|
|
- 1950 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1951 Lower.NoteProcNode(astNode); .)
|
|
|
- 1952 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
- 1953 astDecl := astNode;
|
|
|
- 1954 Lower.ScopeLeave;
|
|
|
- 1955 SymTab.MarkFwd;
|
|
|
- 1956 SymTab.CloseProc;
|
|
|
- 1957 QbeGen.AbortFunc; .)
|
|
|
- 1958 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
- 1959 astDecl := astNode;
|
|
|
- 1960 Lower.MarkProcExternal;
|
|
|
- 1961 Lower.ScopeLeave;
|
|
|
- 1962 SymTab.MarkExternal("");
|
|
|
- 1963 SymTab.CloseProc;
|
|
|
- 1964 QbeGen.AbortFunc; .)
|
|
|
- 1965 |
|
|
|
- 1966 (. allowDefer := TRUE; deferredBody := FALSE;
|
|
|
- 1967 curProcNode := astNode; .)
|
|
|
- 1968 Block<pn> (. IF deferredBody THEN
|
|
|
- 1969 (* body skipped: close like
|
|
|
- 1970 FORWARD (no body node) *)
|
|
|
- 1971 astDecl := astNode;
|
|
|
- 1972 Lower.ScopeLeave;
|
|
|
- 1973 SymTab.CloseProc;
|
|
|
- 1974 QbeGen.AbortFunc
|
|
|
- 1975 ELSE
|
|
|
- 1976 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1977 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
- 1978 astDecl := astNode;
|
|
|
- 1979 Lower.ScopeLeave;
|
|
|
- 1980 SymTab.CloseProc;
|
|
|
- 1981 QbeGen.EndFunc(
|
|
|
- 1982 SymTab.ProcRes(pn))
|
|
|
- 1983 END; .) ) .
|
|
|
- 1984 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; dfr: BOOLEAN; .)
|
|
|
- 1985 = (. dfr := FALSE;
|
|
|
- 1986 IF allowDefer AND twoPhaseParse
|
|
|
- 1987 AND NOT repassing THEN
|
|
|
- 1988 dfr := DeferSkip(pn)
|
|
|
- 1989 END;
|
|
|
- 1990 allowDefer := FALSE;
|
|
|
- 1991 .)
|
|
|
- 1992 DeclSeq (. astBlkDecls := astDecl;
|
|
|
- 1993 astStmt := AST.NoNode;
|
|
|
- 1994 nLab := 0; nGot := 0; .)
|
|
|
- 1995 [ "BEGIN" (. (* an empty body is still a
|
|
|
- 1996 body: mark it so Lower
|
|
|
- 1997 does not read it as a
|
|
|
- 1998 definition heading *)
|
|
|
- 1999 IF NOT dfr THEN
|
|
|
- 2000 IF astStmt = AST.NoNode THEN
|
|
|
- 2001 astStmt :=
|
|
|
- 2002 AST.MakeNode(AST.NkBlock)
|
|
|
- 2003 END
|
|
|
- 2004 END; .)
|
|
|
- 2005 [ StatSeq ] ]
|
|
|
- 2006 "END"
|
|
|
- 2007 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
- 2008 SemError(202) END;
|
|
|
- 2009 CheckGotos; .) .
|
|
|
- 2010 (* Two-phase, phase 2 (milestone 2c): re-parse every deferred module-
|
|
|
- 2011 level body once the unit's declarations are complete. Inlined at
|
|
|
- 2012 both call sites because a stand-alone epsilon production is
|
|
|
- 2013 "unreachable" to Coco/R (referenced only from actions). *)
|
|
|
- 2014 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 2015 = (. astSeq := AST.NoNode;
|
|
|
- 2016 astTail := AST.NoNode; .)
|
|
|
- 2017 Statement (. AstAppend(AST.NkBlock,
|
|
|
- 2018 astSeq, astTail, astStmt); .)
|
|
|
- 2019 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
- 2020 astSeq, astTail, astStmt); .) ] }
|
|
|
- 2021 (. astStmt := astSeq; .) .
|
|
|
- 2022 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
- 2023 are accepted: the statement after ';' is optional. *)
|
|
|
- 2024 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
- 2025 = (. astStmt := AST.NoNode; .)
|
|
|
- 2026 ( AssOrCall
|
|
|
- 2027 | IfStat
|
|
|
- 2028 | WhileStat
|
|
|
- 2029 | RepeatStat
|
|
|
- 2030 | LoopStat
|
|
|
- 2031 | ForStat
|
|
|
- 2032 | CaseStat
|
|
|
- 2033 | WithStat
|
|
|
- 2034 | ReturnStat
|
|
|
- 2035 | HaltStat
|
|
|
- 2036 | NewStat
|
|
|
- 2037 | DisposeStat
|
|
|
- 2038 | IncDecStat
|
|
|
- 2039 | InclExclStat
|
|
|
- 2040 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
- 2041 SemError(230) END;
|
|
|
- 2042 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
- 2043 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
- 2044 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
- 2045 AST.SetChild(astStmt, 0,
|
|
|
- 2046 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
- 2047 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
- 2048 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
- 2049 dk: INTEGER;
|
|
|
- 2050 qd, qe: QbeGen.QVal;
|
|
|
- 2051 qn: SymTab.Name;
|
|
|
- 2052 sfx, isInc: BOOLEAN;
|
|
|
- 2053 astNode, astD: AST.Node; .)
|
|
|
- 2054 = ( "INCL" (. isInc := TRUE; .)
|
|
|
- 2055 | "EXCL" (. isInc := FALSE; .) )
|
|
|
- 2056 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
- 2057 Expr<et2, qe> ")"
|
|
|
- 2058 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2059 IF isInc THEN
|
|
|
- 2060 AST.SetChild(astNode, 0,
|
|
|
- 2061 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
- 2062 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2063 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
- 2064 END;
|
|
|
- 2065 IF astD # AST.NoNode THEN
|
|
|
- 2066 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2067 IF astCur # AST.NoNode THEN
|
|
|
- 2068 AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 2069 astStmt := astNode; .)
|
|
|
- 2070 (. IF (at # SymTab.InvalidType)
|
|
|
- 2071 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
- 2072 SemError(222)
|
|
|
- 2073 END; .) .
|
|
|
- 2074 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
- 2075 integer designator. *)
|
|
|
- 2076 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
- 2077 dk: INTEGER;
|
|
|
- 2078 qd, qv, qn2, qstep:
|
|
|
- 2079 QbeGen.QVal;
|
|
|
- 2080 qn: SymTab.Name;
|
|
|
- 2081 sfx, isInc: BOOLEAN;
|
|
|
- 2082 astNode, astD, astStep:
|
|
|
- 2083 AST.Node; .)
|
|
|
- 2084 = (. isInc := TRUE; .)
|
|
|
- 2085 ( "INC" (. isInc := TRUE; .)
|
|
|
- 2086 | "DEC" (. isInc := FALSE; .) )
|
|
|
- 2087 "(" (. astStep := AST.NoNode; .)
|
|
|
- 2088 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
- 2089 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
- 2090 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2091 IF isInc THEN
|
|
|
- 2092 AST.SetChild(astNode, 0,
|
|
|
- 2093 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
- 2094 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2095 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
- 2096 END;
|
|
|
- 2097 IF astD # AST.NoNode THEN
|
|
|
- 2098 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2099 IF astStep # AST.NoNode THEN
|
|
|
- 2100 AST.SetChild(astNode, 2, astStep) END;
|
|
|
- 2101 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2102 ELSIF (dk # SymTab.KindVar)
|
|
|
- 2103 AND (dk # SymTab.KindParam)
|
|
|
- 2104 AND (dk # SymTab.KindField) THEN
|
|
|
- 2105 SemError(210)
|
|
|
- 2106 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
- 2107 SemError(211)
|
|
|
- 2108 END; .) .
|
|
|
- 2109 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
- 2110 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
- 2111 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
- 2112 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 2113 dk: INTEGER;
|
|
|
- 2114 qd, qm: QbeGen.QVal;
|
|
|
- 2115 qn: SymTab.Name;
|
|
|
- 2116 sfx: BOOLEAN;
|
|
|
- 2117 bt: SymTab.TypeIndex;
|
|
|
- 2118 astNode, astD: AST.Node; .)
|
|
|
- 2119 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 2120 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2121 AST.SetChild(astNode, 0,
|
|
|
- 2122 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
- 2123 IF astD # AST.NoNode THEN
|
|
|
- 2124 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2125 astStmt := astNode; .)
|
|
|
- 2126 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2127 ELSIF (dk # SymTab.KindVar)
|
|
|
- 2128 AND (dk # SymTab.KindParam)
|
|
|
- 2129 AND (dk # SymTab.KindField) THEN
|
|
|
- 2130 SemError(210)
|
|
|
- 2131 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 2132 SymTab.ClPtr THEN
|
|
|
- 2133 SemError(219)
|
|
|
- 2134 END; .) .
|
|
|
- 2135 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 2136 dk: INTEGER;
|
|
|
- 2137 qd, qv: QbeGen.QVal;
|
|
|
- 2138 qn: SymTab.Name;
|
|
|
- 2139 sfx: BOOLEAN;
|
|
|
- 2140 astNode, astD: AST.Node; .)
|
|
|
- 2141 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 2142 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2143 AST.SetChild(astNode, 0,
|
|
|
- 2144 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
- 2145 IF astD # AST.NoNode THEN
|
|
|
- 2146 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 2147 astStmt := astNode; .)
|
|
|
- 2148 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2149 ELSIF (dk # SymTab.KindVar)
|
|
|
- 2150 AND (dk # SymTab.KindParam)
|
|
|
- 2151 AND (dk # SymTab.KindField) THEN
|
|
|
- 2152 SemError(210)
|
|
|
- 2153 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 2154 SymTab.ClPtr THEN
|
|
|
- 2155 SemError(219)
|
|
|
- 2156 END; .) .
|
|
|
- 2157 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
- 2158 address; field designators resolve through both stacks. *)
|
|
|
- 2159 WithStat (. VAR nW: CARDINAL;
|
|
|
- 2160 astNode: AST.Node; .)
|
|
|
- 2161 = "WITH" (. nW := 0;
|
|
|
- 2162 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
- 2163 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
- 2164 "DO" (. astStmt := AST.NoNode; .)
|
|
|
- 2165 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
- 2166 AST.NChild(astNode), astStmt);
|
|
|
- 2167 astStmt := astNode;
|
|
|
- 2168 WHILE nW > 0 DO
|
|
|
- 2169 SymTab.PopScope;
|
|
|
- 2170 QbeGen.PopWith;
|
|
|
- 2171 DEC(nW)
|
|
|
- 2172 END; .) .
|
|
|
- 2173 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
- 2174 (. VAR dt: SymTab.TypeIndex;
|
|
|
- 2175 dk: INTEGER;
|
|
|
- 2176 qd, qe: QbeGen.QVal;
|
|
|
- 2177 qn: SymTab.Name;
|
|
|
- 2178 sfx: BOOLEAN; .)
|
|
|
- 2179 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 2180 (. IF astCur # AST.NoNode THEN
|
|
|
- 2181 AST.SetChild(wnode,
|
|
|
- 2182 AST.NChild(wnode), astCur) END;
|
|
|
- 2183 IF dt = SymTab.InvalidType THEN
|
|
|
- 2184 ELSIF (SymTab.ClassOf(dt) #
|
|
|
- 2185 SymTab.ClRecord)
|
|
|
- 2186 AND (SymTab.ClassOf(dt) #
|
|
|
- 2187 SymTab.ClClass) THEN
|
|
|
- 2188 SemError(215)
|
|
|
- 2189 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
- 2190 QbeGen.PushWith(qd);
|
|
|
- 2191 INC(nW)
|
|
|
- 2192 END; .) .
|
|
|
- 2193 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
- 2194 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
- 2195 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 2196 dk: INTEGER;
|
|
|
- 2197 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
- 2198 qn: SymTab.Name;
|
|
|
- 2199 ct2, res0: SymTab.TypeIndex;
|
|
|
- 2200 q2, mg0: QbeGen.QVal;
|
|
|
- 2201 isR, conv, wconv: BOOLEAN;
|
|
|
- 2202 called, sfx: BOOLEAN;
|
|
|
- 2203 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
- 2204 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
- 2205 = GetIdent<n>
|
|
|
- 2206 ( ":" (. NoteLabel(n);
|
|
|
- 2207 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
- 2208 AST.SetChild(astNode, 0,
|
|
|
- 2209 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 2210 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
- 2211 AST.SetChild(astLab, 0, astNode); .)
|
|
|
- 2212 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
- 2213 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
- 2214 astStmt := astLab; .)
|
|
|
- 2215 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
- 2216 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
- 2217 ( ":="
|
|
|
- 2218 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 2219 AST.NkAssign, 0, astLhs, astCur);
|
|
|
- 2220 IF (dt # SymTab.InvalidType)
|
|
|
- 2221 AND (dk # SymTab.KindVar)
|
|
|
- 2222 AND (dk # SymTab.KindParam)
|
|
|
- 2223 AND (dk # SymTab.KindField) THEN
|
|
|
- 2224 SemError(210)
|
|
|
- 2225 ELSIF NOT SymTab.Assignable(et,
|
|
|
- 2226 dt) THEN
|
|
|
- 2227 SemError(210)
|
|
|
- 2228 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 2229 AND (SymTab.ClassOf(dt) =
|
|
|
- 2230 SymTab.ClClass) THEN
|
|
|
- 2231 SemError(230) END;
|
|
|
- 2232 isR := (dt #
|
|
|
- 2233 SymTab.InvalidType)
|
|
|
- 2234 AND (SymTab.ClassOf(dt)
|
|
|
- 2235 = SymTab.ClReal);
|
|
|
- 2236 conv := isR
|
|
|
- 2237 AND SymTab.IsIntFamily(et);
|
|
|
- 2238 wconv := (dt #
|
|
|
- 2239 SymTab.InvalidType)
|
|
|
- 2240 AND SymTab.IsLongFamily(dt)
|
|
|
- 2241 AND SymTab.IsIntFamily(et);
|
|
|
- 2242 IF ((dk = SymTab.KindVar)
|
|
|
- 2243 OR (dk = SymTab.KindParam)
|
|
|
- 2244 OR (dk = SymTab.KindField))
|
|
|
- 2245 AND (dt # SymTab.InvalidType)
|
|
|
- 2246 AND (et # SymTab.InvalidType)
|
|
|
- 2247 AND (SymTab.ClassOf(dt) #
|
|
|
- 2248 SymTab.ClClass) THEN
|
|
|
- 2249 END; .)
|
|
|
- 2250 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
- 2251 (. astRes := AstCallNode(astLhs);
|
|
|
- 2252 sfx := FALSE; .)
|
|
|
- 2253 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
- 2254 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 2255 AST.NkAssign, 0, astRes, astCur);
|
|
|
- 2256 IF NOT sfx THEN
|
|
|
- 2257 SemError(233)
|
|
|
- 2258 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
- 2259 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
- 2260 SemError(210)
|
|
|
- 2261 END; .)
|
|
|
- 2262 | (. IF ct2 #
|
|
|
- 2263 SymTab.InvalidType THEN
|
|
|
- 2264 SemError(233) END;
|
|
|
- 2265 astStmt := astRes; .) )
|
|
|
- 2266 | (* bare `P;`: proper parameterless
|
|
|
- 2267 procedure call; anything else
|
|
|
- 2268 here is 233 (was a bare syntax
|
|
|
- 2269 error before 4.2) *)
|
|
|
- 2270 (. astStmt := AstCallNode(astLhs);
|
|
|
- 2271 IF (dk = SymTab.KindProc)
|
|
|
- 2272 AND NOT sfx THEN
|
|
|
- 2273 res0 := SymTab.ProcRes(qn);
|
|
|
- 2274 IF res0 #
|
|
|
- 2275 SymTab.InvalidType THEN
|
|
|
- 2276 SemError(233)
|
|
|
- 2277 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 2278 0 THEN
|
|
|
- 2279 SemError(233)
|
|
|
- 2280 END
|
|
|
- 2281 ELSE SemError(233)
|
|
|
- 2282 END; .) ) ) .
|
|
|
- 2283 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 2284 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 2285 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 2286 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 2287 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 2288 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
- 2289 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2290 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
- 2291 vs: INTEGER;
|
|
|
- 2292 res: SymTab.TypeIndex;
|
|
|
- 2293 mg: QbeGen.QVal;
|
|
|
- 2294 ok, ind, isMeth, va, isConv: BOOLEAN; .)
|
|
|
- 2295 = "(" (. called := TRUE;
|
|
|
- 2296 ok := TRUE;
|
|
|
- 2297 ind := FALSE;
|
|
|
- 2298 isConv := FALSE;
|
|
|
- 2299 isMeth := methCls #
|
|
|
- 2300 SymTab.InvalidType;
|
|
|
- 2301 IF isMeth THEN
|
|
|
- 2302 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
- 2303 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
- 2304 res := SymTab.ProcRes(pn)
|
|
|
- 2305 ELSIF (SymTab.SymKind(pn) = SymTab.KindType)
|
|
|
- 2306 OR (SymTab.SymKind(pn) = SymTab.KindPredef) THEN
|
|
|
- 2307 (* ISO type conversion T(x):
|
|
|
- 2308 one value, result is T *)
|
|
|
- 2309 isConv := TRUE;
|
|
|
- 2310 res := SymTab.SymType(pn)
|
|
|
- 2311 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 2312 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 2313 ind := TRUE;
|
|
|
- 2314 res := SymTab.ProcTypeRes(pt)
|
|
|
- 2315 ELSE SemError(233);
|
|
|
- 2316 ok := FALSE;
|
|
|
- 2317 res := SymTab.InvalidType
|
|
|
- 2318 END;
|
|
|
- 2319 i := 0; .)
|
|
|
- 2320 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
- 2321 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
- 2322 ")" (. IF ok THEN
|
|
|
- 2323 IF isConv THEN
|
|
|
- 2324 (* a conversion takes
|
|
|
- 2325 exactly one value *)
|
|
|
- 2326 IF i # 1 THEN
|
|
|
- 2327 SemError(233); ok := FALSE
|
|
|
- 2328 END
|
|
|
- 2329 ELSE
|
|
|
- 2330 IF isMeth THEN
|
|
|
- 2331 np := SymTab.ClassMethodNPar(
|
|
|
- 2332 methCls, pn)
|
|
|
- 2333 ELSIF ind THEN
|
|
|
- 2334 np := SymTab.ProcTypeNPar(pt)
|
|
|
- 2335 ELSE np := SymTab.ProcNPar(pn)
|
|
|
- 2336 END;
|
|
|
- 2337 va := (NOT isMeth) AND (NOT ind)
|
|
|
- 2338 AND (SymTab.SymKind(pn) =
|
|
|
- 2339 SymTab.KindProc)
|
|
|
- 2340 AND SymTab.Varargs(pn);
|
|
|
- 2341 IF (i # np) AND NOT va THEN
|
|
|
- 2342 SemError(233); ok := FALSE
|
|
|
- 2343 END
|
|
|
- 2344 END
|
|
|
- 2345 END;
|
|
|
- 2346 IF NOT ok THEN
|
|
|
- 2347 t := SymTab.InvalidType;
|
|
|
- 2348 QbeGen.CopyOp("0", q)
|
|
|
- 2349 ELSIF want THEN
|
|
|
- 2350 IF res =
|
|
|
- 2351 SymTab.InvalidType THEN
|
|
|
- 2352 IF NOT soft THEN SemError(233) END;
|
|
|
- 2353 t := SymTab.InvalidType;
|
|
|
- 2354 QbeGen.CopyOp("0", q)
|
|
|
- 2355 ELSE t := res;
|
|
|
- 2356 QbeGen.CopyOp("@", q)
|
|
|
- 2357 END
|
|
|
- 2358 ELSE
|
|
|
- 2359 IF res #
|
|
|
- 2360 SymTab.InvalidType THEN
|
|
|
- 2361 SemError(233)
|
|
|
- 2362 END;
|
|
|
- 2363 t := SymTab.InvalidType;
|
|
|
- 2364 QbeGen.CopyOp("0", q);
|
|
|
- 2365 END; .) .
|
|
|
- 2366 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 2367 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 2368 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 2369 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
- 2370 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 2371 qe, qa, qt: QbeGen.QVal;
|
|
|
- 2372 isV, conv, va: BOOLEAN;
|
|
|
- 2373 cl: CHAR;
|
|
|
- 2374 savedN, aj: CARDINAL;
|
|
|
- 2375 savedArgs: ARRAY [0 .. 31]
|
|
|
- 2376 OF AST.Node;
|
|
|
- 2377 astActual: AST.Node; .)
|
|
|
- 2378 = (. (* Parsing the actual can clobber
|
|
|
- 2379 the enclosing call's argument
|
|
|
- 2380 list (Factor resets astNArgs),
|
|
|
- 2381 so save/restore it. *)
|
|
|
- 2382 savedN := astNArgs; aj := 0;
|
|
|
- 2383 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 2384 savedArgs[aj] := astArgs[aj];
|
|
|
- 2385 INC(aj)
|
|
|
- 2386 END; .)
|
|
|
- 2387 Expr<at, qe> (. QbeGen.CopyOp(qe, convQ); convT := at;
|
|
|
- 2388 astActual := astCur;
|
|
|
- 2389 astNArgs := savedN; aj := 0;
|
|
|
- 2390 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 2391 astArgs[aj] := savedArgs[aj];
|
|
|
- 2392 INC(aj)
|
|
|
- 2393 END;
|
|
|
- 2394 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
- 2395 astArgs[astNArgs] := astCur;
|
|
|
- 2396 INC(astNArgs)
|
|
|
- 2397 END;
|
|
|
- 2398 va := (NOT ind)
|
|
|
- 2399 AND (methCls =
|
|
|
- 2400 SymTab.InvalidType)
|
|
|
- 2401 AND (SymTab.SymKind(pn) =
|
|
|
- 2402 SymTab.KindProc)
|
|
|
- 2403 AND SymTab.Varargs(pn);
|
|
|
- 2404 IF ind THEN
|
|
|
- 2405 ft :=
|
|
|
- 2406 SymTab.ProcTypeParamType(pt,
|
|
|
- 2407 i);
|
|
|
- 2408 isV :=
|
|
|
- 2409 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 2410 i)
|
|
|
- 2411 ELSIF methCls #
|
|
|
- 2412 SymTab.InvalidType THEN
|
|
|
- 2413 ft :=
|
|
|
- 2414 SymTab.ClassMethodParamType(
|
|
|
- 2415 methCls, pn, i);
|
|
|
- 2416 isV :=
|
|
|
- 2417 SymTab.ClassMethodParamIsVar(
|
|
|
- 2418 methCls, pn, i)
|
|
|
- 2419 ELSE
|
|
|
- 2420 ft := SymTab.ParamType(pn, i);
|
|
|
- 2421 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 2422 END;
|
|
|
- 2423 IF (at = SymTab.InvalidType) THEN
|
|
|
- 2424 ELSIF ft = SymTab.InvalidType THEN
|
|
|
- 2425 ELSIF isV THEN
|
|
|
- 2426 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 2427 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 2428 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 2429 AND QbeGen.IsImm(qe) THEN
|
|
|
- 2430 ELSIF (AST.Kind(astActual) #
|
|
|
- 2431 AST.NkDesignator)
|
|
|
- 2432 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
- 2433 SemError(233)
|
|
|
- 2434 ELSIF NOT SymTab.VarParamOk(at, ft)
|
|
|
- 2435 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
- 2436 SemError(233)
|
|
|
- 2437 END
|
|
|
- 2438 ELSE
|
|
|
- 2439 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 2440 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 2441 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 2442 AND QbeGen.IsImm(qe) THEN
|
|
|
- 2443 ELSIF NOT SymTab.Assignable(at, ft)
|
|
|
- 2444 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
- 2445 SemError(233)
|
|
|
- 2446 END
|
|
|
- 2447 END; .) .
|
|
|
- 2448 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2449 q: QbeGen.QVal;
|
|
|
- 2450 hasElse: BOOLEAN;
|
|
|
- 2451 astCond, astIf, astLast,
|
|
|
- 2452 astNode: AST.Node; .)
|
|
|
- 2453 = "IF" (. hasElse := FALSE; .)
|
|
|
- 2454 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2455 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2456 SemError(214) END; .)
|
|
|
- 2457 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2458 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2459 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2460 astIf := astNode;
|
|
|
- 2461 astLast := astNode; .)
|
|
|
- 2462 { "ELSIF"
|
|
|
- 2463 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 2464 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2465 SemError(214) END; .)
|
|
|
- 2466 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 2467 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2468 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2469 AST.SetChild(astLast, 2, astNode);
|
|
|
- 2470 astLast := astNode; .) }
|
|
|
- 2471 [ "ELSE" (. hasElse := TRUE;
|
|
|
- 2472 astStmt := AST.NoNode; .)
|
|
|
- 2473 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- 2474 "END" (. astStmt := astIf; .) .
|
|
|
- 2475 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2476 q: QbeGen.QVal;
|
|
|
- 2477 astCond, astNode: AST.Node; .)
|
|
|
- 2478 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
- 2479 Expr<t, q> (. astCond := astCur;
|
|
|
- 2480 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2481 SemError(214) END; .)
|
|
|
- 2482 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
- 2483 AST.SetChild(astNode, 0, astCond);
|
|
|
- 2484 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 2485 astStmt := astNode; .)
|
|
|
- 2486 "END" .
|
|
|
- 2487 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2488 q: QbeGen.QVal;
|
|
|
- 2489 astCond, astBody, astNode:
|
|
|
- 2490 AST.Node; .)
|
|
|
- 2491 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
- 2492 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
- 2493 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
- 2494 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
- 2495 AST.SetChild(astNode, 0, astBody);
|
|
|
- 2496 AST.SetChild(astNode, 1, astCond);
|
|
|
- 2497 astStmt := astNode;
|
|
|
- 2498 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 2499 SemError(214) END; .) .
|
|
|
- 2500 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- 2501 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
- 2502 QbeGen.NewLabel(lEnd);
|
|
|
- 2503 QbeGen.PushLoop(lEnd); .)
|
|
|
- 2504 [ StatSeq ]
|
|
|
- 2505 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
- 2506 AST.SetChild(astNode, 0, astStmt);
|
|
|
- 2507 astStmt := astNode;
|
|
|
- 2508 QbeGen.PopLoop; .) .
|
|
|
- 2509 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 2510 Runtime direction would need a compare-select; the literal
|
|
|
- 2511 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 2512 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 2513 tlo, thi, tby:
|
|
|
- 2514 SymTab.TypeIndex;
|
|
|
- 2515 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 2516 QbeGen.QVal;
|
|
|
- 2517 lTop, lBody, lEnd:
|
|
|
- 2518 QbeGen.QVal;
|
|
|
- 2519 by: INTEGER;
|
|
|
- 2520 ok: BOOLEAN;
|
|
|
- 2521 astVar, astLo, astHi, astBy,
|
|
|
- 2522 astNode: AST.Node; .)
|
|
|
- 2523 = "FOR" (. by := 1; .)
|
|
|
- 2524 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
- 2525 astStmt := AST.NoNode;
|
|
|
- 2526 astBy := AST.NoNode;
|
|
|
- 2527 ok := SymTab.Lookup(lv);
|
|
|
- 2528 IF NOT ok THEN
|
|
|
- 2529 SemError(201)
|
|
|
- 2530 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 2531 SymTab.KindVar)
|
|
|
- 2532 AND (SymTab.SymKind(lv) #
|
|
|
- 2533 SymTab.KindParam) THEN
|
|
|
- 2534 SemError(220); ok := FALSE
|
|
|
- 2535 ELSIF NOT SymTab.IsIntFamily(
|
|
|
- 2536 SymTab.SymType(lv)) THEN
|
|
|
- 2537 SemError(220); ok := FALSE
|
|
|
- 2538 END; .)
|
|
|
- 2539 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
- 2540 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
- 2541 SemError(220); ok := FALSE
|
|
|
- 2542 END; .)
|
|
|
- 2543 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
- 2544 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
- 2545 SemError(220); ok := FALSE
|
|
|
- 2546 END; .)
|
|
|
- 2547 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
- 2548 IF (tby #
|
|
|
- 2549 SymTab.InvalidType)
|
|
|
- 2550 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 2551 SemError(220); ok := FALSE
|
|
|
- 2552 END;
|
|
|
- 2553 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 2554 SemError(230); by := 1
|
|
|
- 2555 ELSIF by = 0 THEN
|
|
|
- 2556 SemError(220); by := 1
|
|
|
- 2557 END; .) ]
|
|
|
- 2558 "DO"
|
|
|
- 2559 [ StatSeq ]
|
|
|
- 2560 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
- 2561 AST.SetChild(astNode, 0, astVar);
|
|
|
- 2562 AST.SetChild(astNode, 1, astLo);
|
|
|
- 2563 AST.SetChild(astNode, 2, astHi);
|
|
|
- 2564 AST.SetChild(astNode, 3, astBy);
|
|
|
- 2565 AST.SetChild(astNode, 4, astStmt);
|
|
|
- 2566 astStmt := astNode;
|
|
|
- 2567 .) .
|
|
|
- 2568 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 2569 qsel, lEnd: QbeGen.QVal;
|
|
|
- 2570 arm, astNode, astArms,
|
|
|
- 2571 astArmsTail: AST.Node; .)
|
|
|
- 2572 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
- 2573 AST.SetChild(astNode, 0, astCur);
|
|
|
- 2574 astArms := AST.NoNode;
|
|
|
- 2575 astArmsTail := AST.NoNode;
|
|
|
- 2576 .)
|
|
|
- 2577 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
- 2578 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
- 2579 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
- 2580 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 2581 AST.SetOp(arm, 1);
|
|
|
- 2582 AST.SetChild(arm, 0, astStmt);
|
|
|
- 2583 AstAppend(AST.NkBlock,
|
|
|
- 2584 astArms, astArmsTail, arm); .) ]
|
|
|
- 2585 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
- 2586 astStmt := astNode;
|
|
|
- 2587 .) .
|
|
|
- 2588 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 2589 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 2590 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 2591 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 2592 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2593 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- 2594 (. VAR arm: AST.Node; .)
|
|
|
- 2595 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
- 2596 CaseLabel<tsel, qsel, arm>
|
|
|
- 2597 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
- 2598 ":" (. astStmt := AST.NoNode; .)
|
|
|
- 2599 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
- 2600 astStmt);
|
|
|
- 2601 AstAppend(AST.NkBlock,
|
|
|
- 2602 arms, armsTail, arm);
|
|
|
- 2603 .) .
|
|
|
- 2604 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2605 arm: AST.Node>
|
|
|
- 2606 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 2607 q2, q3, qc, qd, qe:
|
|
|
- 2608 QbeGen.QVal;
|
|
|
- 2609 astLab: AST.Node;
|
|
|
- 2610 lNext: QbeGen.QVal; .)
|
|
|
- 2611 = Expr<t2, q2> (. astLab := astCur;
|
|
|
- 2612 IF (t2 #
|
|
|
- 2613 SymTab.InvalidType)
|
|
|
- 2614 AND (tsel #
|
|
|
- 2615 SymTab.InvalidType)
|
|
|
- 2616 AND ((SymTab.ClassOf(t2) =
|
|
|
- 2617 SymTab.ClSet)
|
|
|
- 2618 OR (SymTab.ClassOf(tsel) =
|
|
|
- 2619 SymTab.ClSet)) THEN
|
|
|
- 2620 SemError(230)
|
|
|
- 2621 ELSIF (t2 #
|
|
|
- 2622 SymTab.InvalidType)
|
|
|
- 2623 AND (tsel #
|
|
|
- 2624 SymTab.InvalidType)
|
|
|
- 2625 AND NOT SymTab.EqCheck(t2,
|
|
|
- 2626 tsel) THEN
|
|
|
- 2627 SemError(213) END;
|
|
|
- 2628 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- 2629 SemError(230)
|
|
|
- 2630 END; .)
|
|
|
- 2631 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
- 2632 AST.NkSubrange, 0, astLab, astCur);
|
|
|
- 2633 IF (t3 #
|
|
|
- 2634 SymTab.InvalidType)
|
|
|
- 2635 AND (tsel #
|
|
|
- 2636 SymTab.InvalidType)
|
|
|
- 2637 AND NOT SymTab.EqCheck(t3,
|
|
|
- 2638 tsel) THEN
|
|
|
- 2639 SemError(213) END;
|
|
|
- 2640 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- 2641 SemError(230)
|
|
|
- 2642 END; .) ]
|
|
|
- 2643 (. AST.SetChild(arm,
|
|
|
- 2644 AST.NChild(arm), astLab); .) .
|
|
|
- 2645 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2646 q, qt: QbeGen.QVal;
|
|
|
- 2647 res: SymTab.TypeIndex;
|
|
|
- 2648 hadE, conv: BOOLEAN;
|
|
|
- 2649 astVal, astNode: AST.Node; .)
|
|
|
- 2650 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
- 2651 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
- 2652 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
- 2653 IF hadE THEN
|
|
|
- 2654 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2655 END;
|
|
|
- 2656 astStmt := astNode;
|
|
|
- 2657 conv := FALSE;
|
|
|
- 2658 IF NOT SymTab.InProc() THEN
|
|
|
- 2659 SemError(232)
|
|
|
- 2660 ELSE res := SymTab.CurRes();
|
|
|
- 2661 IF NOT hadE THEN
|
|
|
- 2662 IF res #
|
|
|
- 2663 SymTab.InvalidType THEN
|
|
|
- 2664 SemError(232)
|
|
|
- 2665 END
|
|
|
- 2666 ELSIF (res =
|
|
|
- 2667 SymTab.InvalidType)
|
|
|
- 2668 OR (t #
|
|
|
- 2669 SymTab.InvalidType)
|
|
|
- 2670 AND NOT SymTab.Assignable(t,
|
|
|
- 2671 res) THEN
|
|
|
- 2672 SemError(232)
|
|
|
- 2673 END
|
|
|
- 2674 END; .) .
|
|
|
- 2675 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2676 q: QbeGen.QVal;
|
|
|
- 2677 astVal, astNode: AST.Node; .)
|
|
|
- 2678 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
- 2679 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
- 2680 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
- 2681 IF astVal # AST.NoNode THEN
|
|
|
- 2682 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2683 END;
|
|
|
- 2684 astStmt := astNode;
|
|
|
- 2685 .) .
|
|
|
- 2686 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 2687 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 2688 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 2689 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 2690 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 2691 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2692 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2693 (. VAR n: SymTab.Name; .)
|
|
|
- 2694 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
- 2695 (* The part of Design after the identifier: resolve it and walk the
|
|
|
- 2696 selectors. Split out so a statement can decide between a label
|
|
|
- 2697 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
- 2698 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2699 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2700 (. VAR fn, mal: SymTab.Name;
|
|
|
- 2701 cls: INTEGER;
|
|
|
- 2702 ic: SymTab.TypeIndex;
|
|
|
- 2703 curT, it, eT, bt:
|
|
|
- 2704 SymTab.TypeIndex;
|
|
|
- 2705 iq, ql, qlo, qhi, qe:
|
|
|
- 2706 QbeGen.QVal;
|
|
|
- 2707 lo, hi: INTEGER;
|
|
|
- 2708 fo: INTEGER;
|
|
|
- 2709 isOpen: BOOLEAN;
|
|
|
- 2710 qb, cv: QbeGen.QVal;
|
|
|
- 2711 r: BOOLEAN;
|
|
|
- 2712 astDes, astSel: AST.Node; .)
|
|
|
- 2713 = (. methCls := SymTab.InvalidType;
|
|
|
- 2714 QbeGen.CopyOp(n, qn);
|
|
|
- 2715 sfx := FALSE;
|
|
|
- 2716 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 2717 (* a bare method name inside
|
|
|
- 2718 a CLASS IMPLEMENTATION
|
|
|
- 2719 is a sibling call on
|
|
|
- 2720 THIS *)
|
|
|
- 2721 ic := SymTab.CurImplClass();
|
|
|
- 2722 IF (ic #
|
|
|
- 2723 SymTab.InvalidType)
|
|
|
- 2724 AND SymTab.MethodExists(ic, n) THEN
|
|
|
- 2725 sfx := FALSE;
|
|
|
- 2726 QbeGen.CopyOp("@", q);
|
|
|
- 2727 methCls := ic;
|
|
|
- 2728 k := SymTab.KindProc;
|
|
|
- 2729 t := SymTab.InvalidType
|
|
|
- 2730 ELSIF SymTab.InProc() THEN
|
|
|
- 2731 (* not declared anywhere
|
|
|
- 2732 in scope: with bodies
|
|
|
- 2733 parsed at unit end this
|
|
|
- 2734 is a genuine 201 (a
|
|
|
- 2735 nested-local forward is
|
|
|
- 2736 no longer tolerated). *)
|
|
|
- 2737 SemError(201);
|
|
|
- 2738 t := SymTab.InvalidType;
|
|
|
- 2739 k := -1;
|
|
|
- 2740 QbeGen.CopyOp("0", q)
|
|
|
- 2741 ELSE
|
|
|
- 2742 SemError(201);
|
|
|
- 2743 t :=
|
|
|
- 2744 SymTab.InvalidType;
|
|
|
- 2745 k := -1;
|
|
|
- 2746 QbeGen.CopyOp("0", q)
|
|
|
- 2747 END
|
|
|
- 2748 ELSE
|
|
|
- 2749 t := SymTab.SymType(n);
|
|
|
- 2750 k := SymTab.SymKind(n);
|
|
|
- 2751 IF k = SymTab.KindConst THEN
|
|
|
- 2752 IF SymTab.Equal(n,
|
|
|
- 2753 "TRUE") THEN
|
|
|
- 2754 t := SymTab.BoolType();
|
|
|
- 2755 QbeGen.CopyOp("1", q)
|
|
|
- 2756 ELSIF SymTab.Equal(n,
|
|
|
- 2757 "FALSE") THEN
|
|
|
- 2758 t := SymTab.BoolType();
|
|
|
- 2759 QbeGen.CopyOp("0", q)
|
|
|
- 2760 ELSIF SymTab.Equal(n,
|
|
|
- 2761 "NIL") THEN
|
|
|
- 2762 QbeGen.CopyOp("0", q)
|
|
|
- 2763 ELSE
|
|
|
- 2764 cls :=
|
|
|
- 2765 SymTab.ClassOf(t);
|
|
|
- 2766 IF (t #
|
|
|
- 2767 SymTab.InvalidType)
|
|
|
- 2768 AND ((cls = SymTab.ClInt)
|
|
|
- 2769 OR (cls
|
|
|
- 2770 = SymTab.ClChar)
|
|
|
- 2771 OR (cls
|
|
|
- 2772 = SymTab.ClEnum)
|
|
|
- 2773 OR (cls
|
|
|
- 2774 = SymTab.ClReal)
|
|
|
- 2775 OR (cls
|
|
|
- 2776 = SymTab.ClLong)
|
|
|
- 2777 OR (cls
|
|
|
- 2778 = SymTab.ClNil)
|
|
|
- 2779 OR (cls = SymTab.ClBool)) THEN
|
|
|
- 2780 IF cls = SymTab.ClNil THEN
|
|
|
- 2781 QbeGen.CopyOp("0", q)
|
|
|
- 2782 ELSIF ((cls
|
|
|
- 2783 = SymTab.ClInt)
|
|
|
- 2784 OR (cls
|
|
|
- 2785 = SymTab.ClChar)
|
|
|
- 2786 OR (cls
|
|
|
- 2787 = SymTab.ClEnum)
|
|
|
- 2788 OR (cls
|
|
|
- 2789 = SymTab.ClLong)
|
|
|
- 2790 OR (cls = SymTab.ClBool))
|
|
|
- 2791 AND SymTab.GetSymVal(n, cv)
|
|
|
- 2792 AND QbeGen.IsImm(cv) THEN
|
|
|
- 2793 QbeGen.CopyOp(cv, q)
|
|
|
- 2794 ELSE
|
|
|
- 2795 QbeGen.LoadVar(n,
|
|
|
- 2796 cls = SymTab.ClReal,
|
|
|
- 2797 q)
|
|
|
- 2798 END
|
|
|
- 2799 ELSIF (cls = SymTab.ClArray)
|
|
|
- 2800 OR (cls = SymTab.ClRecord)
|
|
|
- 2801 OR (cls = SymTab.ClClass)
|
|
|
- 2802 OR (cls = SymTab.ClStr)
|
|
|
- 2803 OR (cls = SymTab.ClUStr)
|
|
|
- 2804 OR (cls = SymTab.ClSet) THEN
|
|
|
- 2805 (* aggregate constant:
|
|
|
- 2806 its value IS the
|
|
|
- 2807 descriptor address *)
|
|
|
- 2808 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
- 2809 QbeGen.CopyOp(cv, q)
|
|
|
- 2810 ELSE
|
|
|
- 2811 QbeGen.CopyOp("0", q)
|
|
|
- 2812 END
|
|
|
- 2813 ELSE
|
|
|
- 2814 IF t #
|
|
|
- 2815 SymTab.InvalidType THEN
|
|
|
- 2816 SemError(230)
|
|
|
- 2817 END;
|
|
|
- 2818 QbeGen.CopyOp("0", q)
|
|
|
- 2819 END
|
|
|
- 2820 END
|
|
|
- 2821 ELSIF (k = SymTab.KindVar)
|
|
|
- 2822 OR (k = SymTab.KindParam) THEN
|
|
|
- 2823 cls := SymTab.ClassOf(t);
|
|
|
- 2824 IF (cls # SymTab.ClInt)
|
|
|
- 2825 AND (cls # SymTab.ClBool)
|
|
|
- 2826 AND (cls # SymTab.ClChar)
|
|
|
- 2827 AND (cls # SymTab.ClUChar)
|
|
|
- 2828 AND (cls # SymTab.ClEnum)
|
|
|
- 2829 AND (cls # SymTab.ClReal)
|
|
|
- 2830 AND (cls # SymTab.ClPtr)
|
|
|
- 2831 AND (cls # SymTab.ClProc)
|
|
|
- 2832 AND (cls # SymTab.ClLong)
|
|
|
- 2833 AND (cls # SymTab.ClArray)
|
|
|
- 2834 AND (cls # SymTab.ClSet)
|
|
|
- 2835 AND (cls # SymTab.ClRecord)
|
|
|
- 2836 AND (cls # SymTab.ClUStr)
|
|
|
- 2837 AND (cls # SymTab.ClClass) THEN
|
|
|
- 2838 SemError(230);
|
|
|
- 2839 QbeGen.CopyOp("0", q)
|
|
|
- 2840 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2841 END
|
|
|
- 2842 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 2843 IF k = SymTab.KindImport THEN
|
|
|
- 2844 SemError(230)
|
|
|
- 2845 ELSIF k =
|
|
|
- 2846 SymTab.KindProc THEN
|
|
|
- 2847 (* bare procedure name:
|
|
|
- 2848 a following ArgList
|
|
|
- 2849 makes it a call;
|
|
|
- 2850 otherwise Fact
|
|
|
- 2851 reports 230 *)
|
|
|
- 2852 ELSE
|
|
|
- 2853 IF k = SymTab.KindField THEN
|
|
|
- 2854 IF QbeGen.TopWith(qb) THEN
|
|
|
- 2855 sfx := TRUE
|
|
|
- 2856 ELSE SemError(230);
|
|
|
- 2857 QbeGen.CopyOp("0", q)
|
|
|
- 2858 END
|
|
|
- 2859 END
|
|
|
+ 1653 astClsF, astClsFTail, astNode); .) ) .
|
|
|
+ 1654 MethodHeading<VAR pn: SymTab.Name; ct: SymTab.TypeIndex>
|
|
|
+ 1655 (. VAR wantVirt: BOOLEAN; .)
|
|
|
+ 1656 = (. wantVirt := FALSE; .)
|
|
|
+ 1657 [ "VIRTUAL" (. wantVirt := TRUE; .) ]
|
|
|
+ 1658 ProcHeading<pn, ct> (. IF wantVirt THEN
|
|
|
+ 1659 SymTab.MarkVirtual END;
|
|
|
+ 1660 astMethod := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1661 AST.SetChild(astMethod, 0,
|
|
|
+ 1662 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1663 IF wantVirt THEN
|
|
|
+ 1664 AST.SetOp(astMethod, 3)
|
|
|
+ 1665 ELSE AST.SetOp(astMethod, 0)
|
|
|
+ 1666 END;
|
|
|
+ 1667 AstAppend(AST.NkFieldDecl,
|
|
|
+ 1668 astClsM, astClsMTail, astMethod); .) .
|
|
|
+ 1669 ClassImplRest (. VAR cn, m2: SymTab.Name;
|
|
|
+ 1670 ct: SymTab.TypeIndex; .)
|
|
|
+ 1671 = GetIdent<cn> (. IF NOT SymTab.Lookup(cn) THEN
|
|
|
+ 1672 SemError(201);
|
|
|
+ 1673 ct := SymTab.InvalidType
|
|
|
+ 1674 ELSE ct := SymTab.SymType(cn);
|
|
|
+ 1675 IF SymTab.ClassOf(ct) #
|
|
|
+ 1676 SymTab.ClClass THEN
|
|
|
+ 1677 SemError(230);
|
|
|
+ 1678 ct := SymTab.InvalidType
|
|
|
+ 1679 END
|
|
|
+ 1680 END;
|
|
|
+ 1681 astCls := AST.MakeNode(AST.NkClassDecl);
|
|
|
+ 1682 AST.SetOp(astCls, 1);
|
|
|
+ 1683 AST.SetChild(astCls, 0,
|
|
|
+ 1684 AST.MakeLeaf(AST.NkIdent, cn));
|
|
|
+ 1685 astClsM := AST.NoNode;
|
|
|
+ 1686 astClsMTail := AST.NoNode;
|
|
|
+ 1687 astStmt := AST.NoNode;
|
|
|
+ 1688 IF ct #
|
|
|
+ 1689 SymTab.InvalidType THEN
|
|
|
+ 1690 IF NOT SymTab.PushClassMembers(
|
|
|
+ 1691 ct) THEN
|
|
|
+ 1692 SemError(230) END;
|
|
|
+ 1693 SymTab.PushImplClass(ct)
|
|
|
+ 1694 END; .)
|
|
|
+ 1695 ";" { MethodImpl<ct> ";" }
|
|
|
+ 1696 (. astStmt := AST.NoNode; .)
|
|
|
+ 1697 [ "BEGIN" (. astStmt := AST.MakeNode(AST.NkBlock);
|
|
|
+ 1698 .)
|
|
|
+ 1699 [ StatSeq ] ]
|
|
|
+ 1700 "END"
|
|
|
+ 1701 GetIdent<m2> (. IF NOT SymTab.Equal(cn, m2) THEN
|
|
|
+ 1702 SemError(202) END;
|
|
|
+ 1703 SymTab.PopImplClass;
|
|
|
+ 1704 SymTab.PopScope;
|
|
|
+ 1705 AST.SetChild(astCls, 1, AST.NoNode);
|
|
|
+ 1706 AST.SetChild(astCls, 2, astStmt);
|
|
|
+ 1707 AST.SetChild(astCls, 3, astClsM);
|
|
|
+ 1708 astDecl := astCls; .) .
|
|
|
+ 1709 MethodImpl<ct: SymTab.TypeIndex> (. VAR pn: SymTab.Name;
|
|
|
+ 1710 thisQ: QbeGen.QVal;
|
|
|
+ 1711 methRes: SymTab.TypeIndex; .)
|
|
|
+ 1712 = MethodHeading<pn, ct> ";"
|
|
|
+ 1713 (. IF (ct #
|
|
|
+ 1714 SymTab.InvalidType)
|
|
|
+ 1715 AND NOT SymTab.MethodExists(ct,
|
|
|
+ 1716 pn) THEN
|
|
|
+ 1717 SemError(201) END; .)
|
|
|
+ 1718 ( "FORWARD" (. AST.SetOp(astMethod, 1);
|
|
|
+ 1719 SymTab.MarkFwd;
|
|
|
+ 1720 QbeGen.AbortFunc;
|
|
|
+ 1721 Lower.ScopeLeave;
|
|
|
+ 1722 SymTab.CloseProc; .)
|
|
|
+ 1723 | (.
|
|
|
+ 1724 (* bind the receiver: bare
|
|
|
+ 1725 field names resolve
|
|
|
+ 1726 against THIS *)
|
|
|
+ 1727 QbeGen.CopyOp("@", thisQ);
|
|
|
+ 1728 QbeGen.PushWith(thisQ); .)
|
|
|
+ 1729 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
+ 1730 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
+ 1731 QbeGen.PopWith;
|
|
|
+ 1732 methRes := SymTab.CurRes();
|
|
|
+ 1733 Lower.ScopeLeave;
|
|
|
+ 1734 SymTab.CloseProc;
|
|
|
+ 1735 QbeGen.EndFunc(methRes); .) ) .
|
|
|
+ 1736 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1737 = "CONST" (. astSeq := AST.NoNode;
|
|
|
+ 1738 astTail := AST.NoNode; .)
|
|
|
+ 1739 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1740 astSeq, astTail, astDecl); .) }
|
|
|
+ 1741 (. astDecl := astSeq; .) .
|
|
|
+ 1742 ConstDecl (. VAR n: SymTab.Name;
|
|
|
+ 1743 t: SymTab.TypeIndex;
|
|
|
+ 1744 qv: QbeGen.QVal;
|
|
|
+ 1745 cls: INTEGER;
|
|
|
+ 1746 mk: ARRAY [0 .. 15] OF CARDINAL;
|
|
|
+ 1747 mw: CARDINAL;
|
|
|
+ 1748 mlo: INTEGER;
|
|
|
+ 1749 astNode: AST.Node; .)
|
|
|
+ 1750 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1751 SymTab.KindConst) THEN
|
|
|
+ 1752 SemError(200) END; .)
|
|
|
+ 1753 "="
|
|
|
+ 1754 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1755 AST.SetChild(astNode, 0,
|
|
|
+ 1756 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1757 AST.SetChild(astNode, 1, astCur);
|
|
|
+ 1758 AST.SetTy(astNode, t);
|
|
|
+ 1759 astDecl := astNode;
|
|
|
+ 1760 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
+ 1761 Lower.NoteConstVal(qv);
|
|
|
+ 1762 SymTab.SetSymType(n, t);
|
|
|
+ 1763 cls := SymTab.ClassOf(t);
|
|
|
+ 1764 IF cls = SymTab.ClSet THEN
|
|
|
+ 1765 (* a SET CONST needs static
|
|
|
+ 1766 data: fold its mask now
|
|
|
+ 1767 (the grammar sees the
|
|
|
+ 1768 element values) and let
|
|
|
+ 1769 Lower re-emit it *)
|
|
|
+ 1770 IF Lower.SetConstMaskOf(
|
|
|
+ 1771 AST.Child(astNode, 1),
|
|
|
+ 1772 mk, mw, mlo) THEN
|
|
|
+ 1773 Lower.NoteSetMask(n, mk, mw,
|
|
|
+ 1774 mlo);
|
|
|
+ 1775 SymTab.SetSymVal(n, qv)
|
|
|
+ 1776 ELSE
|
|
|
+ 1777 SemError(230)
|
|
|
+ 1778 END
|
|
|
+ 1779 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 1780 OR (cls = SymTab.ClRecord)
|
|
|
+ 1781 OR (cls = SymTab.ClClass)
|
|
|
+ 1782 OR (cls = SymTab.ClStr)
|
|
|
+ 1783 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 1784 (* an aggregate/string
|
|
|
+ 1785 constant: qv is its
|
|
|
+ 1786 descriptor address; no
|
|
|
+ 1787 scalar data *)
|
|
|
+ 1788 SymTab.SetSymVal(n, qv)
|
|
|
+ 1789 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
+ 1790 SemError(230)
|
|
|
+ 1791 ELSE
|
|
|
+ 1792 SymTab.SetSymVal(n, qv);
|
|
|
+ 1793 END; .) .
|
|
|
+ 1794 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1795 = "VAR" (. astSeq := AST.NoNode;
|
|
|
+ 1796 astTail := AST.NoNode; .)
|
|
|
+ 1797 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1798 astSeq, astTail, astDecl); .) }
|
|
|
+ 1799 (. astDecl := astSeq; .) .
|
|
|
+ 1800 VarDecl (. VAR nm: SymTab.Name;
|
|
|
+ 1801 t: SymTab.TypeIndex;
|
|
|
+ 1802 i: CARDINAL;
|
|
|
+ 1803 cls: INTEGER;
|
|
|
+ 1804 astNode, astTail: AST.Node; .)
|
|
|
+ 1805 = VarIdents ":"
|
|
|
+ 1806 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1807 astTail := astNode;
|
|
|
+ 1808 i := 0;
|
|
|
+ 1809 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1810 SymTab.PendName(i, nm);
|
|
|
+ 1811 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
+ 1812 (* chunked: a VAR list can
|
|
|
+ 1813 exceed AST.MaxChild *)
|
|
|
+ 1814 AstAppend(AST.NkBlock,
|
|
|
+ 1815 astNode, astTail,
|
|
|
+ 1816 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
+ 1817 INC(i)
|
|
|
+ 1818 END;
|
|
|
+ 1819 AST.SetTy(astNode, t);
|
|
|
+ 1820 astDecl := astNode;
|
|
|
+ 1821 cls := SymTab.ClassOf(t);
|
|
|
+ 1822 IF (t # SymTab.InvalidType)
|
|
|
+ 1823 AND NOT SymTab.IsUnresolved(t)
|
|
|
+ 1824 AND (cls # SymTab.ClInt)
|
|
|
+ 1825 AND (cls # SymTab.ClBool)
|
|
|
+ 1826 AND (cls # SymTab.ClChar)
|
|
|
+ 1827 AND (cls # SymTab.ClReal)
|
|
|
+ 1828 AND (cls # SymTab.ClArray)
|
|
|
+ 1829 AND (cls # SymTab.ClSet)
|
|
|
+ 1830 AND (cls # SymTab.ClRecord)
|
|
|
+ 1831 AND (cls # SymTab.ClPtr)
|
|
|
+ 1832 AND (cls # SymTab.ClLong)
|
|
|
+ 1833 AND (cls # SymTab.ClProc)
|
|
|
+ 1834 AND (cls # SymTab.ClUChar)
|
|
|
+ 1835 AND (cls # SymTab.ClUStr)
|
|
|
+ 1836 AND (cls # SymTab.ClEnum)
|
|
|
+ 1837 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 1838 SemError(230) END;
|
|
|
+ 1839 IF QbeGen.LocFull() THEN
|
|
|
+ 1840 SemError(233) END;
|
|
|
+ 1841 i := 0;
|
|
|
+ 1842 IF SymTab.IsUnresolved(t)
|
|
|
+ 1843 AND NOT SymTab.InProc() THEN
|
|
|
+ 1844 (* a forward-typed global:
|
|
|
+ 1845 defer emission until the
|
|
|
+ 1846 TYPE block completes *)
|
|
|
+ 1847 AST.SetOp(astNode, 1);
|
|
|
+ 1848 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1849 SymTab.PendName(i, nm);
|
|
|
+ 1850 IF nPendVar <=
|
|
|
+ 1851 HIGH(pendVarName) THEN
|
|
|
+ 1852 pendVarName[nPendVar] := nm;
|
|
|
+ 1853 pendVarT[nPendVar] := t;
|
|
|
+ 1854 INC(nPendVar)
|
|
|
+ 1855 END;
|
|
|
+ 1856 INC(i)
|
|
|
+ 1857 END
|
|
|
+ 1858 ELSE
|
|
|
+ 1859 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1860 SymTab.PendName(i, nm);
|
|
|
+ 1861 INC(i)
|
|
|
+ 1862 END
|
|
|
+ 1863 END;
|
|
|
+ 1864 (* a plain VAR list, not a
|
|
|
+ 1865 heading: the signature
|
|
|
+ 1866 result is discarded *)
|
|
|
+ 1867 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1868 END; .) .
|
|
|
+ 1869 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 1870 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1871 SymTab.KindVar) THEN
|
|
|
+ 1872 SemError(200) END; .)
|
|
|
+ 1873 { ","
|
|
|
+ 1874 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1875 SymTab.KindVar) THEN
|
|
|
+ 1876 SemError(200) END; .) } .
|
|
|
+ 1877 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 1878 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1879 SemError(200) END; .)
|
|
|
+ 1880 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1881 SemError(200) END; .) } .
|
|
|
+ 1882 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
+ 1883 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
+ 1884 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 1885 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
+ 1886 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
+ 1887 (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1888 mg: QbeGen.QVal; .)
|
|
|
+ 1889 = "PROCEDURE"
|
|
|
+ 1890 GetIdent<pn> (. IF methCls #
|
|
|
+ 1891 SymTab.InvalidType THEN
|
|
|
+ 1892 (* a method: resume the
|
|
|
+ 1893 declared symbol (reuse
|
|
|
+ 1894 its uid) *)
|
|
|
+ 1895 IF NOT SymTab.ResumeMethod(
|
|
|
+ 1896 methCls, pn) THEN
|
|
|
+ 1897 SemError(200) END
|
|
|
+ 1898 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
+ 1899 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
+ 1900 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
+ 1901 SemError(200) END
|
|
|
+ 1902 END
|
|
|
+ 1903 END;
|
|
|
+ 1904 Lower.ScopeEnter;
|
|
|
+ 1905 Lower.NoteProc(pn,
|
|
|
+ 1906 SymTab.ProcUid(pn),
|
|
|
+ 1907 SymTab.InvalidType,
|
|
|
+ 1908 SymTab.ProcDepthOf(pn),
|
|
|
+ 1909 FALSE);
|
|
|
+ 1910 QbeGen.BeginFunc("");
|
|
|
+ 1911 IF methCls #
|
|
|
+ 1912 SymTab.InvalidType THEN
|
|
|
+ 1913 (* hidden THIS receiver:
|
|
|
+ 1914 a VAR param of the
|
|
|
+ 1915 class type, pushed as
|
|
|
+ 1916 the WITH base *)
|
|
|
+ 1917 IF NOT SymTab.EnterThisParam(
|
|
|
+ 1918 methCls) THEN
|
|
|
+ 1919 SemError(200) END;
|
|
|
+ 1920 IF NOT QbeGen.FuncParam(
|
|
|
+ 1921 "THIS", TRUE,
|
|
|
+ 1922 methCls) THEN
|
|
|
+ 1923 SemError(233) END
|
|
|
+ 1924 END; .)
|
|
|
+ 1925 [ FormalParams ]
|
|
|
+ 1926 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
+ 1927 SemError(235) END;
|
|
|
+ 1928 Lower.SetProcRes(t); .) ] .
|
|
|
+ 1929 FormalParams
|
|
|
+ 1930 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 1931 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1932 nm: SymTab.Name;
|
|
|
+ 1933 i: CARDINAL;
|
|
|
+ 1934 isV: BOOLEAN; .)
|
|
|
+ 1935 = (. isV := FALSE; .)
|
|
|
+ 1936 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 1937 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
+ 1938 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1939 SymTab.PendName(i, nm);
|
|
|
+ 1940 Lower.NoteParam(nm, t, isV);
|
|
|
+ 1941 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
+ 1942 (* value open arrays are
|
|
|
+ 1943 passed as descriptor
|
|
|
+ 1944 addresses (no copy):
|
|
|
+ 1945 same representation as
|
|
|
+ 1946 VAR formals *)
|
|
|
+ 1947 IF NOT QbeGen.FuncParam(nm,
|
|
|
+ 1948 isV
|
|
|
+ 1949 OR SymTab.IsOpenArray(t),
|
|
|
+ 1950 t) THEN
|
|
|
+ 1951 SemError(233) END;
|
|
|
+ 1952 INC(i)
|
|
|
+ 1953 END;
|
|
|
+ 1954 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1955 SemError(235) END; .) .
|
|
|
+ 1956 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
+ 1957 static link gives them their parent's frame. Methods keep
|
|
|
+ 1958 parse-now/230-later. *)
|
|
|
+ 1959 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
+ 1960 astNode: AST.Node; .)
|
|
|
+ 1961 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1962 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1963 AST.SetOp(astNode, 0);
|
|
|
+ 1964 AST.SetChild(astNode, 0,
|
|
|
+ 1965 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1966 Lower.NoteProcNode(astNode); .)
|
|
|
+ 1967 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
+ 1968 astDecl := astNode;
|
|
|
+ 1969 Lower.ScopeLeave;
|
|
|
+ 1970 SymTab.MarkFwd;
|
|
|
+ 1971 SymTab.CloseProc;
|
|
|
+ 1972 QbeGen.AbortFunc; .)
|
|
|
+ 1973 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
+ 1974 astDecl := astNode;
|
|
|
+ 1975 Lower.MarkProcExternal;
|
|
|
+ 1976 Lower.ScopeLeave;
|
|
|
+ 1977 SymTab.MarkExternal("");
|
|
|
+ 1978 SymTab.CloseProc;
|
|
|
+ 1979 QbeGen.AbortFunc; .)
|
|
|
+ 1980 |
|
|
|
+ 1981 (. allowDefer := TRUE; deferredBody := FALSE;
|
|
|
+ 1982 curProcNode := astNode; .)
|
|
|
+ 1983 Block<pn> (. IF deferredBody THEN
|
|
|
+ 1984 (* body skipped: close like
|
|
|
+ 1985 FORWARD (no body node) *)
|
|
|
+ 1986 astDecl := astNode;
|
|
|
+ 1987 Lower.ScopeLeave;
|
|
|
+ 1988 SymTab.CloseProc;
|
|
|
+ 1989 QbeGen.AbortFunc
|
|
|
+ 1990 ELSE
|
|
|
+ 1991 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1992 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
+ 1993 astDecl := astNode;
|
|
|
+ 1994 Lower.ScopeLeave;
|
|
|
+ 1995 SymTab.CloseProc;
|
|
|
+ 1996 QbeGen.EndFunc(
|
|
|
+ 1997 SymTab.ProcRes(pn))
|
|
|
+ 1998 END; .) ) .
|
|
|
+ 1999 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; dfr: BOOLEAN; .)
|
|
|
+ 2000 = (. dfr := FALSE;
|
|
|
+ 2001 IF allowDefer AND twoPhaseParse
|
|
|
+ 2002 AND NOT repassing THEN
|
|
|
+ 2003 dfr := DeferSkip(pn)
|
|
|
+ 2004 END;
|
|
|
+ 2005 allowDefer := FALSE;
|
|
|
+ 2006 .)
|
|
|
+ 2007 DeclSeq (. astBlkDecls := astDecl;
|
|
|
+ 2008 astStmt := AST.NoNode;
|
|
|
+ 2009 nLab := 0; nGot := 0; .)
|
|
|
+ 2010 [ "BEGIN" (. (* an empty body is still a
|
|
|
+ 2011 body: mark it so Lower
|
|
|
+ 2012 does not read it as a
|
|
|
+ 2013 definition heading *)
|
|
|
+ 2014 IF NOT dfr THEN
|
|
|
+ 2015 IF astStmt = AST.NoNode THEN
|
|
|
+ 2016 astStmt :=
|
|
|
+ 2017 AST.MakeNode(AST.NkBlock)
|
|
|
+ 2018 END
|
|
|
+ 2019 END; .)
|
|
|
+ 2020 [ StatSeq ] ]
|
|
|
+ 2021 "END"
|
|
|
+ 2022 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
+ 2023 SemError(202) END;
|
|
|
+ 2024 CheckGotos; .) .
|
|
|
+ 2025 (* Two-phase, phase 2 (milestone 2c): re-parse every deferred module-
|
|
|
+ 2026 level body once the unit's declarations are complete. Inlined at
|
|
|
+ 2027 both call sites because a stand-alone epsilon production is
|
|
|
+ 2028 "unreachable" to Coco/R (referenced only from actions). *)
|
|
|
+ 2029 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 2030 = (. astSeq := AST.NoNode;
|
|
|
+ 2031 astTail := AST.NoNode; .)
|
|
|
+ 2032 Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 2033 astSeq, astTail, astStmt); .)
|
|
|
+ 2034 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 2035 astSeq, astTail, astStmt); .) ] }
|
|
|
+ 2036 (. astStmt := astSeq; .) .
|
|
|
+ 2037 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
+ 2038 are accepted: the statement after ';' is optional. *)
|
|
|
+ 2039 Statement (. VAR lx: QbeGen.QVal; lxnm: SymTab.Name; .)
|
|
|
+ 2040 = (. astStmt := AST.NoNode; .)
|
|
|
+ 2041 ( AssOrCall
|
|
|
+ 2042 | IfStat
|
|
|
+ 2043 | WhileStat
|
|
|
+ 2044 | RepeatStat
|
|
|
+ 2045 | LoopStat
|
|
|
+ 2046 | ForStat
|
|
|
+ 2047 | CaseStat
|
|
|
+ 2048 | WithStat
|
|
|
+ 2049 | ReturnStat
|
|
|
+ 2050 | HaltStat
|
|
|
+ 2051 | NewStat
|
|
|
+ 2052 | DisposeStat
|
|
|
+ 2053 | IncDecStat
|
|
|
+ 2054 | InclExclStat
|
|
|
+ 2055 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
+ 2056 SemError(230) END;
|
|
|
+ 2057 astStmt := AST.MakeNode(AST.NkExit); .)
|
|
|
+ 2058 | "GOTO" GetIdent<lxnm> (. NoteGoto(lxnm);
|
|
|
+ 2059 astStmt := AST.MakeNode(AST.NkGoto);
|
|
|
+ 2060 AST.SetChild(astStmt, 0,
|
|
|
+ 2061 AST.MakeLeaf(AST.NkIdent, lxnm)); .) ) .
|
|
|
+ 2062 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
+ 2063 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
+ 2064 dk: INTEGER;
|
|
|
+ 2065 qd, qe: QbeGen.QVal;
|
|
|
+ 2066 qn: SymTab.Name;
|
|
|
+ 2067 sfx, isInc: BOOLEAN;
|
|
|
+ 2068 astNode, astD: AST.Node; .)
|
|
|
+ 2069 = ( "INCL" (. isInc := TRUE; .)
|
|
|
+ 2070 | "EXCL" (. isInc := FALSE; .) )
|
|
|
+ 2071 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
+ 2072 Expr<et2, qe> ")"
|
|
|
+ 2073 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2074 IF isInc THEN
|
|
|
+ 2075 AST.SetChild(astNode, 0,
|
|
|
+ 2076 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
+ 2077 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2078 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
+ 2079 END;
|
|
|
+ 2080 IF astD # AST.NoNode THEN
|
|
|
+ 2081 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2082 IF astCur # AST.NoNode THEN
|
|
|
+ 2083 AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 2084 astStmt := astNode; .)
|
|
|
+ 2085 (. IF (at # SymTab.InvalidType)
|
|
|
+ 2086 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
+ 2087 SemError(222)
|
|
|
+ 2088 END; .) .
|
|
|
+ 2089 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
+ 2090 integer designator. *)
|
|
|
+ 2091 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
+ 2092 dk: INTEGER;
|
|
|
+ 2093 qd, qv, qn2, qstep:
|
|
|
+ 2094 QbeGen.QVal;
|
|
|
+ 2095 qn: SymTab.Name;
|
|
|
+ 2096 sfx, isInc: BOOLEAN;
|
|
|
+ 2097 astNode, astD, astStep:
|
|
|
+ 2098 AST.Node; .)
|
|
|
+ 2099 = (. isInc := TRUE; .)
|
|
|
+ 2100 ( "INC" (. isInc := TRUE; .)
|
|
|
+ 2101 | "DEC" (. isInc := FALSE; .) )
|
|
|
+ 2102 "(" (. astStep := AST.NoNode; .)
|
|
|
+ 2103 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
+ 2104 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
+ 2105 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2106 IF isInc THEN
|
|
|
+ 2107 AST.SetChild(astNode, 0,
|
|
|
+ 2108 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
+ 2109 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2110 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
+ 2111 END;
|
|
|
+ 2112 IF astD # AST.NoNode THEN
|
|
|
+ 2113 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2114 IF astStep # AST.NoNode THEN
|
|
|
+ 2115 AST.SetChild(astNode, 2, astStep) END;
|
|
|
+ 2116 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2117 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 2118 AND (dk # SymTab.KindParam)
|
|
|
+ 2119 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2120 SemError(210)
|
|
|
+ 2121 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
+ 2122 SemError(211)
|
|
|
+ 2123 END; .) .
|
|
|
+ 2124 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
+ 2125 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
+ 2126 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
+ 2127 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 2128 dk: INTEGER;
|
|
|
+ 2129 qd, qm: QbeGen.QVal;
|
|
|
+ 2130 qn: SymTab.Name;
|
|
|
+ 2131 sfx: BOOLEAN;
|
|
|
+ 2132 bt: SymTab.TypeIndex;
|
|
|
+ 2133 astNode, astD: AST.Node; .)
|
|
|
+ 2134 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 2135 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2136 AST.SetChild(astNode, 0,
|
|
|
+ 2137 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
+ 2138 IF astD # AST.NoNode THEN
|
|
|
+ 2139 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2140 astStmt := astNode; .)
|
|
|
+ 2141 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2142 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 2143 AND (dk # SymTab.KindParam)
|
|
|
+ 2144 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2145 SemError(210)
|
|
|
+ 2146 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 2147 SymTab.ClPtr THEN
|
|
|
+ 2148 SemError(219)
|
|
|
+ 2149 END; .) .
|
|
|
+ 2150 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 2151 dk: INTEGER;
|
|
|
+ 2152 qd, qv: QbeGen.QVal;
|
|
|
+ 2153 qn: SymTab.Name;
|
|
|
+ 2154 sfx: BOOLEAN;
|
|
|
+ 2155 astNode, astD: AST.Node; .)
|
|
|
+ 2156 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 2157 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2158 AST.SetChild(astNode, 0,
|
|
|
+ 2159 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
+ 2160 IF astD # AST.NoNode THEN
|
|
|
+ 2161 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 2162 astStmt := astNode; .)
|
|
|
+ 2163 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2164 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 2165 AND (dk # SymTab.KindParam)
|
|
|
+ 2166 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2167 SemError(210)
|
|
|
+ 2168 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 2169 SymTab.ClPtr THEN
|
|
|
+ 2170 SemError(219)
|
|
|
+ 2171 END; .) .
|
|
|
+ 2172 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
+ 2173 address; field designators resolve through both stacks. *)
|
|
|
+ 2174 WithStat (. VAR nW: CARDINAL;
|
|
|
+ 2175 astNode: AST.Node; .)
|
|
|
+ 2176 = "WITH" (. nW := 0;
|
|
|
+ 2177 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
+ 2178 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
+ 2179 "DO" (. astStmt := AST.NoNode; .)
|
|
|
+ 2180 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
+ 2181 AST.NChild(astNode), astStmt);
|
|
|
+ 2182 astStmt := astNode;
|
|
|
+ 2183 WHILE nW > 0 DO
|
|
|
+ 2184 SymTab.PopScope;
|
|
|
+ 2185 QbeGen.PopWith;
|
|
|
+ 2186 DEC(nW)
|
|
|
+ 2187 END; .) .
|
|
|
+ 2188 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
+ 2189 (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 2190 dk: INTEGER;
|
|
|
+ 2191 qd, qe: QbeGen.QVal;
|
|
|
+ 2192 qn: SymTab.Name;
|
|
|
+ 2193 sfx: BOOLEAN; .)
|
|
|
+ 2194 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 2195 (. IF astCur # AST.NoNode THEN
|
|
|
+ 2196 AST.SetChild(wnode,
|
|
|
+ 2197 AST.NChild(wnode), astCur) END;
|
|
|
+ 2198 IF dt = SymTab.InvalidType THEN
|
|
|
+ 2199 ELSIF (SymTab.ClassOf(dt) #
|
|
|
+ 2200 SymTab.ClRecord)
|
|
|
+ 2201 AND (SymTab.ClassOf(dt) #
|
|
|
+ 2202 SymTab.ClClass) THEN
|
|
|
+ 2203 SemError(215)
|
|
|
+ 2204 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
+ 2205 QbeGen.PushWith(qd);
|
|
|
+ 2206 INC(nW)
|
|
|
+ 2207 END; .) .
|
|
|
+ 2208 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
+ 2209 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
+ 2210 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 2211 dk: INTEGER;
|
|
|
+ 2212 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
+ 2213 qn: SymTab.Name;
|
|
|
+ 2214 ct2, res0: SymTab.TypeIndex;
|
|
|
+ 2215 q2, mg0: QbeGen.QVal;
|
|
|
+ 2216 isR, conv, wconv: BOOLEAN;
|
|
|
+ 2217 called, sfx: BOOLEAN;
|
|
|
+ 2218 astLhs, astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
+ 2219 n: SymTab.Name; astLab, astNode: AST.Node; .)
|
|
|
+ 2220 = GetIdent<n>
|
|
|
+ 2221 ( ":" (. NoteLabel(n);
|
|
|
+ 2222 astNode := AST.MakeNode(AST.NkLabel);
|
|
|
+ 2223 AST.SetChild(astNode, 0,
|
|
|
+ 2224 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 2225 astLab := AST.MakeNode(AST.NkBlock);
|
|
|
+ 2226 AST.SetChild(astLab, 0, astNode); .)
|
|
|
+ 2227 Statement (. IF astStmt # AST.NoNode THEN
|
|
|
+ 2228 AST.SetChild(astLab, 1, astStmt) END;
|
|
|
+ 2229 astStmt := astLab; .)
|
|
|
+ 2230 | DesignTail<n, dt, dk, qd, qn, sfx>
|
|
|
+ 2231 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
+ 2232 ( ":="
|
|
|
+ 2233 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 2234 AST.NkAssign, 0, astLhs, astCur);
|
|
|
+ 2235 IF (dt # SymTab.InvalidType)
|
|
|
+ 2236 AND (dk # SymTab.KindVar)
|
|
|
+ 2237 AND (dk # SymTab.KindParam)
|
|
|
+ 2238 AND (dk # SymTab.KindField) THEN
|
|
|
+ 2239 SemError(210)
|
|
|
+ 2240 ELSIF NOT SymTab.Assignable(et,
|
|
|
+ 2241 dt) THEN
|
|
|
+ 2242 SemError(210)
|
|
|
+ 2243 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 2244 AND (SymTab.ClassOf(dt) =
|
|
|
+ 2245 SymTab.ClClass) THEN
|
|
|
+ 2246 SemError(230) END;
|
|
|
+ 2247 isR := (dt #
|
|
|
+ 2248 SymTab.InvalidType)
|
|
|
+ 2249 AND (SymTab.ClassOf(dt)
|
|
|
+ 2250 = SymTab.ClReal);
|
|
|
+ 2251 conv := isR
|
|
|
+ 2252 AND SymTab.IsIntFamily(et);
|
|
|
+ 2253 wconv := (dt #
|
|
|
+ 2254 SymTab.InvalidType)
|
|
|
+ 2255 AND SymTab.IsLongFamily(dt)
|
|
|
+ 2256 AND SymTab.IsIntFamily(et);
|
|
|
+ 2257 IF ((dk = SymTab.KindVar)
|
|
|
+ 2258 OR (dk = SymTab.KindParam)
|
|
|
+ 2259 OR (dk = SymTab.KindField))
|
|
|
+ 2260 AND (dt # SymTab.InvalidType)
|
|
|
+ 2261 AND (et # SymTab.InvalidType)
|
|
|
+ 2262 AND (SymTab.ClassOf(dt) #
|
|
|
+ 2263 SymTab.ClClass) THEN
|
|
|
+ 2264 END; .)
|
|
|
+ 2265 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
+ 2266 (. astRes := AstCallNode(astLhs);
|
|
|
+ 2267 sfx := FALSE; .)
|
|
|
+ 2268 ( { ResultComp<ct2, q2, sfx, astRes, mname, methCls, isM> }
|
|
|
+ 2269 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 2270 AST.NkAssign, 0, astRes, astCur);
|
|
|
+ 2271 IF NOT sfx THEN
|
|
|
+ 2272 SemError(233)
|
|
|
+ 2273 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
+ 2274 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
+ 2275 SemError(210)
|
|
|
+ 2276 END; .)
|
|
|
+ 2277 | (. IF ct2 #
|
|
|
+ 2278 SymTab.InvalidType THEN
|
|
|
+ 2279 SemError(233) END;
|
|
|
+ 2280 astStmt := astRes; .) )
|
|
|
+ 2281 | (* bare `P;`: proper parameterless
|
|
|
+ 2282 procedure call; anything else
|
|
|
+ 2283 here is 233 (was a bare syntax
|
|
|
+ 2284 error before 4.2) *)
|
|
|
+ 2285 (. astStmt := AstCallNode(astLhs);
|
|
|
+ 2286 IF (dk = SymTab.KindProc)
|
|
|
+ 2287 AND NOT sfx THEN
|
|
|
+ 2288 res0 := SymTab.ProcRes(qn);
|
|
|
+ 2289 IF res0 #
|
|
|
+ 2290 SymTab.InvalidType THEN
|
|
|
+ 2291 SemError(233)
|
|
|
+ 2292 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 2293 0 THEN
|
|
|
+ 2294 SemError(233)
|
|
|
+ 2295 END
|
|
|
+ 2296 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 2297 AND (SymTab.ClassOf(dt) = SymTab.ClProc) THEN
|
|
|
+ 2298 IF SymTab.ProcTypeRes(dt) #
|
|
|
+ 2299 SymTab.InvalidType THEN
|
|
|
+ 2300 SemError(233)
|
|
|
+ 2301 ELSIF SymTab.ProcTypeNPar(dt) #
|
|
|
+ 2302 0 THEN
|
|
|
+ 2303 SemError(233)
|
|
|
+ 2304 END
|
|
|
+ 2305 ELSE SemError(233)
|
|
|
+ 2306 END; .) ) ) .
|
|
|
+ 2307 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 2308 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 2309 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 2310 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 2311 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 2312 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
+ 2313 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2314 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
+ 2315 vs: INTEGER;
|
|
|
+ 2316 res: SymTab.TypeIndex;
|
|
|
+ 2317 mg: QbeGen.QVal;
|
|
|
+ 2318 ok, ind, isMeth, va, isConv: BOOLEAN; .)
|
|
|
+ 2319 = "(" (. called := TRUE;
|
|
|
+ 2320 ok := TRUE;
|
|
|
+ 2321 ind := FALSE;
|
|
|
+ 2322 isConv := FALSE;
|
|
|
+ 2323 isMeth := methCls #
|
|
|
+ 2324 SymTab.InvalidType;
|
|
|
+ 2325 IF isMeth THEN
|
|
|
+ 2326 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
+ 2327 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
+ 2328 res := SymTab.ProcRes(pn)
|
|
|
+ 2329 ELSIF (SymTab.SymKind(pn) = SymTab.KindType)
|
|
|
+ 2330 OR (SymTab.SymKind(pn) = SymTab.KindPredef) THEN
|
|
|
+ 2331 (* ISO type conversion T(x):
|
|
|
+ 2332 one value, result is T *)
|
|
|
+ 2333 isConv := TRUE;
|
|
|
+ 2334 res := SymTab.SymType(pn)
|
|
|
+ 2335 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 2336 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 2337 ind := TRUE;
|
|
|
+ 2338 res := SymTab.ProcTypeRes(pt)
|
|
|
+ 2339 ELSE SemError(233);
|
|
|
+ 2340 ok := FALSE;
|
|
|
+ 2341 res := SymTab.InvalidType
|
|
|
+ 2342 END;
|
|
|
+ 2343 i := 0; .)
|
|
|
+ 2344 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
+ 2345 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
+ 2346 ")" (. IF ok THEN
|
|
|
+ 2347 IF isConv THEN
|
|
|
+ 2348 (* a conversion takes
|
|
|
+ 2349 exactly one value *)
|
|
|
+ 2350 IF i # 1 THEN
|
|
|
+ 2351 SemError(233); ok := FALSE
|
|
|
+ 2352 END
|
|
|
+ 2353 ELSE
|
|
|
+ 2354 IF isMeth THEN
|
|
|
+ 2355 np := SymTab.ClassMethodNPar(
|
|
|
+ 2356 methCls, pn)
|
|
|
+ 2357 ELSIF ind THEN
|
|
|
+ 2358 np := SymTab.ProcTypeNPar(pt)
|
|
|
+ 2359 ELSE np := SymTab.ProcNPar(pn)
|
|
|
+ 2360 END;
|
|
|
+ 2361 va := (NOT isMeth) AND (NOT ind)
|
|
|
+ 2362 AND (SymTab.SymKind(pn) =
|
|
|
+ 2363 SymTab.KindProc)
|
|
|
+ 2364 AND SymTab.Varargs(pn);
|
|
|
+ 2365 IF (i # np) AND NOT va THEN
|
|
|
+ 2366 SemError(233); ok := FALSE
|
|
|
+ 2367 END
|
|
|
+ 2368 END
|
|
|
+ 2369 END;
|
|
|
+ 2370 IF NOT ok THEN
|
|
|
+ 2371 t := SymTab.InvalidType;
|
|
|
+ 2372 QbeGen.CopyOp("0", q)
|
|
|
+ 2373 ELSIF want THEN
|
|
|
+ 2374 IF res =
|
|
|
+ 2375 SymTab.InvalidType THEN
|
|
|
+ 2376 IF NOT soft THEN SemError(233) END;
|
|
|
+ 2377 t := SymTab.InvalidType;
|
|
|
+ 2378 QbeGen.CopyOp("0", q)
|
|
|
+ 2379 ELSE t := res;
|
|
|
+ 2380 QbeGen.CopyOp("@", q)
|
|
|
+ 2381 END
|
|
|
+ 2382 ELSE
|
|
|
+ 2383 IF res #
|
|
|
+ 2384 SymTab.InvalidType THEN
|
|
|
+ 2385 SemError(233)
|
|
|
+ 2386 END;
|
|
|
+ 2387 t := SymTab.InvalidType;
|
|
|
+ 2388 QbeGen.CopyOp("0", q);
|
|
|
+ 2389 END; .) .
|
|
|
+ 2390 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 2391 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 2392 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 2393 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
+ 2394 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 2395 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 2396 isV, conv, va: BOOLEAN;
|
|
|
+ 2397 cl: CHAR;
|
|
|
+ 2398 savedN, aj: CARDINAL;
|
|
|
+ 2399 savedArgs: ARRAY [0 .. 31]
|
|
|
+ 2400 OF AST.Node;
|
|
|
+ 2401 astActual: AST.Node; .)
|
|
|
+ 2402 = (. (* Parsing the actual can clobber
|
|
|
+ 2403 the enclosing call's argument
|
|
|
+ 2404 list (Factor resets astNArgs),
|
|
|
+ 2405 so save/restore it. *)
|
|
|
+ 2406 savedN := astNArgs; aj := 0;
|
|
|
+ 2407 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 2408 savedArgs[aj] := astArgs[aj];
|
|
|
+ 2409 INC(aj)
|
|
|
+ 2410 END; .)
|
|
|
+ 2411 Expr<at, qe> (. QbeGen.CopyOp(qe, convQ); convT := at;
|
|
|
+ 2412 astActual := astCur;
|
|
|
+ 2413 astNArgs := savedN; aj := 0;
|
|
|
+ 2414 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 2415 astArgs[aj] := savedArgs[aj];
|
|
|
+ 2416 INC(aj)
|
|
|
+ 2417 END;
|
|
|
+ 2418 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
+ 2419 astArgs[astNArgs] := astCur;
|
|
|
+ 2420 INC(astNArgs)
|
|
|
+ 2421 END;
|
|
|
+ 2422 va := (NOT ind)
|
|
|
+ 2423 AND (methCls =
|
|
|
+ 2424 SymTab.InvalidType)
|
|
|
+ 2425 AND (SymTab.SymKind(pn) =
|
|
|
+ 2426 SymTab.KindProc)
|
|
|
+ 2427 AND SymTab.Varargs(pn);
|
|
|
+ 2428 IF ind THEN
|
|
|
+ 2429 ft :=
|
|
|
+ 2430 SymTab.ProcTypeParamType(pt,
|
|
|
+ 2431 i);
|
|
|
+ 2432 isV :=
|
|
|
+ 2433 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 2434 i)
|
|
|
+ 2435 ELSIF methCls #
|
|
|
+ 2436 SymTab.InvalidType THEN
|
|
|
+ 2437 ft :=
|
|
|
+ 2438 SymTab.ClassMethodParamType(
|
|
|
+ 2439 methCls, pn, i);
|
|
|
+ 2440 isV :=
|
|
|
+ 2441 SymTab.ClassMethodParamIsVar(
|
|
|
+ 2442 methCls, pn, i)
|
|
|
+ 2443 ELSE
|
|
|
+ 2444 ft := SymTab.ParamType(pn, i);
|
|
|
+ 2445 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 2446 END;
|
|
|
+ 2447 IF (at = SymTab.InvalidType) THEN
|
|
|
+ 2448 ELSIF ft = SymTab.InvalidType THEN
|
|
|
+ 2449 ELSIF isV THEN
|
|
|
+ 2450 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 2451 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 2452 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 2453 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 2454 ELSIF (AST.Kind(astActual) #
|
|
|
+ 2455 AST.NkDesignator)
|
|
|
+ 2456 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
+ 2457 SemError(233)
|
|
|
+ 2458 ELSIF NOT SymTab.VarParamOk(at, ft)
|
|
|
+ 2459 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
+ 2460 SemError(233)
|
|
|
+ 2461 END
|
|
|
+ 2462 ELSE
|
|
|
+ 2463 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 2464 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 2465 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 2466 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 2467 ELSIF NOT SymTab.Assignable(at, ft)
|
|
|
+ 2468 AND NOT SymTab.ByteBufOk(at, ft) THEN
|
|
|
+ 2469 SemError(233)
|
|
|
+ 2470 END
|
|
|
+ 2471 END; .) .
|
|
|
+ 2472 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2473 q: QbeGen.QVal;
|
|
|
+ 2474 hasElse: BOOLEAN;
|
|
|
+ 2475 astCond, astIf, astLast,
|
|
|
+ 2476 astNode: AST.Node; .)
|
|
|
+ 2477 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 2478 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2479 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2480 SemError(214) END; .)
|
|
|
+ 2481 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2482 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2483 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2484 astIf := astNode;
|
|
|
+ 2485 astLast := astNode; .)
|
|
|
+ 2486 { "ELSIF"
|
|
|
+ 2487 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 2488 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2489 SemError(214) END; .)
|
|
|
+ 2490 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 2491 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2492 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2493 AST.SetChild(astLast, 2, astNode);
|
|
|
+ 2494 astLast := astNode; .) }
|
|
|
+ 2495 [ "ELSE" (. hasElse := TRUE;
|
|
|
+ 2496 astStmt := AST.NoNode; .)
|
|
|
+ 2497 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
+ 2498 "END" (. astStmt := astIf; .) .
|
|
|
+ 2499 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2500 q: QbeGen.QVal;
|
|
|
+ 2501 astCond, astNode: AST.Node; .)
|
|
|
+ 2502 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2503 Expr<t, q> (. astCond := astCur;
|
|
|
+ 2504 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2505 SemError(214) END; .)
|
|
|
+ 2506 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ 2507 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 2508 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 2509 astStmt := astNode; .)
|
|
|
+ 2510 "END" .
|
|
|
+ 2511 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2512 q: QbeGen.QVal;
|
|
|
+ 2513 astCond, astBody, astNode:
|
|
|
+ 2514 AST.Node; .)
|
|
|
+ 2515 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
+ 2516 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
+ 2517 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
+ 2518 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
+ 2519 AST.SetChild(astNode, 0, astBody);
|
|
|
+ 2520 AST.SetChild(astNode, 1, astCond);
|
|
|
+ 2521 astStmt := astNode;
|
|
|
+ 2522 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 2523 SemError(214) END; .) .
|
|
|
+ 2524 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ 2525 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
+ 2526 QbeGen.NewLabel(lEnd);
|
|
|
+ 2527 QbeGen.PushLoop(lEnd); .)
|
|
|
+ 2528 [ StatSeq ]
|
|
|
+ 2529 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
+ 2530 AST.SetChild(astNode, 0, astStmt);
|
|
|
+ 2531 astStmt := astNode;
|
|
|
+ 2532 QbeGen.PopLoop; .) .
|
|
|
+ 2533 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 2534 Runtime direction would need a compare-select; the literal
|
|
|
+ 2535 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 2536 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 2537 tlo, thi, tby:
|
|
|
+ 2538 SymTab.TypeIndex;
|
|
|
+ 2539 qlo, qhi, qby, qt, qk, qb:
|
|
|
+ 2540 QbeGen.QVal;
|
|
|
+ 2541 lTop, lBody, lEnd:
|
|
|
+ 2542 QbeGen.QVal;
|
|
|
+ 2543 by: INTEGER;
|
|
|
+ 2544 ok: BOOLEAN;
|
|
|
+ 2545 astVar, astLo, astHi, astBy,
|
|
|
+ 2546 astNode: AST.Node; .)
|
|
|
+ 2547 = "FOR" (. by := 1; .)
|
|
|
+ 2548 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
+ 2549 astStmt := AST.NoNode;
|
|
|
+ 2550 astBy := AST.NoNode;
|
|
|
+ 2551 ok := SymTab.Lookup(lv);
|
|
|
+ 2552 IF NOT ok THEN
|
|
|
+ 2553 SemError(201)
|
|
|
+ 2554 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 2555 SymTab.KindVar)
|
|
|
+ 2556 AND (SymTab.SymKind(lv) #
|
|
|
+ 2557 SymTab.KindParam) THEN
|
|
|
+ 2558 SemError(220); ok := FALSE
|
|
|
+ 2559 ELSIF NOT SymTab.IsIntFamily(
|
|
|
+ 2560 SymTab.SymType(lv)) THEN
|
|
|
+ 2561 SemError(220); ok := FALSE
|
|
|
+ 2562 END; .)
|
|
|
+ 2563 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
+ 2564 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 2565 SemError(220); ok := FALSE
|
|
|
+ 2566 END; .)
|
|
|
+ 2567 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
+ 2568 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
+ 2569 SemError(220); ok := FALSE
|
|
|
+ 2570 END; .)
|
|
|
+ 2571 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
+ 2572 IF (tby #
|
|
|
+ 2573 SymTab.InvalidType)
|
|
|
+ 2574 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 2575 SemError(220); ok := FALSE
|
|
|
+ 2576 END;
|
|
|
+ 2577 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 2578 SemError(230); by := 1
|
|
|
+ 2579 ELSIF by = 0 THEN
|
|
|
+ 2580 SemError(220); by := 1
|
|
|
+ 2581 END; .) ]
|
|
|
+ 2582 "DO"
|
|
|
+ 2583 [ StatSeq ]
|
|
|
+ 2584 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
+ 2585 AST.SetChild(astNode, 0, astVar);
|
|
|
+ 2586 AST.SetChild(astNode, 1, astLo);
|
|
|
+ 2587 AST.SetChild(astNode, 2, astHi);
|
|
|
+ 2588 AST.SetChild(astNode, 3, astBy);
|
|
|
+ 2589 AST.SetChild(astNode, 4, astStmt);
|
|
|
+ 2590 astStmt := astNode;
|
|
|
+ 2591 .) .
|
|
|
+ 2592 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 2593 qsel, lEnd: QbeGen.QVal;
|
|
|
+ 2594 arm, astNode, astArms,
|
|
|
+ 2595 astArmsTail: AST.Node; .)
|
|
|
+ 2596 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ 2597 AST.SetChild(astNode, 0, astCur);
|
|
|
+ 2598 astArms := AST.NoNode;
|
|
|
+ 2599 astArmsTail := AST.NoNode;
|
|
|
+ 2600 .)
|
|
|
+ 2601 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
+ 2602 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
+ 2603 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2604 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 2605 AST.SetOp(arm, 1);
|
|
|
+ 2606 AST.SetChild(arm, 0, astStmt);
|
|
|
+ 2607 AstAppend(AST.NkBlock,
|
|
|
+ 2608 astArms, astArmsTail, arm); .) ]
|
|
|
+ 2609 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
+ 2610 astStmt := astNode;
|
|
|
+ 2611 .) .
|
|
|
+ 2612 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 2613 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 2614 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 2615 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 2616 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2617 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
+ 2618 (. VAR arm: AST.Node; .)
|
|
|
+ 2619 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
+ 2620 CaseLabel<tsel, qsel, arm>
|
|
|
+ 2621 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
+ 2622 ":" (. astStmt := AST.NoNode; .)
|
|
|
+ 2623 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ 2624 astStmt);
|
|
|
+ 2625 AstAppend(AST.NkBlock,
|
|
|
+ 2626 arms, armsTail, arm);
|
|
|
+ 2627 .) .
|
|
|
+ 2628 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2629 arm: AST.Node>
|
|
|
+ 2630 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 2631 q2, q3, qc, qd, qe:
|
|
|
+ 2632 QbeGen.QVal;
|
|
|
+ 2633 astLab: AST.Node;
|
|
|
+ 2634 lNext: QbeGen.QVal; .)
|
|
|
+ 2635 = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ 2636 IF (t2 #
|
|
|
+ 2637 SymTab.InvalidType)
|
|
|
+ 2638 AND (tsel #
|
|
|
+ 2639 SymTab.InvalidType)
|
|
|
+ 2640 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 2641 tsel) THEN
|
|
|
+ 2642 SemError(213) END;
|
|
|
+ 2643 (* set labels are not immediates:
|
|
|
+ 2644 the CASE chain uses CmpSet *)
|
|
|
+ 2645 IF (SymTab.ClassOf(t2) # SymTab.ClSet)
|
|
|
+ 2646 AND NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 2647 SemError(230)
|
|
|
+ 2648 END; .)
|
|
|
+ 2649 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ 2650 AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ 2651 IF (t3 #
|
|
|
+ 2652 SymTab.InvalidType)
|
|
|
+ 2653 AND (tsel #
|
|
|
+ 2654 SymTab.InvalidType)
|
|
|
+ 2655 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 2656 tsel) THEN
|
|
|
+ 2657 SemError(213) END;
|
|
|
+ 2658 IF (SymTab.ClassOf(t3) # SymTab.ClSet)
|
|
|
+ 2659 AND NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 2660 SemError(230)
|
|
|
+ 2661 END; .) ]
|
|
|
+ 2662 (. AST.SetChild(arm,
|
|
|
+ 2663 AST.NChild(arm), astLab); .) .
|
|
|
+ 2664 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2665 q, qt: QbeGen.QVal;
|
|
|
+ 2666 res: SymTab.TypeIndex;
|
|
|
+ 2667 hadE, conv: BOOLEAN;
|
|
|
+ 2668 astVal, astNode: AST.Node; .)
|
|
|
+ 2669 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
+ 2670 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
+ 2671 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
+ 2672 IF hadE THEN
|
|
|
+ 2673 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2674 END;
|
|
|
+ 2675 astStmt := astNode;
|
|
|
+ 2676 conv := FALSE;
|
|
|
+ 2677 IF NOT SymTab.InProc() THEN
|
|
|
+ 2678 SemError(232)
|
|
|
+ 2679 ELSE res := SymTab.CurRes();
|
|
|
+ 2680 IF NOT hadE THEN
|
|
|
+ 2681 IF res #
|
|
|
+ 2682 SymTab.InvalidType THEN
|
|
|
+ 2683 SemError(232)
|
|
|
+ 2684 END
|
|
|
+ 2685 ELSIF (res =
|
|
|
+ 2686 SymTab.InvalidType)
|
|
|
+ 2687 OR (t #
|
|
|
+ 2688 SymTab.InvalidType)
|
|
|
+ 2689 AND NOT SymTab.Assignable(t,
|
|
|
+ 2690 res) THEN
|
|
|
+ 2691 SemError(232)
|
|
|
+ 2692 END
|
|
|
+ 2693 END; .) .
|
|
|
+ 2694 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2695 q: QbeGen.QVal;
|
|
|
+ 2696 astVal, astNode: AST.Node; .)
|
|
|
+ 2697 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
+ 2698 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
+ 2699 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
+ 2700 IF astVal # AST.NoNode THEN
|
|
|
+ 2701 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2702 END;
|
|
|
+ 2703 astStmt := astNode;
|
|
|
+ 2704 .) .
|
|
|
+ 2705 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 2706 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 2707 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 2708 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 2709 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 2710 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2711 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2712 (. VAR n: SymTab.Name; .)
|
|
|
+ 2713 = GetIdent<n> DesignTail<n, t, k, q, qn, sfx> .
|
|
|
+ 2714 (* The part of Design after the identifier: resolve it and walk the
|
|
|
+ 2715 selectors. Split out so a statement can decide between a label
|
|
|
+ 2716 (`ident :`) and a designator (`ident := ...`) with one token. *)
|
|
|
+ 2717 DesignTail<VAR n: SymTab.Name; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2718 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2719 (. VAR fn, mal: SymTab.Name;
|
|
|
+ 2720 cls: INTEGER;
|
|
|
+ 2721 ic: SymTab.TypeIndex;
|
|
|
+ 2722 curT, it, eT, bt:
|
|
|
+ 2723 SymTab.TypeIndex;
|
|
|
+ 2724 iq, ql, qlo, qhi, qe:
|
|
|
+ 2725 QbeGen.QVal;
|
|
|
+ 2726 lo, hi: INTEGER;
|
|
|
+ 2727 fo: INTEGER;
|
|
|
+ 2728 isOpen: BOOLEAN;
|
|
|
+ 2729 qb, cv: QbeGen.QVal;
|
|
|
+ 2730 r: BOOLEAN;
|
|
|
+ 2731 astDes, astSel: AST.Node; .)
|
|
|
+ 2732 = (. methCls := SymTab.InvalidType;
|
|
|
+ 2733 QbeGen.CopyOp(n, qn);
|
|
|
+ 2734 sfx := FALSE;
|
|
|
+ 2735 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 2736 (* a bare method name inside
|
|
|
+ 2737 a CLASS IMPLEMENTATION
|
|
|
+ 2738 is a sibling call on
|
|
|
+ 2739 THIS *)
|
|
|
+ 2740 ic := SymTab.CurImplClass();
|
|
|
+ 2741 IF (ic #
|
|
|
+ 2742 SymTab.InvalidType)
|
|
|
+ 2743 AND SymTab.MethodExists(ic, n) THEN
|
|
|
+ 2744 sfx := FALSE;
|
|
|
+ 2745 QbeGen.CopyOp("@", q);
|
|
|
+ 2746 methCls := ic;
|
|
|
+ 2747 k := SymTab.KindProc;
|
|
|
+ 2748 t := SymTab.InvalidType
|
|
|
+ 2749 ELSIF SymTab.InProc() THEN
|
|
|
+ 2750 (* not declared anywhere
|
|
|
+ 2751 in scope: with bodies
|
|
|
+ 2752 parsed at unit end this
|
|
|
+ 2753 is a genuine 201 (a
|
|
|
+ 2754 nested-local forward is
|
|
|
+ 2755 no longer tolerated). *)
|
|
|
+ 2756 SemError(201);
|
|
|
+ 2757 t := SymTab.InvalidType;
|
|
|
+ 2758 k := -1;
|
|
|
+ 2759 QbeGen.CopyOp("0", q)
|
|
|
+ 2760 ELSE
|
|
|
+ 2761 SemError(201);
|
|
|
+ 2762 t :=
|
|
|
+ 2763 SymTab.InvalidType;
|
|
|
+ 2764 k := -1;
|
|
|
+ 2765 QbeGen.CopyOp("0", q)
|
|
|
+ 2766 END
|
|
|
+ 2767 ELSE
|
|
|
+ 2768 t := SymTab.SymType(n);
|
|
|
+ 2769 k := SymTab.SymKind(n);
|
|
|
+ 2770 IF k = SymTab.KindConst THEN
|
|
|
+ 2771 IF SymTab.Equal(n,
|
|
|
+ 2772 "TRUE") THEN
|
|
|
+ 2773 t := SymTab.BoolType();
|
|
|
+ 2774 QbeGen.CopyOp("1", q)
|
|
|
+ 2775 ELSIF SymTab.Equal(n,
|
|
|
+ 2776 "FALSE") THEN
|
|
|
+ 2777 t := SymTab.BoolType();
|
|
|
+ 2778 QbeGen.CopyOp("0", q)
|
|
|
+ 2779 ELSIF SymTab.Equal(n,
|
|
|
+ 2780 "NIL") THEN
|
|
|
+ 2781 QbeGen.CopyOp("0", q)
|
|
|
+ 2782 ELSE
|
|
|
+ 2783 cls :=
|
|
|
+ 2784 SymTab.ClassOf(t);
|
|
|
+ 2785 IF (t #
|
|
|
+ 2786 SymTab.InvalidType)
|
|
|
+ 2787 AND ((cls = SymTab.ClInt)
|
|
|
+ 2788 OR (cls
|
|
|
+ 2789 = SymTab.ClChar)
|
|
|
+ 2790 OR (cls
|
|
|
+ 2791 = SymTab.ClEnum)
|
|
|
+ 2792 OR (cls
|
|
|
+ 2793 = SymTab.ClReal)
|
|
|
+ 2794 OR (cls
|
|
|
+ 2795 = SymTab.ClLong)
|
|
|
+ 2796 OR (cls
|
|
|
+ 2797 = SymTab.ClNil)
|
|
|
+ 2798 OR (cls = SymTab.ClBool)) THEN
|
|
|
+ 2799 IF cls = SymTab.ClNil THEN
|
|
|
+ 2800 QbeGen.CopyOp("0", q)
|
|
|
+ 2801 ELSIF ((cls
|
|
|
+ 2802 = SymTab.ClInt)
|
|
|
+ 2803 OR (cls
|
|
|
+ 2804 = SymTab.ClChar)
|
|
|
+ 2805 OR (cls
|
|
|
+ 2806 = SymTab.ClEnum)
|
|
|
+ 2807 OR (cls
|
|
|
+ 2808 = SymTab.ClLong)
|
|
|
+ 2809 OR (cls = SymTab.ClBool))
|
|
|
+ 2810 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 2811 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 2812 QbeGen.CopyOp(cv, q)
|
|
|
+ 2813 ELSE
|
|
|
+ 2814 QbeGen.LoadVar(n,
|
|
|
+ 2815 cls = SymTab.ClReal,
|
|
|
+ 2816 q)
|
|
|
+ 2817 END
|
|
|
+ 2818 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 2819 OR (cls = SymTab.ClRecord)
|
|
|
+ 2820 OR (cls = SymTab.ClClass)
|
|
|
+ 2821 OR (cls = SymTab.ClStr)
|
|
|
+ 2822 OR (cls = SymTab.ClUStr)
|
|
|
+ 2823 OR (cls = SymTab.ClSet) THEN
|
|
|
+ 2824 (* aggregate constant:
|
|
|
+ 2825 its value IS the
|
|
|
+ 2826 descriptor address *)
|
|
|
+ 2827 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ 2828 QbeGen.CopyOp(cv, q)
|
|
|
+ 2829 ELSE
|
|
|
+ 2830 QbeGen.CopyOp("0", q)
|
|
|
+ 2831 END
|
|
|
+ 2832 ELSE
|
|
|
+ 2833 IF t #
|
|
|
+ 2834 SymTab.InvalidType THEN
|
|
|
+ 2835 SemError(230)
|
|
|
+ 2836 END;
|
|
|
+ 2837 QbeGen.CopyOp("0", q)
|
|
|
+ 2838 END
|
|
|
+ 2839 END
|
|
|
+ 2840 ELSIF (k = SymTab.KindVar)
|
|
|
+ 2841 OR (k = SymTab.KindParam) THEN
|
|
|
+ 2842 cls := SymTab.ClassOf(t);
|
|
|
+ 2843 IF (cls # SymTab.ClInt)
|
|
|
+ 2844 AND (cls # SymTab.ClBool)
|
|
|
+ 2845 AND (cls # SymTab.ClChar)
|
|
|
+ 2846 AND (cls # SymTab.ClUChar)
|
|
|
+ 2847 AND (cls # SymTab.ClEnum)
|
|
|
+ 2848 AND (cls # SymTab.ClReal)
|
|
|
+ 2849 AND (cls # SymTab.ClPtr)
|
|
|
+ 2850 AND (cls # SymTab.ClProc)
|
|
|
+ 2851 AND (cls # SymTab.ClLong)
|
|
|
+ 2852 AND (cls # SymTab.ClArray)
|
|
|
+ 2853 AND (cls # SymTab.ClSet)
|
|
|
+ 2854 AND (cls # SymTab.ClRecord)
|
|
|
+ 2855 AND (cls # SymTab.ClUStr)
|
|
|
+ 2856 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 2857 SemError(230);
|
|
|
+ 2858 QbeGen.CopyOp("0", q)
|
|
|
+ 2859 ELSE QbeGen.CopyOp("@", q)
|
|
|
2860 END
|
|
|
- 2861 END
|
|
|
- 2862 END; .)
|
|
|
- 2863 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
- 2864 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 2865 { "[" Expr<it, iq>
|
|
|
- 2866 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2867 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2868 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2869 SymTab.ClArray THEN
|
|
|
- 2870 SemError(217);
|
|
|
- 2871 t := SymTab.InvalidType
|
|
|
- 2872 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2873 AND (SymTab.ClassOf(it) #
|
|
|
- 2874 SymTab.ClChar)
|
|
|
- 2875 AND (SymTab.ClassOf(it) #
|
|
|
- 2876 SymTab.ClEnum)
|
|
|
- 2877 AND (SymTab.ClassOf(it) #
|
|
|
- 2878 SymTab.ClBool) THEN
|
|
|
- 2879 SemError(218);
|
|
|
- 2880 t := SymTab.InvalidType
|
|
|
- 2881 ELSE
|
|
|
- 2882 eT := SymTab.ArrayElem(t);
|
|
|
- 2883 t := eT; sfx := TRUE
|
|
|
- 2884 END; .)
|
|
|
- 2885 { "," Expr<it, iq>
|
|
|
- 2886 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2887 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2888 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2889 SymTab.ClArray THEN
|
|
|
- 2890 SemError(217);
|
|
|
- 2891 t := SymTab.InvalidType
|
|
|
- 2892 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2893 AND (SymTab.ClassOf(it) #
|
|
|
- 2894 SymTab.ClChar)
|
|
|
- 2895 AND (SymTab.ClassOf(it) #
|
|
|
- 2896 SymTab.ClEnum)
|
|
|
- 2897 AND (SymTab.ClassOf(it) #
|
|
|
- 2898 SymTab.ClBool) THEN
|
|
|
- 2899 SemError(218);
|
|
|
- 2900 t := SymTab.InvalidType
|
|
|
- 2901 ELSE
|
|
|
- 2902 eT := SymTab.ArrayElem(t);
|
|
|
- 2903 t := eT; sfx := TRUE
|
|
|
- 2904 END; .) }
|
|
|
- 2905 "]"
|
|
|
- 2906 | "." GetIdent<fn>
|
|
|
- 2907 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2908 AST.SetOp(astSel, AST.SelField);
|
|
|
- 2909 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
- 2910 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
- 2911 (* qualified L.x: materialize
|
|
|
- 2912 the export, then load it *)
|
|
|
- 2913 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 2914 fn, mal) THEN
|
|
|
- 2915 SemError(201);
|
|
|
- 2916 t := SymTab.InvalidType;
|
|
|
- 2917 QbeGen.CopyOp("0", q)
|
|
|
- 2918 ELSE
|
|
|
- 2919 QbeGen.CopyOp(mal, qn);
|
|
|
- 2920 t := SymTab.SymType(mal);
|
|
|
- 2921 k := SymTab.SymKind(mal);
|
|
|
- 2922 sfx := FALSE;
|
|
|
- 2923 IF k = SymTab.KindProc THEN
|
|
|
- 2924 (* call: ArgList supplies
|
|
|
- 2925 the value *)
|
|
|
- 2926 QbeGen.CopyOp("0", q)
|
|
|
- 2927 ELSIF k = SymTab.KindConst THEN
|
|
|
- 2928 IF SymTab.GetSymVal(mal,
|
|
|
- 2929 cv)
|
|
|
- 2930 THEN QbeGen.CopyOp(cv, q)
|
|
|
- 2931 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2932 END
|
|
|
- 2933 END
|
|
|
- 2934 END
|
|
|
- 2935 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 2936 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2937 SymTab.ClRecord)
|
|
|
- 2938 AND (SymTab.ClassOf(t) #
|
|
|
- 2939 SymTab.ClClass) THEN
|
|
|
- 2940 SemError(215);
|
|
|
- 2941 t := SymTab.InvalidType
|
|
|
- 2942 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 2943 SymTab.ClClass)
|
|
|
- 2944 AND SymTab.MethodExists(t, fn) THEN
|
|
|
- 2945 (* obj.Method: bind the
|
|
|
- 2946 method and pass obj as
|
|
|
- 2947 the hidden receiver; q
|
|
|
- 2948 already holds the
|
|
|
- 2949 object's address *)
|
|
|
- 2950 QbeGen.CopyOp(fn, n);
|
|
|
- 2951 QbeGen.CopyOp(fn, qn);
|
|
|
- 2952 methCls := t;
|
|
|
- 2953 k := SymTab.KindProc;
|
|
|
- 2954 t := SymTab.InvalidType
|
|
|
- 2955 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2956 fn) THEN
|
|
|
- 2957 SemError(216);
|
|
|
- 2958 t := SymTab.InvalidType
|
|
|
- 2959 ELSE
|
|
|
- 2960 t := SymTab.FieldType(t, fn);
|
|
|
- 2961 sfx := TRUE
|
|
|
- 2962 END; .)
|
|
|
- 2963 | "^"
|
|
|
- 2964 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2965 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2966 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2967 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2968 SymTab.ClPtr THEN
|
|
|
- 2969 SemError(219);
|
|
|
- 2970 t := SymTab.InvalidType
|
|
|
- 2971 ELSE
|
|
|
- 2972 bt := SymTab.PtrBase(t);
|
|
|
- 2973 IF bt = SymTab.InvalidType THEN
|
|
|
- 2974 ELSE
|
|
|
- 2975 t := bt;
|
|
|
- 2976 sfx := TRUE
|
|
|
- 2977 END
|
|
|
- 2978 END; .) } (. astCur := astDes; .) .
|
|
|
- 2979 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
- 2980 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
- 2981 (a value, or a descriptor address for aggregates); each component
|
|
|
- 2982 descends one level exactly like the Design components. *)
|
|
|
- 2983 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2984 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
- 2985 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
- 2986 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
- 2987 iq, ql, qlo, qhi, qe, qb:
|
|
|
- 2988 QbeGen.QVal;
|
|
|
- 2989 lo, hi, fo: INTEGER;
|
|
|
- 2990 isOpen: BOOLEAN;
|
|
|
- 2991 fname: SymTab.Name;
|
|
|
- 2992 astWrap, astSel: AST.Node; .)
|
|
|
- 2993 = "[" Expr<it, iq>
|
|
|
- 2994 (. isM := FALSE;
|
|
|
- 2995 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2996 astWrap := AST.MakeNode(
|
|
|
- 2997 AST.NkDesignator);
|
|
|
- 2998 AST.SetChild(astWrap, 0, node);
|
|
|
- 2999 node := astWrap
|
|
|
- 3000 END;
|
|
|
- 3001 AST.SetChild(node, AST.NChild(node),
|
|
|
- 3002 AST.MakeUn(AST.NkSelector,
|
|
|
- 3003 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 3004 ELSIF SymTab.ClassOf(t) #
|
|
|
- 3005 SymTab.ClArray THEN
|
|
|
- 3006 SemError(217);
|
|
|
- 3007 t := SymTab.InvalidType
|
|
|
- 3008 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 3009 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
- 3010 AND (SymTab.ClassOf(it) # SymTab.ClEnum)
|
|
|
- 3011 AND (SymTab.ClassOf(it) # SymTab.ClBool) THEN
|
|
|
- 3012 SemError(218);
|
|
|
- 3013 t := SymTab.InvalidType
|
|
|
- 3014 ELSE
|
|
|
- 3015 eT := SymTab.ArrayElem(t);
|
|
|
- 3016 t := eT; sfx := TRUE
|
|
|
- 3017 END; .)
|
|
|
- 3018 "]"
|
|
|
- 3019 | "." GetIdent<fname>
|
|
|
- 3020 (. isM := FALSE;
|
|
|
- 3021 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 3022 astWrap := AST.MakeNode(
|
|
|
- 3023 AST.NkDesignator);
|
|
|
- 3024 AST.SetChild(astWrap, 0, node);
|
|
|
- 3025 node := astWrap
|
|
|
- 3026 END;
|
|
|
- 3027 AST.SetChild(node, AST.NChild(node),
|
|
|
- 3028 AST.MakeUn(AST.NkSelector,
|
|
|
- 3029 AST.SelField,
|
|
|
- 3030 AST.MakeLeaf(AST.NkIdent,
|
|
|
- 3031 fname))); IF t = SymTab.InvalidType THEN
|
|
|
- 3032 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3033 SymTab.ClRecord)
|
|
|
- 3034 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3035 SemError(215);
|
|
|
- 3036 t := SymTab.InvalidType
|
|
|
- 3037 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 3038 SymTab.ClClass)
|
|
|
- 3039 AND SymTab.MethodExists(t, fname) THEN
|
|
|
- 3040 (* a method on the call result:
|
|
|
- 3041 a following ArgList makes
|
|
|
- 3042 the call *)
|
|
|
- 3043 mname := fname;
|
|
|
- 3044 methCls := t; isM := TRUE;
|
|
|
- 3045 t := SymTab.InvalidType
|
|
|
- 3046 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 3047 fname) THEN
|
|
|
- 3048 SemError(216);
|
|
|
- 3049 t := SymTab.InvalidType
|
|
|
- 3050 ELSE
|
|
|
- 3051 t := SymTab.FieldType(t, fname);
|
|
|
- 3052 sfx := TRUE
|
|
|
- 3053 END; .)
|
|
|
- 3054 | "^" (. isM := FALSE;
|
|
|
- 3055 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 3056 astWrap := AST.MakeNode(
|
|
|
- 3057 AST.NkDesignator);
|
|
|
- 3058 AST.SetChild(astWrap, 0, node);
|
|
|
- 3059 node := astWrap
|
|
|
- 3060 END;
|
|
|
- 3061 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 3062 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 3063 AST.SetChild(node,
|
|
|
- 3064 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 3065 ELSIF SymTab.ClassOf(t) #
|
|
|
- 3066 SymTab.ClPtr THEN
|
|
|
- 3067 SemError(219);
|
|
|
+ 2861 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 2862 IF k = SymTab.KindImport THEN
|
|
|
+ 2863 SemError(230)
|
|
|
+ 2864 ELSIF k =
|
|
|
+ 2865 SymTab.KindProc THEN
|
|
|
+ 2866 (* bare procedure name:
|
|
|
+ 2867 a following ArgList
|
|
|
+ 2868 makes it a call;
|
|
|
+ 2869 otherwise Fact
|
|
|
+ 2870 reports 230 *)
|
|
|
+ 2871 ELSE
|
|
|
+ 2872 IF k = SymTab.KindField THEN
|
|
|
+ 2873 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 2874 sfx := TRUE
|
|
|
+ 2875 ELSE SemError(230);
|
|
|
+ 2876 QbeGen.CopyOp("0", q)
|
|
|
+ 2877 END
|
|
|
+ 2878 END
|
|
|
+ 2879 END
|
|
|
+ 2880 END
|
|
|
+ 2881 END; .)
|
|
|
+ 2882 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
+ 2883 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 2884 { "[" Expr<it, iq>
|
|
|
+ 2885 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2886 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2887 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2888 SymTab.ClArray THEN
|
|
|
+ 2889 SemError(217);
|
|
|
+ 2890 t := SymTab.InvalidType
|
|
|
+ 2891 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2892 AND (SymTab.ClassOf(it) #
|
|
|
+ 2893 SymTab.ClChar)
|
|
|
+ 2894 AND (SymTab.ClassOf(it) #
|
|
|
+ 2895 SymTab.ClEnum)
|
|
|
+ 2896 AND (SymTab.ClassOf(it) #
|
|
|
+ 2897 SymTab.ClBool) THEN
|
|
|
+ 2898 SemError(218);
|
|
|
+ 2899 t := SymTab.InvalidType
|
|
|
+ 2900 ELSE
|
|
|
+ 2901 eT := SymTab.ArrayElem(t);
|
|
|
+ 2902 t := eT; sfx := TRUE
|
|
|
+ 2903 END; .)
|
|
|
+ 2904 { "," Expr<it, iq>
|
|
|
+ 2905 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2906 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2907 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2908 SymTab.ClArray THEN
|
|
|
+ 2909 SemError(217);
|
|
|
+ 2910 t := SymTab.InvalidType
|
|
|
+ 2911 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2912 AND (SymTab.ClassOf(it) #
|
|
|
+ 2913 SymTab.ClChar)
|
|
|
+ 2914 AND (SymTab.ClassOf(it) #
|
|
|
+ 2915 SymTab.ClEnum)
|
|
|
+ 2916 AND (SymTab.ClassOf(it) #
|
|
|
+ 2917 SymTab.ClBool) THEN
|
|
|
+ 2918 SemError(218);
|
|
|
+ 2919 t := SymTab.InvalidType
|
|
|
+ 2920 ELSE
|
|
|
+ 2921 eT := SymTab.ArrayElem(t);
|
|
|
+ 2922 t := eT; sfx := TRUE
|
|
|
+ 2923 END; .) }
|
|
|
+ 2924 "]"
|
|
|
+ 2925 | "." GetIdent<fn>
|
|
|
+ 2926 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2927 AST.SetOp(astSel, AST.SelField);
|
|
|
+ 2928 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
+ 2929 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
+ 2930 (* qualified L.x: materialize
|
|
|
+ 2931 the export, then load it *)
|
|
|
+ 2932 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 2933 fn, mal) THEN
|
|
|
+ 2934 SemError(201);
|
|
|
+ 2935 t := SymTab.InvalidType;
|
|
|
+ 2936 QbeGen.CopyOp("0", q)
|
|
|
+ 2937 ELSE
|
|
|
+ 2938 QbeGen.CopyOp(mal, qn);
|
|
|
+ 2939 t := SymTab.SymType(mal);
|
|
|
+ 2940 k := SymTab.SymKind(mal);
|
|
|
+ 2941 sfx := FALSE;
|
|
|
+ 2942 IF k = SymTab.KindProc THEN
|
|
|
+ 2943 (* call: ArgList supplies
|
|
|
+ 2944 the value *)
|
|
|
+ 2945 QbeGen.CopyOp("0", q)
|
|
|
+ 2946 ELSIF k = SymTab.KindConst THEN
|
|
|
+ 2947 IF SymTab.GetSymVal(mal,
|
|
|
+ 2948 cv)
|
|
|
+ 2949 THEN QbeGen.CopyOp(cv, q)
|
|
|
+ 2950 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2951 END
|
|
|
+ 2952 END
|
|
|
+ 2953 END
|
|
|
+ 2954 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 2955 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2956 SymTab.ClRecord)
|
|
|
+ 2957 AND (SymTab.ClassOf(t) #
|
|
|
+ 2958 SymTab.ClClass) THEN
|
|
|
+ 2959 SemError(215);
|
|
|
+ 2960 t := SymTab.InvalidType
|
|
|
+ 2961 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 2962 SymTab.ClClass)
|
|
|
+ 2963 AND SymTab.MethodExists(t, fn) THEN
|
|
|
+ 2964 (* obj.Method: bind the
|
|
|
+ 2965 method and pass obj as
|
|
|
+ 2966 the hidden receiver; q
|
|
|
+ 2967 already holds the
|
|
|
+ 2968 object's address *)
|
|
|
+ 2969 QbeGen.CopyOp(fn, n);
|
|
|
+ 2970 QbeGen.CopyOp(fn, qn);
|
|
|
+ 2971 methCls := t;
|
|
|
+ 2972 k := SymTab.KindProc;
|
|
|
+ 2973 t := SymTab.InvalidType
|
|
|
+ 2974 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2975 fn) THEN
|
|
|
+ 2976 SemError(216);
|
|
|
+ 2977 t := SymTab.InvalidType
|
|
|
+ 2978 ELSE
|
|
|
+ 2979 t := SymTab.FieldType(t, fn);
|
|
|
+ 2980 sfx := TRUE
|
|
|
+ 2981 END; .)
|
|
|
+ 2982 | "^"
|
|
|
+ 2983 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2984 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2985 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2986 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2987 SymTab.ClPtr THEN
|
|
|
+ 2988 SemError(219);
|
|
|
+ 2989 t := SymTab.InvalidType
|
|
|
+ 2990 ELSE
|
|
|
+ 2991 bt := SymTab.PtrBase(t);
|
|
|
+ 2992 IF bt = SymTab.InvalidType THEN
|
|
|
+ 2993 ELSE
|
|
|
+ 2994 t := bt;
|
|
|
+ 2995 sfx := TRUE
|
|
|
+ 2996 END
|
|
|
+ 2997 END; .) } (. astCur := astDes; .) .
|
|
|
+ 2998 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
+ 2999 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
+ 3000 (a value, or a descriptor address for aggregates); each component
|
|
|
+ 3001 descends one level exactly like the Design components. *)
|
|
|
+ 3002 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 3003 VAR sfx: BOOLEAN; VAR node: AST.Node;
|
|
|
+ 3004 VAR mname: SymTab.Name; VAR methCls: SymTab.TypeIndex;
|
|
|
+ 3005 VAR isM: BOOLEAN> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
+ 3006 iq, ql, qlo, qhi, qe, qb:
|
|
|
+ 3007 QbeGen.QVal;
|
|
|
+ 3008 lo, hi, fo: INTEGER;
|
|
|
+ 3009 isOpen: BOOLEAN;
|
|
|
+ 3010 fname: SymTab.Name;
|
|
|
+ 3011 astWrap, astSel: AST.Node; .)
|
|
|
+ 3012 = "[" Expr<it, iq>
|
|
|
+ 3013 (. isM := FALSE;
|
|
|
+ 3014 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3015 astWrap := AST.MakeNode(
|
|
|
+ 3016 AST.NkDesignator);
|
|
|
+ 3017 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3018 node := astWrap
|
|
|
+ 3019 END;
|
|
|
+ 3020 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 3021 AST.MakeUn(AST.NkSelector,
|
|
|
+ 3022 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 3023 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 3024 SymTab.ClArray THEN
|
|
|
+ 3025 SemError(217);
|
|
|
+ 3026 t := SymTab.InvalidType
|
|
|
+ 3027 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 3028 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
+ 3029 AND (SymTab.ClassOf(it) # SymTab.ClEnum)
|
|
|
+ 3030 AND (SymTab.ClassOf(it) # SymTab.ClBool) THEN
|
|
|
+ 3031 SemError(218);
|
|
|
+ 3032 t := SymTab.InvalidType
|
|
|
+ 3033 ELSE
|
|
|
+ 3034 eT := SymTab.ArrayElem(t);
|
|
|
+ 3035 t := eT; sfx := TRUE
|
|
|
+ 3036 END; .)
|
|
|
+ 3037 "]"
|
|
|
+ 3038 | "." GetIdent<fname>
|
|
|
+ 3039 (. isM := FALSE;
|
|
|
+ 3040 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3041 astWrap := AST.MakeNode(
|
|
|
+ 3042 AST.NkDesignator);
|
|
|
+ 3043 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3044 node := astWrap
|
|
|
+ 3045 END;
|
|
|
+ 3046 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 3047 AST.MakeUn(AST.NkSelector,
|
|
|
+ 3048 AST.SelField,
|
|
|
+ 3049 AST.MakeLeaf(AST.NkIdent,
|
|
|
+ 3050 fname))); IF t = SymTab.InvalidType THEN
|
|
|
+ 3051 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3052 SymTab.ClRecord)
|
|
|
+ 3053 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3054 SemError(215);
|
|
|
+ 3055 t := SymTab.InvalidType
|
|
|
+ 3056 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 3057 SymTab.ClClass)
|
|
|
+ 3058 AND SymTab.MethodExists(t, fname) THEN
|
|
|
+ 3059 (* a method on the call result:
|
|
|
+ 3060 a following ArgList makes
|
|
|
+ 3061 the call *)
|
|
|
+ 3062 mname := fname;
|
|
|
+ 3063 methCls := t; isM := TRUE;
|
|
|
+ 3064 t := SymTab.InvalidType
|
|
|
+ 3065 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 3066 fname) THEN
|
|
|
+ 3067 SemError(216);
|
|
|
3068 t := SymTab.InvalidType
|
|
|
- 3069 ELSE
|
|
|
- 3070 bt := SymTab.PtrBase(t);
|
|
|
- 3071 IF bt # SymTab.InvalidType THEN
|
|
|
- 3072 t := bt; sfx := TRUE
|
|
|
- 3073 END
|
|
|
- 3074 END; .) .
|
|
|
- 3075 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3076 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 3077 op: INTEGER;
|
|
|
- 3078 q2, qt, wl: QbeGen.QVal;
|
|
|
- 3079 astA, astB: AST.Node;
|
|
|
- 3080 astOp: INTEGER;
|
|
|
- 3081 astMade: BOOLEAN;
|
|
|
- 3082 isR: BOOLEAN; .)
|
|
|
- 3083 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
- 3084 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 3085 (. astB := astCur; astMade := TRUE;
|
|
|
- 3086 astOp := AST.OpEq;
|
|
|
- 3087 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
- 3088 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
- 3089 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
- 3090 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
- 3091 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
- 3092 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
- 3093 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
- 3094 END;
|
|
|
- 3095 IF op = SymTab.OpIn THEN
|
|
|
- 3096 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 3097 IF (t = SymTab.InvalidType)
|
|
|
- 3098 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 3099 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 3100 ELSE
|
|
|
- 3101 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3102 END
|
|
|
- 3103 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 3104 QbeGen.CopyOp("0", q)
|
|
|
- 3105 END
|
|
|
- 3106 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 3107 IF (t = SymTab.InvalidType)
|
|
|
- 3108 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 3109 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 3110 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 3111 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 3112 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 3113 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 3114 SemError(213); t := SymTab.InvalidType;
|
|
|
- 3115 QbeGen.CopyOp("0", q)
|
|
|
- 3116 ELSE
|
|
|
- 3117 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3118 END
|
|
|
- 3119 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3120 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3121 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3122 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
- 3123 QbeGen.StrEq(op, q, q2, qt);
|
|
|
- 3124 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 3125 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 3126 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 3127 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 3128 ELSE
|
|
|
- 3129 t := SymTab.BoolType();
|
|
|
- 3130 QbeGen.CopyOp("@", q)
|
|
|
- 3131 END
|
|
|
- 3132 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 3133 QbeGen.CopyOp("0", q)
|
|
|
- 3134 END;
|
|
|
- 3135 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
- 3136 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
- 3137 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3138 Rel<VAR op: INTEGER>
|
|
|
- 3139 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 3140 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 3141 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 3142 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 3143 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 3144 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 3145 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 3146 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3147 (. VAR t2, res2, lt, rt:
|
|
|
- 3148 SymTab.TypeIndex;
|
|
|
- 3149 op: INTEGER;
|
|
|
- 3150 q2, qt, wq, qf, q2a, q2b:
|
|
|
- 3151 QbeGen.QVal;
|
|
|
- 3152 neg, isR, isL, folded:
|
|
|
- 3153 BOOLEAN;
|
|
|
- 3154 fok: BOOLEAN;
|
|
|
- 3155 lw, rw, mw: CARDINAL;
|
|
|
- 3156 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3157 astA, astB: AST.Node;
|
|
|
- 3158 astSign, astOp: INTEGER; .)
|
|
|
- 3159 = (. neg := FALSE; astSign := 0; .)
|
|
|
- 3160 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
- 3161 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
- 3162 Term<t, q> (. astA := astCur;
|
|
|
- 3163 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
- 3164 QbeGen.NegFold(q, q)
|
|
|
- 3165 END;
|
|
|
- 3166 IF astSign < 0 THEN
|
|
|
- 3167 astCur := AST.MakeUn(
|
|
|
- 3168 AST.NkUnary, AST.OpSub, astA);
|
|
|
- 3169 astA := astCur
|
|
|
- 3170 END; .)
|
|
|
- 3171 { AddOp<op>
|
|
|
- 3172 Term<t2, q2> (. astB := astCur; .)
|
|
|
- 3173 (. astOp := AST.OpAdd;
|
|
|
- 3174 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
- 3175 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
- 3176 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3177 astCur := astA;
|
|
|
- 3178 IF op = SymTab.OpOr THEN
|
|
|
- 3179 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
- 3180 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3181 t := SymTab.BoolType()
|
|
|
- 3182 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3183 IF t # SymTab.InvalidType THEN
|
|
|
- 3184 QbeGen.CopyOp("@", q)
|
|
|
- 3185 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3186 END
|
|
|
- 3187 ELSIF (op = SymTab.OpAdd)
|
|
|
- 3188 AND (SymTab.UStrCompat(t, t2)
|
|
|
- 3189 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 3190 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
- 3191 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
- 3192 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
- 3193 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 3194 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
- 3195 (* UString concatenation: a UCHAR operand becomes a
|
|
|
- 3196 1-codepoint UString; the result is a descriptor in the
|
|
|
- 3197 shim's concat buffer. Work on copies so neither
|
|
|
- 3198 operand is clobbered. *)
|
|
|
- 3199 t := SymTab.NewUStr();
|
|
|
- 3200 QbeGen.CopyOp("@", q)
|
|
|
- 3201 ELSIF (op = SymTab.OpAdd)
|
|
|
- 3202 AND (SymTab.StrCompat(t, t2)
|
|
|
- 3203 OR (SymTab.IsStrType(t)
|
|
|
- 3204 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
- 3205 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
- 3206 AND SymTab.IsStrType(t2))) THEN
|
|
|
- 3207 (* string concatenation; a CHAR operand becomes a
|
|
|
- 3208 1-character string literal. When both operands are
|
|
|
- 3209 constants, fold to a single string literal so a
|
|
|
- 3210 constructor element stays compile-time. *)
|
|
|
- 3211 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
- 3212 qt, fok);
|
|
|
- 3213 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
- 3214 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3215 END;
|
|
|
- 3216 t := SymTab.NewStr()
|
|
|
- 3217 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3218 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3219 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3220 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3221 mw := lw;
|
|
|
- 3222 IF rw > mw THEN mw := rw END;
|
|
|
- 3223 t := SymTab.NewSet(
|
|
|
- 3224 SymTab.NewSubR(0,
|
|
|
- 3225 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3226 QbeGen.CopyOp("@", q)
|
|
|
- 3227 ELSE
|
|
|
- 3228 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 3229 lt := t; rt := t2; t := res2
|
|
|
- 3230 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3231 IF t # SymTab.InvalidType THEN
|
|
|
- 3232 isL := SymTab.IsLongFamily(t);
|
|
|
- 3233 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3234 folded := FALSE;
|
|
|
- 3235 IF (NOT isL) AND (NOT isR)
|
|
|
- 3236 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3237 IF op = SymTab.OpAdd THEN
|
|
|
- 3238 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 3239 ELSE
|
|
|
- 3240 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 3241 END
|
|
|
- 3242 END;
|
|
|
- 3243 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3244 ELSE
|
|
|
- 3245 QbeGen.CopyOp("@", q)
|
|
|
- 3246 END
|
|
|
- 3247 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3248 END
|
|
|
- 3249 END; .) }
|
|
|
- 3250 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3251 AddOp<VAR op: INTEGER>
|
|
|
- 3252 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 3253 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 3254 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 3255 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3256 (. VAR t2, res2, lt, rt:
|
|
|
- 3257 SymTab.TypeIndex;
|
|
|
- 3258 op: INTEGER;
|
|
|
- 3259 q2, qt, wq, qf:
|
|
|
- 3260 QbeGen.QVal;
|
|
|
- 3261 isR, isL, folded: BOOLEAN;
|
|
|
- 3262 lw, rw, mw: CARDINAL;
|
|
|
- 3263 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3264 astA, astB: AST.Node;
|
|
|
- 3265 astOp: INTEGER; .)
|
|
|
- 3266 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
- 3267 Fact<t2, q2> (. astB := astCur; .)
|
|
|
- 3268 (. astOp := AST.OpMul;
|
|
|
- 3269 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
- 3270 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
- 3271 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
- 3272 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
- 3273 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3274 astCur := astA;
|
|
|
- 3275 IF op = SymTab.OpAnd THEN
|
|
|
- 3276 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
- 3277 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3278 t := SymTab.BoolType()
|
|
|
- 3279 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3280 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
- 3281 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3282 END
|
|
|
- 3283 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3284 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3285 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3286 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3287 mw := lw;
|
|
|
- 3288 IF rw > mw THEN mw := rw END;
|
|
|
- 3289 t := SymTab.NewSet(
|
|
|
- 3290 SymTab.NewSubR(0,
|
|
|
- 3291 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3292 QbeGen.CopyOp("@", q)
|
|
|
- 3293 ELSE
|
|
|
- 3294 IF SymTab.ArithCheck(t, t2,
|
|
|
- 3295 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 3296 res2) THEN
|
|
|
- 3297 lt := t; rt := t2; t := res2
|
|
|
- 3298 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3299 IF t # SymTab.InvalidType THEN
|
|
|
- 3300 isL := SymTab.IsLongFamily(t);
|
|
|
- 3301 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3302 folded := FALSE;
|
|
|
- 3303 IF (NOT isL) AND (NOT isR)
|
|
|
- 3304 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3305 IF op = SymTab.OpTimes THEN
|
|
|
- 3306 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 3307 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 3308 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 3309 ELSIF op = SymTab.OpMod THEN
|
|
|
- 3310 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 3311 END
|
|
|
- 3312 END;
|
|
|
- 3313 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3314 ELSE
|
|
|
- 3315 QbeGen.CopyOp("@", q)
|
|
|
- 3316 END
|
|
|
- 3317 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3318 END
|
|
|
- 3319 END; .) }
|
|
|
- 3320 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3321 MulOp<VAR op: INTEGER>
|
|
|
- 3322 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 3323 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 3324 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 3325 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 3326 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
- 3327 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3328 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 3329 et, dt, t2, st, ct2, et2:
|
|
|
- 3330 SymTab.TypeIndex;
|
|
|
- 3331 dk: INTEGER;
|
|
|
- 3332 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
- 3333 QbeGen.QVal;
|
|
|
- 3334 qn, vn: SymTab.Name;
|
|
|
- 3335 vt: SymTab.TypeIndex;
|
|
|
- 3336 c1, c2: INTEGER;
|
|
|
- 3337 lo, hi: INTEGER;
|
|
|
- 3338 isMax: BOOLEAN;
|
|
|
- 3339 called, isHigh, sfx, isCh,
|
|
|
- 3340 isU, uok, isStr: BOOLEAN;
|
|
|
- 3341 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
- 3342 astD: AST.Node;
|
|
|
- 3343 astCall: BOOLEAN;
|
|
|
- 3344 astNode, astNot: AST.Node;
|
|
|
- 3345 j: CARDINAL;
|
|
|
- 3346 astArg2: AST.Node;
|
|
|
- 3347 astBrace: AST.Node;
|
|
|
- 3348 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
- 3349 isConvF: BOOLEAN;
|
|
|
- 3350 fi, fj: CARDINAL; .)
|
|
|
- 3351 = (. astIsLit := FALSE; .)
|
|
|
- 3352 ( "__LINE__" (. QbeGen.IntStr(M2S.line, q);
|
|
|
- 3353 astIsLit := TRUE;
|
|
|
- 3354 astCur := AST.MakeLeaf(
|
|
|
- 3355 AST.NkIntLit, q);
|
|
|
- 3356 t := SymTab.IntType(); .)
|
|
|
- 3357 | "__FILE__" (. (* fold to the quoted file name *)
|
|
|
- 3358 s[0] := '"'; fi := 1; fj := 0;
|
|
|
- 3359 WHILE (M2S.fileName[fj] # CHR(0))
|
|
|
- 3360 AND (fi < HIGH(s)) DO
|
|
|
- 3361 s[fi] := M2S.fileName[fj];
|
|
|
- 3362 INC(fi); INC(fj)
|
|
|
- 3363 END;
|
|
|
- 3364 s[fi] := '"';
|
|
|
- 3365 s[fi + 1] := CHR(0);
|
|
|
- 3366 astIsLit := TRUE;
|
|
|
- 3367 astCur := AST.MakeLeaf(
|
|
|
- 3368 AST.NkStrLit, s);
|
|
|
- 3369 t := SymTab.NewStr();
|
|
|
- 3370 QbeGen.DeclStr(s, q); .)
|
|
|
- 3371 | integer (. LexString(s);
|
|
|
- 3372 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
- 3373 t := SymTab.IntType(); .)
|
|
|
- 3374 | charConst (. LexString(s);
|
|
|
- 3375 QbeGen.NormLit(s, q, isCh);
|
|
|
- 3376 astIsLit := TRUE;
|
|
|
- 3377 astCur := AST.MakeLeaf(
|
|
|
- 3378 AST.NkCharLit, s);
|
|
|
- 3379 t := SymTab.CharType(); .)
|
|
|
- 3380 | real (. LexString(s);
|
|
|
- 3381 QbeGen.NormReal(s, q);
|
|
|
- 3382 astIsLit := TRUE;
|
|
|
- 3383 astCur := AST.MakeLeaf(
|
|
|
- 3384 AST.NkRealLit, s);
|
|
|
- 3385 t := SymTab.RealType(); .)
|
|
|
- 3386 | string (. LexString(s);
|
|
|
- 3387 astIsLit := TRUE;
|
|
|
- 3388 astCur := AST.MakeLeaf(
|
|
|
- 3389 AST.NkStrLit, s);
|
|
|
- 3390 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3391 t := SymTab.CharType();
|
|
|
- 3392 QbeGen.IntStr(
|
|
|
- 3393 QbeGen.CharVal(s), q)
|
|
|
- 3394 ELSE t := SymTab.NewStr();
|
|
|
- 3395 QbeGen.DeclStr(s, q);
|
|
|
- 3396 (* a literal's value IS its
|
|
|
- 3397 static descriptor address *)
|
|
|
- 3398 END; .)
|
|
|
- 3399 | ustring (. LexString(s);
|
|
|
- 3400 astIsLit := TRUE;
|
|
|
- 3401 astCur := AST.MakeLeaf(
|
|
|
- 3402 AST.NkStrLit, s);
|
|
|
- 3403 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
- 3404 uok);
|
|
|
- 3405 IF NOT uok THEN
|
|
|
- 3406 SemError(234);
|
|
|
- 3407 t := SymTab.InvalidType
|
|
|
- 3408 ELSIF isU THEN
|
|
|
- 3409 t := SymTab.UCharType();
|
|
|
- 3410 QbeGen.IntStr(ucp, q)
|
|
|
- 3411 ELSE
|
|
|
- 3412 t := SymTab.NewUStr();
|
|
|
- 3413 END; .)
|
|
|
- 3414 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
- 3415 astNArgs := 0; called := FALSE;
|
|
|
- 3416 t := dt;
|
|
|
- 3417 IF dk = SymTab.KindConst THEN
|
|
|
- 3418 QbeGen.CopyOp(qd, q)
|
|
|
- 3419 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3420 END; .)
|
|
|
- 3421 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
- 3422 astBrace := astCur; .) ]
|
|
|
- 3423 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3424 (. astCall := TRUE;
|
|
|
- 3425 IF (SymTab.SymKind(qn) = SymTab.KindType)
|
|
|
- 3426 OR (SymTab.SymKind(qn) = SymTab.KindPredef) THEN
|
|
|
- 3427 (* T(x): emit as the VAL builtin so Lower's
|
|
|
- 3428 conversion rules apply unchanged *)
|
|
|
- 3429 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3430 AST.SetChild(astNode, 0,
|
|
|
- 3431 AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3432 AST.SetChild(astNode, 1,
|
|
|
- 3433 AST.MakeLeaf(AST.NkIdent, qn));
|
|
|
- 3434 IF astNArgs = 1 THEN
|
|
|
- 3435 AST.SetChild(astNode, 2, astArgs[0])
|
|
|
- 3436 END;
|
|
|
- 3437 isConvF := TRUE
|
|
|
- 3438 ELSE astNode := AstCallNode(astD)
|
|
|
- 3439 END;
|
|
|
- 3440 astRes := astNode;
|
|
|
- 3441 t := ct2;
|
|
|
- 3442 QbeGen.CopyOp(q2, q);
|
|
|
- 3443 IF isConvF AND QbeGen.IsImm(convQ)
|
|
|
- 3444 AND OrdClass(convT) AND OrdClass(ct2) THEN
|
|
|
- 3445 QbeGen.CopyOp(convQ, q)
|
|
|
- 3446 END;
|
|
|
- 3447 sfx := FALSE; .)
|
|
|
- 3448 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
- 3449 [ (. astNArgs := 0; .)
|
|
|
- 3450 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3451 (. astNode := AstCallNode(astRes);
|
|
|
- 3452 astRes := astNode;
|
|
|
- 3453 t := ct2;
|
|
|
- 3454 QbeGen.CopyOp(q2, q);
|
|
|
- 3455 sfx := FALSE; .) ] }
|
|
|
- 3456 (. IF sfx THEN
|
|
|
- 3457 IF t = SymTab.InvalidType THEN
|
|
|
- 3458 QbeGen.CopyOp("0", q)
|
|
|
- 3459 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3460 SymTab.ClRecord)
|
|
|
- 3461 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
- 3462 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
- 3463 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3464 QbeGen.CopyOp("@", q)
|
|
|
- 3465 END
|
|
|
- 3466 END; .) ]
|
|
|
- 3467 (. IF called THEN
|
|
|
- 3468 astCur := astRes
|
|
|
- 3469 ELSIF astCall THEN
|
|
|
- 3470 astCur := astBrace
|
|
|
- 3471 ELSE astCur := astD
|
|
|
- 3472 END;
|
|
|
- 3473 astIsLit := TRUE;
|
|
|
- 3474 IF NOT called
|
|
|
- 3475 AND (dk = SymTab.KindProc) THEN
|
|
|
- 3476 (* bare zero-arg function
|
|
|
- 3477 call (parentheses may be
|
|
|
- 3478 omitted); a proper or
|
|
|
- 3479 parameterised proc here
|
|
|
- 3480 is 230 *)
|
|
|
- 3481 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 3482 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
- 3483 t := SymTab.ProcRes(qn);
|
|
|
- 3484 QbeGen.CopyOp("@", q);
|
|
|
- 3485 astCur := AST.MakeNode(AST.NkCall);
|
|
|
- 3486 AST.SetChild(astCur, 0, astD)
|
|
|
- 3487 ELSE
|
|
|
- 3488 t := SymTab.ProcTypeOf(qn);
|
|
|
- 3489 QbeGen.CopyOp("@", q)
|
|
|
- 3490 END
|
|
|
- 3491 END; .)
|
|
|
- 3492 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 3493 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- 3494 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
- 3495 isU := FALSE; .)
|
|
|
- 3496 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3497 isStr := TRUE;
|
|
|
- 3498 isU := FALSE;
|
|
|
- 3499 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3500 dt := SymTab.CharType();
|
|
|
- 3501 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
- 3502 qd)
|
|
|
- 3503 ELSE
|
|
|
- 3504 dt := SymTab.NewStr();
|
|
|
- 3505 QbeGen.DeclStr(s, qd);
|
|
|
- 3506 END;
|
|
|
- 3507 dk := -1;
|
|
|
- 3508 qn[0] := CHR(0); .)
|
|
|
- 3509 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3510 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
- 3511 uok);
|
|
|
- 3512 isStr := FALSE;
|
|
|
- 3513 IF NOT uok THEN
|
|
|
- 3514 SemError(234);
|
|
|
- 3515 dt := SymTab.InvalidType
|
|
|
- 3516 ELSIF isU THEN
|
|
|
- 3517 (* one codepoint: a UCHAR;
|
|
|
- 3518 LEN is 1, HIGH is 0 *)
|
|
|
- 3519 dt := SymTab.UCharType();
|
|
|
- 3520 QbeGen.IntStr(ucp, qd)
|
|
|
- 3521 ELSE
|
|
|
- 3522 dt := SymTab.NewUStr();
|
|
|
- 3523 END;
|
|
|
- 3524 dk := -1;
|
|
|
- 3525 qn[0] := CHR(0); .) )
|
|
|
- 3526 ")"
|
|
|
- 3527 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3528 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
- 3529 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
- 3530 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3531 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
- 3532 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3533 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3534 IF (dt # SymTab.InvalidType)
|
|
|
- 3535 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
- 3536 (* UString: the count is
|
|
|
- 3537 the descriptor header *)
|
|
|
- 3538 t := SymTab.IntType();
|
|
|
- 3539 QbeGen.CopyOp("@", q)
|
|
|
- 3540 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 3541 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
- 3542 (* single UCHAR codepoint *)
|
|
|
- 3543 IF isHigh THEN
|
|
|
- 3544 QbeGen.CopyOp("0", qr)
|
|
|
- 3545 ELSE
|
|
|
- 3546 QbeGen.CopyOp("1", qr)
|
|
|
- 3547 END;
|
|
|
- 3548 t := SymTab.IntType();
|
|
|
- 3549 QbeGen.CopyOp(qr, q)
|
|
|
- 3550 ELSIF isStr THEN
|
|
|
- 3551 (* fold: content length at
|
|
|
- 3552 compile time *)
|
|
|
- 3553 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3554 c1 := 1
|
|
|
- 3555 ELSE
|
|
|
- 3556 c1 :=
|
|
|
- 3557 SymTab.StrLen(s) - 2
|
|
|
- 3558 END;
|
|
|
- 3559 IF isHigh THEN
|
|
|
- 3560 DEC(c1)
|
|
|
- 3561 END;
|
|
|
- 3562 QbeGen.IntStr(c1, qr);
|
|
|
- 3563 t := SymTab.IntType();
|
|
|
- 3564 QbeGen.CopyOp(qr, q)
|
|
|
- 3565 ELSIF dt = SymTab.InvalidType THEN
|
|
|
- 3566 t := SymTab.InvalidType;
|
|
|
- 3567 QbeGen.CopyOp("0", q)
|
|
|
- 3568 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 3569 SymTab.ClArray THEN
|
|
|
- 3570 SemError(217);
|
|
|
- 3571 t := SymTab.InvalidType;
|
|
|
- 3572 QbeGen.CopyOp("0", q)
|
|
|
- 3573 ELSE
|
|
|
- 3574 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 3575 t := SymTab.IntType();
|
|
|
- 3576 QbeGen.CopyOp("@", q)
|
|
|
- 3577 ELSE
|
|
|
- 3578 IF isHigh THEN
|
|
|
- 3579 QbeGen.IntStr(
|
|
|
- 3580 SymTab.ArrayHi(dt), qr)
|
|
|
- 3581 ELSE
|
|
|
- 3582 QbeGen.IntStr(VAL(
|
|
|
- 3583 INTEGER,
|
|
|
- 3584 SymTab.ArrayLen(dt)),
|
|
|
- 3585 qr)
|
|
|
- 3586 END;
|
|
|
- 3587 t := SymTab.IntType();
|
|
|
- 3588 QbeGen.CopyOp(qr, q)
|
|
|
- 3589 END
|
|
|
- 3590 END; .)
|
|
|
- 3591 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3592 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3593 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
- 3594 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3595 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3596 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3597 t := SymTab.InvalidType;
|
|
|
- 3598 QbeGen.CopyOp("0", q)
|
|
|
- 3599 ELSE
|
|
|
- 3600 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 3601 SymTab.ObjectSize(dt)), q);
|
|
|
- 3602 t := SymTab.IntType()
|
|
|
- 3603 END; .)
|
|
|
- 3604 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
- 3605 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
- 3606 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
- 3607 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3608 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3609 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
- 3610 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3611 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
- 3612 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3613 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3614 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3615 (* set shift/rotate: isMax
|
|
|
- 3616 doubles as "rotate" *)
|
|
|
- 3617 IF (et # SymTab.InvalidType)
|
|
|
- 3618 AND (SymTab.ClassOf(et) =
|
|
|
- 3619 SymTab.ClSet) THEN
|
|
|
- 3620 t := et;
|
|
|
- 3621 QbeGen.CopyOp("@", q)
|
|
|
- 3622 ELSE SemError(230);
|
|
|
- 3623 t := SymTab.InvalidType;
|
|
|
- 3624 QbeGen.CopyOp("0", q)
|
|
|
- 3625 END; .)
|
|
|
- 3626 | ( "MIN" (. isMax := FALSE; .)
|
|
|
- 3627 | "MAX" (. isMax := TRUE; .) )
|
|
|
- 3628 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3629 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3630 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3631 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
- 3632 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3633 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
- 3634 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3635 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3636 IF (dt # SymTab.InvalidType)
|
|
|
- 3637 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
- 3638 (* REAL/LONGREAL: the
|
|
|
- 3639 implementation bounds *)
|
|
|
- 3640 IF isMax THEN
|
|
|
- 3641 QbeGen.NormReal(
|
|
|
- 3642 "3.402823e38", q)
|
|
|
- 3643 ELSE QbeGen.NormReal(
|
|
|
- 3644 "-3.402823e38", q)
|
|
|
- 3645 END;
|
|
|
- 3646 t := SymTab.RealType()
|
|
|
- 3647 ELSIF (dt #
|
|
|
- 3648 SymTab.InvalidType)
|
|
|
- 3649 AND (SymTab.ClassOf(dt) =
|
|
|
- 3650 SymTab.ClLong) THEN
|
|
|
- 3651 IF isMax THEN
|
|
|
- 3652 QbeGen.CopyOp(
|
|
|
- 3653 "9223372036854775807", q)
|
|
|
- 3654 ELSE QbeGen.CopyOp(
|
|
|
- 3655 "-9223372036854775808", q)
|
|
|
- 3656 END;
|
|
|
- 3657 t := SymTab.LongType()
|
|
|
- 3658 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
- 3659 hi) THEN
|
|
|
- 3660 IF isMax THEN
|
|
|
- 3661 QbeGen.IntStr(hi, q)
|
|
|
- 3662 ELSE QbeGen.IntStr(lo, q)
|
|
|
- 3663 END;
|
|
|
- 3664 t := SymTab.IntType()
|
|
|
- 3665 ELSE SemError(230);
|
|
|
- 3666 t := SymTab.InvalidType;
|
|
|
- 3667 QbeGen.CopyOp("0", q)
|
|
|
- 3668 END; .)
|
|
|
- 3669 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3670 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3671 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
- 3672 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3673 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3674 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3675 t := SymTab.InvalidType;
|
|
|
- 3676 QbeGen.CopyOp("0", q)
|
|
|
- 3677 ELSE
|
|
|
- 3678 IF sfx
|
|
|
- 3679 OR (dk = SymTab.KindVar)
|
|
|
- 3680 OR (dk = SymTab.KindParam) THEN
|
|
|
- 3681 QbeGen.CopyOp("@", q)
|
|
|
- 3682 ELSE SemError(230);
|
|
|
- 3683 QbeGen.CopyOp("0", q)
|
|
|
- 3684 END;
|
|
|
- 3685 t := SymTab.AddrType()
|
|
|
- 3686 END; .)
|
|
|
- 3687 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 3688 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3689 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
- 3690 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3691 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3692 (. IF (et # SymTab.InvalidType)
|
|
|
- 3693 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3694 SemError(211) END;
|
|
|
- 3695 t := SymTab.CharType(); .)
|
|
|
- 3696 | "ORD" "(" Expr<et, q> ")"
|
|
|
- 3697 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3698 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
- 3699 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3700 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3701 (. IF et # SymTab.InvalidType THEN
|
|
|
- 3702 IF (SymTab.ClassOf(et) #
|
|
|
- 3703 SymTab.ClChar)
|
|
|
- 3704 AND (SymTab.ClassOf(et) #
|
|
|
- 3705 SymTab.ClBool)
|
|
|
- 3706 AND (SymTab.ClassOf(et) #
|
|
|
- 3707 SymTab.ClEnum)
|
|
|
- 3708 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3709 SemError(211) END
|
|
|
- 3710 END;
|
|
|
- 3711 t := SymTab.IntType(); .)
|
|
|
- 3712 | "CAP" "(" Expr<et, q> ")"
|
|
|
- 3713 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3714 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
- 3715 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3716 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3717 (. IF QbeGen.IsImm(q)
|
|
|
- 3718 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3719 IF (lo >= VAL(INTEGER, ORD("a"))) AND (lo <= VAL(INTEGER, ORD("z"))) THEN lo := lo - 32 END;
|
|
|
- 3720 QbeGen.IntStr(lo, q)
|
|
|
- 3721 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3722 END;
|
|
|
- 3723 t := SymTab.CharType(); .)
|
|
|
- 3724 | "UCHR" "(" Expr<et, q> ")"
|
|
|
- 3725 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3726 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
- 3727 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3728 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3729 (. (* UCHR: the UCHAR constructor.
|
|
|
- 3730 CHAR -> UCHAR (identity);
|
|
|
- 3731 INTEGER familly -> UCHAR
|
|
|
- 3732 (codepoint value). *)
|
|
|
- 3733 IF (et # SymTab.InvalidType)
|
|
|
- 3734 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
- 3735 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3736 SemError(211) END;
|
|
|
- 3737 t := SymTab.UCharType(); .)
|
|
|
- 3738 | "CHR8" "(" Expr<et, q> ")"
|
|
|
- 3739 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3740 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
- 3741 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3742 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3743 (. IF (et # SymTab.InvalidType)
|
|
|
- 3744 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3745 SemError(211) END;
|
|
|
- 3746 t := SymTab.CharType(); .)
|
|
|
- 3747 | "UORD" "(" Expr<et, q> ")"
|
|
|
- 3748 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3749 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
- 3750 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3751 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3752 (. (* UORD(u): the codepoint as a
|
|
|
- 3753 32-bit ordinal (INTEGER),
|
|
|
- 3754 cf. ORD for CHAR. *)
|
|
|
- 3755 IF (et # SymTab.InvalidType)
|
|
|
- 3756 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3757 SemError(211) END;
|
|
|
- 3758 t := SymTab.IntType(); .)
|
|
|
- 3759 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 3760 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3761 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
- 3762 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3763 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3764 (. IF (et # SymTab.InvalidType)
|
|
|
- 3765 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 3766 AND (SymTab.ClassOf(et) #
|
|
|
- 3767 SymTab.ClReal) THEN
|
|
|
- 3768 SemError(211)
|
|
|
- 3769 ELSIF QbeGen.IsImm(q)
|
|
|
- 3770 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3771 IF lo < 0 THEN lo := -lo END;
|
|
|
- 3772 QbeGen.IntStr(lo, q)
|
|
|
- 3773 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3774 END;
|
|
|
- 3775 t := et; .)
|
|
|
- 3776 | "ODD" "(" Expr<et, q> ")"
|
|
|
- 3777 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3778 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ODD"));
|
|
|
- 3779 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3780 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3781 (. IF (et # SymTab.InvalidType)
|
|
|
- 3782 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3783 SemError(211) END;
|
|
|
- 3784 t := SymTab.BoolType();
|
|
|
- 3785 IF QbeGen.IsImm(q)
|
|
|
- 3786 AND SymTab.ConstInt(q, lo) THEN
|
|
|
- 3787 IF (lo MOD 2) # 0 THEN
|
|
|
- 3788 QbeGen.CopyOp("1", q)
|
|
|
- 3789 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3790 END
|
|
|
- 3791 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 3792 END; .)
|
|
|
- 3793 | "TRUNC" "(" Expr<et, q> ")"
|
|
|
- 3794 (. (* TRUNC(x): real -> INTEGER, as the VAL builtin *)
|
|
|
- 3795 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3796 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3797 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "INTEGER"));
|
|
|
- 3798 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3069 ELSE
|
|
|
+ 3070 t := SymTab.FieldType(t, fname);
|
|
|
+ 3071 sfx := TRUE
|
|
|
+ 3072 END; .)
|
|
|
+ 3073 | "^" (. isM := FALSE;
|
|
|
+ 3074 IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 3075 astWrap := AST.MakeNode(
|
|
|
+ 3076 AST.NkDesignator);
|
|
|
+ 3077 AST.SetChild(astWrap, 0, node);
|
|
|
+ 3078 node := astWrap
|
|
|
+ 3079 END;
|
|
|
+ 3080 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 3081 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 3082 AST.SetChild(node,
|
|
|
+ 3083 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 3084 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 3085 SymTab.ClPtr THEN
|
|
|
+ 3086 SemError(219);
|
|
|
+ 3087 t := SymTab.InvalidType
|
|
|
+ 3088 ELSE
|
|
|
+ 3089 bt := SymTab.PtrBase(t);
|
|
|
+ 3090 IF bt # SymTab.InvalidType THEN
|
|
|
+ 3091 t := bt; sfx := TRUE
|
|
|
+ 3092 END
|
|
|
+ 3093 END; .) .
|
|
|
+ 3094 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3095 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 3096 op: INTEGER;
|
|
|
+ 3097 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 3098 astA, astB: AST.Node;
|
|
|
+ 3099 astOp: INTEGER;
|
|
|
+ 3100 astMade: BOOLEAN;
|
|
|
+ 3101 isR: BOOLEAN; .)
|
|
|
+ 3102 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
+ 3103 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 3104 (. astB := astCur; astMade := TRUE;
|
|
|
+ 3105 astOp := AST.OpEq;
|
|
|
+ 3106 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
+ 3107 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
+ 3108 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
+ 3109 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
+ 3110 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
+ 3111 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
+ 3112 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
+ 3113 END;
|
|
|
+ 3114 IF op = SymTab.OpIn THEN
|
|
|
+ 3115 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 3116 IF (t = SymTab.InvalidType)
|
|
|
+ 3117 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 3118 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 3119 ELSE
|
|
|
+ 3120 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3121 END
|
|
|
+ 3122 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 3123 QbeGen.CopyOp("0", q)
|
|
|
+ 3124 END
|
|
|
+ 3125 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 3126 IF (t = SymTab.InvalidType)
|
|
|
+ 3127 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 3128 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 3129 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 3130 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 3131 IF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 3132 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 3133 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 3134 QbeGen.CopyOp("0", q)
|
|
|
+ 3135 ELSE
|
|
|
+ 3136 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3137 END
|
|
|
+ 3138 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3139 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3140 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3141 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 3142 QbeGen.StrEq(op, q, q2, qt);
|
|
|
+ 3143 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 3144 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 3145 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 3146 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 3147 ELSE
|
|
|
+ 3148 t := SymTab.BoolType();
|
|
|
+ 3149 QbeGen.CopyOp("@", q)
|
|
|
+ 3150 END
|
|
|
+ 3151 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 3152 QbeGen.CopyOp("0", q)
|
|
|
+ 3153 END;
|
|
|
+ 3154 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
+ 3155 (. IF NOT astMade THEN astCur := astA END; .)
|
|
|
+ 3156 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3157 Rel<VAR op: INTEGER>
|
|
|
+ 3158 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 3159 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 3160 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 3161 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 3162 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 3163 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 3164 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 3165 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3166 (. VAR t2, res2, lt, rt:
|
|
|
+ 3167 SymTab.TypeIndex;
|
|
|
+ 3168 op: INTEGER;
|
|
|
+ 3169 q2, qt, wq, qf, q2a, q2b:
|
|
|
+ 3170 QbeGen.QVal;
|
|
|
+ 3171 neg, isR, isL, folded:
|
|
|
+ 3172 BOOLEAN;
|
|
|
+ 3173 fok: BOOLEAN;
|
|
|
+ 3174 lw, rw, mw: CARDINAL;
|
|
|
+ 3175 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3176 astA, astB: AST.Node;
|
|
|
+ 3177 astSign, astOp: INTEGER; .)
|
|
|
+ 3178 = (. neg := FALSE; astSign := 0; .)
|
|
|
+ 3179 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
+ 3180 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
+ 3181 Term<t, q> (. astA := astCur;
|
|
|
+ 3182 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
+ 3183 QbeGen.NegFold(q, q)
|
|
|
+ 3184 END;
|
|
|
+ 3185 IF astSign < 0 THEN
|
|
|
+ 3186 astCur := AST.MakeUn(
|
|
|
+ 3187 AST.NkUnary, AST.OpSub, astA);
|
|
|
+ 3188 astA := astCur
|
|
|
+ 3189 END; .)
|
|
|
+ 3190 { AddOp<op>
|
|
|
+ 3191 Term<t2, q2> (. astB := astCur; .)
|
|
|
+ 3192 (. astOp := AST.OpAdd;
|
|
|
+ 3193 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
+ 3194 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
+ 3195 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3196 astCur := astA;
|
|
|
+ 3197 IF op = SymTab.OpOr THEN
|
|
|
+ 3198 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
+ 3199 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3200 t := SymTab.BoolType()
|
|
|
+ 3201 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3202 IF t # SymTab.InvalidType THEN
|
|
|
+ 3203 QbeGen.CopyOp("@", q)
|
|
|
+ 3204 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3205 END
|
|
|
+ 3206 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 3207 AND (SymTab.UStrCompat(t, t2)
|
|
|
+ 3208 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 3209 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ 3210 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ 3211 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ 3212 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 3213 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ 3214 (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 3215 1-codepoint UString; the result is a descriptor in the
|
|
|
+ 3216 shim's concat buffer. Work on copies so neither
|
|
|
+ 3217 operand is clobbered. *)
|
|
|
+ 3218 t := SymTab.NewUStr();
|
|
|
+ 3219 QbeGen.CopyOp("@", q)
|
|
|
+ 3220 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 3221 AND (SymTab.StrCompat(t, t2)
|
|
|
+ 3222 OR (SymTab.IsStrType(t)
|
|
|
+ 3223 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
+ 3224 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
+ 3225 AND SymTab.IsStrType(t2))) THEN
|
|
|
+ 3226 (* string concatenation; a CHAR operand becomes a
|
|
|
+ 3227 1-character string literal. When both operands are
|
|
|
+ 3228 constants, fold to a single string literal so a
|
|
|
+ 3229 constructor element stays compile-time. *)
|
|
|
+ 3230 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
+ 3231 qt, fok);
|
|
|
+ 3232 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
+ 3233 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3234 END;
|
|
|
+ 3235 t := SymTab.NewStr()
|
|
|
+ 3236 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3237 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3238 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3239 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3240 mw := lw;
|
|
|
+ 3241 IF rw > mw THEN mw := rw END;
|
|
|
+ 3242 t := SymTab.NewSet(
|
|
|
+ 3243 SymTab.NewSubR(0,
|
|
|
+ 3244 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3245 QbeGen.CopyOp("@", q)
|
|
|
+ 3246 ELSE
|
|
|
+ 3247 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 3248 lt := t; rt := t2; t := res2
|
|
|
+ 3249 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3250 IF t # SymTab.InvalidType THEN
|
|
|
+ 3251 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3252 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3253 folded := FALSE;
|
|
|
+ 3254 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3255 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3256 IF op = SymTab.OpAdd THEN
|
|
|
+ 3257 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 3258 ELSE
|
|
|
+ 3259 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 3260 END
|
|
|
+ 3261 END;
|
|
|
+ 3262 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3263 ELSE
|
|
|
+ 3264 QbeGen.CopyOp("@", q)
|
|
|
+ 3265 END
|
|
|
+ 3266 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3267 END
|
|
|
+ 3268 END; .) }
|
|
|
+ 3269 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3270 AddOp<VAR op: INTEGER>
|
|
|
+ 3271 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 3272 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 3273 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 3274 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3275 (. VAR t2, res2, lt, rt:
|
|
|
+ 3276 SymTab.TypeIndex;
|
|
|
+ 3277 op: INTEGER;
|
|
|
+ 3278 q2, qt, wq, qf:
|
|
|
+ 3279 QbeGen.QVal;
|
|
|
+ 3280 isR, isL, folded: BOOLEAN;
|
|
|
+ 3281 lw, rw, mw: CARDINAL;
|
|
|
+ 3282 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3283 astA, astB: AST.Node;
|
|
|
+ 3284 astOp: INTEGER; .)
|
|
|
+ 3285 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
+ 3286 Fact<t2, q2> (. astB := astCur; .)
|
|
|
+ 3287 (. astOp := AST.OpMul;
|
|
|
+ 3288 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
+ 3289 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
+ 3290 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
+ 3291 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
+ 3292 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3293 astCur := astA;
|
|
|
+ 3294 IF op = SymTab.OpAnd THEN
|
|
|
+ 3295 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
+ 3296 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3297 t := SymTab.BoolType()
|
|
|
+ 3298 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3299 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
+ 3300 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3301 END
|
|
|
+ 3302 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3303 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3304 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3305 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3306 mw := lw;
|
|
|
+ 3307 IF rw > mw THEN mw := rw END;
|
|
|
+ 3308 t := SymTab.NewSet(
|
|
|
+ 3309 SymTab.NewSubR(0,
|
|
|
+ 3310 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3311 QbeGen.CopyOp("@", q)
|
|
|
+ 3312 ELSE
|
|
|
+ 3313 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 3314 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 3315 res2) THEN
|
|
|
+ 3316 lt := t; rt := t2; t := res2
|
|
|
+ 3317 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3318 IF t # SymTab.InvalidType THEN
|
|
|
+ 3319 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3320 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3321 folded := FALSE;
|
|
|
+ 3322 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3323 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3324 IF op = SymTab.OpTimes THEN
|
|
|
+ 3325 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 3326 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 3327 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 3328 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 3329 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 3330 END
|
|
|
+ 3331 END;
|
|
|
+ 3332 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3333 ELSE
|
|
|
+ 3334 QbeGen.CopyOp("@", q)
|
|
|
+ 3335 END
|
|
|
+ 3336 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3337 END
|
|
|
+ 3338 END; .) }
|
|
|
+ 3339 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3340 MulOp<VAR op: INTEGER>
|
|
|
+ 3341 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 3342 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 3343 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 3344 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 3345 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 3346 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3347 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 3348 et, dt, t2, st, ct2, et2:
|
|
|
+ 3349 SymTab.TypeIndex;
|
|
|
+ 3350 dk: INTEGER;
|
|
|
+ 3351 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
+ 3352 QbeGen.QVal;
|
|
|
+ 3353 qn, vn: SymTab.Name;
|
|
|
+ 3354 vt: SymTab.TypeIndex;
|
|
|
+ 3355 c1, c2: INTEGER;
|
|
|
+ 3356 lo, hi: INTEGER;
|
|
|
+ 3357 isMax: BOOLEAN;
|
|
|
+ 3358 called, isHigh, sfx, isCh,
|
|
|
+ 3359 isU, uok, isStr: BOOLEAN;
|
|
|
+ 3360 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
+ 3361 astD: AST.Node;
|
|
|
+ 3362 astCall: BOOLEAN;
|
|
|
+ 3363 astNode, astNot: AST.Node;
|
|
|
+ 3364 j: CARDINAL;
|
|
|
+ 3365 astArg2: AST.Node;
|
|
|
+ 3366 astBrace: AST.Node;
|
|
|
+ 3367 astRes: AST.Node; mname: SymTab.Name; isM: BOOLEAN;
|
|
|
+ 3368 isConvF: BOOLEAN;
|
|
|
+ 3369 fi, fj: CARDINAL; .)
|
|
|
+ 3370 = (. astIsLit := FALSE; .)
|
|
|
+ 3371 ( "__LINE__" (. QbeGen.IntStr(M2S.line, q);
|
|
|
+ 3372 astIsLit := TRUE;
|
|
|
+ 3373 astCur := AST.MakeLeaf(
|
|
|
+ 3374 AST.NkIntLit, q);
|
|
|
+ 3375 t := SymTab.IntType(); .)
|
|
|
+ 3376 | "__FILE__" (. (* fold to the quoted file name *)
|
|
|
+ 3377 s[0] := '"'; fi := 1; fj := 0;
|
|
|
+ 3378 WHILE (M2S.fileName[fj] # CHR(0))
|
|
|
+ 3379 AND (fi < HIGH(s)) DO
|
|
|
+ 3380 s[fi] := M2S.fileName[fj];
|
|
|
+ 3381 INC(fi); INC(fj)
|
|
|
+ 3382 END;
|
|
|
+ 3383 s[fi] := '"';
|
|
|
+ 3384 s[fi + 1] := CHR(0);
|
|
|
+ 3385 astIsLit := TRUE;
|
|
|
+ 3386 astCur := AST.MakeLeaf(
|
|
|
+ 3387 AST.NkStrLit, s);
|
|
|
+ 3388 t := SymTab.NewStr();
|
|
|
+ 3389 QbeGen.DeclStr(s, q); .)
|
|
|
+ 3390 | integer (. LexString(s);
|
|
|
+ 3391 QbeGen.NormInt(s, q); astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s);
|
|
|
+ 3392 t := SymTab.IntType(); .)
|
|
|
+ 3393 | charConst (. LexString(s);
|
|
|
+ 3394 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 3395 astIsLit := TRUE;
|
|
|
+ 3396 astCur := AST.MakeLeaf(
|
|
|
+ 3397 AST.NkCharLit, s);
|
|
|
+ 3398 t := SymTab.CharType(); .)
|
|
|
+ 3399 | real (. LexString(s);
|
|
|
+ 3400 QbeGen.NormReal(s, q);
|
|
|
+ 3401 astIsLit := TRUE;
|
|
|
+ 3402 astCur := AST.MakeLeaf(
|
|
|
+ 3403 AST.NkRealLit, s);
|
|
|
+ 3404 t := SymTab.RealType(); .)
|
|
|
+ 3405 | string (. LexString(s);
|
|
|
+ 3406 astIsLit := TRUE;
|
|
|
+ 3407 astCur := AST.MakeLeaf(
|
|
|
+ 3408 AST.NkStrLit, s);
|
|
|
+ 3409 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3410 t := SymTab.CharType();
|
|
|
+ 3411 QbeGen.IntStr(
|
|
|
+ 3412 QbeGen.CharVal(s), q)
|
|
|
+ 3413 ELSE t := SymTab.NewStr();
|
|
|
+ 3414 QbeGen.DeclStr(s, q);
|
|
|
+ 3415 (* a literal's value IS its
|
|
|
+ 3416 static descriptor address *)
|
|
|
+ 3417 END; .)
|
|
|
+ 3418 | ustring (. LexString(s);
|
|
|
+ 3419 astIsLit := TRUE;
|
|
|
+ 3420 astCur := AST.MakeLeaf(
|
|
|
+ 3421 AST.NkStrLit, s);
|
|
|
+ 3422 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
+ 3423 uok);
|
|
|
+ 3424 IF NOT uok THEN
|
|
|
+ 3425 SemError(234);
|
|
|
+ 3426 t := SymTab.InvalidType
|
|
|
+ 3427 ELSIF isU THEN
|
|
|
+ 3428 t := SymTab.UCharType();
|
|
|
+ 3429 QbeGen.IntStr(ucp, q)
|
|
|
+ 3430 ELSE
|
|
|
+ 3431 t := SymTab.NewUStr();
|
|
|
+ 3432 END; .)
|
|
|
+ 3433 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
+ 3434 astNArgs := 0; called := FALSE;
|
|
|
+ 3435 t := dt;
|
|
|
+ 3436 IF dk = SymTab.KindConst THEN
|
|
|
+ 3437 QbeGen.CopyOp(qd, q)
|
|
|
+ 3438 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3439 END; .)
|
|
|
+ 3440 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
+ 3441 astBrace := astCur; .) ]
|
|
|
+ 3442 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3443 (. astCall := TRUE;
|
|
|
+ 3444 IF (SymTab.SymKind(qn) = SymTab.KindType)
|
|
|
+ 3445 OR (SymTab.SymKind(qn) = SymTab.KindPredef) THEN
|
|
|
+ 3446 (* T(x): emit as the VAL builtin so Lower's
|
|
|
+ 3447 conversion rules apply unchanged *)
|
|
|
+ 3448 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3449 AST.SetChild(astNode, 0,
|
|
|
+ 3450 AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3451 AST.SetChild(astNode, 1,
|
|
|
+ 3452 AST.MakeLeaf(AST.NkIdent, qn));
|
|
|
+ 3453 IF astNArgs = 1 THEN
|
|
|
+ 3454 AST.SetChild(astNode, 2, astArgs[0])
|
|
|
+ 3455 END;
|
|
|
+ 3456 isConvF := TRUE
|
|
|
+ 3457 ELSE astNode := AstCallNode(astD)
|
|
|
+ 3458 END;
|
|
|
+ 3459 astRes := astNode;
|
|
|
+ 3460 t := ct2;
|
|
|
+ 3461 QbeGen.CopyOp(q2, q);
|
|
|
+ 3462 IF isConvF AND QbeGen.IsImm(convQ)
|
|
|
+ 3463 AND OrdClass(convT) AND OrdClass(ct2) THEN
|
|
|
+ 3464 QbeGen.CopyOp(convQ, q)
|
|
|
+ 3465 END;
|
|
|
+ 3466 sfx := FALSE; .)
|
|
|
+ 3467 { ResultComp<t, q, sfx, astRes, mname, methCls, isM>
|
|
|
+ 3468 [ (. astNArgs := 0; .)
|
|
|
+ 3469 ArgList<mname, t, q, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3470 (. astNode := AstCallNode(astRes);
|
|
|
+ 3471 astRes := astNode;
|
|
|
+ 3472 t := ct2;
|
|
|
+ 3473 QbeGen.CopyOp(q2, q);
|
|
|
+ 3474 sfx := FALSE; .) ] }
|
|
|
+ 3475 (. IF sfx THEN
|
|
|
+ 3476 IF t = SymTab.InvalidType THEN
|
|
|
+ 3477 QbeGen.CopyOp("0", q)
|
|
|
+ 3478 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3479 SymTab.ClRecord)
|
|
|
+ 3480 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
+ 3481 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
+ 3482 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3483 QbeGen.CopyOp("@", q)
|
|
|
+ 3484 END
|
|
|
+ 3485 END; .) ]
|
|
|
+ 3486 (. IF called THEN
|
|
|
+ 3487 astCur := astRes
|
|
|
+ 3488 ELSIF astCall THEN
|
|
|
+ 3489 astCur := astBrace
|
|
|
+ 3490 ELSE astCur := astD
|
|
|
+ 3491 END;
|
|
|
+ 3492 astIsLit := TRUE;
|
|
|
+ 3493 IF NOT called
|
|
|
+ 3494 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 3495 (* bare zero-arg function
|
|
|
+ 3496 call (parentheses may be
|
|
|
+ 3497 omitted); a proper or
|
|
|
+ 3498 parameterised proc here
|
|
|
+ 3499 is 230 *)
|
|
|
+ 3500 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 3501 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
+ 3502 t := SymTab.ProcRes(qn);
|
|
|
+ 3503 QbeGen.CopyOp("@", q);
|
|
|
+ 3504 astCur := AST.MakeNode(AST.NkCall);
|
|
|
+ 3505 AST.SetChild(astCur, 0, astD)
|
|
|
+ 3506 ELSE
|
|
|
+ 3507 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 3508 QbeGen.CopyOp("@", q)
|
|
|
+ 3509 END
|
|
|
+ 3510 END; .)
|
|
|
+ 3511 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 3512 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 3513 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ 3514 isU := FALSE; .)
|
|
|
+ 3515 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3516 isStr := TRUE;
|
|
|
+ 3517 isU := FALSE;
|
|
|
+ 3518 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3519 dt := SymTab.CharType();
|
|
|
+ 3520 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
+ 3521 qd)
|
|
|
+ 3522 ELSE
|
|
|
+ 3523 dt := SymTab.NewStr();
|
|
|
+ 3524 QbeGen.DeclStr(s, qd);
|
|
|
+ 3525 END;
|
|
|
+ 3526 dk := -1;
|
|
|
+ 3527 qn[0] := CHR(0); .)
|
|
|
+ 3528 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3529 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ 3530 uok);
|
|
|
+ 3531 isStr := FALSE;
|
|
|
+ 3532 IF NOT uok THEN
|
|
|
+ 3533 SemError(234);
|
|
|
+ 3534 dt := SymTab.InvalidType
|
|
|
+ 3535 ELSIF isU THEN
|
|
|
+ 3536 (* one codepoint: a UCHAR;
|
|
|
+ 3537 LEN is 1, HIGH is 0 *)
|
|
|
+ 3538 dt := SymTab.UCharType();
|
|
|
+ 3539 QbeGen.IntStr(ucp, qd)
|
|
|
+ 3540 ELSE
|
|
|
+ 3541 dt := SymTab.NewUStr();
|
|
|
+ 3542 END;
|
|
|
+ 3543 dk := -1;
|
|
|
+ 3544 qn[0] := CHR(0); .) )
|
|
|
+ 3545 ")"
|
|
|
+ 3546 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3547 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
+ 3548 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
+ 3549 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3550 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
+ 3551 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3552 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3553 IF (dt # SymTab.InvalidType)
|
|
|
+ 3554 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ 3555 (* UString: the count is
|
|
|
+ 3556 the descriptor header *)
|
|
|
+ 3557 t := SymTab.IntType();
|
|
|
+ 3558 QbeGen.CopyOp("@", q)
|
|
|
+ 3559 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 3560 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ 3561 (* single UCHAR codepoint *)
|
|
|
+ 3562 IF isHigh THEN
|
|
|
+ 3563 QbeGen.CopyOp("0", qr)
|
|
|
+ 3564 ELSE
|
|
|
+ 3565 QbeGen.CopyOp("1", qr)
|
|
|
+ 3566 END;
|
|
|
+ 3567 t := SymTab.IntType();
|
|
|
+ 3568 QbeGen.CopyOp(qr, q)
|
|
|
+ 3569 ELSIF isStr THEN
|
|
|
+ 3570 (* fold: content length at
|
|
|
+ 3571 compile time *)
|
|
|
+ 3572 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3573 c1 := 1
|
|
|
+ 3574 ELSE
|
|
|
+ 3575 c1 :=
|
|
|
+ 3576 SymTab.StrLen(s) - 2
|
|
|
+ 3577 END;
|
|
|
+ 3578 IF isHigh THEN
|
|
|
+ 3579 DEC(c1)
|
|
|
+ 3580 END;
|
|
|
+ 3581 QbeGen.IntStr(c1, qr);
|
|
|
+ 3582 t := SymTab.IntType();
|
|
|
+ 3583 QbeGen.CopyOp(qr, q)
|
|
|
+ 3584 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 3585 t := SymTab.InvalidType;
|
|
|
+ 3586 QbeGen.CopyOp("0", q)
|
|
|
+ 3587 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 3588 SymTab.ClArray THEN
|
|
|
+ 3589 SemError(217);
|
|
|
+ 3590 t := SymTab.InvalidType;
|
|
|
+ 3591 QbeGen.CopyOp("0", q)
|
|
|
+ 3592 ELSE
|
|
|
+ 3593 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 3594 t := SymTab.IntType();
|
|
|
+ 3595 QbeGen.CopyOp("@", q)
|
|
|
+ 3596 ELSE
|
|
|
+ 3597 IF isHigh THEN
|
|
|
+ 3598 QbeGen.IntStr(
|
|
|
+ 3599 SymTab.ArrayHi(dt), qr)
|
|
|
+ 3600 ELSE
|
|
|
+ 3601 QbeGen.IntStr(VAL(
|
|
|
+ 3602 INTEGER,
|
|
|
+ 3603 SymTab.ArrayLen(dt)),
|
|
|
+ 3604 qr)
|
|
|
+ 3605 END;
|
|
|
+ 3606 t := SymTab.IntType();
|
|
|
+ 3607 QbeGen.CopyOp(qr, q)
|
|
|
+ 3608 END
|
|
|
+ 3609 END; .)
|
|
|
+ 3610 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3611 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3612 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
+ 3613 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3614 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3615 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3616 t := SymTab.InvalidType;
|
|
|
+ 3617 QbeGen.CopyOp("0", q)
|
|
|
+ 3618 ELSE
|
|
|
+ 3619 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 3620 SymTab.ObjectSize(dt)), q);
|
|
|
+ 3621 t := SymTab.IntType()
|
|
|
+ 3622 END; .)
|
|
|
+ 3623 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
+ 3624 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
+ 3625 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
+ 3626 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3627 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3628 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
+ 3629 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3630 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
+ 3631 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3632 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3633 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3634 (* set shift/rotate: isMax
|
|
|
+ 3635 doubles as "rotate" *)
|
|
|
+ 3636 IF (et # SymTab.InvalidType)
|
|
|
+ 3637 AND (SymTab.ClassOf(et) =
|
|
|
+ 3638 SymTab.ClSet) THEN
|
|
|
+ 3639 t := et;
|
|
|
+ 3640 QbeGen.CopyOp("@", q)
|
|
|
+ 3641 ELSE SemError(230);
|
|
|
+ 3642 t := SymTab.InvalidType;
|
|
|
+ 3643 QbeGen.CopyOp("0", q)
|
|
|
+ 3644 END; .)
|
|
|
+ 3645 | ( "MIN" (. isMax := FALSE; .)
|
|
|
+ 3646 | "MAX" (. isMax := TRUE; .) )
|
|
|
+ 3647 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3648 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3649 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3650 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
+ 3651 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3652 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
+ 3653 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3654 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3655 IF (dt # SymTab.InvalidType)
|
|
|
+ 3656 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
+ 3657 (* REAL/LONGREAL: the
|
|
|
+ 3658 implementation bounds *)
|
|
|
+ 3659 IF isMax THEN
|
|
|
+ 3660 QbeGen.NormReal(
|
|
|
+ 3661 "3.402823e38", q)
|
|
|
+ 3662 ELSE QbeGen.NormReal(
|
|
|
+ 3663 "-3.402823e38", q)
|
|
|
+ 3664 END;
|
|
|
+ 3665 t := SymTab.RealType()
|
|
|
+ 3666 ELSIF (dt #
|
|
|
+ 3667 SymTab.InvalidType)
|
|
|
+ 3668 AND (SymTab.ClassOf(dt) =
|
|
|
+ 3669 SymTab.ClLong) THEN
|
|
|
+ 3670 IF isMax THEN
|
|
|
+ 3671 QbeGen.CopyOp(
|
|
|
+ 3672 "9223372036854775807", q)
|
|
|
+ 3673 ELSE QbeGen.CopyOp(
|
|
|
+ 3674 "-9223372036854775808", q)
|
|
|
+ 3675 END;
|
|
|
+ 3676 t := SymTab.LongType()
|
|
|
+ 3677 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
+ 3678 hi) THEN
|
|
|
+ 3679 IF isMax THEN
|
|
|
+ 3680 QbeGen.IntStr(hi, q)
|
|
|
+ 3681 ELSE QbeGen.IntStr(lo, q)
|
|
|
+ 3682 END;
|
|
|
+ 3683 t := SymTab.IntType()
|
|
|
+ 3684 ELSE SemError(230);
|
|
|
+ 3685 t := SymTab.InvalidType;
|
|
|
+ 3686 QbeGen.CopyOp("0", q)
|
|
|
+ 3687 END; .)
|
|
|
+ 3688 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3689 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3690 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
+ 3691 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3692 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3693 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3694 t := SymTab.InvalidType;
|
|
|
+ 3695 QbeGen.CopyOp("0", q)
|
|
|
+ 3696 ELSE
|
|
|
+ 3697 IF sfx
|
|
|
+ 3698 OR (dk = SymTab.KindVar)
|
|
|
+ 3699 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 3700 QbeGen.CopyOp("@", q)
|
|
|
+ 3701 ELSE SemError(230);
|
|
|
+ 3702 QbeGen.CopyOp("0", q)
|
|
|
+ 3703 END;
|
|
|
+ 3704 t := SymTab.AddrType()
|
|
|
+ 3705 END; .)
|
|
|
+ 3706 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 3707 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3708 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
+ 3709 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3710 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3711 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3712 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3713 SemError(211) END;
|
|
|
+ 3714 t := SymTab.CharType(); .)
|
|
|
+ 3715 | "ORD" "(" Expr<et, q> ")"
|
|
|
+ 3716 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3717 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
+ 3718 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3719 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3720 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 3721 IF (SymTab.ClassOf(et) #
|
|
|
+ 3722 SymTab.ClChar)
|
|
|
+ 3723 AND (SymTab.ClassOf(et) #
|
|
|
+ 3724 SymTab.ClBool)
|
|
|
+ 3725 AND (SymTab.ClassOf(et) #
|
|
|
+ 3726 SymTab.ClEnum)
|
|
|
+ 3727 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3728 SemError(211) END
|
|
|
+ 3729 END;
|
|
|
+ 3730 t := SymTab.IntType(); .)
|
|
|
+ 3731 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 3732 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3733 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
+ 3734 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3735 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3736 (. IF QbeGen.IsImm(q)
|
|
|
+ 3737 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3738 IF (lo >= VAL(INTEGER, ORD("a"))) AND (lo <= VAL(INTEGER, ORD("z"))) THEN lo := lo - 32 END;
|
|
|
+ 3739 QbeGen.IntStr(lo, q)
|
|
|
+ 3740 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3741 END;
|
|
|
+ 3742 t := SymTab.CharType(); .)
|
|
|
+ 3743 | "UCHR" "(" Expr<et, q> ")"
|
|
|
+ 3744 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3745 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
+ 3746 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3747 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3748 (. (* UCHR: the UCHAR constructor.
|
|
|
+ 3749 CHAR -> UCHAR (identity);
|
|
|
+ 3750 INTEGER familly -> UCHAR
|
|
|
+ 3751 (codepoint value). *)
|
|
|
+ 3752 IF (et # SymTab.InvalidType)
|
|
|
+ 3753 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
+ 3754 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3755 SemError(211) END;
|
|
|
+ 3756 t := SymTab.UCharType(); .)
|
|
|
+ 3757 | "CHR8" "(" Expr<et, q> ")"
|
|
|
+ 3758 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3759 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
+ 3760 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3761 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3762 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3763 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3764 SemError(211) END;
|
|
|
+ 3765 t := SymTab.CharType(); .)
|
|
|
+ 3766 | "UORD" "(" Expr<et, q> ")"
|
|
|
+ 3767 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3768 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
+ 3769 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3770 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3771 (. (* UORD(u): the codepoint as a
|
|
|
+ 3772 32-bit ordinal (INTEGER),
|
|
|
+ 3773 cf. ORD for CHAR. *)
|
|
|
+ 3774 IF (et # SymTab.InvalidType)
|
|
|
+ 3775 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3776 SemError(211) END;
|
|
|
+ 3777 t := SymTab.IntType(); .)
|
|
|
+ 3778 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 3779 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3780 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
+ 3781 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3782 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3783 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3784 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 3785 AND (SymTab.ClassOf(et) #
|
|
|
+ 3786 SymTab.ClReal) THEN
|
|
|
+ 3787 SemError(211)
|
|
|
+ 3788 ELSIF QbeGen.IsImm(q)
|
|
|
+ 3789 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3790 IF lo < 0 THEN lo := -lo END;
|
|
|
+ 3791 QbeGen.IntStr(lo, q)
|
|
|
+ 3792 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3793 END;
|
|
|
+ 3794 t := et; .)
|
|
|
+ 3795 | "ODD" "(" Expr<et, q> ")"
|
|
|
+ 3796 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3797 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ODD"));
|
|
|
+ 3798 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
3799 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3800 (. t := SymTab.IntType();
|
|
|
- 3801 QbeGen.CopyOp("@", q); .)
|
|
|
- 3802 | "FLOAT" "(" Expr<et, q> ")"
|
|
|
- 3803 (. (* FLOAT(i): integer -> REAL, as the VAL builtin *)
|
|
|
- 3804 astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3805 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3806 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "REAL"));
|
|
|
- 3807 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3808 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3809 (. t := SymTab.RealType();
|
|
|
- 3810 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa); QbeGen.CopyOp(qa, q)
|
|
|
- 3811 ELSE QbeGen.CopyOp("@", q) END; .)
|
|
|
- 3812 | ( "VAL" | "CONVERT" | "CAST" ) "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
- 3813 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3814 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3815 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3816 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3817 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3818 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 3819 SemError(201);
|
|
|
- 3820 t := SymTab.InvalidType
|
|
|
- 3821 ELSE vt := SymTab.SymType(vn);
|
|
|
- 3822 IF vt = SymTab.InvalidType THEN
|
|
|
- 3823 t := SymTab.InvalidType
|
|
|
- 3824 ELSIF et =
|
|
|
- 3825 SymTab.InvalidType THEN
|
|
|
- 3826 t := vt
|
|
|
- 3827 ELSE
|
|
|
- 3828 c1 := SymTab.ClassOf(et);
|
|
|
- 3829 c2 := SymTab.ClassOf(vt);
|
|
|
- 3830 IF (c1 = SymTab.ClInt)
|
|
|
- 3831 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3832 IF NOT QbeGen.IsImm(q) THEN QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
- 3833 t := vt
|
|
|
- 3834 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3835 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3836 IF NOT (QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo)) THEN QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
- 3837 t := vt
|
|
|
- 3838 ELSIF (c1 = SymTab.ClInt)
|
|
|
- 3839 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3840 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvIR(q, qa) END;
|
|
|
- 3841 QbeGen.CopyOp(qa, q);
|
|
|
- 3842 t := vt
|
|
|
- 3843 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3844 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3845 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvLR(q, qa) END;
|
|
|
- 3846 QbeGen.CopyOp(qa, q);
|
|
|
- 3847 t := vt
|
|
|
- 3848 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3849 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3850 QbeGen.ConvRI(q, qa);
|
|
|
- 3851 QbeGen.CopyOp(qa, q);
|
|
|
+ 3800 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3801 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3802 SemError(211) END;
|
|
|
+ 3803 t := SymTab.BoolType();
|
|
|
+ 3804 IF QbeGen.IsImm(q)
|
|
|
+ 3805 AND SymTab.ConstInt(q, lo) THEN
|
|
|
+ 3806 IF (lo MOD 2) # 0 THEN
|
|
|
+ 3807 QbeGen.CopyOp("1", q)
|
|
|
+ 3808 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3809 END
|
|
|
+ 3810 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 3811 END; .)
|
|
|
+ 3812 | "TRUNC" "(" Expr<et, q> ")"
|
|
|
+ 3813 (. (* TRUNC(x): real -> INTEGER, as the VAL builtin *)
|
|
|
+ 3814 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3815 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3816 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "INTEGER"));
|
|
|
+ 3817 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3818 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3819 (. t := SymTab.IntType();
|
|
|
+ 3820 QbeGen.CopyOp("@", q); .)
|
|
|
+ 3821 | "FLOAT" "(" Expr<et, q> ")"
|
|
|
+ 3822 (. (* FLOAT(i): integer -> REAL, as the VAL builtin *)
|
|
|
+ 3823 astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3824 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3825 AST.SetChild(astNode, 1, AST.MakeLeaf(AST.NkIdent, "REAL"));
|
|
|
+ 3826 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3827 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3828 (. t := SymTab.RealType();
|
|
|
+ 3829 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa); QbeGen.CopyOp(qa, q)
|
|
|
+ 3830 ELSE QbeGen.CopyOp("@", q) END; .)
|
|
|
+ 3831 | ( "VAL" | "CONVERT" | "CAST" ) "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
+ 3832 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3833 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3834 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3835 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3836 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3837 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 3838 SemError(201);
|
|
|
+ 3839 t := SymTab.InvalidType
|
|
|
+ 3840 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 3841 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3842 t := SymTab.InvalidType
|
|
|
+ 3843 ELSIF et =
|
|
|
+ 3844 SymTab.InvalidType THEN
|
|
|
+ 3845 t := vt
|
|
|
+ 3846 ELSE
|
|
|
+ 3847 c1 := SymTab.ClassOf(et);
|
|
|
+ 3848 c2 := SymTab.ClassOf(vt);
|
|
|
+ 3849 IF (c1 = SymTab.ClInt)
|
|
|
+ 3850 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3851 IF NOT QbeGen.IsImm(q) THEN QbeGen.WidenLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
3852 t := vt
|
|
|
- 3853 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3854 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3855 QbeGen.ConvRL(q, qa);
|
|
|
- 3856 QbeGen.CopyOp(qa, q);
|
|
|
- 3857 t := vt
|
|
|
- 3858 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3859 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3860 t := vt
|
|
|
- 3861 ELSIF ((c1 = SymTab.ClInt)
|
|
|
- 3862 OR (c1 =
|
|
|
- 3863 SymTab.ClChar)
|
|
|
- 3864 OR (c1 =
|
|
|
- 3865 SymTab.ClBool)
|
|
|
- 3866 OR (c1 =
|
|
|
- 3867 SymTab.ClEnum))
|
|
|
- 3868 AND ((c2 = SymTab.ClInt)
|
|
|
- 3869 OR (c2 =
|
|
|
- 3870 SymTab.ClChar)
|
|
|
- 3871 OR (c2 =
|
|
|
- 3872 SymTab.ClBool)
|
|
|
- 3873 OR (c2 =
|
|
|
- 3874 SymTab.ClEnum)) THEN
|
|
|
- 3875 t := vt
|
|
|
- 3876 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 3877 AND (c2 = SymTab.ClPtr) THEN
|
|
|
- 3878 t := vt
|
|
|
- 3879 ELSIF ((c1 = SymTab.ClProc)
|
|
|
- 3880 AND (c2 = SymTab.ClProc))
|
|
|
- 3881 OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))
|
|
|
- 3882 OR ((c1 = SymTab.ClPtr) AND (c2 = SymTab.ClProc)) THEN
|
|
|
- 3883 t := vt
|
|
|
- 3884 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3885 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3886 t := vt
|
|
|
- 3887 ELSIF ((c1 = SymTab.ClSet) AND (c2 = SymTab.ClInt))
|
|
|
- 3888 OR ((c1 = SymTab.ClInt) AND (c2 = SymTab.ClSet)) THEN
|
|
|
- 3889 (* a set <-> its machine word (BITSET) *)
|
|
|
- 3890 t := vt
|
|
|
- 3891 ELSE SemError(230);
|
|
|
- 3892 t := SymTab.InvalidType
|
|
|
- 3893 END
|
|
|
- 3894 END
|
|
|
- 3895 END; .)
|
|
|
- 3896 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
- 3897 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
- 3898 QbeGen.CopyOp(sq, q); .)
|
|
|
- 3899 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
- 3900 IF SymTab.BoolCheck(t2) THEN
|
|
|
- 3901 t := SymTab.BoolType()
|
|
|
- 3902 ELSE SemError(212);
|
|
|
- 3903 t := SymTab.InvalidType END;
|
|
|
- 3904 IF t # SymTab.InvalidType THEN
|
|
|
- 3905 QbeGen.CopyOp("@", q)
|
|
|
- 3906 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3907 END;
|
|
|
- 3908 astIsLit := TRUE;
|
|
|
- 3909 astCur := AST.MakeUn(
|
|
|
- 3910 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
- 3911 )
|
|
|
- 3912 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
- 3913 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
- 3914 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 3915 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 3916 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 3917 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3918 (. VAR astNode: AST.Node; .)
|
|
|
- 3919 = "{" (. t := SymTab.NewSet(
|
|
|
- 3920 SymTab.NewSubR(0, 255));
|
|
|
- 3921 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
- 3922 QbeGen.NewSetTemp(8, q);
|
|
|
- 3923 QbeGen.SetZero(q, 8); .)
|
|
|
- 3924 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
- 3925 "}" (. astCur := astNode; .) .
|
|
|
- 3926 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
- 3927 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
- 3928 declared type sets the width (set) or element type (array). *)
|
|
|
- 3929 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3930 (. VAR nw: CARDINAL;
|
|
|
- 3931 astNode, astTail: AST.Node;
|
|
|
- 3932 savedCls: INTEGER; .)
|
|
|
- 3933 = "{" (. savedCls := braceCls;
|
|
|
- 3934 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
- 3935 AST.SetTy(astNode, vt);
|
|
|
- 3936 astTail := astNode;
|
|
|
- 3937 IF vt = SymTab.InvalidType THEN
|
|
|
- 3938 braceCls := -1
|
|
|
- 3939 ELSE braceCls :=
|
|
|
- 3940 SymTab.ClassOf(vt)
|
|
|
- 3941 END;
|
|
|
- 3942 IF braceCls = SymTab.ClSet THEN
|
|
|
- 3943 IF vt = SymTab.InvalidType THEN
|
|
|
- 3944 nw := 8
|
|
|
- 3945 ELSE nw := SymTab.SetWords(vt);
|
|
|
- 3946 IF nw = 0 THEN nw := 8 END
|
|
|
- 3947 END;
|
|
|
- 3948 QbeGen.NewSetTemp(nw, q);
|
|
|
- 3949 QbeGen.SetZero(q, nw)
|
|
|
- 3950 ELSIF (braceCls =
|
|
|
- 3951 SymTab.ClArray)
|
|
|
- 3952 OR (braceCls =
|
|
|
- 3953 SymTab.ClRecord)
|
|
|
- 3954 OR (braceCls =
|
|
|
- 3955 SymTab.ClClass) THEN
|
|
|
- 3956 QbeGen.CtorBegin(vt)
|
|
|
- 3957 ELSE
|
|
|
- 3958 IF vt # SymTab.InvalidType THEN
|
|
|
- 3959 SemError(230) END;
|
|
|
- 3960 braceCls := -1
|
|
|
- 3961 END; .)
|
|
|
- 3962 [ BraceElem<vt, q, astNode, astTail>
|
|
|
- 3963 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
- 3964 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
- 3965 OR (braceCls =
|
|
|
- 3966 SymTab.ClRecord)
|
|
|
- 3967 OR (braceCls =
|
|
|
- 3968 SymTab.ClClass) THEN
|
|
|
- 3969 QbeGen.CtorEnd(q)
|
|
|
- 3970 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
- 3971 QbeGen.CopyOp("0", q)
|
|
|
- 3972 END;
|
|
|
- 3973 braceCls := savedCls; .)
|
|
|
- 3974 (. astCur := astNode; .) .
|
|
|
- 3975 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
- 3976 VAR node, tail: AST.Node>
|
|
|
- 3977 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3978 qe, q2: QbeGen.QVal;
|
|
|
- 3979 v, v2, reps, k: INTEGER;
|
|
|
- 3980 elem: SymTab.TypeIndex;
|
|
|
- 3981 lo: INTEGER;
|
|
|
- 3982 span: CARDINAL;
|
|
|
- 3983 cl, cl2: INTEGER;
|
|
|
- 3984 hasR, hasB: BOOLEAN;
|
|
|
- 3985 astEl: AST.Node; .)
|
|
|
- 3986 = (. hasR := FALSE; hasB := FALSE;
|
|
|
- 3987 reps := 1; .)
|
|
|
- 3988 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3989 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3990 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3991 hasR := TRUE; .) ]
|
|
|
- 3992 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
- 3993 (. IF braceCls = SymTab.ClSet THEN
|
|
|
- 3994 IF hasB THEN SemError(230) END;
|
|
|
- 3995 lo := SymTab.SetBaseLo(vt);
|
|
|
- 3996 span := SymTab.SetCount(vt);
|
|
|
- 3997 IF (et = SymTab.InvalidType)
|
|
|
- 3998 OR (hasR AND (et2 =
|
|
|
- 3999 SymTab.InvalidType)) THEN
|
|
|
- 4000 ELSE cl :=
|
|
|
- 4001 SymTab.ClassOf(et);
|
|
|
- 4002 IF hasR THEN
|
|
|
- 4003 cl2 :=
|
|
|
- 4004 SymTab.ClassOf(et2)
|
|
|
- 4005 ELSE cl2 := SymTab.ClInt
|
|
|
- 4006 END;
|
|
|
- 4007 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 4008 OR (hasR AND NOT
|
|
|
- 4009 SymTab.SetElemClassOk(cl2))
|
|
|
- 4010 THEN
|
|
|
- 4011 SemError(222)
|
|
|
- 4012 ELSIF hasR
|
|
|
- 4013 AND SymTab.ConstInt(qe, v)
|
|
|
- 4014 AND SymTab.ConstInt(q2,
|
|
|
- 4015 v2)
|
|
|
- 4016 AND ((v < lo)
|
|
|
- 4017 OR (v2 < lo)
|
|
|
- 4018 OR (v >= lo +
|
|
|
- 4019 VAL(INTEGER, span))
|
|
|
- 4020 OR (v2 >= lo +
|
|
|
- 4021 VAL(INTEGER, span))
|
|
|
- 4022 OR (v > v2)) THEN
|
|
|
- 4023 SemError(222)
|
|
|
- 4024 ELSIF hasR THEN
|
|
|
- 4025 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 4026 lo, span)
|
|
|
- 4027 ELSIF SymTab.ConstInt(qe,
|
|
|
- 4028 v)
|
|
|
- 4029 AND ((v < lo)
|
|
|
- 4030 OR (v >= lo +
|
|
|
- 4031 VAL(INTEGER,
|
|
|
- 4032 span))) THEN
|
|
|
- 4033 SemError(222)
|
|
|
- 4034 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 4035 lo, span)
|
|
|
- 4036 END
|
|
|
- 4037 END
|
|
|
- 4038 ELSIF (braceCls = SymTab.ClArray)
|
|
|
- 4039 OR (braceCls =
|
|
|
- 4040 SymTab.ClRecord)
|
|
|
- 4041 OR (braceCls =
|
|
|
- 4042 SymTab.ClClass) THEN
|
|
|
- 4043 IF hasR THEN SemError(230) END;
|
|
|
- 4044 reps := 1;
|
|
|
- 4045 IF hasB THEN
|
|
|
- 4046 IF SymTab.ConstInt(q2, v2)
|
|
|
- 4047 AND (v2 >= 1) THEN
|
|
|
- 4048 reps := v2
|
|
|
- 4049 ELSE SemError(230)
|
|
|
- 4050 END
|
|
|
- 4051 END;
|
|
|
- 4052 k := 0;
|
|
|
- 4053 WHILE k < reps DO
|
|
|
- 4054 QbeGen.CtorElem(qe);
|
|
|
- 4055 INC(k)
|
|
|
+ 3853 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3854 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3855 IF NOT (QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo)) THEN QbeGen.NarrowLong(q, qa); QbeGen.CopyOp(qa, q) END;
|
|
|
+ 3856 t := vt
|
|
|
+ 3857 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 3858 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3859 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvIR(q, qa) END;
|
|
|
+ 3860 QbeGen.CopyOp(qa, q);
|
|
|
+ 3861 t := vt
|
|
|
+ 3862 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3863 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3864 IF QbeGen.IsImm(q) AND SymTab.ConstInt(q, lo) THEN QbeGen.NormReal(q, qa) ELSE QbeGen.ConvLR(q, qa) END;
|
|
|
+ 3865 QbeGen.CopyOp(qa, q);
|
|
|
+ 3866 t := vt
|
|
|
+ 3867 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3868 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3869 QbeGen.ConvRI(q, qa);
|
|
|
+ 3870 QbeGen.CopyOp(qa, q);
|
|
|
+ 3871 t := vt
|
|
|
+ 3872 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3873 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3874 QbeGen.ConvRL(q, qa);
|
|
|
+ 3875 QbeGen.CopyOp(qa, q);
|
|
|
+ 3876 t := vt
|
|
|
+ 3877 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3878 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3879 t := vt
|
|
|
+ 3880 ELSIF ((c1 = SymTab.ClInt)
|
|
|
+ 3881 OR (c1 =
|
|
|
+ 3882 SymTab.ClChar)
|
|
|
+ 3883 OR (c1 =
|
|
|
+ 3884 SymTab.ClBool)
|
|
|
+ 3885 OR (c1 =
|
|
|
+ 3886 SymTab.ClEnum))
|
|
|
+ 3887 AND ((c2 = SymTab.ClInt)
|
|
|
+ 3888 OR (c2 =
|
|
|
+ 3889 SymTab.ClChar)
|
|
|
+ 3890 OR (c2 =
|
|
|
+ 3891 SymTab.ClBool)
|
|
|
+ 3892 OR (c2 =
|
|
|
+ 3893 SymTab.ClEnum)) THEN
|
|
|
+ 3894 t := vt
|
|
|
+ 3895 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 3896 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 3897 t := vt
|
|
|
+ 3898 ELSIF ((c1 = SymTab.ClProc)
|
|
|
+ 3899 AND (c2 = SymTab.ClProc))
|
|
|
+ 3900 OR ((c1 = SymTab.ClProc) AND (c2 = SymTab.ClPtr))
|
|
|
+ 3901 OR ((c1 = SymTab.ClPtr) AND (c2 = SymTab.ClProc)) THEN
|
|
|
+ 3902 t := vt
|
|
|
+ 3903 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3904 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3905 t := vt
|
|
|
+ 3906 ELSIF ((c1 = SymTab.ClSet) AND (c2 = SymTab.ClInt))
|
|
|
+ 3907 OR ((c1 = SymTab.ClInt) AND (c2 = SymTab.ClSet)) THEN
|
|
|
+ 3908 (* a set <-> its machine word (BITSET) *)
|
|
|
+ 3909 t := vt
|
|
|
+ 3910 ELSE SemError(230);
|
|
|
+ 3911 t := SymTab.InvalidType
|
|
|
+ 3912 END
|
|
|
+ 3913 END
|
|
|
+ 3914 END; .)
|
|
|
+ 3915 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
+ 3916 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
+ 3917 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 3918 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
+ 3919 IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 3920 t := SymTab.BoolType()
|
|
|
+ 3921 ELSE SemError(212);
|
|
|
+ 3922 t := SymTab.InvalidType END;
|
|
|
+ 3923 IF t # SymTab.InvalidType THEN
|
|
|
+ 3924 QbeGen.CopyOp("@", q)
|
|
|
+ 3925 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3926 END;
|
|
|
+ 3927 astIsLit := TRUE;
|
|
|
+ 3928 astCur := AST.MakeUn(
|
|
|
+ 3929 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
+ 3930 )
|
|
|
+ 3931 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .)
|
|
|
+ 3932 (. IF astCur # AST.NoNode THEN AST.SetTy(astCur, t) END; .) .
|
|
|
+ 3933 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 3934 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 3935 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 3936 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3937 (. VAR astNode: AST.Node; .)
|
|
|
+ 3938 = "{" (. t := SymTab.NewSet(
|
|
|
+ 3939 SymTab.NewSubR(0, 255));
|
|
|
+ 3940 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
+ 3941 QbeGen.NewSetTemp(8, q);
|
|
|
+ 3942 QbeGen.SetZero(q, 8); .)
|
|
|
+ 3943 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
+ 3944 "}" (. astCur := astNode; .) .
|
|
|
+ 3945 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ 3946 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ 3947 declared type sets the width (set) or element type (array). *)
|
|
|
+ 3948 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3949 (. VAR nw: CARDINAL;
|
|
|
+ 3950 astNode, astTail: AST.Node;
|
|
|
+ 3951 savedCls: INTEGER; .)
|
|
|
+ 3952 = "{" (. savedCls := braceCls;
|
|
|
+ 3953 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
+ 3954 AST.SetTy(astNode, vt);
|
|
|
+ 3955 astTail := astNode;
|
|
|
+ 3956 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3957 braceCls := -1
|
|
|
+ 3958 ELSE braceCls :=
|
|
|
+ 3959 SymTab.ClassOf(vt)
|
|
|
+ 3960 END;
|
|
|
+ 3961 IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3962 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3963 nw := 8
|
|
|
+ 3964 ELSE nw := SymTab.SetWords(vt);
|
|
|
+ 3965 IF nw = 0 THEN nw := 8 END
|
|
|
+ 3966 END;
|
|
|
+ 3967 QbeGen.NewSetTemp(nw, q);
|
|
|
+ 3968 QbeGen.SetZero(q, nw)
|
|
|
+ 3969 ELSIF (braceCls =
|
|
|
+ 3970 SymTab.ClArray)
|
|
|
+ 3971 OR (braceCls =
|
|
|
+ 3972 SymTab.ClRecord)
|
|
|
+ 3973 OR (braceCls =
|
|
|
+ 3974 SymTab.ClClass) THEN
|
|
|
+ 3975 QbeGen.CtorBegin(vt)
|
|
|
+ 3976 ELSE
|
|
|
+ 3977 IF vt # SymTab.InvalidType THEN
|
|
|
+ 3978 SemError(230) END;
|
|
|
+ 3979 braceCls := -1
|
|
|
+ 3980 END; .)
|
|
|
+ 3981 [ BraceElem<vt, q, astNode, astTail>
|
|
|
+ 3982 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
+ 3983 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
+ 3984 OR (braceCls =
|
|
|
+ 3985 SymTab.ClRecord)
|
|
|
+ 3986 OR (braceCls =
|
|
|
+ 3987 SymTab.ClClass) THEN
|
|
|
+ 3988 QbeGen.CtorEnd(q)
|
|
|
+ 3989 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ 3990 QbeGen.CopyOp("0", q)
|
|
|
+ 3991 END;
|
|
|
+ 3992 braceCls := savedCls; .)
|
|
|
+ 3993 (. astCur := astNode; .) .
|
|
|
+ 3994 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
+ 3995 VAR node, tail: AST.Node>
|
|
|
+ 3996 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3997 qe, q2: QbeGen.QVal;
|
|
|
+ 3998 v, v2, reps, k: INTEGER;
|
|
|
+ 3999 elem: SymTab.TypeIndex;
|
|
|
+ 4000 lo: INTEGER;
|
|
|
+ 4001 span: CARDINAL;
|
|
|
+ 4002 cl, cl2: INTEGER;
|
|
|
+ 4003 hasR, hasB: BOOLEAN;
|
|
|
+ 4004 astEl: AST.Node; .)
|
|
|
+ 4005 = (. hasR := FALSE; hasB := FALSE;
|
|
|
+ 4006 reps := 1; .)
|
|
|
+ 4007 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 4008 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 4009 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 4010 hasR := TRUE; .) ]
|
|
|
+ 4011 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ 4012 (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ 4013 IF hasB THEN SemError(230) END;
|
|
|
+ 4014 lo := SymTab.SetBaseLo(vt);
|
|
|
+ 4015 span := SymTab.SetCount(vt);
|
|
|
+ 4016 IF (et = SymTab.InvalidType)
|
|
|
+ 4017 OR (hasR AND (et2 =
|
|
|
+ 4018 SymTab.InvalidType)) THEN
|
|
|
+ 4019 ELSE cl :=
|
|
|
+ 4020 SymTab.ClassOf(et);
|
|
|
+ 4021 IF hasR THEN
|
|
|
+ 4022 cl2 :=
|
|
|
+ 4023 SymTab.ClassOf(et2)
|
|
|
+ 4024 ELSE cl2 := SymTab.ClInt
|
|
|
+ 4025 END;
|
|
|
+ 4026 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 4027 OR (hasR AND NOT
|
|
|
+ 4028 SymTab.SetElemClassOk(cl2))
|
|
|
+ 4029 THEN
|
|
|
+ 4030 SemError(222)
|
|
|
+ 4031 ELSIF hasR
|
|
|
+ 4032 AND SymTab.ConstInt(qe, v)
|
|
|
+ 4033 AND SymTab.ConstInt(q2,
|
|
|
+ 4034 v2)
|
|
|
+ 4035 AND ((v < lo)
|
|
|
+ 4036 OR (v2 < lo)
|
|
|
+ 4037 OR (v >= lo +
|
|
|
+ 4038 VAL(INTEGER, span))
|
|
|
+ 4039 OR (v2 >= lo +
|
|
|
+ 4040 VAL(INTEGER, span))
|
|
|
+ 4041 OR (v > v2)) THEN
|
|
|
+ 4042 SemError(222)
|
|
|
+ 4043 ELSIF hasR THEN
|
|
|
+ 4044 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 4045 lo, span)
|
|
|
+ 4046 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 4047 v)
|
|
|
+ 4048 AND ((v < lo)
|
|
|
+ 4049 OR (v >= lo +
|
|
|
+ 4050 VAL(INTEGER,
|
|
|
+ 4051 span))) THEN
|
|
|
+ 4052 SemError(222)
|
|
|
+ 4053 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 4054 lo, span)
|
|
|
+ 4055 END
|
|
|
4056 END
|
|
|
- 4057 END; .)
|
|
|
- 4058 (. (* the BY form repeats the
|
|
|
- 4059 element; keep the AST in
|
|
|
- 4060 step with CtorElem *)
|
|
|
- 4061 k := 0;
|
|
|
- 4062 WHILE k < reps DO
|
|
|
- 4063 AstAppend(AST.NkBlock,
|
|
|
- 4064 node, tail, astEl);
|
|
|
- 4065 INC(k)
|
|
|
- 4066 END; .) .
|
|
|
- 4067 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 4068 qe, q2: QbeGen.QVal;
|
|
|
- 4069 v, v2: INTEGER;
|
|
|
- 4070 lo: INTEGER;
|
|
|
- 4071 span: CARDINAL;
|
|
|
- 4072 cl, cl2: INTEGER;
|
|
|
- 4073 hasR: BOOLEAN;
|
|
|
- 4074 astEl: AST.Node; .)
|
|
|
- 4075 = (. hasR := FALSE; .)
|
|
|
- 4076 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 4077 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 4078 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 4079 hasR := TRUE; .) ]
|
|
|
- 4080 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 4081 span := SymTab.SetCount(st);
|
|
|
- 4082 IF (et = SymTab.InvalidType)
|
|
|
- 4083 OR (hasR AND (et2 =
|
|
|
- 4084 SymTab.InvalidType)) THEN
|
|
|
- 4085 ELSE cl :=
|
|
|
- 4086 SymTab.ClassOf(et);
|
|
|
- 4087 IF hasR THEN
|
|
|
- 4088 cl2 :=
|
|
|
- 4089 SymTab.ClassOf(et2)
|
|
|
- 4090 ELSE cl2 := SymTab.ClInt
|
|
|
- 4091 END;
|
|
|
- 4092 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 4093 OR (hasR AND NOT
|
|
|
- 4094 SymTab.SetElemClassOk(cl2))
|
|
|
- 4095 THEN
|
|
|
- 4096 SemError(222)
|
|
|
- 4097 ELSIF hasR
|
|
|
- 4098 AND SymTab.ConstInt(qe, v)
|
|
|
- 4099 AND SymTab.ConstInt(q2,
|
|
|
- 4100 v2)
|
|
|
- 4101 AND ((v < lo)
|
|
|
- 4102 OR (v2 < lo)
|
|
|
- 4103 OR (v >= lo +
|
|
|
- 4104 VAL(INTEGER, span))
|
|
|
- 4105 OR (v2 >= lo +
|
|
|
- 4106 VAL(INTEGER, span))
|
|
|
- 4107 OR (v > v2)) THEN
|
|
|
- 4108 SemError(222)
|
|
|
- 4109 ELSIF hasR THEN
|
|
|
- 4110 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 4111 lo, span)
|
|
|
- 4112 ELSIF SymTab.ConstInt(qe,
|
|
|
- 4113 v)
|
|
|
- 4114 AND ((v < lo)
|
|
|
- 4115 OR (v >= lo +
|
|
|
- 4116 VAL(INTEGER,
|
|
|
- 4117 span))) THEN
|
|
|
- 4118 SemError(222)
|
|
|
- 4119 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 4120 lo, span)
|
|
|
- 4121 END
|
|
|
- 4122 END; .)
|
|
|
- 4123 (. AST.SetChild(node,
|
|
|
- 4124 AST.NChild(node), astEl); .) .
|
|
|
- 4125 GetIdent<VAR n: SymTab.Name>
|
|
|
- 4126 = ident (. LexName(n); .) .
|
|
|
- 4127
|
|
|
- 4128 END M2.
|
|
|
+ 4057 ELSIF (braceCls = SymTab.ClArray)
|
|
|
+ 4058 OR (braceCls =
|
|
|
+ 4059 SymTab.ClRecord)
|
|
|
+ 4060 OR (braceCls =
|
|
|
+ 4061 SymTab.ClClass) THEN
|
|
|
+ 4062 IF hasR THEN SemError(230) END;
|
|
|
+ 4063 reps := 1;
|
|
|
+ 4064 IF hasB THEN
|
|
|
+ 4065 IF SymTab.ConstInt(q2, v2)
|
|
|
+ 4066 AND (v2 >= 1) THEN
|
|
|
+ 4067 reps := v2
|
|
|
+ 4068 ELSE SemError(230)
|
|
|
+ 4069 END
|
|
|
+ 4070 END;
|
|
|
+ 4071 k := 0;
|
|
|
+ 4072 WHILE k < reps DO
|
|
|
+ 4073 QbeGen.CtorElem(qe);
|
|
|
+ 4074 INC(k)
|
|
|
+ 4075 END
|
|
|
+ 4076 END; .)
|
|
|
+ 4077 (. (* the BY form repeats the
|
|
|
+ 4078 element; keep the AST in
|
|
|
+ 4079 step with CtorElem *)
|
|
|
+ 4080 k := 0;
|
|
|
+ 4081 WHILE k < reps DO
|
|
|
+ 4082 AstAppend(AST.NkBlock,
|
|
|
+ 4083 node, tail, astEl);
|
|
|
+ 4084 INC(k)
|
|
|
+ 4085 END; .) .
|
|
|
+ 4086 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 4087 qe, q2: QbeGen.QVal;
|
|
|
+ 4088 v, v2: INTEGER;
|
|
|
+ 4089 lo: INTEGER;
|
|
|
+ 4090 span: CARDINAL;
|
|
|
+ 4091 cl, cl2: INTEGER;
|
|
|
+ 4092 hasR: BOOLEAN;
|
|
|
+ 4093 astEl: AST.Node; .)
|
|
|
+ 4094 = (. hasR := FALSE; .)
|
|
|
+ 4095 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 4096 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 4097 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 4098 hasR := TRUE; .) ]
|
|
|
+ 4099 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 4100 span := SymTab.SetCount(st);
|
|
|
+ 4101 IF (et = SymTab.InvalidType)
|
|
|
+ 4102 OR (hasR AND (et2 =
|
|
|
+ 4103 SymTab.InvalidType)) THEN
|
|
|
+ 4104 ELSE cl :=
|
|
|
+ 4105 SymTab.ClassOf(et);
|
|
|
+ 4106 IF hasR THEN
|
|
|
+ 4107 cl2 :=
|
|
|
+ 4108 SymTab.ClassOf(et2)
|
|
|
+ 4109 ELSE cl2 := SymTab.ClInt
|
|
|
+ 4110 END;
|
|
|
+ 4111 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 4112 OR (hasR AND NOT
|
|
|
+ 4113 SymTab.SetElemClassOk(cl2))
|
|
|
+ 4114 THEN
|
|
|
+ 4115 SemError(222)
|
|
|
+ 4116 ELSIF hasR
|
|
|
+ 4117 AND SymTab.ConstInt(qe, v)
|
|
|
+ 4118 AND SymTab.ConstInt(q2,
|
|
|
+ 4119 v2)
|
|
|
+ 4120 AND ((v < lo)
|
|
|
+ 4121 OR (v2 < lo)
|
|
|
+ 4122 OR (v >= lo +
|
|
|
+ 4123 VAL(INTEGER, span))
|
|
|
+ 4124 OR (v2 >= lo +
|
|
|
+ 4125 VAL(INTEGER, span))
|
|
|
+ 4126 OR (v > v2)) THEN
|
|
|
+ 4127 SemError(222)
|
|
|
+ 4128 ELSIF hasR THEN
|
|
|
+ 4129 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 4130 lo, span)
|
|
|
+ 4131 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 4132 v)
|
|
|
+ 4133 AND ((v < lo)
|
|
|
+ 4134 OR (v >= lo +
|
|
|
+ 4135 VAL(INTEGER,
|
|
|
+ 4136 span))) THEN
|
|
|
+ 4137 SemError(222)
|
|
|
+ 4138 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 4139 lo, span)
|
|
|
+ 4140 END
|
|
|
+ 4141 END; .)
|
|
|
+ 4142 (. AST.SetChild(node,
|
|
|
+ 4143 AST.NChild(node), astEl); .) .
|
|
|
+ 4144 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 4145 = ident (. LexName(n); .) .
|
|
|
+ 4146
|
|
|
+ 4147 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|
|
|
|
|
|
Statistics:
|
|
|
|
|
|
- nr of terminals: 114 (limit 400)
|
|
|
- nr of non-terminals: 90 (limit 210)
|
|
|
- nr of pragmas: 0 (limit 386)
|
|
|
- nr of symbolnodes: 204 (limit 500)
|
|
|
- nr of graphnodes: 1295 (limit 1500)
|
|
|
+ nr of terminals: 115 (limit 400)
|
|
|
+ nr of non-terminals: 91 (limit 210)
|
|
|
+ nr of pragmas: 0 (limit 385)
|
|
|
+ nr of symbolnodes: 206 (limit 500)
|
|
|
+ nr of graphnodes: 1317 (limit 1500)
|
|
|
nr of conditionsets: 12 (limit 100)
|
|
|
nr of charactersets: 17 (limit 250)
|
|
|
|