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