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