|
|
@@ -1031,2227 +1031,2222 @@ Listing:
|
|
|
1013 QbeGen.CopyOp("@", thisQ);
|
|
|
1014 QbeGen.PushWith(thisQ); .)
|
|
|
1015 Block<pn> (. AST.SetChild(astMethod, 1, astStmt);
|
|
|
- 1016 QbeGen.PopWith;
|
|
|
- 1017 methRes := SymTab.CurRes();
|
|
|
- 1018 Lower.ScopeLeave;
|
|
|
- 1019 SymTab.CloseProc;
|
|
|
- 1020 QbeGen.EndFunc(methRes); .) ) .
|
|
|
- 1021 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1022 = "CONST" (. astSeq := AST.NoNode;
|
|
|
- 1023 astTail := AST.NoNode; .)
|
|
|
- 1024 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1025 astSeq, astTail, astDecl); .) }
|
|
|
- 1026 (. astDecl := astSeq; .) .
|
|
|
- 1027 ConstDecl (. VAR n: SymTab.Name;
|
|
|
- 1028 t: SymTab.TypeIndex;
|
|
|
- 1029 qv: QbeGen.QVal;
|
|
|
- 1030 cls: INTEGER;
|
|
|
- 1031 astNode: AST.Node; .)
|
|
|
- 1032 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
- 1033 SymTab.KindConst) THEN
|
|
|
- 1034 SemError(200) END; .)
|
|
|
- 1035 "="
|
|
|
- 1036 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
- 1037 AST.SetChild(astNode, 0,
|
|
|
- 1038 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 1039 AST.SetChild(astNode, 1, astCur);
|
|
|
- 1040 AST.SetTy(astNode, t);
|
|
|
- 1041 astDecl := astNode;
|
|
|
- 1042 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
- 1043 Lower.NoteConstVal(qv);
|
|
|
- 1044 SymTab.SetSymType(n, t);
|
|
|
- 1045 cls := SymTab.ClassOf(t);
|
|
|
- 1046 IF (cls = SymTab.ClArray)
|
|
|
- 1047 OR (cls = SymTab.ClRecord)
|
|
|
- 1048 OR (cls = SymTab.ClClass)
|
|
|
- 1049 OR (cls = SymTab.ClStr)
|
|
|
- 1050 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 1051 (* an aggregate/string
|
|
|
- 1052 constant: qv is its
|
|
|
- 1053 descriptor address; no
|
|
|
- 1054 scalar data *)
|
|
|
- 1055 SymTab.SetSymVal(n, qv)
|
|
|
- 1056 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
- 1057 SemError(230)
|
|
|
- 1058 ELSE
|
|
|
- 1059 SymTab.SetSymVal(n, qv);
|
|
|
- 1060 END; .) .
|
|
|
- 1061 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1062 = "VAR" (. astSeq := AST.NoNode;
|
|
|
- 1063 astTail := AST.NoNode; .)
|
|
|
- 1064 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
- 1065 astSeq, astTail, astDecl); .) }
|
|
|
- 1066 (. astDecl := astSeq; .) .
|
|
|
- 1067 VarDecl (. VAR nm: SymTab.Name;
|
|
|
- 1068 t: SymTab.TypeIndex;
|
|
|
- 1069 i: CARDINAL;
|
|
|
- 1070 cls: INTEGER;
|
|
|
- 1071 astNode, astTail: AST.Node; .)
|
|
|
- 1072 = VarIdents ":"
|
|
|
- 1073 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
- 1074 astTail := astNode;
|
|
|
- 1075 i := 0;
|
|
|
- 1076 WHILE i < SymTab.PendCount() DO
|
|
|
- 1077 SymTab.PendName(i, nm);
|
|
|
- 1078 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
- 1079 (* chunked: a VAR list can
|
|
|
- 1080 exceed AST.MaxChild *)
|
|
|
- 1081 AstAppend(AST.NkBlock,
|
|
|
- 1082 astNode, astTail,
|
|
|
- 1083 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
- 1084 INC(i)
|
|
|
- 1085 END;
|
|
|
- 1086 AST.SetTy(astNode, t);
|
|
|
- 1087 astDecl := astNode;
|
|
|
- 1088 cls := SymTab.ClassOf(t);
|
|
|
- 1089 IF (t # SymTab.InvalidType)
|
|
|
- 1090 AND NOT SymTab.IsUnresolved(t)
|
|
|
- 1091 AND (cls # SymTab.ClInt)
|
|
|
- 1092 AND (cls # SymTab.ClBool)
|
|
|
- 1093 AND (cls # SymTab.ClChar)
|
|
|
- 1094 AND (cls # SymTab.ClReal)
|
|
|
- 1095 AND (cls # SymTab.ClArray)
|
|
|
- 1096 AND (cls # SymTab.ClSet)
|
|
|
- 1097 AND (cls # SymTab.ClRecord)
|
|
|
- 1098 AND (cls # SymTab.ClPtr)
|
|
|
- 1099 AND (cls # SymTab.ClLong)
|
|
|
- 1100 AND (cls # SymTab.ClProc)
|
|
|
- 1101 AND (cls # SymTab.ClUChar)
|
|
|
- 1102 AND (cls # SymTab.ClUStr)
|
|
|
- 1103 AND (cls # SymTab.ClEnum)
|
|
|
- 1104 AND (cls # SymTab.ClClass) THEN
|
|
|
- 1105 SemError(230) END;
|
|
|
- 1106 IF QbeGen.LocFull() THEN
|
|
|
- 1107 SemError(233) END;
|
|
|
- 1108 i := 0;
|
|
|
- 1109 IF SymTab.IsUnresolved(t)
|
|
|
- 1110 AND NOT SymTab.InProc() THEN
|
|
|
- 1111 (* a forward-typed global:
|
|
|
- 1112 defer emission until the
|
|
|
- 1113 TYPE block completes *)
|
|
|
- 1114 AST.SetOp(astNode, 1);
|
|
|
- 1115 WHILE i < SymTab.PendCount() DO
|
|
|
- 1116 SymTab.PendName(i, nm);
|
|
|
- 1117 IF nPendVar <=
|
|
|
- 1118 HIGH(pendVarName) THEN
|
|
|
- 1119 pendVarName[nPendVar] := nm;
|
|
|
- 1120 pendVarT[nPendVar] := t;
|
|
|
- 1121 INC(nPendVar)
|
|
|
- 1122 END;
|
|
|
- 1123 INC(i)
|
|
|
- 1124 END
|
|
|
- 1125 ELSE
|
|
|
- 1126 WHILE i < SymTab.PendCount() DO
|
|
|
- 1127 SymTab.PendName(i, nm);
|
|
|
- 1128 INC(i)
|
|
|
- 1129 END
|
|
|
- 1130 END;
|
|
|
- 1131 (* a plain VAR list, not a
|
|
|
- 1132 heading: the signature
|
|
|
- 1133 result is discarded *)
|
|
|
- 1134 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1135 END; .) .
|
|
|
- 1136 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 1137 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1138 SymTab.KindVar) THEN
|
|
|
- 1139 SemError(200) END; .)
|
|
|
- 1140 { ","
|
|
|
- 1141 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1142 SymTab.KindVar) THEN
|
|
|
- 1143 SemError(200) END; .) } .
|
|
|
- 1144 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 1145 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1146 SemError(200) END; .)
|
|
|
- 1147 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1148 SemError(200) END; .) } .
|
|
|
- 1149 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
- 1150 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
- 1151 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 1152 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
- 1153 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
- 1154 (. VAR t: SymTab.TypeIndex;
|
|
|
- 1155 mg: QbeGen.QVal; .)
|
|
|
- 1156 = "PROCEDURE"
|
|
|
- 1157 GetIdent<pn> (. IF methCls #
|
|
|
- 1158 SymTab.InvalidType THEN
|
|
|
- 1159 (* a method: resume the
|
|
|
- 1160 declared symbol (reuse
|
|
|
- 1161 its uid) *)
|
|
|
- 1162 IF NOT SymTab.ResumeMethod(
|
|
|
- 1163 methCls, pn) THEN
|
|
|
- 1164 SemError(200) END
|
|
|
- 1165 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
- 1166 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
- 1167 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
- 1168 SemError(200) END
|
|
|
- 1169 END
|
|
|
- 1170 END;
|
|
|
- 1171 Lower.ScopeEnter;
|
|
|
- 1172 Lower.NoteProc(pn,
|
|
|
- 1173 SymTab.ProcUid(pn),
|
|
|
- 1174 SymTab.InvalidType,
|
|
|
- 1175 SymTab.ProcDepthOf(pn),
|
|
|
- 1176 FALSE);
|
|
|
- 1177 QbeGen.BeginFunc("");
|
|
|
- 1178 IF methCls #
|
|
|
- 1179 SymTab.InvalidType THEN
|
|
|
- 1180 (* hidden THIS receiver:
|
|
|
- 1181 a VAR param of the
|
|
|
- 1182 class type, pushed as
|
|
|
- 1183 the WITH base *)
|
|
|
- 1184 IF NOT SymTab.EnterThisParam(
|
|
|
- 1185 methCls) THEN
|
|
|
- 1186 SemError(200) END;
|
|
|
- 1187 IF NOT QbeGen.FuncParam(
|
|
|
- 1188 "THIS", TRUE,
|
|
|
- 1189 methCls) THEN
|
|
|
- 1190 SemError(233) END
|
|
|
- 1191 END; .)
|
|
|
- 1192 [ FormalParams ]
|
|
|
- 1193 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
- 1194 SemError(235) END;
|
|
|
- 1195 Lower.SetProcRes(t);
|
|
|
- 1196 IF (t #
|
|
|
- 1197 SymTab.InvalidType)
|
|
|
- 1198 AND ((SymTab.ClassOf(t)
|
|
|
- 1199 = SymTab.ClArray)
|
|
|
- 1200 OR (SymTab.ClassOf(t)
|
|
|
- 1201 = SymTab.ClRecord)
|
|
|
- 1202 OR (SymTab.ClassOf(t)
|
|
|
- 1203 = SymTab.ClSet)
|
|
|
- 1204 OR (SymTab.ClassOf(t)
|
|
|
- 1205 = SymTab.ClClass)) THEN
|
|
|
- 1206 SemError(230) END; .) ] .
|
|
|
- 1207 FormalParams
|
|
|
- 1208 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 1209 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 1210 nm: SymTab.Name;
|
|
|
- 1211 i: CARDINAL;
|
|
|
- 1212 isV: BOOLEAN; .)
|
|
|
- 1213 = (. isV := FALSE; .)
|
|
|
- 1214 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 1215 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
- 1216 WHILE i < SymTab.PendCount() DO
|
|
|
- 1217 SymTab.PendName(i, nm);
|
|
|
- 1218 Lower.NoteParam(nm, t, isV);
|
|
|
- 1219 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
- 1220 (* value open arrays are
|
|
|
- 1221 passed as descriptor
|
|
|
- 1222 addresses (no copy):
|
|
|
- 1223 same representation as
|
|
|
- 1224 VAR formals *)
|
|
|
- 1225 IF NOT QbeGen.FuncParam(nm,
|
|
|
- 1226 isV
|
|
|
- 1227 OR SymTab.IsOpenArray(t),
|
|
|
- 1228 t) THEN
|
|
|
- 1229 SemError(233) END;
|
|
|
- 1230 INC(i)
|
|
|
- 1231 END;
|
|
|
- 1232 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1233 SemError(235) END; .) .
|
|
|
- 1234 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
- 1235 static link gives them their parent's frame. Methods keep
|
|
|
- 1236 parse-now/230-later. *)
|
|
|
- 1237 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
- 1238 astNode: AST.Node; .)
|
|
|
- 1239 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1240 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1241 AST.SetOp(astNode, 0);
|
|
|
- 1242 AST.SetChild(astNode, 0,
|
|
|
- 1243 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1244 Lower.NoteProcNode(astNode); .)
|
|
|
- 1245 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
- 1246 astDecl := astNode;
|
|
|
- 1247 Lower.ScopeLeave;
|
|
|
- 1248 SymTab.MarkFwd;
|
|
|
- 1249 SymTab.CloseProc;
|
|
|
- 1250 QbeGen.AbortFunc; .)
|
|
|
- 1251 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
- 1252 astDecl := astNode;
|
|
|
- 1253 Lower.MarkProcExternal;
|
|
|
- 1254 Lower.ScopeLeave;
|
|
|
- 1255 SymTab.MarkExternal("");
|
|
|
- 1256 SymTab.CloseProc;
|
|
|
- 1257 QbeGen.AbortFunc; .)
|
|
|
- 1258 |
|
|
|
- 1259 Block<pn> (. AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1260 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
- 1261 astDecl := astNode;
|
|
|
- 1262 Lower.ScopeLeave;
|
|
|
- 1263 SymTab.CloseProc;
|
|
|
- 1264 QbeGen.EndFunc(
|
|
|
- 1265 SymTab.ProcRes(pn)); .) ) .
|
|
|
- 1266 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
- 1267 = DeclSeq (. astBlkDecls := astDecl;
|
|
|
- 1268 astStmt := AST.NoNode; .)
|
|
|
- 1269 [ "BEGIN" (. (* an empty body is still a
|
|
|
- 1270 body: mark it so Lower
|
|
|
- 1271 does not read it as a
|
|
|
- 1272 definition heading *)
|
|
|
- 1273 IF astStmt = AST.NoNode THEN
|
|
|
- 1274 astStmt :=
|
|
|
- 1275 AST.MakeNode(AST.NkBlock)
|
|
|
- 1276 END; .)
|
|
|
- 1277 [ StatSeq ] ]
|
|
|
- 1278 "END"
|
|
|
- 1279 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
- 1280 SemError(202) END; .) .
|
|
|
- 1281 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1282 = (. astSeq := AST.NoNode;
|
|
|
- 1283 astTail := AST.NoNode; .)
|
|
|
- 1284 Statement (. AstAppend(AST.NkBlock,
|
|
|
- 1285 astSeq, astTail, astStmt); .)
|
|
|
- 1286 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
- 1287 astSeq, astTail, astStmt); .) ] }
|
|
|
- 1288 (. astStmt := astSeq; .) .
|
|
|
- 1289 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
- 1290 are accepted: the statement after ';' is optional. *)
|
|
|
- 1291 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
- 1292 = (. astStmt := AST.NoNode; .)
|
|
|
- 1293 ( AssOrCall
|
|
|
- 1294 | IfStat
|
|
|
- 1295 | WhileStat
|
|
|
- 1296 | RepeatStat
|
|
|
- 1297 | LoopStat
|
|
|
- 1298 | ForStat
|
|
|
- 1299 | CaseStat
|
|
|
- 1300 | WithStat
|
|
|
- 1301 | ReturnStat
|
|
|
- 1302 | HaltStat
|
|
|
- 1303 | NewStat
|
|
|
- 1304 | DisposeStat
|
|
|
- 1305 | IncDecStat
|
|
|
- 1306 | InclExclStat
|
|
|
- 1307 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
- 1308 SemError(230) END;
|
|
|
- 1309 astStmt := AST.MakeNode(AST.NkExit); .) ) .
|
|
|
- 1310 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
- 1311 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
- 1312 dk: INTEGER;
|
|
|
- 1313 qd, qe: QbeGen.QVal;
|
|
|
- 1314 qn: SymTab.Name;
|
|
|
- 1315 sfx, isInc: BOOLEAN;
|
|
|
- 1316 astNode, astD: AST.Node; .)
|
|
|
- 1317 = ( "INCL" (. isInc := TRUE; .)
|
|
|
- 1318 | "EXCL" (. isInc := FALSE; .) )
|
|
|
- 1319 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
- 1320 Expr<et2, qe> ")"
|
|
|
- 1321 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1322 IF isInc THEN
|
|
|
- 1323 AST.SetChild(astNode, 0,
|
|
|
- 1324 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
- 1325 ELSE AST.SetChild(astNode, 0,
|
|
|
- 1326 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
- 1327 END;
|
|
|
- 1328 IF astD # AST.NoNode THEN
|
|
|
- 1329 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1330 IF astCur # AST.NoNode THEN
|
|
|
- 1331 AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 1332 astStmt := astNode; .)
|
|
|
- 1333 (. IF (at # SymTab.InvalidType)
|
|
|
- 1334 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
- 1335 SemError(222)
|
|
|
- 1336 END; .) .
|
|
|
- 1337 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
- 1338 integer designator. *)
|
|
|
- 1339 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
- 1340 dk: INTEGER;
|
|
|
- 1341 qd, qv, qn2, qstep:
|
|
|
- 1342 QbeGen.QVal;
|
|
|
- 1343 qn: SymTab.Name;
|
|
|
- 1344 sfx, isInc: BOOLEAN;
|
|
|
- 1345 astNode, astD, astStep:
|
|
|
- 1346 AST.Node; .)
|
|
|
- 1347 = (. isInc := TRUE; .)
|
|
|
- 1348 ( "INC" (. isInc := TRUE; .)
|
|
|
- 1349 | "DEC" (. isInc := FALSE; .) )
|
|
|
- 1350 "(" (. astStep := AST.NoNode; .)
|
|
|
- 1351 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
- 1352 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
- 1353 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1354 IF isInc THEN
|
|
|
- 1355 AST.SetChild(astNode, 0,
|
|
|
- 1356 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
- 1357 ELSE AST.SetChild(astNode, 0,
|
|
|
- 1358 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
- 1359 END;
|
|
|
- 1360 IF astD # AST.NoNode THEN
|
|
|
- 1361 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1362 IF astStep # AST.NoNode THEN
|
|
|
- 1363 AST.SetChild(astNode, 2, astStep) END;
|
|
|
- 1364 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1365 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1366 AND (dk # SymTab.KindParam)
|
|
|
- 1367 AND (dk # SymTab.KindField) THEN
|
|
|
- 1368 SemError(210)
|
|
|
- 1369 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
- 1370 SemError(211)
|
|
|
- 1371 END; .) .
|
|
|
- 1372 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
- 1373 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
- 1374 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
- 1375 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1376 dk: INTEGER;
|
|
|
- 1377 qd, qm: QbeGen.QVal;
|
|
|
- 1378 qn: SymTab.Name;
|
|
|
- 1379 sfx: BOOLEAN;
|
|
|
- 1380 bt: SymTab.TypeIndex;
|
|
|
- 1381 astNode, astD: AST.Node; .)
|
|
|
- 1382 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 1383 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1384 AST.SetChild(astNode, 0,
|
|
|
- 1385 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
- 1386 IF astD # AST.NoNode THEN
|
|
|
- 1387 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1388 astStmt := astNode; .)
|
|
|
- 1389 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1390 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1391 AND (dk # SymTab.KindParam)
|
|
|
- 1392 AND (dk # SymTab.KindField) THEN
|
|
|
- 1393 SemError(210)
|
|
|
- 1394 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1395 SymTab.ClPtr THEN
|
|
|
- 1396 SemError(219)
|
|
|
- 1397 END; .) .
|
|
|
- 1398 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1399 dk: INTEGER;
|
|
|
- 1400 qd, qv: QbeGen.QVal;
|
|
|
- 1401 qn: SymTab.Name;
|
|
|
- 1402 sfx: BOOLEAN;
|
|
|
- 1403 astNode, astD: AST.Node; .)
|
|
|
- 1404 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 1405 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1406 AST.SetChild(astNode, 0,
|
|
|
- 1407 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
- 1408 IF astD # AST.NoNode THEN
|
|
|
- 1409 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1410 astStmt := astNode; .)
|
|
|
- 1411 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1412 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1413 AND (dk # SymTab.KindParam)
|
|
|
- 1414 AND (dk # SymTab.KindField) THEN
|
|
|
- 1415 SemError(210)
|
|
|
- 1416 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1417 SymTab.ClPtr THEN
|
|
|
- 1418 SemError(219)
|
|
|
- 1419 END; .) .
|
|
|
- 1420 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
- 1421 address; field designators resolve through both stacks. *)
|
|
|
- 1422 WithStat (. VAR nW: CARDINAL;
|
|
|
- 1423 astNode: AST.Node; .)
|
|
|
- 1424 = "WITH" (. nW := 0;
|
|
|
- 1425 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
- 1426 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
- 1427 "DO" (. astStmt := AST.NoNode; .)
|
|
|
- 1428 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
- 1429 AST.NChild(astNode), astStmt);
|
|
|
- 1430 astStmt := astNode;
|
|
|
- 1431 WHILE nW > 0 DO
|
|
|
- 1432 SymTab.PopScope;
|
|
|
- 1433 QbeGen.PopWith;
|
|
|
- 1434 DEC(nW)
|
|
|
- 1435 END; .) .
|
|
|
- 1436 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
- 1437 (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1438 dk: INTEGER;
|
|
|
- 1439 qd, qe: QbeGen.QVal;
|
|
|
- 1440 qn: SymTab.Name;
|
|
|
- 1441 sfx: BOOLEAN; .)
|
|
|
- 1442 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 1443 (. IF astCur # AST.NoNode THEN
|
|
|
- 1444 AST.SetChild(wnode,
|
|
|
- 1445 AST.NChild(wnode), astCur) END;
|
|
|
- 1446 IF dt = SymTab.InvalidType THEN
|
|
|
- 1447 ELSIF (SymTab.ClassOf(dt) #
|
|
|
- 1448 SymTab.ClRecord)
|
|
|
- 1449 AND (SymTab.ClassOf(dt) #
|
|
|
- 1450 SymTab.ClClass) THEN
|
|
|
- 1451 SemError(215)
|
|
|
- 1452 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
- 1453 QbeGen.PushWith(qd);
|
|
|
- 1454 INC(nW)
|
|
|
- 1455 END; .) .
|
|
|
- 1456 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
- 1457 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
- 1458 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 1459 dk: INTEGER;
|
|
|
- 1460 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
- 1461 qn: SymTab.Name;
|
|
|
- 1462 ct2, res0: SymTab.TypeIndex;
|
|
|
- 1463 q2, mg0: QbeGen.QVal;
|
|
|
- 1464 isR, conv, wconv: BOOLEAN;
|
|
|
- 1465 called, sfx: BOOLEAN;
|
|
|
- 1466 astLhs, astRes: AST.Node; .)
|
|
|
- 1467 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 1468 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
- 1469 ( ":="
|
|
|
- 1470 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 1471 AST.NkAssign, 0, astLhs, astCur);
|
|
|
- 1472 IF (dt # SymTab.InvalidType)
|
|
|
- 1473 AND (dk # SymTab.KindVar)
|
|
|
- 1474 AND (dk # SymTab.KindParam)
|
|
|
- 1475 AND (dk # SymTab.KindField) THEN
|
|
|
- 1476 SemError(210)
|
|
|
- 1477 ELSIF NOT SymTab.Assignable(et,
|
|
|
- 1478 dt) THEN
|
|
|
- 1479 SemError(210)
|
|
|
- 1480 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 1481 AND (SymTab.ClassOf(dt) =
|
|
|
- 1482 SymTab.ClClass) THEN
|
|
|
- 1483 SemError(230) END;
|
|
|
- 1484 isR := (dt #
|
|
|
- 1485 SymTab.InvalidType)
|
|
|
- 1486 AND (SymTab.ClassOf(dt)
|
|
|
- 1487 = SymTab.ClReal);
|
|
|
- 1488 conv := isR
|
|
|
- 1489 AND SymTab.IsIntFamily(et);
|
|
|
- 1490 wconv := (dt #
|
|
|
- 1491 SymTab.InvalidType)
|
|
|
- 1492 AND SymTab.IsLongFamily(dt)
|
|
|
- 1493 AND SymTab.IsIntFamily(et);
|
|
|
- 1494 IF ((dk = SymTab.KindVar)
|
|
|
- 1495 OR (dk = SymTab.KindParam)
|
|
|
- 1496 OR (dk = SymTab.KindField))
|
|
|
- 1497 AND (dt # SymTab.InvalidType)
|
|
|
- 1498 AND (et # SymTab.InvalidType)
|
|
|
- 1499 AND (SymTab.ClassOf(dt) #
|
|
|
- 1500 SymTab.ClClass) THEN
|
|
|
- 1501 END; .)
|
|
|
- 1502 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
- 1503 (. astRes := AstCallNode(astLhs);
|
|
|
- 1504 sfx := FALSE; .)
|
|
|
- 1505 ( { ResultComp<ct2, q2, sfx, astRes> }
|
|
|
- 1506 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 1507 AST.NkAssign, 0, astRes, astCur);
|
|
|
- 1508 IF NOT sfx THEN
|
|
|
- 1509 SemError(233)
|
|
|
- 1510 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
- 1511 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
- 1512 SemError(210)
|
|
|
- 1513 END; .)
|
|
|
- 1514 | (. IF ct2 #
|
|
|
- 1515 SymTab.InvalidType THEN
|
|
|
- 1516 SemError(233) END;
|
|
|
- 1517 astStmt := astRes; .) )
|
|
|
- 1518 | (* bare `P;`: proper parameterless
|
|
|
- 1519 procedure call; anything else
|
|
|
- 1520 here is 233 (was a bare syntax
|
|
|
- 1521 error before 4.2) *)
|
|
|
- 1522 (. astStmt := AstCallNode(astLhs);
|
|
|
- 1523 IF (dk = SymTab.KindProc)
|
|
|
- 1524 AND NOT sfx THEN
|
|
|
- 1525 res0 := SymTab.ProcRes(qn);
|
|
|
- 1526 IF res0 #
|
|
|
- 1527 SymTab.InvalidType THEN
|
|
|
- 1528 SemError(233)
|
|
|
- 1529 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 1530 0 THEN
|
|
|
- 1531 SemError(233)
|
|
|
- 1532 END
|
|
|
- 1533 ELSE SemError(233)
|
|
|
- 1534 END; .) ) .
|
|
|
- 1535 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 1536 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 1537 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 1538 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 1539 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 1540 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
- 1541 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 1542 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
- 1543 vs: INTEGER;
|
|
|
- 1544 res: SymTab.TypeIndex;
|
|
|
- 1545 mg: QbeGen.QVal;
|
|
|
- 1546 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
- 1547 = "(" (. called := TRUE;
|
|
|
- 1548 ok := TRUE;
|
|
|
- 1549 ind := FALSE;
|
|
|
- 1550 isMeth := methCls #
|
|
|
- 1551 SymTab.InvalidType;
|
|
|
- 1552 IF isMeth THEN
|
|
|
- 1553 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
- 1554 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
- 1555 res := SymTab.ProcRes(pn)
|
|
|
- 1556 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 1557 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 1558 ind := TRUE;
|
|
|
- 1559 res := SymTab.ProcTypeRes(pt)
|
|
|
- 1560 ELSE SemError(233);
|
|
|
- 1561 ok := FALSE;
|
|
|
- 1562 res := SymTab.InvalidType
|
|
|
- 1563 END;
|
|
|
- 1564 i := 0; .)
|
|
|
- 1565 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
- 1566 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
- 1567 ")" (. IF ok THEN
|
|
|
- 1568 IF isMeth THEN
|
|
|
- 1569 np := SymTab.ClassMethodNPar(
|
|
|
- 1570 methCls, pn)
|
|
|
- 1571 ELSIF ind THEN
|
|
|
- 1572 np := SymTab.ProcTypeNPar(pt)
|
|
|
- 1573 ELSE np := SymTab.ProcNPar(pn)
|
|
|
- 1574 END;
|
|
|
- 1575 va := (NOT isMeth) AND (NOT ind)
|
|
|
- 1576 AND (SymTab.SymKind(pn) =
|
|
|
- 1577 SymTab.KindProc)
|
|
|
- 1578 AND SymTab.Varargs(pn);
|
|
|
- 1579 IF (i # np) AND NOT va THEN
|
|
|
- 1580 SemError(233); ok := FALSE
|
|
|
- 1581 END
|
|
|
- 1582 END;
|
|
|
- 1583 IF NOT ok THEN
|
|
|
- 1584 t := SymTab.InvalidType;
|
|
|
- 1585 QbeGen.CopyOp("0", q)
|
|
|
- 1586 ELSIF want THEN
|
|
|
- 1587 IF res =
|
|
|
- 1588 SymTab.InvalidType THEN
|
|
|
- 1589 IF NOT soft THEN SemError(233) END;
|
|
|
- 1590 t := SymTab.InvalidType;
|
|
|
- 1591 QbeGen.CopyOp("0", q)
|
|
|
- 1592 ELSE t := res;
|
|
|
- 1593 QbeGen.CopyOp("@", q)
|
|
|
- 1594 END
|
|
|
- 1595 ELSE
|
|
|
- 1596 IF res #
|
|
|
- 1597 SymTab.InvalidType THEN
|
|
|
- 1598 SemError(233)
|
|
|
- 1599 END;
|
|
|
- 1600 t := SymTab.InvalidType;
|
|
|
- 1601 QbeGen.CopyOp("0", q);
|
|
|
- 1602 END; .) .
|
|
|
- 1603 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 1604 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 1605 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 1606 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
- 1607 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 1608 qe, qa, qt: QbeGen.QVal;
|
|
|
- 1609 isV, conv, va: BOOLEAN;
|
|
|
- 1610 cl: CHAR;
|
|
|
- 1611 savedN, aj: CARDINAL;
|
|
|
- 1612 savedArgs: ARRAY [0 .. 31]
|
|
|
- 1613 OF AST.Node;
|
|
|
- 1614 astActual: AST.Node; .)
|
|
|
- 1615 = (. (* Parsing the actual can clobber
|
|
|
- 1616 the enclosing call's argument
|
|
|
- 1617 list (Factor resets astNArgs),
|
|
|
- 1618 so save/restore it. *)
|
|
|
- 1619 savedN := astNArgs; aj := 0;
|
|
|
- 1620 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 1621 savedArgs[aj] := astArgs[aj];
|
|
|
- 1622 INC(aj)
|
|
|
- 1623 END; .)
|
|
|
- 1624 Expr<at, qe> (. astActual := astCur;
|
|
|
- 1625 astNArgs := savedN; aj := 0;
|
|
|
- 1626 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 1627 astArgs[aj] := savedArgs[aj];
|
|
|
- 1628 INC(aj)
|
|
|
- 1629 END;
|
|
|
- 1630 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
- 1631 astArgs[astNArgs] := astCur;
|
|
|
- 1632 INC(astNArgs)
|
|
|
- 1633 END;
|
|
|
- 1634 va := (NOT ind)
|
|
|
- 1635 AND (methCls =
|
|
|
- 1636 SymTab.InvalidType)
|
|
|
- 1637 AND (SymTab.SymKind(pn) =
|
|
|
- 1638 SymTab.KindProc)
|
|
|
- 1639 AND SymTab.Varargs(pn);
|
|
|
- 1640 IF ind THEN
|
|
|
- 1641 ft :=
|
|
|
- 1642 SymTab.ProcTypeParamType(pt,
|
|
|
- 1643 i);
|
|
|
- 1644 isV :=
|
|
|
- 1645 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 1646 i)
|
|
|
- 1647 ELSIF methCls #
|
|
|
- 1648 SymTab.InvalidType THEN
|
|
|
- 1649 ft :=
|
|
|
- 1650 SymTab.ClassMethodParamType(
|
|
|
- 1651 methCls, pn, i);
|
|
|
- 1652 isV :=
|
|
|
- 1653 SymTab.ClassMethodParamIsVar(
|
|
|
- 1654 methCls, pn, i)
|
|
|
- 1655 ELSE
|
|
|
- 1656 ft := SymTab.ParamType(pn, i);
|
|
|
- 1657 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 1658 END;
|
|
|
- 1659 IF (at = SymTab.InvalidType) THEN
|
|
|
- 1660 ELSIF ft = SymTab.InvalidType THEN
|
|
|
- 1661 ELSIF isV THEN
|
|
|
- 1662 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 1663 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1664 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 1665 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1666 ELSIF (AST.Kind(astActual) #
|
|
|
- 1667 AST.NkDesignator)
|
|
|
- 1668 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
- 1669 SemError(233)
|
|
|
- 1670 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
- 1671 SemError(233)
|
|
|
- 1672 END
|
|
|
- 1673 ELSE
|
|
|
- 1674 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
- 1675 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1676 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
- 1677 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1678 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
- 1679 SemError(233)
|
|
|
- 1680 END
|
|
|
- 1681 END; .) .
|
|
|
- 1682 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1683 q: QbeGen.QVal;
|
|
|
- 1684 hasElse: BOOLEAN;
|
|
|
- 1685 astCond, astIf, astLast,
|
|
|
- 1686 astNode: AST.Node; .)
|
|
|
- 1687 = "IF" (. hasElse := FALSE; .)
|
|
|
- 1688 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 1689 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1690 SemError(214) END; .)
|
|
|
- 1691 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 1692 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1693 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1694 astIf := astNode;
|
|
|
- 1695 astLast := astNode; .)
|
|
|
- 1696 { "ELSIF"
|
|
|
- 1697 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 1698 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1699 SemError(214) END; .)
|
|
|
- 1700 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 1701 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1702 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1703 AST.SetChild(astLast, 2, astNode);
|
|
|
- 1704 astLast := astNode; .) }
|
|
|
- 1705 [ "ELSE" (. hasElse := TRUE;
|
|
|
- 1706 astStmt := AST.NoNode; .)
|
|
|
- 1707 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- 1708 "END" (. astStmt := astIf; .) .
|
|
|
- 1709 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1710 q: QbeGen.QVal;
|
|
|
- 1711 astCond, astNode: AST.Node; .)
|
|
|
- 1712 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
- 1713 Expr<t, q> (. astCond := astCur;
|
|
|
- 1714 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1715 SemError(214) END; .)
|
|
|
- 1716 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
- 1717 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1718 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1719 astStmt := astNode; .)
|
|
|
- 1720 "END" .
|
|
|
- 1721 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1722 q: QbeGen.QVal;
|
|
|
- 1723 astCond, astBody, astNode:
|
|
|
- 1724 AST.Node; .)
|
|
|
- 1725 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
- 1726 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
- 1727 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
- 1728 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
- 1729 AST.SetChild(astNode, 0, astBody);
|
|
|
- 1730 AST.SetChild(astNode, 1, astCond);
|
|
|
- 1731 astStmt := astNode;
|
|
|
- 1732 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1733 SemError(214) END; .) .
|
|
|
- 1734 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- 1735 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
- 1736 QbeGen.NewLabel(lEnd);
|
|
|
- 1737 QbeGen.PushLoop(lEnd); .)
|
|
|
- 1738 [ StatSeq ]
|
|
|
- 1739 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
- 1740 AST.SetChild(astNode, 0, astStmt);
|
|
|
- 1741 astStmt := astNode;
|
|
|
- 1742 QbeGen.PopLoop; .) .
|
|
|
- 1743 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 1744 Runtime direction would need a compare-select; the literal
|
|
|
- 1745 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 1746 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 1747 tlo, thi, tby:
|
|
|
- 1748 SymTab.TypeIndex;
|
|
|
- 1749 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 1750 QbeGen.QVal;
|
|
|
- 1751 lTop, lBody, lEnd:
|
|
|
- 1752 QbeGen.QVal;
|
|
|
- 1753 by: INTEGER;
|
|
|
- 1754 ok: BOOLEAN;
|
|
|
- 1755 astVar, astLo, astHi, astBy,
|
|
|
- 1756 astNode: AST.Node; .)
|
|
|
- 1757 = "FOR" (. by := 1; .)
|
|
|
- 1758 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
- 1759 astStmt := AST.NoNode;
|
|
|
- 1760 astBy := AST.NoNode;
|
|
|
- 1761 ok := SymTab.Lookup(lv);
|
|
|
- 1762 IF NOT ok THEN
|
|
|
- 1763 SemError(201)
|
|
|
- 1764 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 1765 SymTab.KindVar)
|
|
|
- 1766 AND (SymTab.SymKind(lv) #
|
|
|
- 1767 SymTab.KindParam) THEN
|
|
|
- 1768 SemError(220); ok := FALSE
|
|
|
- 1769 ELSIF NOT SymTab.IsIntFamily(
|
|
|
- 1770 SymTab.SymType(lv)) THEN
|
|
|
- 1771 SemError(220); ok := FALSE
|
|
|
- 1772 END; .)
|
|
|
- 1773 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
- 1774 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
- 1775 SemError(220); ok := FALSE
|
|
|
- 1776 END; .)
|
|
|
- 1777 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
- 1778 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
- 1779 SemError(220); ok := FALSE
|
|
|
- 1780 END; .)
|
|
|
- 1781 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
- 1782 IF (tby #
|
|
|
- 1783 SymTab.InvalidType)
|
|
|
- 1784 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 1785 SemError(220); ok := FALSE
|
|
|
- 1786 END;
|
|
|
- 1787 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 1788 SemError(230); by := 1
|
|
|
- 1789 ELSIF by = 0 THEN
|
|
|
- 1790 SemError(220); by := 1
|
|
|
- 1791 END; .) ]
|
|
|
- 1792 "DO"
|
|
|
- 1793 [ StatSeq ]
|
|
|
- 1794 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
- 1795 AST.SetChild(astNode, 0, astVar);
|
|
|
- 1796 AST.SetChild(astNode, 1, astLo);
|
|
|
- 1797 AST.SetChild(astNode, 2, astHi);
|
|
|
- 1798 AST.SetChild(astNode, 3, astBy);
|
|
|
- 1799 AST.SetChild(astNode, 4, astStmt);
|
|
|
- 1800 astStmt := astNode;
|
|
|
- 1801 .) .
|
|
|
- 1802 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 1803 qsel, lEnd: QbeGen.QVal;
|
|
|
- 1804 arm, astNode, astArms,
|
|
|
- 1805 astArmsTail: AST.Node; .)
|
|
|
- 1806 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
- 1807 AST.SetChild(astNode, 0, astCur);
|
|
|
- 1808 astArms := AST.NoNode;
|
|
|
- 1809 astArmsTail := AST.NoNode;
|
|
|
- 1810 .)
|
|
|
- 1811 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
- 1812 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
- 1813 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
- 1814 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 1815 AST.SetOp(arm, 1);
|
|
|
- 1816 AST.SetChild(arm, 0, astStmt);
|
|
|
- 1817 AstAppend(AST.NkBlock,
|
|
|
- 1818 astArms, astArmsTail, arm); .) ]
|
|
|
- 1819 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
- 1820 astStmt := astNode;
|
|
|
- 1821 .) .
|
|
|
- 1822 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 1823 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 1824 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 1825 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 1826 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 1827 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- 1828 (. VAR arm: AST.Node; .)
|
|
|
- 1829 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
- 1830 CaseLabel<tsel, qsel, arm>
|
|
|
- 1831 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
- 1832 ":" (. astStmt := AST.NoNode; .)
|
|
|
- 1833 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
- 1834 astStmt);
|
|
|
- 1835 AstAppend(AST.NkBlock,
|
|
|
- 1836 arms, armsTail, arm);
|
|
|
- 1837 .) .
|
|
|
- 1838 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 1839 arm: AST.Node>
|
|
|
- 1840 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 1841 q2, q3, qc, qd, qe:
|
|
|
- 1842 QbeGen.QVal;
|
|
|
- 1843 astLab: AST.Node;
|
|
|
- 1844 lNext: QbeGen.QVal; .)
|
|
|
- 1845 = Expr<t2, q2> (. astLab := astCur;
|
|
|
- 1846 IF (t2 #
|
|
|
- 1847 SymTab.InvalidType)
|
|
|
- 1848 AND (tsel #
|
|
|
- 1849 SymTab.InvalidType)
|
|
|
- 1850 AND ((SymTab.ClassOf(t2) =
|
|
|
- 1851 SymTab.ClSet)
|
|
|
- 1852 OR (SymTab.ClassOf(tsel) =
|
|
|
- 1853 SymTab.ClSet)) THEN
|
|
|
- 1854 SemError(230)
|
|
|
- 1855 ELSIF (t2 #
|
|
|
- 1856 SymTab.InvalidType)
|
|
|
- 1857 AND (tsel #
|
|
|
- 1858 SymTab.InvalidType)
|
|
|
- 1859 AND NOT SymTab.EqCheck(t2,
|
|
|
- 1860 tsel) THEN
|
|
|
- 1861 SemError(213) END;
|
|
|
- 1862 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- 1863 SemError(230)
|
|
|
- 1864 END; .)
|
|
|
- 1865 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
- 1866 AST.NkSubrange, 0, astLab, astCur);
|
|
|
- 1867 IF (t3 #
|
|
|
- 1868 SymTab.InvalidType)
|
|
|
- 1869 AND (tsel #
|
|
|
- 1870 SymTab.InvalidType)
|
|
|
- 1871 AND NOT SymTab.EqCheck(t3,
|
|
|
- 1872 tsel) THEN
|
|
|
- 1873 SemError(213) END;
|
|
|
- 1874 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- 1875 SemError(230)
|
|
|
- 1876 END; .) ]
|
|
|
- 1877 (. AST.SetChild(arm,
|
|
|
- 1878 AST.NChild(arm), astLab); .) .
|
|
|
- 1879 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1880 q, qt: QbeGen.QVal;
|
|
|
- 1881 res: SymTab.TypeIndex;
|
|
|
- 1882 hadE, conv: BOOLEAN;
|
|
|
- 1883 astVal, astNode: AST.Node; .)
|
|
|
- 1884 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
- 1885 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
- 1886 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
- 1887 IF hadE THEN
|
|
|
- 1888 AST.SetChild(astNode, 0, astVal)
|
|
|
- 1889 END;
|
|
|
- 1890 astStmt := astNode;
|
|
|
- 1891 conv := FALSE;
|
|
|
- 1892 IF NOT SymTab.InProc() THEN
|
|
|
- 1893 SemError(232)
|
|
|
- 1894 ELSE res := SymTab.CurRes();
|
|
|
- 1895 IF NOT hadE THEN
|
|
|
- 1896 IF res #
|
|
|
- 1897 SymTab.InvalidType THEN
|
|
|
- 1898 SemError(232)
|
|
|
- 1899 END
|
|
|
- 1900 ELSIF (res =
|
|
|
- 1901 SymTab.InvalidType)
|
|
|
- 1902 OR (t #
|
|
|
- 1903 SymTab.InvalidType)
|
|
|
- 1904 AND NOT SymTab.Assignable(t,
|
|
|
- 1905 res) THEN
|
|
|
- 1906 SemError(232)
|
|
|
- 1907 END
|
|
|
- 1908 END; .) .
|
|
|
- 1909 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1910 q: QbeGen.QVal;
|
|
|
- 1911 astVal, astNode: AST.Node; .)
|
|
|
- 1912 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
- 1913 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
- 1914 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
- 1915 IF astVal # AST.NoNode THEN
|
|
|
- 1916 AST.SetChild(astNode, 0, astVal)
|
|
|
- 1917 END;
|
|
|
- 1918 astStmt := astNode;
|
|
|
- 1919 .) .
|
|
|
- 1920 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 1921 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 1922 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 1923 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 1924 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 1925 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 1926 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 1927 (. VAR n, fn, mal: SymTab.Name;
|
|
|
- 1928 cls: INTEGER;
|
|
|
- 1929 ic: SymTab.TypeIndex;
|
|
|
- 1930 curT, it, eT, bt:
|
|
|
- 1931 SymTab.TypeIndex;
|
|
|
- 1932 iq, ql, qlo, qhi, qe:
|
|
|
- 1933 QbeGen.QVal;
|
|
|
- 1934 lo, hi: INTEGER;
|
|
|
- 1935 fo: INTEGER;
|
|
|
- 1936 isOpen: BOOLEAN;
|
|
|
- 1937 qb, cv: QbeGen.QVal;
|
|
|
- 1938 fid, fref, slot: INTEGER;
|
|
|
- 1939 r: BOOLEAN;
|
|
|
- 1940 astDes, astSel: AST.Node;
|
|
|
- 1941 fwd: BOOLEAN; .)
|
|
|
- 1942 = GetIdent<n> (. methCls := SymTab.InvalidType;
|
|
|
- 1943 QbeGen.CopyOp(n, qn);
|
|
|
- 1944 sfx := FALSE; fwd := FALSE;
|
|
|
- 1945 fid := 0; fref := 0; slot := 0;
|
|
|
- 1946 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 1947 (* a bare method name inside
|
|
|
- 1948 a CLASS IMPLEMENTATION
|
|
|
- 1949 is a sibling call on
|
|
|
- 1950 THIS *)
|
|
|
- 1951 ic := SymTab.CurImplClass();
|
|
|
- 1952 IF (ic #
|
|
|
- 1953 SymTab.InvalidType)
|
|
|
- 1954 AND SymTab.MethodExists(ic, n) THEN
|
|
|
- 1955 sfx := FALSE;
|
|
|
- 1956 QbeGen.CopyOp("@", q);
|
|
|
- 1957 methCls := ic;
|
|
|
- 1958 k := SymTab.KindProc;
|
|
|
- 1959 t := SymTab.InvalidType
|
|
|
- 1960 ELSIF SymTab.InProc() THEN
|
|
|
- 1961 (* not declared yet: a
|
|
|
- 1962 forward reference to a
|
|
|
- 1963 module-level variable
|
|
|
- 1964 declared further down. *)
|
|
|
- 1965 k := SymTab.KindVar;
|
|
|
- 1966 r := SymTab.FwdVarRef(n, k,
|
|
|
- 1967 fref, t);
|
|
|
- 1968 FwdVarNote(fref, 0);
|
|
|
- 1969 QbeGen.CopyOp("@", q);
|
|
|
- 1970 sfx := TRUE; fwd := TRUE
|
|
|
- 1971 ELSE
|
|
|
- 1972 SemError(201);
|
|
|
- 1973 t :=
|
|
|
- 1974 SymTab.InvalidType;
|
|
|
- 1975 k := -1;
|
|
|
- 1976 QbeGen.CopyOp("0", q)
|
|
|
- 1977 END
|
|
|
- 1978 ELSE
|
|
|
- 1979 t := SymTab.SymType(n);
|
|
|
- 1980 k := SymTab.SymKind(n);
|
|
|
- 1981 IF k = SymTab.KindConst THEN
|
|
|
- 1982 IF SymTab.Equal(n,
|
|
|
- 1983 "TRUE") THEN
|
|
|
- 1984 t := SymTab.BoolType();
|
|
|
- 1985 QbeGen.CopyOp("1", q)
|
|
|
- 1986 ELSIF SymTab.Equal(n,
|
|
|
- 1987 "FALSE") THEN
|
|
|
- 1988 t := SymTab.BoolType();
|
|
|
- 1989 QbeGen.CopyOp("0", q)
|
|
|
- 1990 ELSIF SymTab.Equal(n,
|
|
|
- 1991 "NIL") THEN
|
|
|
- 1992 QbeGen.CopyOp("0", q)
|
|
|
- 1993 ELSE
|
|
|
- 1994 cls :=
|
|
|
- 1995 SymTab.ClassOf(t);
|
|
|
- 1996 IF (t #
|
|
|
- 1997 SymTab.InvalidType)
|
|
|
- 1998 AND ((cls = SymTab.ClInt)
|
|
|
- 1999 OR (cls
|
|
|
- 2000 = SymTab.ClChar)
|
|
|
- 2001 OR (cls
|
|
|
- 2002 = SymTab.ClEnum)
|
|
|
- 2003 OR (cls
|
|
|
- 2004 = SymTab.ClReal)
|
|
|
- 2005 OR (cls
|
|
|
- 2006 = SymTab.ClLong)
|
|
|
- 2007 OR (cls
|
|
|
- 2008 = SymTab.ClNil)) THEN
|
|
|
- 2009 IF cls = SymTab.ClNil THEN
|
|
|
- 2010 QbeGen.CopyOp("0", q)
|
|
|
- 2011 ELSIF ((cls
|
|
|
- 2012 = SymTab.ClInt)
|
|
|
- 2013 OR (cls
|
|
|
- 2014 = SymTab.ClChar)
|
|
|
- 2015 OR (cls
|
|
|
- 2016 = SymTab.ClEnum)
|
|
|
- 2017 OR (cls
|
|
|
- 2018 = SymTab.ClLong))
|
|
|
- 2019 AND SymTab.GetSymVal(n, cv)
|
|
|
- 2020 AND QbeGen.IsImm(cv) THEN
|
|
|
- 2021 QbeGen.CopyOp(cv, q)
|
|
|
- 2022 ELSE
|
|
|
- 2023 QbeGen.LoadVar(n,
|
|
|
- 2024 cls = SymTab.ClReal,
|
|
|
- 2025 q)
|
|
|
- 2026 END
|
|
|
- 2027 ELSIF (cls = SymTab.ClArray)
|
|
|
- 2028 OR (cls = SymTab.ClRecord)
|
|
|
- 2029 OR (cls = SymTab.ClClass)
|
|
|
- 2030 OR (cls = SymTab.ClStr)
|
|
|
- 2031 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 2032 (* aggregate constant:
|
|
|
- 2033 its value IS the
|
|
|
- 2034 descriptor address *)
|
|
|
- 2035 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
- 2036 QbeGen.CopyOp(cv, q)
|
|
|
- 2037 ELSE
|
|
|
- 2038 QbeGen.CopyOp("0", q)
|
|
|
- 2039 END
|
|
|
- 2040 ELSE
|
|
|
- 2041 IF t #
|
|
|
- 2042 SymTab.InvalidType THEN
|
|
|
- 2043 SemError(230)
|
|
|
- 2044 END;
|
|
|
- 2045 QbeGen.CopyOp("0", q)
|
|
|
- 2046 END
|
|
|
- 2047 END
|
|
|
- 2048 ELSIF (k = SymTab.KindVar)
|
|
|
- 2049 OR (k = SymTab.KindParam) THEN
|
|
|
- 2050 cls := SymTab.ClassOf(t);
|
|
|
- 2051 IF (cls # SymTab.ClInt)
|
|
|
- 2052 AND (cls # SymTab.ClBool)
|
|
|
- 2053 AND (cls # SymTab.ClChar)
|
|
|
- 2054 AND (cls # SymTab.ClUChar)
|
|
|
- 2055 AND (cls # SymTab.ClEnum)
|
|
|
- 2056 AND (cls # SymTab.ClReal)
|
|
|
- 2057 AND (cls # SymTab.ClPtr)
|
|
|
- 2058 AND (cls # SymTab.ClProc)
|
|
|
- 2059 AND (cls # SymTab.ClLong)
|
|
|
- 2060 AND (cls # SymTab.ClArray)
|
|
|
- 2061 AND (cls # SymTab.ClSet)
|
|
|
- 2062 AND (cls # SymTab.ClRecord)
|
|
|
- 2063 AND (cls # SymTab.ClUStr)
|
|
|
- 2064 AND (cls # SymTab.ClClass) THEN
|
|
|
- 2065 SemError(230);
|
|
|
- 2066 QbeGen.CopyOp("0", q)
|
|
|
- 2067 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2068 END
|
|
|
- 2069 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 2070 IF k = SymTab.KindImport THEN
|
|
|
- 2071 SemError(230)
|
|
|
- 2072 ELSIF k =
|
|
|
- 2073 SymTab.KindProc THEN
|
|
|
- 2074 (* bare procedure name:
|
|
|
- 2075 a following ArgList
|
|
|
- 2076 makes it a call;
|
|
|
- 2077 otherwise Fact
|
|
|
- 2078 reports 230 *)
|
|
|
- 2079 ELSE
|
|
|
- 2080 IF k = SymTab.KindField THEN
|
|
|
- 2081 IF QbeGen.TopWith(qb) THEN
|
|
|
- 2082 sfx := TRUE
|
|
|
- 2083 ELSE SemError(230);
|
|
|
- 2084 QbeGen.CopyOp("0", q)
|
|
|
- 2085 END
|
|
|
- 2086 END
|
|
|
- 2087 END
|
|
|
- 2088 END
|
|
|
- 2089 END; .)
|
|
|
- 2090 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
- 2091 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
|
|
|
- 2092 IF fwd THEN AST.SetOp(astDes, 1) END; .)
|
|
|
- 2093 { "[" Expr<it, iq>
|
|
|
- 2094 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2095 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2096 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2097 SymTab.ClArray THEN
|
|
|
- 2098 SemError(217);
|
|
|
- 2099 t := SymTab.InvalidType
|
|
|
- 2100 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2101 AND (SymTab.ClassOf(it) #
|
|
|
- 2102 SymTab.ClChar)
|
|
|
- 2103 AND (SymTab.ClassOf(it) #
|
|
|
- 2104 SymTab.ClEnum) THEN
|
|
|
- 2105 SemError(218);
|
|
|
- 2106 t := SymTab.InvalidType
|
|
|
- 2107 ELSE
|
|
|
- 2108 eT := SymTab.ArrayElem(t);
|
|
|
- 2109 t := eT; sfx := TRUE
|
|
|
- 2110 END; .)
|
|
|
- 2111 { "," Expr<it, iq>
|
|
|
- 2112 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2113 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2114 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2115 SymTab.ClArray THEN
|
|
|
- 2116 SemError(217);
|
|
|
- 2117 t := SymTab.InvalidType
|
|
|
- 2118 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2119 AND (SymTab.ClassOf(it) #
|
|
|
- 2120 SymTab.ClChar)
|
|
|
- 2121 AND (SymTab.ClassOf(it) #
|
|
|
- 2122 SymTab.ClEnum) THEN
|
|
|
- 2123 SemError(218);
|
|
|
- 2124 t := SymTab.InvalidType
|
|
|
- 2125 ELSE
|
|
|
- 2126 eT := SymTab.ArrayElem(t);
|
|
|
- 2127 t := eT; sfx := TRUE
|
|
|
- 2128 END; .) }
|
|
|
- 2129 "]"
|
|
|
- 2130 | "." GetIdent<fn>
|
|
|
- 2131 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2132 AST.SetOp(astSel, AST.SelField);
|
|
|
- 2133 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
- 2134 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
- 2135 (* qualified L.x: materialize
|
|
|
- 2136 the export, then load it *)
|
|
|
- 2137 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 2138 fn, mal) THEN
|
|
|
- 2139 SemError(201);
|
|
|
- 2140 t := SymTab.InvalidType;
|
|
|
- 2141 QbeGen.CopyOp("0", q)
|
|
|
- 2142 ELSE
|
|
|
- 2143 QbeGen.CopyOp(mal, qn);
|
|
|
- 2144 t := SymTab.SymType(mal);
|
|
|
- 2145 k := SymTab.SymKind(mal);
|
|
|
- 2146 sfx := FALSE;
|
|
|
- 2147 IF k = SymTab.KindProc THEN
|
|
|
- 2148 (* call: ArgList supplies
|
|
|
- 2149 the value *)
|
|
|
- 2150 QbeGen.CopyOp("0", q)
|
|
|
- 2151 END
|
|
|
- 2152 END
|
|
|
- 2153 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 2154 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2155 SymTab.ClRecord)
|
|
|
- 2156 AND (SymTab.ClassOf(t) #
|
|
|
- 2157 SymTab.ClClass) THEN
|
|
|
- 2158 SemError(215);
|
|
|
- 2159 t := SymTab.InvalidType
|
|
|
- 2160 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 2161 SymTab.ClClass)
|
|
|
- 2162 AND SymTab.MethodExists(t, fn) THEN
|
|
|
- 2163 (* obj.Method: bind the
|
|
|
- 2164 method and pass obj as
|
|
|
- 2165 the hidden receiver; q
|
|
|
- 2166 already holds the
|
|
|
- 2167 object's address *)
|
|
|
- 2168 QbeGen.CopyOp(fn, n);
|
|
|
- 2169 QbeGen.CopyOp(fn, qn);
|
|
|
- 2170 methCls := t;
|
|
|
- 2171 k := SymTab.KindProc;
|
|
|
- 2172 t := SymTab.InvalidType
|
|
|
- 2173 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2174 fn) THEN
|
|
|
- 2175 SemError(216);
|
|
|
- 2176 t := SymTab.InvalidType
|
|
|
- 2177 ELSE
|
|
|
- 2178 t := SymTab.FieldType(t, fn);
|
|
|
- 2179 sfx := TRUE
|
|
|
- 2180 END; .)
|
|
|
- 2181 | "^"
|
|
|
- 2182 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2183 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2184 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2185 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2186 SymTab.ClPtr THEN
|
|
|
- 2187 SemError(219);
|
|
|
- 2188 t := SymTab.InvalidType
|
|
|
- 2189 ELSE
|
|
|
- 2190 bt := SymTab.PtrBase(t);
|
|
|
- 2191 IF bt = SymTab.InvalidType THEN
|
|
|
- 2192 ELSE
|
|
|
- 2193 t := bt;
|
|
|
- 2194 sfx := TRUE
|
|
|
- 2195 END
|
|
|
- 2196 END; .) } (. astCur := astDes; .) .
|
|
|
- 2197 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
- 2198 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
- 2199 (a value, or a descriptor address for aggregates); each component
|
|
|
- 2200 descends one level exactly like the Design components. *)
|
|
|
- 2201 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2202 VAR sfx: BOOLEAN; VAR node: AST.Node> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
- 2203 iq, ql, qlo, qhi, qe, qb:
|
|
|
- 2204 QbeGen.QVal;
|
|
|
- 2205 lo, hi, fo: INTEGER;
|
|
|
- 2206 isOpen: BOOLEAN;
|
|
|
- 2207 fname: SymTab.Name;
|
|
|
- 2208 astWrap, astSel: AST.Node; .)
|
|
|
- 2209 = "[" Expr<it, iq>
|
|
|
- 2210 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2211 astWrap := AST.MakeNode(
|
|
|
- 2212 AST.NkDesignator);
|
|
|
- 2213 AST.SetChild(astWrap, 0, node);
|
|
|
- 2214 node := astWrap
|
|
|
- 2215 END;
|
|
|
- 2216 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2217 AST.MakeUn(AST.NkSelector,
|
|
|
- 2218 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2219 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2220 SymTab.ClArray THEN
|
|
|
- 2221 SemError(217);
|
|
|
+ 1016 AST.SetChild(astMethod, 2, astBlkDecls);
|
|
|
+ 1017 QbeGen.PopWith;
|
|
|
+ 1018 methRes := SymTab.CurRes();
|
|
|
+ 1019 Lower.ScopeLeave;
|
|
|
+ 1020 SymTab.CloseProc;
|
|
|
+ 1021 QbeGen.EndFunc(methRes); .) ) .
|
|
|
+ 1022 ConstBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1023 = "CONST" (. astSeq := AST.NoNode;
|
|
|
+ 1024 astTail := AST.NoNode; .)
|
|
|
+ 1025 { ConstDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1026 astSeq, astTail, astDecl); .) }
|
|
|
+ 1027 (. astDecl := astSeq; .) .
|
|
|
+ 1028 ConstDecl (. VAR n: SymTab.Name;
|
|
|
+ 1029 t: SymTab.TypeIndex;
|
|
|
+ 1030 qv: QbeGen.QVal;
|
|
|
+ 1031 cls: INTEGER;
|
|
|
+ 1032 astNode: AST.Node; .)
|
|
|
+ 1033 = GetIdent<n> (. IF NOT SymTab.Enter(n,
|
|
|
+ 1034 SymTab.KindConst) THEN
|
|
|
+ 1035 SemError(200) END; .)
|
|
|
+ 1036 "="
|
|
|
+ 1037 Expr<t, qv> (. astNode := AST.MakeNode(AST.NkConstDecl);
|
|
|
+ 1038 AST.SetChild(astNode, 0,
|
|
|
+ 1039 AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 1040 AST.SetChild(astNode, 1, astCur);
|
|
|
+ 1041 AST.SetTy(astNode, t);
|
|
|
+ 1042 astDecl := astNode;
|
|
|
+ 1043 Lower.NoteVar(n, SymTab.KindConst, t);
|
|
|
+ 1044 Lower.NoteConstVal(qv);
|
|
|
+ 1045 SymTab.SetSymType(n, t);
|
|
|
+ 1046 cls := SymTab.ClassOf(t);
|
|
|
+ 1047 IF (cls = SymTab.ClArray)
|
|
|
+ 1048 OR (cls = SymTab.ClRecord)
|
|
|
+ 1049 OR (cls = SymTab.ClClass)
|
|
|
+ 1050 OR (cls = SymTab.ClStr)
|
|
|
+ 1051 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 1052 (* an aggregate/string
|
|
|
+ 1053 constant: qv is its
|
|
|
+ 1054 descriptor address; no
|
|
|
+ 1055 scalar data *)
|
|
|
+ 1056 SymTab.SetSymVal(n, qv)
|
|
|
+ 1057 ELSIF NOT QbeGen.IsImm(qv) THEN
|
|
|
+ 1058 SemError(230)
|
|
|
+ 1059 ELSE
|
|
|
+ 1060 SymTab.SetSymVal(n, qv);
|
|
|
+ 1061 END; .) .
|
|
|
+ 1062 VarBlock (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1063 = "VAR" (. astSeq := AST.NoNode;
|
|
|
+ 1064 astTail := AST.NoNode; .)
|
|
|
+ 1065 { VarDecl ";" (. AstAppend(AST.NkDeclSeq,
|
|
|
+ 1066 astSeq, astTail, astDecl); .) }
|
|
|
+ 1067 (. astDecl := astSeq; .) .
|
|
|
+ 1068 VarDecl (. VAR nm: SymTab.Name;
|
|
|
+ 1069 t: SymTab.TypeIndex;
|
|
|
+ 1070 i: CARDINAL;
|
|
|
+ 1071 cls: INTEGER;
|
|
|
+ 1072 astNode, astTail: AST.Node; .)
|
|
|
+ 1073 = VarIdents ":"
|
|
|
+ 1074 Type<t, FALSE> (. astNode := AST.MakeNode(AST.NkVarDecl);
|
|
|
+ 1075 astTail := astNode;
|
|
|
+ 1076 i := 0;
|
|
|
+ 1077 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1078 SymTab.PendName(i, nm);
|
|
|
+ 1079 Lower.NoteVar(nm, SymTab.KindVar, t);
|
|
|
+ 1080 (* chunked: a VAR list can
|
|
|
+ 1081 exceed AST.MaxChild *)
|
|
|
+ 1082 AstAppend(AST.NkBlock,
|
|
|
+ 1083 astNode, astTail,
|
|
|
+ 1084 AST.MakeLeaf(AST.NkIdent, nm));
|
|
|
+ 1085 INC(i)
|
|
|
+ 1086 END;
|
|
|
+ 1087 AST.SetTy(astNode, t);
|
|
|
+ 1088 astDecl := astNode;
|
|
|
+ 1089 cls := SymTab.ClassOf(t);
|
|
|
+ 1090 IF (t # SymTab.InvalidType)
|
|
|
+ 1091 AND NOT SymTab.IsUnresolved(t)
|
|
|
+ 1092 AND (cls # SymTab.ClInt)
|
|
|
+ 1093 AND (cls # SymTab.ClBool)
|
|
|
+ 1094 AND (cls # SymTab.ClChar)
|
|
|
+ 1095 AND (cls # SymTab.ClReal)
|
|
|
+ 1096 AND (cls # SymTab.ClArray)
|
|
|
+ 1097 AND (cls # SymTab.ClSet)
|
|
|
+ 1098 AND (cls # SymTab.ClRecord)
|
|
|
+ 1099 AND (cls # SymTab.ClPtr)
|
|
|
+ 1100 AND (cls # SymTab.ClLong)
|
|
|
+ 1101 AND (cls # SymTab.ClProc)
|
|
|
+ 1102 AND (cls # SymTab.ClUChar)
|
|
|
+ 1103 AND (cls # SymTab.ClUStr)
|
|
|
+ 1104 AND (cls # SymTab.ClEnum)
|
|
|
+ 1105 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 1106 SemError(230) END;
|
|
|
+ 1107 IF QbeGen.LocFull() THEN
|
|
|
+ 1108 SemError(233) END;
|
|
|
+ 1109 i := 0;
|
|
|
+ 1110 IF SymTab.IsUnresolved(t)
|
|
|
+ 1111 AND NOT SymTab.InProc() THEN
|
|
|
+ 1112 (* a forward-typed global:
|
|
|
+ 1113 defer emission until the
|
|
|
+ 1114 TYPE block completes *)
|
|
|
+ 1115 AST.SetOp(astNode, 1);
|
|
|
+ 1116 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1117 SymTab.PendName(i, nm);
|
|
|
+ 1118 IF nPendVar <=
|
|
|
+ 1119 HIGH(pendVarName) THEN
|
|
|
+ 1120 pendVarName[nPendVar] := nm;
|
|
|
+ 1121 pendVarT[nPendVar] := t;
|
|
|
+ 1122 INC(nPendVar)
|
|
|
+ 1123 END;
|
|
|
+ 1124 INC(i)
|
|
|
+ 1125 END
|
|
|
+ 1126 ELSE
|
|
|
+ 1127 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1128 SymTab.PendName(i, nm);
|
|
|
+ 1129 INC(i)
|
|
|
+ 1130 END
|
|
|
+ 1131 END;
|
|
|
+ 1132 (* a plain VAR list, not a
|
|
|
+ 1133 heading: the signature
|
|
|
+ 1134 result is discarded *)
|
|
|
+ 1135 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1136 END; .) .
|
|
|
+ 1137 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 1138 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1139 SymTab.KindVar) THEN
|
|
|
+ 1140 SemError(200) END; .)
|
|
|
+ 1141 { ","
|
|
|
+ 1142 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1143 SymTab.KindVar) THEN
|
|
|
+ 1144 SemError(200) END; .) } .
|
|
|
+ 1145 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 1146 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1147 SemError(200) END; .)
|
|
|
+ 1148 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1149 SemError(200) END; .) } .
|
|
|
+ 1150 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
+ 1151 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
+ 1152 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 1153 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
+ 1154 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
+ 1155 (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1156 mg: QbeGen.QVal; .)
|
|
|
+ 1157 = "PROCEDURE"
|
|
|
+ 1158 GetIdent<pn> (. IF methCls #
|
|
|
+ 1159 SymTab.InvalidType THEN
|
|
|
+ 1160 (* a method: resume the
|
|
|
+ 1161 declared symbol (reuse
|
|
|
+ 1162 its uid) *)
|
|
|
+ 1163 IF NOT SymTab.ResumeMethod(
|
|
|
+ 1164 methCls, pn) THEN
|
|
|
+ 1165 SemError(200) END
|
|
|
+ 1166 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
+ 1167 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
+ 1168 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
+ 1169 SemError(200) END
|
|
|
+ 1170 END
|
|
|
+ 1171 END;
|
|
|
+ 1172 Lower.ScopeEnter;
|
|
|
+ 1173 Lower.NoteProc(pn,
|
|
|
+ 1174 SymTab.ProcUid(pn),
|
|
|
+ 1175 SymTab.InvalidType,
|
|
|
+ 1176 SymTab.ProcDepthOf(pn),
|
|
|
+ 1177 FALSE);
|
|
|
+ 1178 QbeGen.BeginFunc("");
|
|
|
+ 1179 IF methCls #
|
|
|
+ 1180 SymTab.InvalidType THEN
|
|
|
+ 1181 (* hidden THIS receiver:
|
|
|
+ 1182 a VAR param of the
|
|
|
+ 1183 class type, pushed as
|
|
|
+ 1184 the WITH base *)
|
|
|
+ 1185 IF NOT SymTab.EnterThisParam(
|
|
|
+ 1186 methCls) THEN
|
|
|
+ 1187 SemError(200) END;
|
|
|
+ 1188 IF NOT QbeGen.FuncParam(
|
|
|
+ 1189 "THIS", TRUE,
|
|
|
+ 1190 methCls) THEN
|
|
|
+ 1191 SemError(233) END
|
|
|
+ 1192 END; .)
|
|
|
+ 1193 [ FormalParams ]
|
|
|
+ 1194 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
+ 1195 SemError(235) END;
|
|
|
+ 1196 Lower.SetProcRes(t);
|
|
|
+ 1197 IF (t #
|
|
|
+ 1198 SymTab.InvalidType)
|
|
|
+ 1199 AND (SymTab.ClassOf(t)
|
|
|
+ 1200 = SymTab.ClClass) THEN
|
|
|
+ 1201 SemError(230) END; .) ] .
|
|
|
+ 1202 FormalParams
|
|
|
+ 1203 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 1204 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1205 nm: SymTab.Name;
|
|
|
+ 1206 i: CARDINAL;
|
|
|
+ 1207 isV: BOOLEAN; .)
|
|
|
+ 1208 = (. isV := FALSE; .)
|
|
|
+ 1209 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 1210 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
+ 1211 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1212 SymTab.PendName(i, nm);
|
|
|
+ 1213 Lower.NoteParam(nm, t, isV);
|
|
|
+ 1214 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
+ 1215 (* value open arrays are
|
|
|
+ 1216 passed as descriptor
|
|
|
+ 1217 addresses (no copy):
|
|
|
+ 1218 same representation as
|
|
|
+ 1219 VAR formals *)
|
|
|
+ 1220 IF NOT QbeGen.FuncParam(nm,
|
|
|
+ 1221 isV
|
|
|
+ 1222 OR SymTab.IsOpenArray(t),
|
|
|
+ 1223 t) THEN
|
|
|
+ 1224 SemError(233) END;
|
|
|
+ 1225 INC(i)
|
|
|
+ 1226 END;
|
|
|
+ 1227 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1228 SemError(235) END; .) .
|
|
|
+ 1229 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
+ 1230 static link gives them their parent's frame. Methods keep
|
|
|
+ 1231 parse-now/230-later. *)
|
|
|
+ 1232 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
+ 1233 astNode: AST.Node; .)
|
|
|
+ 1234 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1235 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1236 AST.SetOp(astNode, 0);
|
|
|
+ 1237 AST.SetChild(astNode, 0,
|
|
|
+ 1238 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1239 Lower.NoteProcNode(astNode); .)
|
|
|
+ 1240 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
+ 1241 astDecl := astNode;
|
|
|
+ 1242 Lower.ScopeLeave;
|
|
|
+ 1243 SymTab.MarkFwd;
|
|
|
+ 1244 SymTab.CloseProc;
|
|
|
+ 1245 QbeGen.AbortFunc; .)
|
|
|
+ 1246 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
+ 1247 astDecl := astNode;
|
|
|
+ 1248 Lower.MarkProcExternal;
|
|
|
+ 1249 Lower.ScopeLeave;
|
|
|
+ 1250 SymTab.MarkExternal("");
|
|
|
+ 1251 SymTab.CloseProc;
|
|
|
+ 1252 QbeGen.AbortFunc; .)
|
|
|
+ 1253 |
|
|
|
+ 1254 Block<pn> (. AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1255 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
+ 1256 astDecl := astNode;
|
|
|
+ 1257 Lower.ScopeLeave;
|
|
|
+ 1258 SymTab.CloseProc;
|
|
|
+ 1259 QbeGen.EndFunc(
|
|
|
+ 1260 SymTab.ProcRes(pn)); .) ) .
|
|
|
+ 1261 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
+ 1262 = DeclSeq (. astBlkDecls := astDecl;
|
|
|
+ 1263 astStmt := AST.NoNode; .)
|
|
|
+ 1264 [ "BEGIN" (. (* an empty body is still a
|
|
|
+ 1265 body: mark it so Lower
|
|
|
+ 1266 does not read it as a
|
|
|
+ 1267 definition heading *)
|
|
|
+ 1268 IF astStmt = AST.NoNode THEN
|
|
|
+ 1269 astStmt :=
|
|
|
+ 1270 AST.MakeNode(AST.NkBlock)
|
|
|
+ 1271 END; .)
|
|
|
+ 1272 [ StatSeq ] ]
|
|
|
+ 1273 "END"
|
|
|
+ 1274 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
+ 1275 SemError(202) END; .) .
|
|
|
+ 1276 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1277 = (. astSeq := AST.NoNode;
|
|
|
+ 1278 astTail := AST.NoNode; .)
|
|
|
+ 1279 Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 1280 astSeq, astTail, astStmt); .)
|
|
|
+ 1281 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 1282 astSeq, astTail, astStmt); .) ] }
|
|
|
+ 1283 (. astStmt := astSeq; .) .
|
|
|
+ 1284 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
+ 1285 are accepted: the statement after ';' is optional. *)
|
|
|
+ 1286 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
+ 1287 = (. astStmt := AST.NoNode; .)
|
|
|
+ 1288 ( AssOrCall
|
|
|
+ 1289 | IfStat
|
|
|
+ 1290 | WhileStat
|
|
|
+ 1291 | RepeatStat
|
|
|
+ 1292 | LoopStat
|
|
|
+ 1293 | ForStat
|
|
|
+ 1294 | CaseStat
|
|
|
+ 1295 | WithStat
|
|
|
+ 1296 | ReturnStat
|
|
|
+ 1297 | HaltStat
|
|
|
+ 1298 | NewStat
|
|
|
+ 1299 | DisposeStat
|
|
|
+ 1300 | IncDecStat
|
|
|
+ 1301 | InclExclStat
|
|
|
+ 1302 | "EXIT" (. IF NOT QbeGen.TopLoop(lx) THEN
|
|
|
+ 1303 SemError(230) END;
|
|
|
+ 1304 astStmt := AST.MakeNode(AST.NkExit); .) ) .
|
|
|
+ 1305 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
+ 1306 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
+ 1307 dk: INTEGER;
|
|
|
+ 1308 qd, qe: QbeGen.QVal;
|
|
|
+ 1309 qn: SymTab.Name;
|
|
|
+ 1310 sfx, isInc: BOOLEAN;
|
|
|
+ 1311 astNode, astD: AST.Node; .)
|
|
|
+ 1312 = ( "INCL" (. isInc := TRUE; .)
|
|
|
+ 1313 | "EXCL" (. isInc := FALSE; .) )
|
|
|
+ 1314 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
+ 1315 Expr<et2, qe> ")"
|
|
|
+ 1316 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1317 IF isInc THEN
|
|
|
+ 1318 AST.SetChild(astNode, 0,
|
|
|
+ 1319 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
+ 1320 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 1321 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
+ 1322 END;
|
|
|
+ 1323 IF astD # AST.NoNode THEN
|
|
|
+ 1324 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1325 IF astCur # AST.NoNode THEN
|
|
|
+ 1326 AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 1327 astStmt := astNode; .)
|
|
|
+ 1328 (. IF (at # SymTab.InvalidType)
|
|
|
+ 1329 AND (SymTab.ClassOf(at) # SymTab.ClSet) THEN
|
|
|
+ 1330 SemError(222)
|
|
|
+ 1331 END; .) .
|
|
|
+ 1332 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
+ 1333 integer designator. *)
|
|
|
+ 1334 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
+ 1335 dk: INTEGER;
|
|
|
+ 1336 qd, qv, qn2, qstep:
|
|
|
+ 1337 QbeGen.QVal;
|
|
|
+ 1338 qn: SymTab.Name;
|
|
|
+ 1339 sfx, isInc: BOOLEAN;
|
|
|
+ 1340 astNode, astD, astStep:
|
|
|
+ 1341 AST.Node; .)
|
|
|
+ 1342 = (. isInc := TRUE; .)
|
|
|
+ 1343 ( "INC" (. isInc := TRUE; .)
|
|
|
+ 1344 | "DEC" (. isInc := FALSE; .) )
|
|
|
+ 1345 "(" (. astStep := AST.NoNode; .)
|
|
|
+ 1346 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
+ 1347 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
+ 1348 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1349 IF isInc THEN
|
|
|
+ 1350 AST.SetChild(astNode, 0,
|
|
|
+ 1351 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
+ 1352 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 1353 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
+ 1354 END;
|
|
|
+ 1355 IF astD # AST.NoNode THEN
|
|
|
+ 1356 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1357 IF astStep # AST.NoNode THEN
|
|
|
+ 1358 AST.SetChild(astNode, 2, astStep) END;
|
|
|
+ 1359 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1360 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1361 AND (dk # SymTab.KindParam)
|
|
|
+ 1362 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1363 SemError(210)
|
|
|
+ 1364 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
+ 1365 SemError(211)
|
|
|
+ 1366 END; .) .
|
|
|
+ 1367 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
+ 1368 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
+ 1369 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
+ 1370 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1371 dk: INTEGER;
|
|
|
+ 1372 qd, qm: QbeGen.QVal;
|
|
|
+ 1373 qn: SymTab.Name;
|
|
|
+ 1374 sfx: BOOLEAN;
|
|
|
+ 1375 bt: SymTab.TypeIndex;
|
|
|
+ 1376 astNode, astD: AST.Node; .)
|
|
|
+ 1377 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 1378 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1379 AST.SetChild(astNode, 0,
|
|
|
+ 1380 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
+ 1381 IF astD # AST.NoNode THEN
|
|
|
+ 1382 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1383 astStmt := astNode; .)
|
|
|
+ 1384 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1385 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1386 AND (dk # SymTab.KindParam)
|
|
|
+ 1387 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1388 SemError(210)
|
|
|
+ 1389 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1390 SymTab.ClPtr THEN
|
|
|
+ 1391 SemError(219)
|
|
|
+ 1392 END; .) .
|
|
|
+ 1393 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1394 dk: INTEGER;
|
|
|
+ 1395 qd, qv: QbeGen.QVal;
|
|
|
+ 1396 qn: SymTab.Name;
|
|
|
+ 1397 sfx: BOOLEAN;
|
|
|
+ 1398 astNode, astD: AST.Node; .)
|
|
|
+ 1399 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 1400 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1401 AST.SetChild(astNode, 0,
|
|
|
+ 1402 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
+ 1403 IF astD # AST.NoNode THEN
|
|
|
+ 1404 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1405 astStmt := astNode; .)
|
|
|
+ 1406 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1407 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1408 AND (dk # SymTab.KindParam)
|
|
|
+ 1409 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1410 SemError(210)
|
|
|
+ 1411 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1412 SymTab.ClPtr THEN
|
|
|
+ 1413 SemError(219)
|
|
|
+ 1414 END; .) .
|
|
|
+ 1415 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
+ 1416 address; field designators resolve through both stacks. *)
|
|
|
+ 1417 WithStat (. VAR nW: CARDINAL;
|
|
|
+ 1418 astNode: AST.Node; .)
|
|
|
+ 1419 = "WITH" (. nW := 0;
|
|
|
+ 1420 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
+ 1421 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
+ 1422 "DO" (. astStmt := AST.NoNode; .)
|
|
|
+ 1423 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
+ 1424 AST.NChild(astNode), astStmt);
|
|
|
+ 1425 astStmt := astNode;
|
|
|
+ 1426 WHILE nW > 0 DO
|
|
|
+ 1427 SymTab.PopScope;
|
|
|
+ 1428 QbeGen.PopWith;
|
|
|
+ 1429 DEC(nW)
|
|
|
+ 1430 END; .) .
|
|
|
+ 1431 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
+ 1432 (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1433 dk: INTEGER;
|
|
|
+ 1434 qd, qe: QbeGen.QVal;
|
|
|
+ 1435 qn: SymTab.Name;
|
|
|
+ 1436 sfx: BOOLEAN; .)
|
|
|
+ 1437 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 1438 (. IF astCur # AST.NoNode THEN
|
|
|
+ 1439 AST.SetChild(wnode,
|
|
|
+ 1440 AST.NChild(wnode), astCur) END;
|
|
|
+ 1441 IF dt = SymTab.InvalidType THEN
|
|
|
+ 1442 ELSIF (SymTab.ClassOf(dt) #
|
|
|
+ 1443 SymTab.ClRecord)
|
|
|
+ 1444 AND (SymTab.ClassOf(dt) #
|
|
|
+ 1445 SymTab.ClClass) THEN
|
|
|
+ 1446 SemError(215)
|
|
|
+ 1447 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
+ 1448 QbeGen.PushWith(qd);
|
|
|
+ 1449 INC(nW)
|
|
|
+ 1450 END; .) .
|
|
|
+ 1451 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
+ 1452 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
+ 1453 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 1454 dk: INTEGER;
|
|
|
+ 1455 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
+ 1456 qn: SymTab.Name;
|
|
|
+ 1457 ct2, res0: SymTab.TypeIndex;
|
|
|
+ 1458 q2, mg0: QbeGen.QVal;
|
|
|
+ 1459 isR, conv, wconv: BOOLEAN;
|
|
|
+ 1460 called, sfx: BOOLEAN;
|
|
|
+ 1461 astLhs, astRes: AST.Node; .)
|
|
|
+ 1462 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 1463 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
+ 1464 ( ":="
|
|
|
+ 1465 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 1466 AST.NkAssign, 0, astLhs, astCur);
|
|
|
+ 1467 IF (dt # SymTab.InvalidType)
|
|
|
+ 1468 AND (dk # SymTab.KindVar)
|
|
|
+ 1469 AND (dk # SymTab.KindParam)
|
|
|
+ 1470 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1471 SemError(210)
|
|
|
+ 1472 ELSIF NOT SymTab.Assignable(et,
|
|
|
+ 1473 dt) THEN
|
|
|
+ 1474 SemError(210)
|
|
|
+ 1475 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 1476 AND (SymTab.ClassOf(dt) =
|
|
|
+ 1477 SymTab.ClClass) THEN
|
|
|
+ 1478 SemError(230) END;
|
|
|
+ 1479 isR := (dt #
|
|
|
+ 1480 SymTab.InvalidType)
|
|
|
+ 1481 AND (SymTab.ClassOf(dt)
|
|
|
+ 1482 = SymTab.ClReal);
|
|
|
+ 1483 conv := isR
|
|
|
+ 1484 AND SymTab.IsIntFamily(et);
|
|
|
+ 1485 wconv := (dt #
|
|
|
+ 1486 SymTab.InvalidType)
|
|
|
+ 1487 AND SymTab.IsLongFamily(dt)
|
|
|
+ 1488 AND SymTab.IsIntFamily(et);
|
|
|
+ 1489 IF ((dk = SymTab.KindVar)
|
|
|
+ 1490 OR (dk = SymTab.KindParam)
|
|
|
+ 1491 OR (dk = SymTab.KindField))
|
|
|
+ 1492 AND (dt # SymTab.InvalidType)
|
|
|
+ 1493 AND (et # SymTab.InvalidType)
|
|
|
+ 1494 AND (SymTab.ClassOf(dt) #
|
|
|
+ 1495 SymTab.ClClass) THEN
|
|
|
+ 1496 END; .)
|
|
|
+ 1497 | ArgList<qn, dt, qd, TRUE, TRUE, methCls, ct2, q2, called>
|
|
|
+ 1498 (. astRes := AstCallNode(astLhs);
|
|
|
+ 1499 sfx := FALSE; .)
|
|
|
+ 1500 ( { ResultComp<ct2, q2, sfx, astRes> }
|
|
|
+ 1501 ":=" Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 1502 AST.NkAssign, 0, astRes, astCur);
|
|
|
+ 1503 IF NOT sfx THEN
|
|
|
+ 1504 SemError(233)
|
|
|
+ 1505 ELSIF (ct2 # SymTab.InvalidType)
|
|
|
+ 1506 AND NOT SymTab.Assignable(et, ct2) THEN
|
|
|
+ 1507 SemError(210)
|
|
|
+ 1508 END; .)
|
|
|
+ 1509 | (. IF ct2 #
|
|
|
+ 1510 SymTab.InvalidType THEN
|
|
|
+ 1511 SemError(233) END;
|
|
|
+ 1512 astStmt := astRes; .) )
|
|
|
+ 1513 | (* bare `P;`: proper parameterless
|
|
|
+ 1514 procedure call; anything else
|
|
|
+ 1515 here is 233 (was a bare syntax
|
|
|
+ 1516 error before 4.2) *)
|
|
|
+ 1517 (. astStmt := AstCallNode(astLhs);
|
|
|
+ 1518 IF (dk = SymTab.KindProc)
|
|
|
+ 1519 AND NOT sfx THEN
|
|
|
+ 1520 res0 := SymTab.ProcRes(qn);
|
|
|
+ 1521 IF res0 #
|
|
|
+ 1522 SymTab.InvalidType THEN
|
|
|
+ 1523 SemError(233)
|
|
|
+ 1524 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 1525 0 THEN
|
|
|
+ 1526 SemError(233)
|
|
|
+ 1527 END
|
|
|
+ 1528 ELSE SemError(233)
|
|
|
+ 1529 END; .) ) .
|
|
|
+ 1530 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 1531 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 1532 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 1533 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 1534 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 1535 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
+ 1536 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 1537 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
+ 1538 vs: INTEGER;
|
|
|
+ 1539 res: SymTab.TypeIndex;
|
|
|
+ 1540 mg: QbeGen.QVal;
|
|
|
+ 1541 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
+ 1542 = "(" (. called := TRUE;
|
|
|
+ 1543 ok := TRUE;
|
|
|
+ 1544 ind := FALSE;
|
|
|
+ 1545 isMeth := methCls #
|
|
|
+ 1546 SymTab.InvalidType;
|
|
|
+ 1547 IF isMeth THEN
|
|
|
+ 1548 res := SymTab.ClassMethodRes(methCls, pn)
|
|
|
+ 1549 ELSIF SymTab.SymKind(pn) = SymTab.KindProc THEN
|
|
|
+ 1550 res := SymTab.ProcRes(pn)
|
|
|
+ 1551 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 1552 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 1553 ind := TRUE;
|
|
|
+ 1554 res := SymTab.ProcTypeRes(pt)
|
|
|
+ 1555 ELSE SemError(233);
|
|
|
+ 1556 ok := FALSE;
|
|
|
+ 1557 res := SymTab.InvalidType
|
|
|
+ 1558 END;
|
|
|
+ 1559 i := 0; .)
|
|
|
+ 1560 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
+ 1561 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
+ 1562 ")" (. IF ok THEN
|
|
|
+ 1563 IF isMeth THEN
|
|
|
+ 1564 np := SymTab.ClassMethodNPar(
|
|
|
+ 1565 methCls, pn)
|
|
|
+ 1566 ELSIF ind THEN
|
|
|
+ 1567 np := SymTab.ProcTypeNPar(pt)
|
|
|
+ 1568 ELSE np := SymTab.ProcNPar(pn)
|
|
|
+ 1569 END;
|
|
|
+ 1570 va := (NOT isMeth) AND (NOT ind)
|
|
|
+ 1571 AND (SymTab.SymKind(pn) =
|
|
|
+ 1572 SymTab.KindProc)
|
|
|
+ 1573 AND SymTab.Varargs(pn);
|
|
|
+ 1574 IF (i # np) AND NOT va THEN
|
|
|
+ 1575 SemError(233); ok := FALSE
|
|
|
+ 1576 END
|
|
|
+ 1577 END;
|
|
|
+ 1578 IF NOT ok THEN
|
|
|
+ 1579 t := SymTab.InvalidType;
|
|
|
+ 1580 QbeGen.CopyOp("0", q)
|
|
|
+ 1581 ELSIF want THEN
|
|
|
+ 1582 IF res =
|
|
|
+ 1583 SymTab.InvalidType THEN
|
|
|
+ 1584 IF NOT soft THEN SemError(233) END;
|
|
|
+ 1585 t := SymTab.InvalidType;
|
|
|
+ 1586 QbeGen.CopyOp("0", q)
|
|
|
+ 1587 ELSE t := res;
|
|
|
+ 1588 QbeGen.CopyOp("@", q)
|
|
|
+ 1589 END
|
|
|
+ 1590 ELSE
|
|
|
+ 1591 IF res #
|
|
|
+ 1592 SymTab.InvalidType THEN
|
|
|
+ 1593 SemError(233)
|
|
|
+ 1594 END;
|
|
|
+ 1595 t := SymTab.InvalidType;
|
|
|
+ 1596 QbeGen.CopyOp("0", q);
|
|
|
+ 1597 END; .) .
|
|
|
+ 1598 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 1599 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 1600 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 1601 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
+ 1602 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 1603 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 1604 isV, conv, va: BOOLEAN;
|
|
|
+ 1605 cl: CHAR;
|
|
|
+ 1606 savedN, aj: CARDINAL;
|
|
|
+ 1607 savedArgs: ARRAY [0 .. 31]
|
|
|
+ 1608 OF AST.Node;
|
|
|
+ 1609 astActual: AST.Node; .)
|
|
|
+ 1610 = (. (* Parsing the actual can clobber
|
|
|
+ 1611 the enclosing call's argument
|
|
|
+ 1612 list (Factor resets astNArgs),
|
|
|
+ 1613 so save/restore it. *)
|
|
|
+ 1614 savedN := astNArgs; aj := 0;
|
|
|
+ 1615 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 1616 savedArgs[aj] := astArgs[aj];
|
|
|
+ 1617 INC(aj)
|
|
|
+ 1618 END; .)
|
|
|
+ 1619 Expr<at, qe> (. astActual := astCur;
|
|
|
+ 1620 astNArgs := savedN; aj := 0;
|
|
|
+ 1621 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 1622 astArgs[aj] := savedArgs[aj];
|
|
|
+ 1623 INC(aj)
|
|
|
+ 1624 END;
|
|
|
+ 1625 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
+ 1626 astArgs[astNArgs] := astCur;
|
|
|
+ 1627 INC(astNArgs)
|
|
|
+ 1628 END;
|
|
|
+ 1629 va := (NOT ind)
|
|
|
+ 1630 AND (methCls =
|
|
|
+ 1631 SymTab.InvalidType)
|
|
|
+ 1632 AND (SymTab.SymKind(pn) =
|
|
|
+ 1633 SymTab.KindProc)
|
|
|
+ 1634 AND SymTab.Varargs(pn);
|
|
|
+ 1635 IF ind THEN
|
|
|
+ 1636 ft :=
|
|
|
+ 1637 SymTab.ProcTypeParamType(pt,
|
|
|
+ 1638 i);
|
|
|
+ 1639 isV :=
|
|
|
+ 1640 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 1641 i)
|
|
|
+ 1642 ELSIF methCls #
|
|
|
+ 1643 SymTab.InvalidType THEN
|
|
|
+ 1644 ft :=
|
|
|
+ 1645 SymTab.ClassMethodParamType(
|
|
|
+ 1646 methCls, pn, i);
|
|
|
+ 1647 isV :=
|
|
|
+ 1648 SymTab.ClassMethodParamIsVar(
|
|
|
+ 1649 methCls, pn, i)
|
|
|
+ 1650 ELSE
|
|
|
+ 1651 ft := SymTab.ParamType(pn, i);
|
|
|
+ 1652 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 1653 END;
|
|
|
+ 1654 IF (at = SymTab.InvalidType) THEN
|
|
|
+ 1655 ELSIF ft = SymTab.InvalidType THEN
|
|
|
+ 1656 ELSIF isV THEN
|
|
|
+ 1657 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 1658 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1659 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 1660 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1661 ELSIF (AST.Kind(astActual) #
|
|
|
+ 1662 AST.NkDesignator)
|
|
|
+ 1663 AND (AST.Kind(astActual) # AST.NkStrLit) THEN
|
|
|
+ 1664 SemError(233)
|
|
|
+ 1665 ELSIF NOT SymTab.VarParamOk(at, ft) THEN
|
|
|
+ 1666 SemError(233)
|
|
|
+ 1667 END
|
|
|
+ 1668 ELSE
|
|
|
+ 1669 IF (SymTab.ClassOf(at) = SymTab.ClChar)
|
|
|
+ 1670 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1671 AND (SymTab.ClassOf(SymTab.ArrayElem(ft)) = SymTab.ClChar)
|
|
|
+ 1672 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1673 ELSIF NOT SymTab.Assignable(at, ft) THEN
|
|
|
+ 1674 SemError(233)
|
|
|
+ 1675 END
|
|
|
+ 1676 END; .) .
|
|
|
+ 1677 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1678 q: QbeGen.QVal;
|
|
|
+ 1679 hasElse: BOOLEAN;
|
|
|
+ 1680 astCond, astIf, astLast,
|
|
|
+ 1681 astNode: AST.Node; .)
|
|
|
+ 1682 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 1683 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 1684 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1685 SemError(214) END; .)
|
|
|
+ 1686 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 1687 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1688 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1689 astIf := astNode;
|
|
|
+ 1690 astLast := astNode; .)
|
|
|
+ 1691 { "ELSIF"
|
|
|
+ 1692 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 1693 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1694 SemError(214) END; .)
|
|
|
+ 1695 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 1696 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1697 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1698 AST.SetChild(astLast, 2, astNode);
|
|
|
+ 1699 astLast := astNode; .) }
|
|
|
+ 1700 [ "ELSE" (. hasElse := TRUE;
|
|
|
+ 1701 astStmt := AST.NoNode; .)
|
|
|
+ 1702 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
+ 1703 "END" (. astStmt := astIf; .) .
|
|
|
+ 1704 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1705 q: QbeGen.QVal;
|
|
|
+ 1706 astCond, astNode: AST.Node; .)
|
|
|
+ 1707 = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
+ 1708 Expr<t, q> (. astCond := astCur;
|
|
|
+ 1709 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1710 SemError(214) END; .)
|
|
|
+ 1711 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ 1712 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1713 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1714 astStmt := astNode; .)
|
|
|
+ 1715 "END" .
|
|
|
+ 1716 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1717 q: QbeGen.QVal;
|
|
|
+ 1718 astCond, astBody, astNode:
|
|
|
+ 1719 AST.Node; .)
|
|
|
+ 1720 = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
+ 1721 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
+ 1722 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
+ 1723 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
+ 1724 AST.SetChild(astNode, 0, astBody);
|
|
|
+ 1725 AST.SetChild(astNode, 1, astCond);
|
|
|
+ 1726 astStmt := astNode;
|
|
|
+ 1727 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1728 SemError(214) END; .) .
|
|
|
+ 1729 LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ 1730 = "LOOP" (. astStmt := AST.NoNode;
|
|
|
+ 1731 QbeGen.NewLabel(lEnd);
|
|
|
+ 1732 QbeGen.PushLoop(lEnd); .)
|
|
|
+ 1733 [ StatSeq ]
|
|
|
+ 1734 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
+ 1735 AST.SetChild(astNode, 0, astStmt);
|
|
|
+ 1736 astStmt := astNode;
|
|
|
+ 1737 QbeGen.PopLoop; .) .
|
|
|
+ 1738 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 1739 Runtime direction would need a compare-select; the literal
|
|
|
+ 1740 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 1741 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 1742 tlo, thi, tby:
|
|
|
+ 1743 SymTab.TypeIndex;
|
|
|
+ 1744 qlo, qhi, qby, qt, qk, qb:
|
|
|
+ 1745 QbeGen.QVal;
|
|
|
+ 1746 lTop, lBody, lEnd:
|
|
|
+ 1747 QbeGen.QVal;
|
|
|
+ 1748 by: INTEGER;
|
|
|
+ 1749 ok: BOOLEAN;
|
|
|
+ 1750 astVar, astLo, astHi, astBy,
|
|
|
+ 1751 astNode: AST.Node; .)
|
|
|
+ 1752 = "FOR" (. by := 1; .)
|
|
|
+ 1753 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
+ 1754 astStmt := AST.NoNode;
|
|
|
+ 1755 astBy := AST.NoNode;
|
|
|
+ 1756 ok := SymTab.Lookup(lv);
|
|
|
+ 1757 IF NOT ok THEN
|
|
|
+ 1758 SemError(201)
|
|
|
+ 1759 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 1760 SymTab.KindVar)
|
|
|
+ 1761 AND (SymTab.SymKind(lv) #
|
|
|
+ 1762 SymTab.KindParam) THEN
|
|
|
+ 1763 SemError(220); ok := FALSE
|
|
|
+ 1764 ELSIF NOT SymTab.IsIntFamily(
|
|
|
+ 1765 SymTab.SymType(lv)) THEN
|
|
|
+ 1766 SemError(220); ok := FALSE
|
|
|
+ 1767 END; .)
|
|
|
+ 1768 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
+ 1769 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 1770 SemError(220); ok := FALSE
|
|
|
+ 1771 END; .)
|
|
|
+ 1772 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
+ 1773 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
+ 1774 SemError(220); ok := FALSE
|
|
|
+ 1775 END; .)
|
|
|
+ 1776 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
+ 1777 IF (tby #
|
|
|
+ 1778 SymTab.InvalidType)
|
|
|
+ 1779 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 1780 SemError(220); ok := FALSE
|
|
|
+ 1781 END;
|
|
|
+ 1782 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 1783 SemError(230); by := 1
|
|
|
+ 1784 ELSIF by = 0 THEN
|
|
|
+ 1785 SemError(220); by := 1
|
|
|
+ 1786 END; .) ]
|
|
|
+ 1787 "DO"
|
|
|
+ 1788 [ StatSeq ]
|
|
|
+ 1789 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
+ 1790 AST.SetChild(astNode, 0, astVar);
|
|
|
+ 1791 AST.SetChild(astNode, 1, astLo);
|
|
|
+ 1792 AST.SetChild(astNode, 2, astHi);
|
|
|
+ 1793 AST.SetChild(astNode, 3, astBy);
|
|
|
+ 1794 AST.SetChild(astNode, 4, astStmt);
|
|
|
+ 1795 astStmt := astNode;
|
|
|
+ 1796 .) .
|
|
|
+ 1797 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 1798 qsel, lEnd: QbeGen.QVal;
|
|
|
+ 1799 arm, astNode, astArms,
|
|
|
+ 1800 astArmsTail: AST.Node; .)
|
|
|
+ 1801 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ 1802 AST.SetChild(astNode, 0, astCur);
|
|
|
+ 1803 astArms := AST.NoNode;
|
|
|
+ 1804 astArmsTail := AST.NoNode;
|
|
|
+ 1805 .)
|
|
|
+ 1806 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
+ 1807 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
+ 1808 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ 1809 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 1810 AST.SetOp(arm, 1);
|
|
|
+ 1811 AST.SetChild(arm, 0, astStmt);
|
|
|
+ 1812 AstAppend(AST.NkBlock,
|
|
|
+ 1813 astArms, astArmsTail, arm); .) ]
|
|
|
+ 1814 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
+ 1815 astStmt := astNode;
|
|
|
+ 1816 .) .
|
|
|
+ 1817 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 1818 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 1819 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 1820 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 1821 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 1822 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
+ 1823 (. VAR arm: AST.Node; .)
|
|
|
+ 1824 = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
+ 1825 CaseLabel<tsel, qsel, arm>
|
|
|
+ 1826 { "," CaseLabel<tsel, qsel, arm> }
|
|
|
+ 1827 ":" (. astStmt := AST.NoNode; .)
|
|
|
+ 1828 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ 1829 astStmt);
|
|
|
+ 1830 AstAppend(AST.NkBlock,
|
|
|
+ 1831 arms, armsTail, arm);
|
|
|
+ 1832 .) .
|
|
|
+ 1833 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 1834 arm: AST.Node>
|
|
|
+ 1835 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 1836 q2, q3, qc, qd, qe:
|
|
|
+ 1837 QbeGen.QVal;
|
|
|
+ 1838 astLab: AST.Node;
|
|
|
+ 1839 lNext: QbeGen.QVal; .)
|
|
|
+ 1840 = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ 1841 IF (t2 #
|
|
|
+ 1842 SymTab.InvalidType)
|
|
|
+ 1843 AND (tsel #
|
|
|
+ 1844 SymTab.InvalidType)
|
|
|
+ 1845 AND ((SymTab.ClassOf(t2) =
|
|
|
+ 1846 SymTab.ClSet)
|
|
|
+ 1847 OR (SymTab.ClassOf(tsel) =
|
|
|
+ 1848 SymTab.ClSet)) THEN
|
|
|
+ 1849 SemError(230)
|
|
|
+ 1850 ELSIF (t2 #
|
|
|
+ 1851 SymTab.InvalidType)
|
|
|
+ 1852 AND (tsel #
|
|
|
+ 1853 SymTab.InvalidType)
|
|
|
+ 1854 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 1855 tsel) THEN
|
|
|
+ 1856 SemError(213) END;
|
|
|
+ 1857 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 1858 SemError(230)
|
|
|
+ 1859 END; .)
|
|
|
+ 1860 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ 1861 AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ 1862 IF (t3 #
|
|
|
+ 1863 SymTab.InvalidType)
|
|
|
+ 1864 AND (tsel #
|
|
|
+ 1865 SymTab.InvalidType)
|
|
|
+ 1866 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 1867 tsel) THEN
|
|
|
+ 1868 SemError(213) END;
|
|
|
+ 1869 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 1870 SemError(230)
|
|
|
+ 1871 END; .) ]
|
|
|
+ 1872 (. AST.SetChild(arm,
|
|
|
+ 1873 AST.NChild(arm), astLab); .) .
|
|
|
+ 1874 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1875 q, qt: QbeGen.QVal;
|
|
|
+ 1876 res: SymTab.TypeIndex;
|
|
|
+ 1877 hadE, conv: BOOLEAN;
|
|
|
+ 1878 astVal, astNode: AST.Node; .)
|
|
|
+ 1879 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
+ 1880 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
+ 1881 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
+ 1882 IF hadE THEN
|
|
|
+ 1883 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 1884 END;
|
|
|
+ 1885 astStmt := astNode;
|
|
|
+ 1886 conv := FALSE;
|
|
|
+ 1887 IF NOT SymTab.InProc() THEN
|
|
|
+ 1888 SemError(232)
|
|
|
+ 1889 ELSE res := SymTab.CurRes();
|
|
|
+ 1890 IF NOT hadE THEN
|
|
|
+ 1891 IF res #
|
|
|
+ 1892 SymTab.InvalidType THEN
|
|
|
+ 1893 SemError(232)
|
|
|
+ 1894 END
|
|
|
+ 1895 ELSIF (res =
|
|
|
+ 1896 SymTab.InvalidType)
|
|
|
+ 1897 OR (t #
|
|
|
+ 1898 SymTab.InvalidType)
|
|
|
+ 1899 AND NOT SymTab.Assignable(t,
|
|
|
+ 1900 res) THEN
|
|
|
+ 1901 SemError(232)
|
|
|
+ 1902 END
|
|
|
+ 1903 END; .) .
|
|
|
+ 1904 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1905 q: QbeGen.QVal;
|
|
|
+ 1906 astVal, astNode: AST.Node; .)
|
|
|
+ 1907 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
+ 1908 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
+ 1909 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
+ 1910 IF astVal # AST.NoNode THEN
|
|
|
+ 1911 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 1912 END;
|
|
|
+ 1913 astStmt := astNode;
|
|
|
+ 1914 .) .
|
|
|
+ 1915 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 1916 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 1917 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 1918 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 1919 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 1920 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 1921 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 1922 (. VAR n, fn, mal: SymTab.Name;
|
|
|
+ 1923 cls: INTEGER;
|
|
|
+ 1924 ic: SymTab.TypeIndex;
|
|
|
+ 1925 curT, it, eT, bt:
|
|
|
+ 1926 SymTab.TypeIndex;
|
|
|
+ 1927 iq, ql, qlo, qhi, qe:
|
|
|
+ 1928 QbeGen.QVal;
|
|
|
+ 1929 lo, hi: INTEGER;
|
|
|
+ 1930 fo: INTEGER;
|
|
|
+ 1931 isOpen: BOOLEAN;
|
|
|
+ 1932 qb, cv: QbeGen.QVal;
|
|
|
+ 1933 fid, fref, slot: INTEGER;
|
|
|
+ 1934 r: BOOLEAN;
|
|
|
+ 1935 astDes, astSel: AST.Node;
|
|
|
+ 1936 fwd: BOOLEAN; .)
|
|
|
+ 1937 = GetIdent<n> (. methCls := SymTab.InvalidType;
|
|
|
+ 1938 QbeGen.CopyOp(n, qn);
|
|
|
+ 1939 sfx := FALSE; fwd := FALSE;
|
|
|
+ 1940 fid := 0; fref := 0; slot := 0;
|
|
|
+ 1941 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 1942 (* a bare method name inside
|
|
|
+ 1943 a CLASS IMPLEMENTATION
|
|
|
+ 1944 is a sibling call on
|
|
|
+ 1945 THIS *)
|
|
|
+ 1946 ic := SymTab.CurImplClass();
|
|
|
+ 1947 IF (ic #
|
|
|
+ 1948 SymTab.InvalidType)
|
|
|
+ 1949 AND SymTab.MethodExists(ic, n) THEN
|
|
|
+ 1950 sfx := FALSE;
|
|
|
+ 1951 QbeGen.CopyOp("@", q);
|
|
|
+ 1952 methCls := ic;
|
|
|
+ 1953 k := SymTab.KindProc;
|
|
|
+ 1954 t := SymTab.InvalidType
|
|
|
+ 1955 ELSIF SymTab.InProc() THEN
|
|
|
+ 1956 (* not declared yet: a
|
|
|
+ 1957 forward reference to a
|
|
|
+ 1958 module-level variable
|
|
|
+ 1959 declared further down. *)
|
|
|
+ 1960 k := SymTab.KindVar;
|
|
|
+ 1961 r := SymTab.FwdVarRef(n, k,
|
|
|
+ 1962 fref, t);
|
|
|
+ 1963 FwdVarNote(fref, 0);
|
|
|
+ 1964 QbeGen.CopyOp("@", q);
|
|
|
+ 1965 sfx := TRUE; fwd := TRUE
|
|
|
+ 1966 ELSE
|
|
|
+ 1967 SemError(201);
|
|
|
+ 1968 t :=
|
|
|
+ 1969 SymTab.InvalidType;
|
|
|
+ 1970 k := -1;
|
|
|
+ 1971 QbeGen.CopyOp("0", q)
|
|
|
+ 1972 END
|
|
|
+ 1973 ELSE
|
|
|
+ 1974 t := SymTab.SymType(n);
|
|
|
+ 1975 k := SymTab.SymKind(n);
|
|
|
+ 1976 IF k = SymTab.KindConst THEN
|
|
|
+ 1977 IF SymTab.Equal(n,
|
|
|
+ 1978 "TRUE") THEN
|
|
|
+ 1979 t := SymTab.BoolType();
|
|
|
+ 1980 QbeGen.CopyOp("1", q)
|
|
|
+ 1981 ELSIF SymTab.Equal(n,
|
|
|
+ 1982 "FALSE") THEN
|
|
|
+ 1983 t := SymTab.BoolType();
|
|
|
+ 1984 QbeGen.CopyOp("0", q)
|
|
|
+ 1985 ELSIF SymTab.Equal(n,
|
|
|
+ 1986 "NIL") THEN
|
|
|
+ 1987 QbeGen.CopyOp("0", q)
|
|
|
+ 1988 ELSE
|
|
|
+ 1989 cls :=
|
|
|
+ 1990 SymTab.ClassOf(t);
|
|
|
+ 1991 IF (t #
|
|
|
+ 1992 SymTab.InvalidType)
|
|
|
+ 1993 AND ((cls = SymTab.ClInt)
|
|
|
+ 1994 OR (cls
|
|
|
+ 1995 = SymTab.ClChar)
|
|
|
+ 1996 OR (cls
|
|
|
+ 1997 = SymTab.ClEnum)
|
|
|
+ 1998 OR (cls
|
|
|
+ 1999 = SymTab.ClReal)
|
|
|
+ 2000 OR (cls
|
|
|
+ 2001 = SymTab.ClLong)
|
|
|
+ 2002 OR (cls
|
|
|
+ 2003 = SymTab.ClNil)) THEN
|
|
|
+ 2004 IF cls = SymTab.ClNil THEN
|
|
|
+ 2005 QbeGen.CopyOp("0", q)
|
|
|
+ 2006 ELSIF ((cls
|
|
|
+ 2007 = SymTab.ClInt)
|
|
|
+ 2008 OR (cls
|
|
|
+ 2009 = SymTab.ClChar)
|
|
|
+ 2010 OR (cls
|
|
|
+ 2011 = SymTab.ClEnum)
|
|
|
+ 2012 OR (cls
|
|
|
+ 2013 = SymTab.ClLong))
|
|
|
+ 2014 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 2015 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 2016 QbeGen.CopyOp(cv, q)
|
|
|
+ 2017 ELSE
|
|
|
+ 2018 QbeGen.LoadVar(n,
|
|
|
+ 2019 cls = SymTab.ClReal,
|
|
|
+ 2020 q)
|
|
|
+ 2021 END
|
|
|
+ 2022 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 2023 OR (cls = SymTab.ClRecord)
|
|
|
+ 2024 OR (cls = SymTab.ClClass)
|
|
|
+ 2025 OR (cls = SymTab.ClStr)
|
|
|
+ 2026 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 2027 (* aggregate constant:
|
|
|
+ 2028 its value IS the
|
|
|
+ 2029 descriptor address *)
|
|
|
+ 2030 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ 2031 QbeGen.CopyOp(cv, q)
|
|
|
+ 2032 ELSE
|
|
|
+ 2033 QbeGen.CopyOp("0", q)
|
|
|
+ 2034 END
|
|
|
+ 2035 ELSE
|
|
|
+ 2036 IF t #
|
|
|
+ 2037 SymTab.InvalidType THEN
|
|
|
+ 2038 SemError(230)
|
|
|
+ 2039 END;
|
|
|
+ 2040 QbeGen.CopyOp("0", q)
|
|
|
+ 2041 END
|
|
|
+ 2042 END
|
|
|
+ 2043 ELSIF (k = SymTab.KindVar)
|
|
|
+ 2044 OR (k = SymTab.KindParam) THEN
|
|
|
+ 2045 cls := SymTab.ClassOf(t);
|
|
|
+ 2046 IF (cls # SymTab.ClInt)
|
|
|
+ 2047 AND (cls # SymTab.ClBool)
|
|
|
+ 2048 AND (cls # SymTab.ClChar)
|
|
|
+ 2049 AND (cls # SymTab.ClUChar)
|
|
|
+ 2050 AND (cls # SymTab.ClEnum)
|
|
|
+ 2051 AND (cls # SymTab.ClReal)
|
|
|
+ 2052 AND (cls # SymTab.ClPtr)
|
|
|
+ 2053 AND (cls # SymTab.ClProc)
|
|
|
+ 2054 AND (cls # SymTab.ClLong)
|
|
|
+ 2055 AND (cls # SymTab.ClArray)
|
|
|
+ 2056 AND (cls # SymTab.ClSet)
|
|
|
+ 2057 AND (cls # SymTab.ClRecord)
|
|
|
+ 2058 AND (cls # SymTab.ClUStr)
|
|
|
+ 2059 AND (cls # SymTab.ClClass) THEN
|
|
|
+ 2060 SemError(230);
|
|
|
+ 2061 QbeGen.CopyOp("0", q)
|
|
|
+ 2062 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2063 END
|
|
|
+ 2064 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 2065 IF k = SymTab.KindImport THEN
|
|
|
+ 2066 SemError(230)
|
|
|
+ 2067 ELSIF k =
|
|
|
+ 2068 SymTab.KindProc THEN
|
|
|
+ 2069 (* bare procedure name:
|
|
|
+ 2070 a following ArgList
|
|
|
+ 2071 makes it a call;
|
|
|
+ 2072 otherwise Fact
|
|
|
+ 2073 reports 230 *)
|
|
|
+ 2074 ELSE
|
|
|
+ 2075 IF k = SymTab.KindField THEN
|
|
|
+ 2076 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 2077 sfx := TRUE
|
|
|
+ 2078 ELSE SemError(230);
|
|
|
+ 2079 QbeGen.CopyOp("0", q)
|
|
|
+ 2080 END
|
|
|
+ 2081 END
|
|
|
+ 2082 END
|
|
|
+ 2083 END
|
|
|
+ 2084 END; .)
|
|
|
+ 2085 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
+ 2086 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n));
|
|
|
+ 2087 IF fwd THEN AST.SetOp(astDes, 1) END; .)
|
|
|
+ 2088 { "[" Expr<it, iq>
|
|
|
+ 2089 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2090 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2091 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2092 SymTab.ClArray THEN
|
|
|
+ 2093 SemError(217);
|
|
|
+ 2094 t := SymTab.InvalidType
|
|
|
+ 2095 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2096 AND (SymTab.ClassOf(it) #
|
|
|
+ 2097 SymTab.ClChar)
|
|
|
+ 2098 AND (SymTab.ClassOf(it) #
|
|
|
+ 2099 SymTab.ClEnum) THEN
|
|
|
+ 2100 SemError(218);
|
|
|
+ 2101 t := SymTab.InvalidType
|
|
|
+ 2102 ELSE
|
|
|
+ 2103 eT := SymTab.ArrayElem(t);
|
|
|
+ 2104 t := eT; sfx := TRUE
|
|
|
+ 2105 END; .)
|
|
|
+ 2106 { "," Expr<it, iq>
|
|
|
+ 2107 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2108 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2109 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2110 SymTab.ClArray THEN
|
|
|
+ 2111 SemError(217);
|
|
|
+ 2112 t := SymTab.InvalidType
|
|
|
+ 2113 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2114 AND (SymTab.ClassOf(it) #
|
|
|
+ 2115 SymTab.ClChar)
|
|
|
+ 2116 AND (SymTab.ClassOf(it) #
|
|
|
+ 2117 SymTab.ClEnum) THEN
|
|
|
+ 2118 SemError(218);
|
|
|
+ 2119 t := SymTab.InvalidType
|
|
|
+ 2120 ELSE
|
|
|
+ 2121 eT := SymTab.ArrayElem(t);
|
|
|
+ 2122 t := eT; sfx := TRUE
|
|
|
+ 2123 END; .) }
|
|
|
+ 2124 "]"
|
|
|
+ 2125 | "." GetIdent<fn>
|
|
|
+ 2126 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2127 AST.SetOp(astSel, AST.SelField);
|
|
|
+ 2128 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
+ 2129 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
+ 2130 (* qualified L.x: materialize
|
|
|
+ 2131 the export, then load it *)
|
|
|
+ 2132 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 2133 fn, mal) THEN
|
|
|
+ 2134 SemError(201);
|
|
|
+ 2135 t := SymTab.InvalidType;
|
|
|
+ 2136 QbeGen.CopyOp("0", q)
|
|
|
+ 2137 ELSE
|
|
|
+ 2138 QbeGen.CopyOp(mal, qn);
|
|
|
+ 2139 t := SymTab.SymType(mal);
|
|
|
+ 2140 k := SymTab.SymKind(mal);
|
|
|
+ 2141 sfx := FALSE;
|
|
|
+ 2142 IF k = SymTab.KindProc THEN
|
|
|
+ 2143 (* call: ArgList supplies
|
|
|
+ 2144 the value *)
|
|
|
+ 2145 QbeGen.CopyOp("0", q)
|
|
|
+ 2146 END
|
|
|
+ 2147 END
|
|
|
+ 2148 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 2149 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2150 SymTab.ClRecord)
|
|
|
+ 2151 AND (SymTab.ClassOf(t) #
|
|
|
+ 2152 SymTab.ClClass) THEN
|
|
|
+ 2153 SemError(215);
|
|
|
+ 2154 t := SymTab.InvalidType
|
|
|
+ 2155 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 2156 SymTab.ClClass)
|
|
|
+ 2157 AND SymTab.MethodExists(t, fn) THEN
|
|
|
+ 2158 (* obj.Method: bind the
|
|
|
+ 2159 method and pass obj as
|
|
|
+ 2160 the hidden receiver; q
|
|
|
+ 2161 already holds the
|
|
|
+ 2162 object's address *)
|
|
|
+ 2163 QbeGen.CopyOp(fn, n);
|
|
|
+ 2164 QbeGen.CopyOp(fn, qn);
|
|
|
+ 2165 methCls := t;
|
|
|
+ 2166 k := SymTab.KindProc;
|
|
|
+ 2167 t := SymTab.InvalidType
|
|
|
+ 2168 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2169 fn) THEN
|
|
|
+ 2170 SemError(216);
|
|
|
+ 2171 t := SymTab.InvalidType
|
|
|
+ 2172 ELSE
|
|
|
+ 2173 t := SymTab.FieldType(t, fn);
|
|
|
+ 2174 sfx := TRUE
|
|
|
+ 2175 END; .)
|
|
|
+ 2176 | "^"
|
|
|
+ 2177 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2178 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2179 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2180 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2181 SymTab.ClPtr THEN
|
|
|
+ 2182 SemError(219);
|
|
|
+ 2183 t := SymTab.InvalidType
|
|
|
+ 2184 ELSE
|
|
|
+ 2185 bt := SymTab.PtrBase(t);
|
|
|
+ 2186 IF bt = SymTab.InvalidType THEN
|
|
|
+ 2187 ELSE
|
|
|
+ 2188 t := bt;
|
|
|
+ 2189 sfx := TRUE
|
|
|
+ 2190 END
|
|
|
+ 2191 END; .) } (. astCur := astDes; .) .
|
|
|
+ 2192 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
+ 2193 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
+ 2194 (a value, or a descriptor address for aggregates); each component
|
|
|
+ 2195 descends one level exactly like the Design components. *)
|
|
|
+ 2196 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2197 VAR sfx: BOOLEAN; VAR node: AST.Node> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
+ 2198 iq, ql, qlo, qhi, qe, qb:
|
|
|
+ 2199 QbeGen.QVal;
|
|
|
+ 2200 lo, hi, fo: INTEGER;
|
|
|
+ 2201 isOpen: BOOLEAN;
|
|
|
+ 2202 fname: SymTab.Name;
|
|
|
+ 2203 astWrap, astSel: AST.Node; .)
|
|
|
+ 2204 = "[" Expr<it, iq>
|
|
|
+ 2205 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2206 astWrap := AST.MakeNode(
|
|
|
+ 2207 AST.NkDesignator);
|
|
|
+ 2208 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2209 node := astWrap
|
|
|
+ 2210 END;
|
|
|
+ 2211 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2212 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2213 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2214 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2215 SymTab.ClArray THEN
|
|
|
+ 2216 SemError(217);
|
|
|
+ 2217 t := SymTab.InvalidType
|
|
|
+ 2218 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2219 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
+ 2220 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
+ 2221 SemError(218);
|
|
|
2222 t := SymTab.InvalidType
|
|
|
- 2223 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2224 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
- 2225 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
- 2226 SemError(218);
|
|
|
- 2227 t := SymTab.InvalidType
|
|
|
- 2228 ELSE
|
|
|
- 2229 eT := SymTab.ArrayElem(t);
|
|
|
- 2230 t := eT; sfx := TRUE
|
|
|
- 2231 END; .)
|
|
|
- 2232 "]"
|
|
|
- 2233 | "." GetIdent<fname>
|
|
|
- 2234 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2235 astWrap := AST.MakeNode(
|
|
|
- 2236 AST.NkDesignator);
|
|
|
- 2237 AST.SetChild(astWrap, 0, node);
|
|
|
- 2238 node := astWrap
|
|
|
- 2239 END;
|
|
|
- 2240 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2241 AST.MakeUn(AST.NkSelector,
|
|
|
- 2242 AST.SelField,
|
|
|
- 2243 AST.MakeLeaf(AST.NkIdent,
|
|
|
- 2244 fname))); IF t = SymTab.InvalidType THEN
|
|
|
- 2245 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2246 SymTab.ClRecord)
|
|
|
- 2247 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 2248 SemError(215);
|
|
|
- 2249 t := SymTab.InvalidType
|
|
|
- 2250 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2251 fname) THEN
|
|
|
- 2252 SemError(216);
|
|
|
- 2253 t := SymTab.InvalidType
|
|
|
- 2254 ELSE
|
|
|
- 2255 t := SymTab.FieldType(t, fname);
|
|
|
- 2256 sfx := TRUE
|
|
|
- 2257 END; .)
|
|
|
- 2258 | "^" (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2259 astWrap := AST.MakeNode(
|
|
|
- 2260 AST.NkDesignator);
|
|
|
- 2261 AST.SetChild(astWrap, 0, node);
|
|
|
- 2262 node := astWrap
|
|
|
- 2263 END;
|
|
|
- 2264 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2265 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2266 AST.SetChild(node,
|
|
|
- 2267 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2268 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2269 SymTab.ClPtr THEN
|
|
|
- 2270 SemError(219);
|
|
|
- 2271 t := SymTab.InvalidType
|
|
|
- 2272 ELSE
|
|
|
- 2273 bt := SymTab.PtrBase(t);
|
|
|
- 2274 IF bt # SymTab.InvalidType THEN
|
|
|
- 2275 t := bt; sfx := TRUE
|
|
|
- 2276 END
|
|
|
- 2277 END; .) .
|
|
|
- 2278 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2279 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 2280 op: INTEGER;
|
|
|
- 2281 q2, qt, wl: QbeGen.QVal;
|
|
|
- 2282 astA, astB: AST.Node;
|
|
|
- 2283 astOp: INTEGER;
|
|
|
- 2284 astMade: BOOLEAN;
|
|
|
- 2285 isR: BOOLEAN; .)
|
|
|
- 2286 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
- 2287 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 2288 (. astB := astCur; astMade := TRUE;
|
|
|
- 2289 astOp := AST.OpEq;
|
|
|
- 2290 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
- 2291 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
- 2292 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
- 2293 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
- 2294 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
- 2295 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
- 2296 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
- 2297 END;
|
|
|
- 2298 IF op = SymTab.OpIn THEN
|
|
|
- 2299 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 2300 IF (t = SymTab.InvalidType)
|
|
|
- 2301 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 2302 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 2303 ELSE
|
|
|
- 2304 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2305 END
|
|
|
- 2306 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 2307 QbeGen.CopyOp("0", q)
|
|
|
- 2308 END
|
|
|
- 2309 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 2310 IF (t = SymTab.InvalidType)
|
|
|
- 2311 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 2312 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 2313 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 2314 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 2315 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
|
|
|
- 2316 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2317 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 2318 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 2319 SemError(213); t := SymTab.InvalidType;
|
|
|
- 2320 QbeGen.CopyOp("0", q)
|
|
|
- 2321 ELSE
|
|
|
- 2322 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2323 END
|
|
|
- 2324 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2325 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2326 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2327 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
- 2328 QbeGen.StrEq(op, q, q2, qt);
|
|
|
- 2329 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2330 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 2331 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 2332 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
- 2333 ELSE
|
|
|
- 2334 t := SymTab.BoolType();
|
|
|
- 2335 QbeGen.CopyOp("@", q)
|
|
|
- 2336 END
|
|
|
- 2337 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 2338 QbeGen.CopyOp("0", q)
|
|
|
- 2339 END;
|
|
|
- 2340 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
- 2341 (. IF NOT astMade THEN astCur := astA END; .) .
|
|
|
- 2342 Rel<VAR op: INTEGER>
|
|
|
- 2343 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 2344 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 2345 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 2346 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 2347 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 2348 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 2349 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 2350 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2351 (. VAR t2, res2, lt, rt:
|
|
|
- 2352 SymTab.TypeIndex;
|
|
|
- 2353 op: INTEGER;
|
|
|
- 2354 q2, qt, wq, qf, q2a, q2b:
|
|
|
- 2355 QbeGen.QVal;
|
|
|
- 2356 neg, isR, isL, folded:
|
|
|
- 2357 BOOLEAN;
|
|
|
- 2358 fok: BOOLEAN;
|
|
|
- 2359 lw, rw, mw: CARDINAL;
|
|
|
- 2360 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 2361 astA, astB: AST.Node;
|
|
|
- 2362 astSign, astOp: INTEGER; .)
|
|
|
- 2363 = (. neg := FALSE; astSign := 0; .)
|
|
|
- 2364 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
- 2365 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
- 2366 Term<t, q> (. astA := astCur;
|
|
|
- 2367 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
- 2368 QbeGen.NegFold(q, q)
|
|
|
- 2369 END;
|
|
|
- 2370 IF astSign < 0 THEN
|
|
|
- 2371 astCur := AST.MakeUn(
|
|
|
- 2372 AST.NkUnary, AST.OpSub, astA);
|
|
|
- 2373 astA := astCur
|
|
|
- 2374 END; .)
|
|
|
- 2375 { AddOp<op>
|
|
|
- 2376 Term<t2, q2> (. astB := astCur; .)
|
|
|
- 2377 (. astOp := AST.OpAdd;
|
|
|
- 2378 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
- 2379 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
- 2380 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 2381 astCur := astA;
|
|
|
- 2382 IF op = SymTab.OpOr THEN
|
|
|
- 2383 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
- 2384 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 2385 t := SymTab.BoolType()
|
|
|
- 2386 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 2387 IF t # SymTab.InvalidType THEN
|
|
|
- 2388 QbeGen.CopyOp("@", q)
|
|
|
- 2389 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2390 END
|
|
|
- 2391 ELSIF (op = SymTab.OpAdd)
|
|
|
- 2392 AND (SymTab.UStrCompat(t, t2)
|
|
|
- 2393 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 2394 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
- 2395 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
- 2396 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
- 2397 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 2398 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
- 2399 (* UString concatenation: a UCHAR operand becomes a
|
|
|
- 2400 1-codepoint UString; the result is a descriptor in the
|
|
|
- 2401 shim's concat buffer. Work on copies so neither
|
|
|
- 2402 operand is clobbered. *)
|
|
|
- 2403 t := SymTab.NewUStr();
|
|
|
- 2404 QbeGen.CopyOp("@", q)
|
|
|
- 2405 ELSIF (op = SymTab.OpAdd)
|
|
|
- 2406 AND (SymTab.StrCompat(t, t2)
|
|
|
- 2407 OR (SymTab.IsStrType(t)
|
|
|
- 2408 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
- 2409 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
- 2410 AND SymTab.IsStrType(t2))) THEN
|
|
|
- 2411 (* string concatenation; a CHAR operand becomes a
|
|
|
- 2412 1-character string literal. When both operands are
|
|
|
- 2413 constants, fold to a single string literal so a
|
|
|
- 2414 constructor element stays compile-time. *)
|
|
|
- 2415 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
- 2416 qt, fok);
|
|
|
- 2417 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
- 2418 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2419 END;
|
|
|
- 2420 t := SymTab.NewStr()
|
|
|
- 2421 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 2422 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2423 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2424 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 2425 mw := lw;
|
|
|
- 2426 IF rw > mw THEN mw := rw END;
|
|
|
- 2427 t := SymTab.NewSet(
|
|
|
- 2428 SymTab.NewSubR(0,
|
|
|
- 2429 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 2430 QbeGen.CopyOp("@", q)
|
|
|
- 2431 ELSE
|
|
|
- 2432 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 2433 lt := t; rt := t2; t := res2
|
|
|
- 2434 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 2435 IF t # SymTab.InvalidType THEN
|
|
|
- 2436 isL := SymTab.IsLongFamily(t);
|
|
|
- 2437 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 2438 folded := FALSE;
|
|
|
- 2439 IF (NOT isL) AND (NOT isR)
|
|
|
- 2440 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 2441 IF op = SymTab.OpAdd THEN
|
|
|
- 2442 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 2443 ELSE
|
|
|
- 2444 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 2445 END
|
|
|
- 2446 END;
|
|
|
- 2447 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 2448 ELSE
|
|
|
- 2449 QbeGen.CopyOp("@", q)
|
|
|
- 2450 END
|
|
|
- 2451 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2452 END
|
|
|
- 2453 END; .) } .
|
|
|
- 2454 AddOp<VAR op: INTEGER>
|
|
|
- 2455 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 2456 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 2457 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 2458 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2459 (. VAR t2, res2, lt, rt:
|
|
|
- 2460 SymTab.TypeIndex;
|
|
|
- 2461 op: INTEGER;
|
|
|
- 2462 q2, qt, wq, qf:
|
|
|
- 2463 QbeGen.QVal;
|
|
|
- 2464 isR, isL, folded: BOOLEAN;
|
|
|
- 2465 lw, rw, mw: CARDINAL;
|
|
|
- 2466 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 2467 astA, astB: AST.Node;
|
|
|
- 2468 astOp: INTEGER; .)
|
|
|
- 2469 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
- 2470 Fact<t2, q2> (. astB := astCur; .)
|
|
|
- 2471 (. astOp := AST.OpMul;
|
|
|
- 2472 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
- 2473 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
- 2474 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
- 2475 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
- 2476 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 2477 astCur := astA;
|
|
|
- 2478 IF op = SymTab.OpAnd THEN
|
|
|
- 2479 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
- 2480 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 2481 t := SymTab.BoolType()
|
|
|
- 2482 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 2483 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
- 2484 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2485 END
|
|
|
- 2486 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 2487 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2488 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2489 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 2490 mw := lw;
|
|
|
- 2491 IF rw > mw THEN mw := rw END;
|
|
|
- 2492 t := SymTab.NewSet(
|
|
|
- 2493 SymTab.NewSubR(0,
|
|
|
- 2494 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 2495 QbeGen.CopyOp("@", q)
|
|
|
- 2496 ELSE
|
|
|
- 2497 IF SymTab.ArithCheck(t, t2,
|
|
|
- 2498 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 2499 res2) THEN
|
|
|
- 2500 lt := t; rt := t2; t := res2
|
|
|
- 2501 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 2502 IF t # SymTab.InvalidType THEN
|
|
|
- 2503 isL := SymTab.IsLongFamily(t);
|
|
|
- 2504 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 2505 folded := FALSE;
|
|
|
- 2506 IF (NOT isL) AND (NOT isR)
|
|
|
- 2507 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 2508 IF op = SymTab.OpTimes THEN
|
|
|
- 2509 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 2510 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 2511 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 2512 ELSIF op = SymTab.OpMod THEN
|
|
|
- 2513 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 2514 END
|
|
|
- 2515 END;
|
|
|
- 2516 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 2517 ELSE
|
|
|
- 2518 QbeGen.CopyOp("@", q)
|
|
|
- 2519 END
|
|
|
- 2520 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2521 END
|
|
|
- 2522 END; .) } .
|
|
|
- 2523 MulOp<VAR op: INTEGER>
|
|
|
- 2524 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 2525 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 2526 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 2527 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 2528 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
- 2529 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2530 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 2531 et, dt, t2, st, ct2, et2:
|
|
|
- 2532 SymTab.TypeIndex;
|
|
|
- 2533 dk: INTEGER;
|
|
|
- 2534 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
- 2535 QbeGen.QVal;
|
|
|
- 2536 qn, vn: SymTab.Name;
|
|
|
- 2537 vt: SymTab.TypeIndex;
|
|
|
- 2538 c1, c2: INTEGER;
|
|
|
- 2539 lo, hi: INTEGER;
|
|
|
- 2540 isMax: BOOLEAN;
|
|
|
- 2541 called, isHigh, sfx, isCh,
|
|
|
- 2542 isU, uok, isStr: BOOLEAN;
|
|
|
- 2543 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
- 2544 astD: AST.Node;
|
|
|
- 2545 astCall: BOOLEAN;
|
|
|
- 2546 astNode, astNot: AST.Node;
|
|
|
- 2547 j: CARDINAL;
|
|
|
- 2548 astArg2: AST.Node;
|
|
|
- 2549 astBrace: AST.Node;
|
|
|
- 2550 astRes: AST.Node; .)
|
|
|
- 2551 = (. astIsLit := FALSE; .)
|
|
|
- 2552 ( integer (. LexString(s);
|
|
|
- 2553 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
- 2554 t := SymTab.IntType(); .)
|
|
|
- 2555 | charConst (. LexString(s);
|
|
|
- 2556 QbeGen.NormLit(s, q, isCh);
|
|
|
- 2557 IF twoPhase THEN
|
|
|
- 2558 astIsLit := TRUE;
|
|
|
- 2559 astCur := AST.MakeLeaf(
|
|
|
- 2560 AST.NkCharLit, s)
|
|
|
- 2561 END;
|
|
|
- 2562 t := SymTab.CharType(); .)
|
|
|
- 2563 | real (. LexString(s);
|
|
|
- 2564 QbeGen.NormReal(s, q);
|
|
|
- 2565 IF twoPhase THEN
|
|
|
- 2566 astIsLit := TRUE;
|
|
|
- 2567 astCur := AST.MakeLeaf(
|
|
|
- 2568 AST.NkRealLit, s)
|
|
|
- 2569 END;
|
|
|
- 2570 t := SymTab.RealType(); .)
|
|
|
- 2571 | string (. LexString(s);
|
|
|
- 2572 IF twoPhase THEN
|
|
|
- 2573 astIsLit := TRUE;
|
|
|
- 2574 astCur := AST.MakeLeaf(
|
|
|
- 2575 AST.NkStrLit, s)
|
|
|
- 2576 END;
|
|
|
- 2577 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 2578 t := SymTab.CharType();
|
|
|
- 2579 QbeGen.IntStr(
|
|
|
- 2580 QbeGen.CharVal(s), q)
|
|
|
- 2581 ELSE t := SymTab.NewStr();
|
|
|
- 2582 QbeGen.DeclStr(s, q);
|
|
|
- 2583 (* a literal's value IS its
|
|
|
- 2584 static descriptor address *)
|
|
|
- 2585 END; .)
|
|
|
- 2586 | ustring (. LexString(s);
|
|
|
- 2587 IF twoPhase THEN
|
|
|
- 2588 astIsLit := TRUE;
|
|
|
- 2589 astCur := AST.MakeLeaf(
|
|
|
- 2590 AST.NkStrLit, s)
|
|
|
- 2591 END;
|
|
|
- 2592 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
- 2593 uok);
|
|
|
- 2594 IF NOT uok THEN
|
|
|
- 2595 SemError(234);
|
|
|
- 2596 t := SymTab.InvalidType
|
|
|
- 2597 ELSIF isU THEN
|
|
|
- 2598 t := SymTab.UCharType();
|
|
|
- 2599 QbeGen.IntStr(ucp, q)
|
|
|
- 2600 ELSE
|
|
|
- 2601 t := SymTab.NewUStr();
|
|
|
- 2602 END; .)
|
|
|
- 2603 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
- 2604 astNArgs := 0; called := FALSE;
|
|
|
- 2605 t := dt;
|
|
|
- 2606 IF dk = SymTab.KindConst THEN
|
|
|
- 2607 QbeGen.CopyOp(qd, q)
|
|
|
- 2608 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2609 END; .)
|
|
|
- 2610 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
- 2611 astBrace := astCur; .) ]
|
|
|
- 2612 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 2613 (. astCall := TRUE;
|
|
|
- 2614 astNode := AstCallNode(astD);
|
|
|
- 2615 astRes := astNode;
|
|
|
- 2616 t := ct2;
|
|
|
- 2617 QbeGen.CopyOp(q2, q);
|
|
|
- 2618 sfx := FALSE; .)
|
|
|
- 2619 { ResultComp<t, q, sfx, astRes> }
|
|
|
- 2620 (. IF sfx THEN
|
|
|
- 2621 IF t = SymTab.InvalidType THEN
|
|
|
- 2622 QbeGen.CopyOp("0", q)
|
|
|
- 2623 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2624 SymTab.ClRecord)
|
|
|
- 2625 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
- 2626 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
- 2627 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 2628 QbeGen.CopyOp("@", q)
|
|
|
- 2629 END
|
|
|
- 2630 END; .) ]
|
|
|
- 2631 (. IF called THEN
|
|
|
- 2632 astCur := astRes
|
|
|
- 2633 ELSIF astCall THEN
|
|
|
- 2634 astCur := astBrace
|
|
|
- 2635 ELSE astCur := astD
|
|
|
- 2636 END;
|
|
|
- 2637 astIsLit := TRUE;
|
|
|
- 2638 IF NOT called
|
|
|
- 2639 AND (dk = SymTab.KindProc) THEN
|
|
|
- 2640 (* bare zero-arg function
|
|
|
- 2641 call (parentheses may be
|
|
|
- 2642 omitted); a proper or
|
|
|
- 2643 parameterised proc here
|
|
|
- 2644 is 230 *)
|
|
|
- 2645 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 2646 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
- 2647 t := SymTab.ProcRes(qn);
|
|
|
- 2648 QbeGen.CopyOp("@", q);
|
|
|
- 2649 astCur := AST.MakeNode(AST.NkCall);
|
|
|
- 2650 AST.SetChild(astCur, 0, astD)
|
|
|
- 2651 ELSE
|
|
|
- 2652 t := SymTab.ProcTypeOf(qn);
|
|
|
- 2653 QbeGen.CopyOp("@", q)
|
|
|
- 2654 END
|
|
|
- 2655 END; .)
|
|
|
- 2656 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 2657 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- 2658 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
- 2659 isU := FALSE; .)
|
|
|
- 2660 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 2661 isStr := TRUE;
|
|
|
- 2662 isU := FALSE;
|
|
|
- 2663 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 2664 dt := SymTab.CharType();
|
|
|
- 2665 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
- 2666 qd)
|
|
|
- 2667 ELSE
|
|
|
- 2668 dt := SymTab.NewStr();
|
|
|
- 2669 QbeGen.DeclStr(s, qd);
|
|
|
- 2670 END;
|
|
|
- 2671 dk := -1;
|
|
|
- 2672 qn[0] := CHR(0); .)
|
|
|
- 2673 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 2674 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
- 2675 uok);
|
|
|
- 2676 isStr := FALSE;
|
|
|
- 2677 IF NOT uok THEN
|
|
|
- 2678 SemError(234);
|
|
|
- 2679 dt := SymTab.InvalidType
|
|
|
- 2680 ELSIF isU THEN
|
|
|
- 2681 (* one codepoint: a UCHAR;
|
|
|
- 2682 LEN is 1, HIGH is 0 *)
|
|
|
- 2683 dt := SymTab.UCharType();
|
|
|
- 2684 QbeGen.IntStr(ucp, qd)
|
|
|
- 2685 ELSE
|
|
|
- 2686 dt := SymTab.NewUStr();
|
|
|
- 2687 END;
|
|
|
- 2688 dk := -1;
|
|
|
- 2689 qn[0] := CHR(0); .) )
|
|
|
- 2690 ")"
|
|
|
- 2691 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2692 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
- 2693 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
- 2694 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2695 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
- 2696 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2697 astCur := astNode; astIsLit := TRUE;
|
|
|
- 2698 IF (dt # SymTab.InvalidType)
|
|
|
- 2699 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
- 2700 (* UString: the count is
|
|
|
- 2701 the descriptor header *)
|
|
|
- 2702 t := SymTab.IntType();
|
|
|
- 2703 QbeGen.CopyOp("@", q)
|
|
|
- 2704 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 2705 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
- 2706 (* single UCHAR codepoint *)
|
|
|
- 2707 IF isHigh THEN
|
|
|
- 2708 QbeGen.CopyOp("0", qr)
|
|
|
- 2709 ELSE
|
|
|
- 2710 QbeGen.CopyOp("1", qr)
|
|
|
- 2711 END;
|
|
|
- 2712 t := SymTab.IntType();
|
|
|
- 2713 QbeGen.CopyOp(qr, q)
|
|
|
- 2714 ELSIF isStr THEN
|
|
|
- 2715 (* fold: content length at
|
|
|
- 2716 compile time *)
|
|
|
- 2717 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 2718 c1 := 1
|
|
|
- 2719 ELSE
|
|
|
- 2720 c1 :=
|
|
|
- 2721 SymTab.StrLen(s) - 2
|
|
|
- 2722 END;
|
|
|
- 2723 IF isHigh THEN
|
|
|
- 2724 DEC(c1)
|
|
|
- 2725 END;
|
|
|
- 2726 QbeGen.IntStr(c1, qr);
|
|
|
- 2727 t := SymTab.IntType();
|
|
|
- 2728 QbeGen.CopyOp(qr, q)
|
|
|
- 2729 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 2223 ELSE
|
|
|
+ 2224 eT := SymTab.ArrayElem(t);
|
|
|
+ 2225 t := eT; sfx := TRUE
|
|
|
+ 2226 END; .)
|
|
|
+ 2227 "]"
|
|
|
+ 2228 | "." GetIdent<fname>
|
|
|
+ 2229 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2230 astWrap := AST.MakeNode(
|
|
|
+ 2231 AST.NkDesignator);
|
|
|
+ 2232 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2233 node := astWrap
|
|
|
+ 2234 END;
|
|
|
+ 2235 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2236 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2237 AST.SelField,
|
|
|
+ 2238 AST.MakeLeaf(AST.NkIdent,
|
|
|
+ 2239 fname))); IF t = SymTab.InvalidType THEN
|
|
|
+ 2240 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2241 SymTab.ClRecord)
|
|
|
+ 2242 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 2243 SemError(215);
|
|
|
+ 2244 t := SymTab.InvalidType
|
|
|
+ 2245 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2246 fname) THEN
|
|
|
+ 2247 SemError(216);
|
|
|
+ 2248 t := SymTab.InvalidType
|
|
|
+ 2249 ELSE
|
|
|
+ 2250 t := SymTab.FieldType(t, fname);
|
|
|
+ 2251 sfx := TRUE
|
|
|
+ 2252 END; .)
|
|
|
+ 2253 | "^" (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2254 astWrap := AST.MakeNode(
|
|
|
+ 2255 AST.NkDesignator);
|
|
|
+ 2256 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2257 node := astWrap
|
|
|
+ 2258 END;
|
|
|
+ 2259 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2260 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2261 AST.SetChild(node,
|
|
|
+ 2262 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2263 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2264 SymTab.ClPtr THEN
|
|
|
+ 2265 SemError(219);
|
|
|
+ 2266 t := SymTab.InvalidType
|
|
|
+ 2267 ELSE
|
|
|
+ 2268 bt := SymTab.PtrBase(t);
|
|
|
+ 2269 IF bt # SymTab.InvalidType THEN
|
|
|
+ 2270 t := bt; sfx := TRUE
|
|
|
+ 2271 END
|
|
|
+ 2272 END; .) .
|
|
|
+ 2273 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2274 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 2275 op: INTEGER;
|
|
|
+ 2276 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 2277 astA, astB: AST.Node;
|
|
|
+ 2278 astOp: INTEGER;
|
|
|
+ 2279 astMade: BOOLEAN;
|
|
|
+ 2280 isR: BOOLEAN; .)
|
|
|
+ 2281 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
+ 2282 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 2283 (. astB := astCur; astMade := TRUE;
|
|
|
+ 2284 astOp := AST.OpEq;
|
|
|
+ 2285 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
+ 2286 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
+ 2287 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
+ 2288 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
+ 2289 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
+ 2290 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
+ 2291 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
+ 2292 END;
|
|
|
+ 2293 IF op = SymTab.OpIn THEN
|
|
|
+ 2294 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 2295 IF (t = SymTab.InvalidType)
|
|
|
+ 2296 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 2297 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 2298 ELSE
|
|
|
+ 2299 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2300 END
|
|
|
+ 2301 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 2302 QbeGen.CopyOp("0", q)
|
|
|
+ 2303 END
|
|
|
+ 2304 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 2305 IF (t = SymTab.InvalidType)
|
|
|
+ 2306 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 2307 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 2308 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 2309 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 2310 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
|
|
|
+ 2311 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2312 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 2313 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 2314 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 2315 QbeGen.CopyOp("0", q)
|
|
|
+ 2316 ELSE
|
|
|
+ 2317 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2318 END
|
|
|
+ 2319 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2320 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2321 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2322 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 2323 QbeGen.StrEq(op, q, q2, qt);
|
|
|
+ 2324 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2325 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 2326 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 2327 t := SymTab.BoolType(); QbeGen.CopyOp("@", q)
|
|
|
+ 2328 ELSE
|
|
|
+ 2329 t := SymTab.BoolType();
|
|
|
+ 2330 QbeGen.CopyOp("@", q)
|
|
|
+ 2331 END
|
|
|
+ 2332 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 2333 QbeGen.CopyOp("0", q)
|
|
|
+ 2334 END;
|
|
|
+ 2335 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
+ 2336 (. IF NOT astMade THEN astCur := astA END; .) .
|
|
|
+ 2337 Rel<VAR op: INTEGER>
|
|
|
+ 2338 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 2339 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 2340 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 2341 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 2342 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 2343 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 2344 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 2345 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2346 (. VAR t2, res2, lt, rt:
|
|
|
+ 2347 SymTab.TypeIndex;
|
|
|
+ 2348 op: INTEGER;
|
|
|
+ 2349 q2, qt, wq, qf, q2a, q2b:
|
|
|
+ 2350 QbeGen.QVal;
|
|
|
+ 2351 neg, isR, isL, folded:
|
|
|
+ 2352 BOOLEAN;
|
|
|
+ 2353 fok: BOOLEAN;
|
|
|
+ 2354 lw, rw, mw: CARDINAL;
|
|
|
+ 2355 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 2356 astA, astB: AST.Node;
|
|
|
+ 2357 astSign, astOp: INTEGER; .)
|
|
|
+ 2358 = (. neg := FALSE; astSign := 0; .)
|
|
|
+ 2359 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
+ 2360 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
+ 2361 Term<t, q> (. astA := astCur;
|
|
|
+ 2362 IF neg AND QbeGen.IsImm(q) THEN
|
|
|
+ 2363 QbeGen.NegFold(q, q)
|
|
|
+ 2364 END;
|
|
|
+ 2365 IF astSign < 0 THEN
|
|
|
+ 2366 astCur := AST.MakeUn(
|
|
|
+ 2367 AST.NkUnary, AST.OpSub, astA);
|
|
|
+ 2368 astA := astCur
|
|
|
+ 2369 END; .)
|
|
|
+ 2370 { AddOp<op>
|
|
|
+ 2371 Term<t2, q2> (. astB := astCur; .)
|
|
|
+ 2372 (. astOp := AST.OpAdd;
|
|
|
+ 2373 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
+ 2374 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
+ 2375 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 2376 astCur := astA;
|
|
|
+ 2377 IF op = SymTab.OpOr THEN
|
|
|
+ 2378 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
+ 2379 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 2380 t := SymTab.BoolType()
|
|
|
+ 2381 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 2382 IF t # SymTab.InvalidType THEN
|
|
|
+ 2383 QbeGen.CopyOp("@", q)
|
|
|
+ 2384 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2385 END
|
|
|
+ 2386 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 2387 AND (SymTab.UStrCompat(t, t2)
|
|
|
+ 2388 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 2389 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ 2390 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ 2391 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ 2392 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 2393 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ 2394 (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 2395 1-codepoint UString; the result is a descriptor in the
|
|
|
+ 2396 shim's concat buffer. Work on copies so neither
|
|
|
+ 2397 operand is clobbered. *)
|
|
|
+ 2398 t := SymTab.NewUStr();
|
|
|
+ 2399 QbeGen.CopyOp("@", q)
|
|
|
+ 2400 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 2401 AND (SymTab.StrCompat(t, t2)
|
|
|
+ 2402 OR (SymTab.IsStrType(t)
|
|
|
+ 2403 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
+ 2404 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
+ 2405 AND SymTab.IsStrType(t2))) THEN
|
|
|
+ 2406 (* string concatenation; a CHAR operand becomes a
|
|
|
+ 2407 1-character string literal. When both operands are
|
|
|
+ 2408 constants, fold to a single string literal so a
|
|
|
+ 2409 constructor element stays compile-time. *)
|
|
|
+ 2410 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
+ 2411 qt, fok);
|
|
|
+ 2412 IF fok THEN QbeGen.CopyOp(qt, q)
|
|
|
+ 2413 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2414 END;
|
|
|
+ 2415 t := SymTab.NewStr()
|
|
|
+ 2416 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 2417 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2418 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2419 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 2420 mw := lw;
|
|
|
+ 2421 IF rw > mw THEN mw := rw END;
|
|
|
+ 2422 t := SymTab.NewSet(
|
|
|
+ 2423 SymTab.NewSubR(0,
|
|
|
+ 2424 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 2425 QbeGen.CopyOp("@", q)
|
|
|
+ 2426 ELSE
|
|
|
+ 2427 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 2428 lt := t; rt := t2; t := res2
|
|
|
+ 2429 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 2430 IF t # SymTab.InvalidType THEN
|
|
|
+ 2431 isL := SymTab.IsLongFamily(t);
|
|
|
+ 2432 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 2433 folded := FALSE;
|
|
|
+ 2434 IF (NOT isL) AND (NOT isR)
|
|
|
+ 2435 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 2436 IF op = SymTab.OpAdd THEN
|
|
|
+ 2437 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 2438 ELSE
|
|
|
+ 2439 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 2440 END
|
|
|
+ 2441 END;
|
|
|
+ 2442 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 2443 ELSE
|
|
|
+ 2444 QbeGen.CopyOp("@", q)
|
|
|
+ 2445 END
|
|
|
+ 2446 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2447 END
|
|
|
+ 2448 END; .) } .
|
|
|
+ 2449 AddOp<VAR op: INTEGER>
|
|
|
+ 2450 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 2451 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 2452 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 2453 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2454 (. VAR t2, res2, lt, rt:
|
|
|
+ 2455 SymTab.TypeIndex;
|
|
|
+ 2456 op: INTEGER;
|
|
|
+ 2457 q2, qt, wq, qf:
|
|
|
+ 2458 QbeGen.QVal;
|
|
|
+ 2459 isR, isL, folded: BOOLEAN;
|
|
|
+ 2460 lw, rw, mw: CARDINAL;
|
|
|
+ 2461 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 2462 astA, astB: AST.Node;
|
|
|
+ 2463 astOp: INTEGER; .)
|
|
|
+ 2464 = Fact<t, q> (. astA := astCur; .) { MulOp<op>
|
|
|
+ 2465 Fact<t2, q2> (. astB := astCur; .)
|
|
|
+ 2466 (. astOp := AST.OpMul;
|
|
|
+ 2467 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
+ 2468 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
+ 2469 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
+ 2470 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
+ 2471 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 2472 astCur := astA;
|
|
|
+ 2473 IF op = SymTab.OpAnd THEN
|
|
|
+ 2474 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
+ 2475 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 2476 t := SymTab.BoolType()
|
|
|
+ 2477 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 2478 IF t # SymTab.InvalidType THEN QbeGen.CopyOp("@", q)
|
|
|
+ 2479 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2480 END
|
|
|
+ 2481 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 2482 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2483 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2484 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 2485 mw := lw;
|
|
|
+ 2486 IF rw > mw THEN mw := rw END;
|
|
|
+ 2487 t := SymTab.NewSet(
|
|
|
+ 2488 SymTab.NewSubR(0,
|
|
|
+ 2489 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 2490 QbeGen.CopyOp("@", q)
|
|
|
+ 2491 ELSE
|
|
|
+ 2492 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 2493 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 2494 res2) THEN
|
|
|
+ 2495 lt := t; rt := t2; t := res2
|
|
|
+ 2496 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 2497 IF t # SymTab.InvalidType THEN
|
|
|
+ 2498 isL := SymTab.IsLongFamily(t);
|
|
|
+ 2499 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 2500 folded := FALSE;
|
|
|
+ 2501 IF (NOT isL) AND (NOT isR)
|
|
|
+ 2502 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 2503 IF op = SymTab.OpTimes THEN
|
|
|
+ 2504 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 2505 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 2506 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 2507 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 2508 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 2509 END
|
|
|
+ 2510 END;
|
|
|
+ 2511 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 2512 ELSE
|
|
|
+ 2513 QbeGen.CopyOp("@", q)
|
|
|
+ 2514 END
|
|
|
+ 2515 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2516 END
|
|
|
+ 2517 END; .) } .
|
|
|
+ 2518 MulOp<VAR op: INTEGER>
|
|
|
+ 2519 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 2520 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 2521 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 2522 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 2523 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 2524 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2525 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 2526 et, dt, t2, st, ct2, et2:
|
|
|
+ 2527 SymTab.TypeIndex;
|
|
|
+ 2528 dk: INTEGER;
|
|
|
+ 2529 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
+ 2530 QbeGen.QVal;
|
|
|
+ 2531 qn, vn: SymTab.Name;
|
|
|
+ 2532 vt: SymTab.TypeIndex;
|
|
|
+ 2533 c1, c2: INTEGER;
|
|
|
+ 2534 lo, hi: INTEGER;
|
|
|
+ 2535 isMax: BOOLEAN;
|
|
|
+ 2536 called, isHigh, sfx, isCh,
|
|
|
+ 2537 isU, uok, isStr: BOOLEAN;
|
|
|
+ 2538 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
+ 2539 astD: AST.Node;
|
|
|
+ 2540 astCall: BOOLEAN;
|
|
|
+ 2541 astNode, astNot: AST.Node;
|
|
|
+ 2542 j: CARDINAL;
|
|
|
+ 2543 astArg2: AST.Node;
|
|
|
+ 2544 astBrace: AST.Node;
|
|
|
+ 2545 astRes: AST.Node; .)
|
|
|
+ 2546 = (. astIsLit := FALSE; .)
|
|
|
+ 2547 ( integer (. LexString(s);
|
|
|
+ 2548 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
+ 2549 t := SymTab.IntType(); .)
|
|
|
+ 2550 | charConst (. LexString(s);
|
|
|
+ 2551 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 2552 IF twoPhase THEN
|
|
|
+ 2553 astIsLit := TRUE;
|
|
|
+ 2554 astCur := AST.MakeLeaf(
|
|
|
+ 2555 AST.NkCharLit, s)
|
|
|
+ 2556 END;
|
|
|
+ 2557 t := SymTab.CharType(); .)
|
|
|
+ 2558 | real (. LexString(s);
|
|
|
+ 2559 QbeGen.NormReal(s, q);
|
|
|
+ 2560 IF twoPhase THEN
|
|
|
+ 2561 astIsLit := TRUE;
|
|
|
+ 2562 astCur := AST.MakeLeaf(
|
|
|
+ 2563 AST.NkRealLit, s)
|
|
|
+ 2564 END;
|
|
|
+ 2565 t := SymTab.RealType(); .)
|
|
|
+ 2566 | string (. LexString(s);
|
|
|
+ 2567 IF twoPhase THEN
|
|
|
+ 2568 astIsLit := TRUE;
|
|
|
+ 2569 astCur := AST.MakeLeaf(
|
|
|
+ 2570 AST.NkStrLit, s)
|
|
|
+ 2571 END;
|
|
|
+ 2572 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 2573 t := SymTab.CharType();
|
|
|
+ 2574 QbeGen.IntStr(
|
|
|
+ 2575 QbeGen.CharVal(s), q)
|
|
|
+ 2576 ELSE t := SymTab.NewStr();
|
|
|
+ 2577 QbeGen.DeclStr(s, q);
|
|
|
+ 2578 (* a literal's value IS its
|
|
|
+ 2579 static descriptor address *)
|
|
|
+ 2580 END; .)
|
|
|
+ 2581 | ustring (. LexString(s);
|
|
|
+ 2582 IF twoPhase THEN
|
|
|
+ 2583 astIsLit := TRUE;
|
|
|
+ 2584 astCur := AST.MakeLeaf(
|
|
|
+ 2585 AST.NkStrLit, s)
|
|
|
+ 2586 END;
|
|
|
+ 2587 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
+ 2588 uok);
|
|
|
+ 2589 IF NOT uok THEN
|
|
|
+ 2590 SemError(234);
|
|
|
+ 2591 t := SymTab.InvalidType
|
|
|
+ 2592 ELSIF isU THEN
|
|
|
+ 2593 t := SymTab.UCharType();
|
|
|
+ 2594 QbeGen.IntStr(ucp, q)
|
|
|
+ 2595 ELSE
|
|
|
+ 2596 t := SymTab.NewUStr();
|
|
|
+ 2597 END; .)
|
|
|
+ 2598 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
+ 2599 astNArgs := 0; called := FALSE;
|
|
|
+ 2600 t := dt;
|
|
|
+ 2601 IF dk = SymTab.KindConst THEN
|
|
|
+ 2602 QbeGen.CopyOp(qd, q)
|
|
|
+ 2603 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2604 END; .)
|
|
|
+ 2605 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
+ 2606 astBrace := astCur; .) ]
|
|
|
+ 2607 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 2608 (. astCall := TRUE;
|
|
|
+ 2609 astNode := AstCallNode(astD);
|
|
|
+ 2610 astRes := astNode;
|
|
|
+ 2611 t := ct2;
|
|
|
+ 2612 QbeGen.CopyOp(q2, q);
|
|
|
+ 2613 sfx := FALSE; .)
|
|
|
+ 2614 { ResultComp<t, q, sfx, astRes> }
|
|
|
+ 2615 (. IF sfx THEN
|
|
|
+ 2616 IF t = SymTab.InvalidType THEN
|
|
|
+ 2617 QbeGen.CopyOp("0", q)
|
|
|
+ 2618 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2619 SymTab.ClRecord)
|
|
|
+ 2620 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
+ 2621 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
+ 2622 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 2623 QbeGen.CopyOp("@", q)
|
|
|
+ 2624 END
|
|
|
+ 2625 END; .) ]
|
|
|
+ 2626 (. IF called THEN
|
|
|
+ 2627 astCur := astRes
|
|
|
+ 2628 ELSIF astCall THEN
|
|
|
+ 2629 astCur := astBrace
|
|
|
+ 2630 ELSE astCur := astD
|
|
|
+ 2631 END;
|
|
|
+ 2632 astIsLit := TRUE;
|
|
|
+ 2633 IF NOT called
|
|
|
+ 2634 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 2635 (* bare zero-arg function
|
|
|
+ 2636 call (parentheses may be
|
|
|
+ 2637 omitted); a proper or
|
|
|
+ 2638 parameterised proc here
|
|
|
+ 2639 is 230 *)
|
|
|
+ 2640 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 2641 AND (SymTab.ProcRes(qn) # SymTab.InvalidType) THEN
|
|
|
+ 2642 t := SymTab.ProcRes(qn);
|
|
|
+ 2643 QbeGen.CopyOp("@", q);
|
|
|
+ 2644 astCur := AST.MakeNode(AST.NkCall);
|
|
|
+ 2645 AST.SetChild(astCur, 0, astD)
|
|
|
+ 2646 ELSE
|
|
|
+ 2647 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 2648 QbeGen.CopyOp("@", q)
|
|
|
+ 2649 END
|
|
|
+ 2650 END; .)
|
|
|
+ 2651 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 2652 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 2653 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ 2654 isU := FALSE; .)
|
|
|
+ 2655 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 2656 isStr := TRUE;
|
|
|
+ 2657 isU := FALSE;
|
|
|
+ 2658 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 2659 dt := SymTab.CharType();
|
|
|
+ 2660 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
+ 2661 qd)
|
|
|
+ 2662 ELSE
|
|
|
+ 2663 dt := SymTab.NewStr();
|
|
|
+ 2664 QbeGen.DeclStr(s, qd);
|
|
|
+ 2665 END;
|
|
|
+ 2666 dk := -1;
|
|
|
+ 2667 qn[0] := CHR(0); .)
|
|
|
+ 2668 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 2669 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ 2670 uok);
|
|
|
+ 2671 isStr := FALSE;
|
|
|
+ 2672 IF NOT uok THEN
|
|
|
+ 2673 SemError(234);
|
|
|
+ 2674 dt := SymTab.InvalidType
|
|
|
+ 2675 ELSIF isU THEN
|
|
|
+ 2676 (* one codepoint: a UCHAR;
|
|
|
+ 2677 LEN is 1, HIGH is 0 *)
|
|
|
+ 2678 dt := SymTab.UCharType();
|
|
|
+ 2679 QbeGen.IntStr(ucp, qd)
|
|
|
+ 2680 ELSE
|
|
|
+ 2681 dt := SymTab.NewUStr();
|
|
|
+ 2682 END;
|
|
|
+ 2683 dk := -1;
|
|
|
+ 2684 qn[0] := CHR(0); .) )
|
|
|
+ 2685 ")"
|
|
|
+ 2686 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2687 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
+ 2688 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
+ 2689 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2690 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
+ 2691 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2692 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 2693 IF (dt # SymTab.InvalidType)
|
|
|
+ 2694 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ 2695 (* UString: the count is
|
|
|
+ 2696 the descriptor header *)
|
|
|
+ 2697 t := SymTab.IntType();
|
|
|
+ 2698 QbeGen.CopyOp("@", q)
|
|
|
+ 2699 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 2700 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ 2701 (* single UCHAR codepoint *)
|
|
|
+ 2702 IF isHigh THEN
|
|
|
+ 2703 QbeGen.CopyOp("0", qr)
|
|
|
+ 2704 ELSE
|
|
|
+ 2705 QbeGen.CopyOp("1", qr)
|
|
|
+ 2706 END;
|
|
|
+ 2707 t := SymTab.IntType();
|
|
|
+ 2708 QbeGen.CopyOp(qr, q)
|
|
|
+ 2709 ELSIF isStr THEN
|
|
|
+ 2710 (* fold: content length at
|
|
|
+ 2711 compile time *)
|
|
|
+ 2712 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 2713 c1 := 1
|
|
|
+ 2714 ELSE
|
|
|
+ 2715 c1 :=
|
|
|
+ 2716 SymTab.StrLen(s) - 2
|
|
|
+ 2717 END;
|
|
|
+ 2718 IF isHigh THEN
|
|
|
+ 2719 DEC(c1)
|
|
|
+ 2720 END;
|
|
|
+ 2721 QbeGen.IntStr(c1, qr);
|
|
|
+ 2722 t := SymTab.IntType();
|
|
|
+ 2723 QbeGen.CopyOp(qr, q)
|
|
|
+ 2724 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 2725 t := SymTab.InvalidType;
|
|
|
+ 2726 QbeGen.CopyOp("0", q)
|
|
|
+ 2727 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 2728 SymTab.ClArray THEN
|
|
|
+ 2729 SemError(217);
|
|
|
2730 t := SymTab.InvalidType;
|
|
|
2731 QbeGen.CopyOp("0", q)
|
|
|
- 2732 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 2733 SymTab.ClArray THEN
|
|
|
- 2734 SemError(217);
|
|
|
- 2735 t := SymTab.InvalidType;
|
|
|
- 2736 QbeGen.CopyOp("0", q)
|
|
|
- 2737 ELSE
|
|
|
- 2738 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 2739 t := SymTab.IntType();
|
|
|
- 2740 QbeGen.CopyOp("@", q)
|
|
|
- 2741 ELSE
|
|
|
- 2742 IF isHigh THEN
|
|
|
- 2743 QbeGen.IntStr(
|
|
|
- 2744 SymTab.ArrayHi(dt), qr)
|
|
|
- 2745 ELSE
|
|
|
- 2746 QbeGen.IntStr(VAL(
|
|
|
- 2747 INTEGER,
|
|
|
- 2748 SymTab.ArrayLen(dt)),
|
|
|
- 2749 qr)
|
|
|
- 2750 END;
|
|
|
- 2751 t := SymTab.IntType();
|
|
|
- 2752 QbeGen.CopyOp(qr, q)
|
|
|
- 2753 END
|
|
|
- 2754 END; .)
|
|
|
- 2755 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 2756 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2757 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
- 2758 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2759 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2760 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2761 t := SymTab.InvalidType;
|
|
|
- 2762 QbeGen.CopyOp("0", q)
|
|
|
- 2763 ELSE
|
|
|
- 2764 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 2765 SymTab.ObjectSize(dt)), q);
|
|
|
- 2766 t := SymTab.IntType()
|
|
|
- 2767 END; .)
|
|
|
- 2768 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
- 2769 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
- 2770 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
- 2771 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2772 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 2773 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
- 2774 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2775 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
- 2776 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 2777 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 2778 astCur := astNode; astIsLit := TRUE;
|
|
|
- 2779 (* set shift/rotate: isMax
|
|
|
- 2780 doubles as "rotate" *)
|
|
|
- 2781 IF (et # SymTab.InvalidType)
|
|
|
- 2782 AND (SymTab.ClassOf(et) =
|
|
|
- 2783 SymTab.ClSet) THEN
|
|
|
- 2784 t := et;
|
|
|
- 2785 QbeGen.CopyOp("@", q)
|
|
|
- 2786 ELSE SemError(230);
|
|
|
- 2787 t := SymTab.InvalidType;
|
|
|
- 2788 QbeGen.CopyOp("0", q)
|
|
|
- 2789 END; .)
|
|
|
- 2790 | ( "MIN" (. isMax := FALSE; .)
|
|
|
- 2791 | "MAX" (. isMax := TRUE; .) )
|
|
|
- 2792 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 2793 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2794 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 2795 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
- 2796 ELSE AST.SetChild(astNode, 0,
|
|
|
- 2797 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
- 2798 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2799 astCur := astNode; astIsLit := TRUE;
|
|
|
- 2800 IF (dt # SymTab.InvalidType)
|
|
|
- 2801 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
- 2802 (* REAL/LONGREAL: the
|
|
|
- 2803 implementation bounds *)
|
|
|
- 2804 IF isMax THEN
|
|
|
- 2805 QbeGen.NormReal(
|
|
|
- 2806 "3.402823e38", q)
|
|
|
- 2807 ELSE QbeGen.NormReal(
|
|
|
- 2808 "-3.402823e38", q)
|
|
|
- 2809 END;
|
|
|
- 2810 t := SymTab.RealType()
|
|
|
- 2811 ELSIF (dt #
|
|
|
- 2812 SymTab.InvalidType)
|
|
|
- 2813 AND (SymTab.ClassOf(dt) =
|
|
|
- 2814 SymTab.ClLong) THEN
|
|
|
- 2815 IF isMax THEN
|
|
|
- 2816 QbeGen.CopyOp(
|
|
|
- 2817 "9223372036854775807", q)
|
|
|
- 2818 ELSE QbeGen.CopyOp(
|
|
|
- 2819 "-9223372036854775808", q)
|
|
|
- 2820 END;
|
|
|
- 2821 t := SymTab.LongType()
|
|
|
- 2822 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
- 2823 hi) THEN
|
|
|
- 2824 IF isMax THEN
|
|
|
- 2825 QbeGen.IntStr(hi, q)
|
|
|
- 2826 ELSE QbeGen.IntStr(lo, q)
|
|
|
- 2827 END;
|
|
|
- 2828 t := SymTab.IntType()
|
|
|
- 2829 ELSE SemError(230);
|
|
|
- 2830 t := SymTab.InvalidType;
|
|
|
- 2831 QbeGen.CopyOp("0", q)
|
|
|
- 2832 END; .)
|
|
|
- 2833 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 2834 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2835 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
- 2836 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2837 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2838 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 2839 t := SymTab.InvalidType;
|
|
|
- 2840 QbeGen.CopyOp("0", q)
|
|
|
- 2841 ELSE
|
|
|
- 2842 IF sfx
|
|
|
- 2843 OR (dk = SymTab.KindVar)
|
|
|
- 2844 OR (dk = SymTab.KindParam) THEN
|
|
|
- 2845 QbeGen.CopyOp("@", q)
|
|
|
- 2846 ELSE SemError(230);
|
|
|
- 2847 QbeGen.CopyOp("0", q)
|
|
|
- 2848 END;
|
|
|
- 2849 t := SymTab.AddrType()
|
|
|
- 2850 END; .)
|
|
|
- 2851 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 2852 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2853 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
- 2854 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2855 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2856 (. IF (et # SymTab.InvalidType)
|
|
|
- 2857 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 2858 SemError(211) END;
|
|
|
- 2859 t := SymTab.CharType(); .)
|
|
|
- 2860 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
- 2861 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2862 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
- 2863 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2864 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2865 (. IF et # SymTab.InvalidType THEN
|
|
|
- 2866 IF (SymTab.ClassOf(et) #
|
|
|
- 2867 SymTab.ClChar)
|
|
|
- 2868 AND (SymTab.ClassOf(et) #
|
|
|
- 2869 SymTab.ClBool)
|
|
|
- 2870 AND (SymTab.ClassOf(et) #
|
|
|
- 2871 SymTab.ClEnum)
|
|
|
- 2872 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 2873 SemError(211) END
|
|
|
- 2874 END;
|
|
|
- 2875 t := SymTab.IntType(); .)
|
|
|
- 2876 | "CAP" "(" Expr<et, q> ")"
|
|
|
- 2877 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2878 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
- 2879 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2880 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2881 (. QbeGen.CopyOp("@", q);
|
|
|
- 2882 t := SymTab.CharType(); .)
|
|
|
- 2883 | "UCHR" "(" Expr<et, q> ")"
|
|
|
- 2884 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2885 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
- 2886 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2887 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2888 (. (* UCHR: the UCHAR constructor.
|
|
|
- 2889 CHAR -> UCHAR (identity);
|
|
|
- 2890 INTEGER familly -> UCHAR
|
|
|
- 2891 (codepoint value). *)
|
|
|
- 2892 IF (et # SymTab.InvalidType)
|
|
|
- 2893 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
- 2894 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 2895 SemError(211) END;
|
|
|
- 2896 t := SymTab.UCharType(); .)
|
|
|
- 2897 | "CHR8" "(" Expr<et, q> ")"
|
|
|
- 2898 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2899 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
- 2900 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2901 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2902 (. IF (et # SymTab.InvalidType)
|
|
|
- 2903 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 2904 SemError(211) END;
|
|
|
- 2905 t := SymTab.CharType(); .)
|
|
|
- 2906 | "UORD" "(" Expr<et, q> ")"
|
|
|
- 2907 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2908 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
- 2909 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2910 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2911 (. (* UORD(u): the codepoint as a
|
|
|
- 2912 32-bit ordinal (INTEGER),
|
|
|
- 2913 cf. ORD for CHAR. *)
|
|
|
- 2914 IF (et # SymTab.InvalidType)
|
|
|
- 2915 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 2916 SemError(211) END;
|
|
|
- 2917 t := SymTab.IntType(); .)
|
|
|
- 2918 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 2919 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2920 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
- 2921 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 2922 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2923 (. IF (et # SymTab.InvalidType)
|
|
|
- 2924 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 2925 AND (SymTab.ClassOf(et) #
|
|
|
- 2926 SymTab.ClReal) THEN
|
|
|
- 2927 SemError(211)
|
|
|
- 2928 ELSE QbeGen.CopyOp("@", q)
|
|
|
- 2929 END;
|
|
|
- 2930 t := et; .)
|
|
|
- 2931 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
- 2932 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 2933 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 2934 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 2935 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 2936 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 2937 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 2938 SemError(201);
|
|
|
- 2939 t := SymTab.InvalidType
|
|
|
- 2940 ELSE vt := SymTab.SymType(vn);
|
|
|
- 2941 IF vt = SymTab.InvalidType THEN
|
|
|
- 2942 t := SymTab.InvalidType
|
|
|
- 2943 ELSIF et =
|
|
|
- 2944 SymTab.InvalidType THEN
|
|
|
- 2945 t := vt
|
|
|
- 2946 ELSE
|
|
|
- 2947 c1 := SymTab.ClassOf(et);
|
|
|
- 2948 c2 := SymTab.ClassOf(vt);
|
|
|
- 2949 IF (c1 = SymTab.ClInt)
|
|
|
- 2950 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 2951 QbeGen.WidenLong(q, qa);
|
|
|
+ 2732 ELSE
|
|
|
+ 2733 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 2734 t := SymTab.IntType();
|
|
|
+ 2735 QbeGen.CopyOp("@", q)
|
|
|
+ 2736 ELSE
|
|
|
+ 2737 IF isHigh THEN
|
|
|
+ 2738 QbeGen.IntStr(
|
|
|
+ 2739 SymTab.ArrayHi(dt), qr)
|
|
|
+ 2740 ELSE
|
|
|
+ 2741 QbeGen.IntStr(VAL(
|
|
|
+ 2742 INTEGER,
|
|
|
+ 2743 SymTab.ArrayLen(dt)),
|
|
|
+ 2744 qr)
|
|
|
+ 2745 END;
|
|
|
+ 2746 t := SymTab.IntType();
|
|
|
+ 2747 QbeGen.CopyOp(qr, q)
|
|
|
+ 2748 END
|
|
|
+ 2749 END; .)
|
|
|
+ 2750 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 2751 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2752 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
+ 2753 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2754 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2755 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2756 t := SymTab.InvalidType;
|
|
|
+ 2757 QbeGen.CopyOp("0", q)
|
|
|
+ 2758 ELSE
|
|
|
+ 2759 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 2760 SymTab.ObjectSize(dt)), q);
|
|
|
+ 2761 t := SymTab.IntType()
|
|
|
+ 2762 END; .)
|
|
|
+ 2763 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
+ 2764 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
+ 2765 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
+ 2766 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2767 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 2768 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
+ 2769 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2770 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
+ 2771 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 2772 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 2773 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 2774 (* set shift/rotate: isMax
|
|
|
+ 2775 doubles as "rotate" *)
|
|
|
+ 2776 IF (et # SymTab.InvalidType)
|
|
|
+ 2777 AND (SymTab.ClassOf(et) =
|
|
|
+ 2778 SymTab.ClSet) THEN
|
|
|
+ 2779 t := et;
|
|
|
+ 2780 QbeGen.CopyOp("@", q)
|
|
|
+ 2781 ELSE SemError(230);
|
|
|
+ 2782 t := SymTab.InvalidType;
|
|
|
+ 2783 QbeGen.CopyOp("0", q)
|
|
|
+ 2784 END; .)
|
|
|
+ 2785 | ( "MIN" (. isMax := FALSE; .)
|
|
|
+ 2786 | "MAX" (. isMax := TRUE; .) )
|
|
|
+ 2787 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 2788 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2789 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 2790 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
+ 2791 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 2792 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
+ 2793 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2794 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 2795 IF (dt # SymTab.InvalidType)
|
|
|
+ 2796 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
+ 2797 (* REAL/LONGREAL: the
|
|
|
+ 2798 implementation bounds *)
|
|
|
+ 2799 IF isMax THEN
|
|
|
+ 2800 QbeGen.NormReal(
|
|
|
+ 2801 "3.402823e38", q)
|
|
|
+ 2802 ELSE QbeGen.NormReal(
|
|
|
+ 2803 "-3.402823e38", q)
|
|
|
+ 2804 END;
|
|
|
+ 2805 t := SymTab.RealType()
|
|
|
+ 2806 ELSIF (dt #
|
|
|
+ 2807 SymTab.InvalidType)
|
|
|
+ 2808 AND (SymTab.ClassOf(dt) =
|
|
|
+ 2809 SymTab.ClLong) THEN
|
|
|
+ 2810 IF isMax THEN
|
|
|
+ 2811 QbeGen.CopyOp(
|
|
|
+ 2812 "9223372036854775807", q)
|
|
|
+ 2813 ELSE QbeGen.CopyOp(
|
|
|
+ 2814 "-9223372036854775808", q)
|
|
|
+ 2815 END;
|
|
|
+ 2816 t := SymTab.LongType()
|
|
|
+ 2817 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
+ 2818 hi) THEN
|
|
|
+ 2819 IF isMax THEN
|
|
|
+ 2820 QbeGen.IntStr(hi, q)
|
|
|
+ 2821 ELSE QbeGen.IntStr(lo, q)
|
|
|
+ 2822 END;
|
|
|
+ 2823 t := SymTab.IntType()
|
|
|
+ 2824 ELSE SemError(230);
|
|
|
+ 2825 t := SymTab.InvalidType;
|
|
|
+ 2826 QbeGen.CopyOp("0", q)
|
|
|
+ 2827 END; .)
|
|
|
+ 2828 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 2829 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2830 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
+ 2831 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2832 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2833 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 2834 t := SymTab.InvalidType;
|
|
|
+ 2835 QbeGen.CopyOp("0", q)
|
|
|
+ 2836 ELSE
|
|
|
+ 2837 IF sfx
|
|
|
+ 2838 OR (dk = SymTab.KindVar)
|
|
|
+ 2839 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 2840 QbeGen.CopyOp("@", q)
|
|
|
+ 2841 ELSE SemError(230);
|
|
|
+ 2842 QbeGen.CopyOp("0", q)
|
|
|
+ 2843 END;
|
|
|
+ 2844 t := SymTab.AddrType()
|
|
|
+ 2845 END; .)
|
|
|
+ 2846 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 2847 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2848 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
+ 2849 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2850 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2851 (. IF (et # SymTab.InvalidType)
|
|
|
+ 2852 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 2853 SemError(211) END;
|
|
|
+ 2854 t := SymTab.CharType(); .)
|
|
|
+ 2855 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
+ 2856 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2857 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
+ 2858 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2859 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2860 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 2861 IF (SymTab.ClassOf(et) #
|
|
|
+ 2862 SymTab.ClChar)
|
|
|
+ 2863 AND (SymTab.ClassOf(et) #
|
|
|
+ 2864 SymTab.ClBool)
|
|
|
+ 2865 AND (SymTab.ClassOf(et) #
|
|
|
+ 2866 SymTab.ClEnum)
|
|
|
+ 2867 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 2868 SemError(211) END
|
|
|
+ 2869 END;
|
|
|
+ 2870 t := SymTab.IntType(); .)
|
|
|
+ 2871 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 2872 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2873 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
+ 2874 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2875 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2876 (. QbeGen.CopyOp("@", q);
|
|
|
+ 2877 t := SymTab.CharType(); .)
|
|
|
+ 2878 | "UCHR" "(" Expr<et, q> ")"
|
|
|
+ 2879 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2880 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
+ 2881 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2882 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2883 (. (* UCHR: the UCHAR constructor.
|
|
|
+ 2884 CHAR -> UCHAR (identity);
|
|
|
+ 2885 INTEGER familly -> UCHAR
|
|
|
+ 2886 (codepoint value). *)
|
|
|
+ 2887 IF (et # SymTab.InvalidType)
|
|
|
+ 2888 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
+ 2889 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 2890 SemError(211) END;
|
|
|
+ 2891 t := SymTab.UCharType(); .)
|
|
|
+ 2892 | "CHR8" "(" Expr<et, q> ")"
|
|
|
+ 2893 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2894 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
+ 2895 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2896 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2897 (. IF (et # SymTab.InvalidType)
|
|
|
+ 2898 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 2899 SemError(211) END;
|
|
|
+ 2900 t := SymTab.CharType(); .)
|
|
|
+ 2901 | "UORD" "(" Expr<et, q> ")"
|
|
|
+ 2902 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2903 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
+ 2904 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2905 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2906 (. (* UORD(u): the codepoint as a
|
|
|
+ 2907 32-bit ordinal (INTEGER),
|
|
|
+ 2908 cf. ORD for CHAR. *)
|
|
|
+ 2909 IF (et # SymTab.InvalidType)
|
|
|
+ 2910 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 2911 SemError(211) END;
|
|
|
+ 2912 t := SymTab.IntType(); .)
|
|
|
+ 2913 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 2914 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2915 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
+ 2916 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 2917 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2918 (. IF (et # SymTab.InvalidType)
|
|
|
+ 2919 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 2920 AND (SymTab.ClassOf(et) #
|
|
|
+ 2921 SymTab.ClReal) THEN
|
|
|
+ 2922 SemError(211)
|
|
|
+ 2923 ELSE QbeGen.CopyOp("@", q)
|
|
|
+ 2924 END;
|
|
|
+ 2925 t := et; .)
|
|
|
+ 2926 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
+ 2927 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 2928 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 2929 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 2930 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 2931 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 2932 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 2933 SemError(201);
|
|
|
+ 2934 t := SymTab.InvalidType
|
|
|
+ 2935 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 2936 IF vt = SymTab.InvalidType THEN
|
|
|
+ 2937 t := SymTab.InvalidType
|
|
|
+ 2938 ELSIF et =
|
|
|
+ 2939 SymTab.InvalidType THEN
|
|
|
+ 2940 t := vt
|
|
|
+ 2941 ELSE
|
|
|
+ 2942 c1 := SymTab.ClassOf(et);
|
|
|
+ 2943 c2 := SymTab.ClassOf(vt);
|
|
|
+ 2944 IF (c1 = SymTab.ClInt)
|
|
|
+ 2945 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 2946 QbeGen.WidenLong(q, qa);
|
|
|
+ 2947 QbeGen.CopyOp(qa, q);
|
|
|
+ 2948 t := vt
|
|
|
+ 2949 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 2950 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 2951 QbeGen.NarrowLong(q, qa);
|
|
|
2952 QbeGen.CopyOp(qa, q);
|
|
|
2953 t := vt
|
|
|
- 2954 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 2955 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 2956 QbeGen.NarrowLong(q, qa);
|
|
|
+ 2954 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 2955 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 2956 QbeGen.ConvIR(q, qa);
|
|
|
2957 QbeGen.CopyOp(qa, q);
|
|
|
2958 t := vt
|
|
|
- 2959 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 2959 ELSIF (c1 = SymTab.ClLong)
|
|
|
2960 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 2961 QbeGen.ConvIR(q, qa);
|
|
|
+ 2961 QbeGen.ConvLR(q, qa);
|
|
|
2962 QbeGen.CopyOp(qa, q);
|
|
|
2963 t := vt
|
|
|
- 2964 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 2965 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 2966 QbeGen.ConvLR(q, qa);
|
|
|
+ 2964 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 2965 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 2966 QbeGen.ConvRI(q, qa);
|
|
|
2967 QbeGen.CopyOp(qa, q);
|
|
|
2968 t := vt
|
|
|
2969 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 2970 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 2971 QbeGen.ConvRI(q, qa);
|
|
|
+ 2970 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 2971 QbeGen.ConvRL(q, qa);
|
|
|
2972 QbeGen.CopyOp(qa, q);
|
|
|
2973 t := vt
|
|
|
- 2974 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 2975 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 2976 QbeGen.ConvRL(q, qa);
|
|
|
- 2977 QbeGen.CopyOp(qa, q);
|
|
|
- 2978 t := vt
|
|
|
- 2979 ELSIF ((c1 = SymTab.ClInt)
|
|
|
- 2980 OR (c1 =
|
|
|
- 2981 SymTab.ClChar)
|
|
|
- 2982 OR (c1 =
|
|
|
- 2983 SymTab.ClBool)
|
|
|
- 2984 OR (c1 =
|
|
|
- 2985 SymTab.ClEnum))
|
|
|
- 2986 AND ((c2 = SymTab.ClInt)
|
|
|
- 2987 OR (c2 =
|
|
|
- 2988 SymTab.ClChar)
|
|
|
- 2989 OR (c2 =
|
|
|
- 2990 SymTab.ClBool)
|
|
|
- 2991 OR (c2 =
|
|
|
- 2992 SymTab.ClEnum)) THEN
|
|
|
- 2993 t := vt
|
|
|
- 2994 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 2995 AND (c2 = SymTab.ClPtr) THEN
|
|
|
- 2996 t := vt
|
|
|
- 2997 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 2998 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 2999 t := vt
|
|
|
- 3000 ELSE SemError(230);
|
|
|
- 3001 t := SymTab.InvalidType
|
|
|
- 3002 END
|
|
|
- 3003 END
|
|
|
- 3004 END; .)
|
|
|
- 3005 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
- 3006 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
- 3007 QbeGen.CopyOp(sq, q); .)
|
|
|
- 3008 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
- 3009 IF SymTab.BoolCheck(t2) THEN
|
|
|
- 3010 t := SymTab.BoolType()
|
|
|
- 3011 ELSE SemError(212);
|
|
|
- 3012 t := SymTab.InvalidType END;
|
|
|
- 3013 IF t # SymTab.InvalidType THEN
|
|
|
- 3014 QbeGen.CopyOp("@", q)
|
|
|
- 3015 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3016 END;
|
|
|
- 3017 astIsLit := TRUE;
|
|
|
- 3018 astCur := AST.MakeUn(
|
|
|
- 3019 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
- 3020 )
|
|
|
- 3021 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
|
|
|
- 3022 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 3023 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 3024 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 3025 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3026 (. VAR astNode: AST.Node; .)
|
|
|
- 3027 = "{" (. t := SymTab.NewSet(
|
|
|
- 3028 SymTab.NewSubR(0, 255));
|
|
|
- 3029 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
- 3030 QbeGen.NewSetTemp(8, q);
|
|
|
- 3031 QbeGen.SetZero(q, 8); .)
|
|
|
- 3032 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
- 3033 "}" (. astCur := astNode; .) .
|
|
|
- 3034 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
- 3035 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
- 3036 declared type sets the width (set) or element type (array). *)
|
|
|
- 3037 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3038 (. VAR nw: CARDINAL;
|
|
|
- 3039 astNode, astTail: AST.Node;
|
|
|
- 3040 savedCls: INTEGER; .)
|
|
|
- 3041 = "{" (. savedCls := braceCls;
|
|
|
- 3042 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
- 3043 AST.SetTy(astNode, vt);
|
|
|
- 3044 astTail := astNode;
|
|
|
- 3045 IF vt = SymTab.InvalidType THEN
|
|
|
- 3046 braceCls := -1
|
|
|
- 3047 ELSE braceCls :=
|
|
|
- 3048 SymTab.ClassOf(vt)
|
|
|
- 3049 END;
|
|
|
- 3050 IF braceCls = SymTab.ClSet THEN
|
|
|
- 3051 IF vt = SymTab.InvalidType THEN
|
|
|
- 3052 nw := 8
|
|
|
- 3053 ELSE nw := SymTab.SetWords(vt);
|
|
|
- 3054 IF nw = 0 THEN nw := 8 END
|
|
|
- 3055 END;
|
|
|
- 3056 QbeGen.NewSetTemp(nw, q);
|
|
|
- 3057 QbeGen.SetZero(q, nw)
|
|
|
- 3058 ELSIF (braceCls =
|
|
|
- 3059 SymTab.ClArray)
|
|
|
- 3060 OR (braceCls =
|
|
|
- 3061 SymTab.ClRecord)
|
|
|
- 3062 OR (braceCls =
|
|
|
- 3063 SymTab.ClClass) THEN
|
|
|
- 3064 QbeGen.CtorBegin(vt)
|
|
|
- 3065 ELSE
|
|
|
- 3066 IF vt # SymTab.InvalidType THEN
|
|
|
- 3067 SemError(230) END;
|
|
|
- 3068 braceCls := -1
|
|
|
- 3069 END; .)
|
|
|
- 3070 [ BraceElem<vt, q, astNode, astTail>
|
|
|
- 3071 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
- 3072 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
- 3073 OR (braceCls =
|
|
|
- 3074 SymTab.ClRecord)
|
|
|
- 3075 OR (braceCls =
|
|
|
- 3076 SymTab.ClClass) THEN
|
|
|
- 3077 QbeGen.CtorEnd(q)
|
|
|
- 3078 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
- 3079 QbeGen.CopyOp("0", q)
|
|
|
- 3080 END;
|
|
|
- 3081 braceCls := savedCls; .)
|
|
|
- 3082 (. astCur := astNode; .) .
|
|
|
- 3083 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
- 3084 VAR node, tail: AST.Node>
|
|
|
- 3085 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3086 qe, q2: QbeGen.QVal;
|
|
|
- 3087 v, v2, reps, k: INTEGER;
|
|
|
- 3088 elem: SymTab.TypeIndex;
|
|
|
- 3089 lo: INTEGER;
|
|
|
- 3090 span: CARDINAL;
|
|
|
- 3091 cl, cl2: INTEGER;
|
|
|
- 3092 hasR, hasB: BOOLEAN;
|
|
|
- 3093 astEl: AST.Node; .)
|
|
|
- 3094 = (. hasR := FALSE; hasB := FALSE;
|
|
|
- 3095 reps := 1; .)
|
|
|
- 3096 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3097 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3098 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3099 hasR := TRUE; .) ]
|
|
|
- 3100 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
- 3101 (. IF braceCls = SymTab.ClSet THEN
|
|
|
- 3102 IF hasB THEN SemError(230) END;
|
|
|
- 3103 lo := SymTab.SetBaseLo(vt);
|
|
|
- 3104 span := SymTab.SetCount(vt);
|
|
|
- 3105 IF (et = SymTab.InvalidType)
|
|
|
- 3106 OR (hasR AND (et2 =
|
|
|
- 3107 SymTab.InvalidType)) THEN
|
|
|
- 3108 ELSE cl :=
|
|
|
- 3109 SymTab.ClassOf(et);
|
|
|
- 3110 IF hasR THEN
|
|
|
- 3111 cl2 :=
|
|
|
- 3112 SymTab.ClassOf(et2)
|
|
|
- 3113 ELSE cl2 := SymTab.ClInt
|
|
|
- 3114 END;
|
|
|
- 3115 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3116 OR (hasR AND NOT
|
|
|
- 3117 SymTab.SetElemClassOk(cl2))
|
|
|
- 3118 THEN
|
|
|
- 3119 SemError(222)
|
|
|
- 3120 ELSIF hasR
|
|
|
- 3121 AND SymTab.ConstInt(qe, v)
|
|
|
- 3122 AND SymTab.ConstInt(q2,
|
|
|
- 3123 v2)
|
|
|
- 3124 AND ((v < lo)
|
|
|
- 3125 OR (v2 < lo)
|
|
|
- 3126 OR (v >= lo +
|
|
|
- 3127 VAL(INTEGER, span))
|
|
|
- 3128 OR (v2 >= lo +
|
|
|
- 3129 VAL(INTEGER, span))
|
|
|
- 3130 OR (v > v2)) THEN
|
|
|
- 3131 SemError(222)
|
|
|
- 3132 ELSIF hasR THEN
|
|
|
- 3133 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3134 lo, span)
|
|
|
- 3135 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3136 v)
|
|
|
- 3137 AND ((v < lo)
|
|
|
- 3138 OR (v >= lo +
|
|
|
- 3139 VAL(INTEGER,
|
|
|
- 3140 span))) THEN
|
|
|
- 3141 SemError(222)
|
|
|
- 3142 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3143 lo, span)
|
|
|
- 3144 END
|
|
|
- 3145 END
|
|
|
- 3146 ELSIF (braceCls = SymTab.ClArray)
|
|
|
- 3147 OR (braceCls =
|
|
|
- 3148 SymTab.ClRecord)
|
|
|
- 3149 OR (braceCls =
|
|
|
- 3150 SymTab.ClClass) THEN
|
|
|
- 3151 IF hasR THEN SemError(230) END;
|
|
|
- 3152 reps := 1;
|
|
|
- 3153 IF hasB THEN
|
|
|
- 3154 IF SymTab.ConstInt(q2, v2)
|
|
|
- 3155 AND (v2 >= 1) THEN
|
|
|
- 3156 reps := v2
|
|
|
- 3157 ELSE SemError(230)
|
|
|
- 3158 END
|
|
|
- 3159 END;
|
|
|
- 3160 k := 0;
|
|
|
- 3161 WHILE k < reps DO
|
|
|
- 3162 QbeGen.CtorElem(qe);
|
|
|
- 3163 INC(k)
|
|
|
- 3164 END
|
|
|
- 3165 END; .)
|
|
|
- 3166 (. (* the BY form repeats the
|
|
|
- 3167 element; keep the AST in
|
|
|
- 3168 step with CtorElem *)
|
|
|
- 3169 k := 0;
|
|
|
- 3170 WHILE k < reps DO
|
|
|
- 3171 AstAppend(AST.NkBlock,
|
|
|
- 3172 node, tail, astEl);
|
|
|
- 3173 INC(k)
|
|
|
- 3174 END; .) .
|
|
|
- 3175 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3176 qe, q2: QbeGen.QVal;
|
|
|
- 3177 v, v2: INTEGER;
|
|
|
- 3178 lo: INTEGER;
|
|
|
- 3179 span: CARDINAL;
|
|
|
- 3180 cl, cl2: INTEGER;
|
|
|
- 3181 hasR: BOOLEAN;
|
|
|
- 3182 astEl: AST.Node; .)
|
|
|
- 3183 = (. hasR := FALSE; .)
|
|
|
- 3184 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3185 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3186 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3187 hasR := TRUE; .) ]
|
|
|
- 3188 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 3189 span := SymTab.SetCount(st);
|
|
|
- 3190 IF (et = SymTab.InvalidType)
|
|
|
- 3191 OR (hasR AND (et2 =
|
|
|
- 3192 SymTab.InvalidType)) THEN
|
|
|
- 3193 ELSE cl :=
|
|
|
- 3194 SymTab.ClassOf(et);
|
|
|
- 3195 IF hasR THEN
|
|
|
- 3196 cl2 :=
|
|
|
- 3197 SymTab.ClassOf(et2)
|
|
|
- 3198 ELSE cl2 := SymTab.ClInt
|
|
|
- 3199 END;
|
|
|
- 3200 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3201 OR (hasR AND NOT
|
|
|
- 3202 SymTab.SetElemClassOk(cl2))
|
|
|
- 3203 THEN
|
|
|
- 3204 SemError(222)
|
|
|
- 3205 ELSIF hasR
|
|
|
- 3206 AND SymTab.ConstInt(qe, v)
|
|
|
- 3207 AND SymTab.ConstInt(q2,
|
|
|
- 3208 v2)
|
|
|
- 3209 AND ((v < lo)
|
|
|
- 3210 OR (v2 < lo)
|
|
|
- 3211 OR (v >= lo +
|
|
|
- 3212 VAL(INTEGER, span))
|
|
|
- 3213 OR (v2 >= lo +
|
|
|
- 3214 VAL(INTEGER, span))
|
|
|
- 3215 OR (v > v2)) THEN
|
|
|
- 3216 SemError(222)
|
|
|
- 3217 ELSIF hasR THEN
|
|
|
- 3218 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3219 lo, span)
|
|
|
- 3220 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3221 v)
|
|
|
- 3222 AND ((v < lo)
|
|
|
- 3223 OR (v >= lo +
|
|
|
- 3224 VAL(INTEGER,
|
|
|
- 3225 span))) THEN
|
|
|
- 3226 SemError(222)
|
|
|
- 3227 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3228 lo, span)
|
|
|
- 3229 END
|
|
|
- 3230 END; .)
|
|
|
- 3231 (. AST.SetChild(node,
|
|
|
- 3232 AST.NChild(node), astEl); .) .
|
|
|
- 3233 GetIdent<VAR n: SymTab.Name>
|
|
|
- 3234 = ident (. LexName(n); .) .
|
|
|
- 3235
|
|
|
- 3236 END M2.
|
|
|
+ 2974 ELSIF ((c1 = SymTab.ClInt)
|
|
|
+ 2975 OR (c1 =
|
|
|
+ 2976 SymTab.ClChar)
|
|
|
+ 2977 OR (c1 =
|
|
|
+ 2978 SymTab.ClBool)
|
|
|
+ 2979 OR (c1 =
|
|
|
+ 2980 SymTab.ClEnum))
|
|
|
+ 2981 AND ((c2 = SymTab.ClInt)
|
|
|
+ 2982 OR (c2 =
|
|
|
+ 2983 SymTab.ClChar)
|
|
|
+ 2984 OR (c2 =
|
|
|
+ 2985 SymTab.ClBool)
|
|
|
+ 2986 OR (c2 =
|
|
|
+ 2987 SymTab.ClEnum)) THEN
|
|
|
+ 2988 t := vt
|
|
|
+ 2989 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 2990 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 2991 t := vt
|
|
|
+ 2992 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 2993 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 2994 t := vt
|
|
|
+ 2995 ELSE SemError(230);
|
|
|
+ 2996 t := SymTab.InvalidType
|
|
|
+ 2997 END
|
|
|
+ 2998 END
|
|
|
+ 2999 END; .)
|
|
|
+ 3000 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
+ 3001 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
+ 3002 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 3003 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
+ 3004 IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 3005 t := SymTab.BoolType()
|
|
|
+ 3006 ELSE SemError(212);
|
|
|
+ 3007 t := SymTab.InvalidType END;
|
|
|
+ 3008 IF t # SymTab.InvalidType THEN
|
|
|
+ 3009 QbeGen.CopyOp("@", q)
|
|
|
+ 3010 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3011 END;
|
|
|
+ 3012 astIsLit := TRUE;
|
|
|
+ 3013 astCur := AST.MakeUn(
|
|
|
+ 3014 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
+ 3015 )
|
|
|
+ 3016 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
|
|
|
+ 3017 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 3018 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 3019 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 3020 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3021 (. VAR astNode: AST.Node; .)
|
|
|
+ 3022 = "{" (. t := SymTab.NewSet(
|
|
|
+ 3023 SymTab.NewSubR(0, 255));
|
|
|
+ 3024 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
+ 3025 QbeGen.NewSetTemp(8, q);
|
|
|
+ 3026 QbeGen.SetZero(q, 8); .)
|
|
|
+ 3027 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
+ 3028 "}" (. astCur := astNode; .) .
|
|
|
+ 3029 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ 3030 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ 3031 declared type sets the width (set) or element type (array). *)
|
|
|
+ 3032 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3033 (. VAR nw: CARDINAL;
|
|
|
+ 3034 astNode, astTail: AST.Node;
|
|
|
+ 3035 savedCls: INTEGER; .)
|
|
|
+ 3036 = "{" (. savedCls := braceCls;
|
|
|
+ 3037 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
+ 3038 AST.SetTy(astNode, vt);
|
|
|
+ 3039 astTail := astNode;
|
|
|
+ 3040 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3041 braceCls := -1
|
|
|
+ 3042 ELSE braceCls :=
|
|
|
+ 3043 SymTab.ClassOf(vt)
|
|
|
+ 3044 END;
|
|
|
+ 3045 IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3046 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3047 nw := 8
|
|
|
+ 3048 ELSE nw := SymTab.SetWords(vt);
|
|
|
+ 3049 IF nw = 0 THEN nw := 8 END
|
|
|
+ 3050 END;
|
|
|
+ 3051 QbeGen.NewSetTemp(nw, q);
|
|
|
+ 3052 QbeGen.SetZero(q, nw)
|
|
|
+ 3053 ELSIF (braceCls =
|
|
|
+ 3054 SymTab.ClArray)
|
|
|
+ 3055 OR (braceCls =
|
|
|
+ 3056 SymTab.ClRecord)
|
|
|
+ 3057 OR (braceCls =
|
|
|
+ 3058 SymTab.ClClass) THEN
|
|
|
+ 3059 QbeGen.CtorBegin(vt)
|
|
|
+ 3060 ELSE
|
|
|
+ 3061 IF vt # SymTab.InvalidType THEN
|
|
|
+ 3062 SemError(230) END;
|
|
|
+ 3063 braceCls := -1
|
|
|
+ 3064 END; .)
|
|
|
+ 3065 [ BraceElem<vt, q, astNode, astTail>
|
|
|
+ 3066 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
+ 3067 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
+ 3068 OR (braceCls =
|
|
|
+ 3069 SymTab.ClRecord)
|
|
|
+ 3070 OR (braceCls =
|
|
|
+ 3071 SymTab.ClClass) THEN
|
|
|
+ 3072 QbeGen.CtorEnd(q)
|
|
|
+ 3073 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ 3074 QbeGen.CopyOp("0", q)
|
|
|
+ 3075 END;
|
|
|
+ 3076 braceCls := savedCls; .)
|
|
|
+ 3077 (. astCur := astNode; .) .
|
|
|
+ 3078 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
+ 3079 VAR node, tail: AST.Node>
|
|
|
+ 3080 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3081 qe, q2: QbeGen.QVal;
|
|
|
+ 3082 v, v2, reps, k: INTEGER;
|
|
|
+ 3083 elem: SymTab.TypeIndex;
|
|
|
+ 3084 lo: INTEGER;
|
|
|
+ 3085 span: CARDINAL;
|
|
|
+ 3086 cl, cl2: INTEGER;
|
|
|
+ 3087 hasR, hasB: BOOLEAN;
|
|
|
+ 3088 astEl: AST.Node; .)
|
|
|
+ 3089 = (. hasR := FALSE; hasB := FALSE;
|
|
|
+ 3090 reps := 1; .)
|
|
|
+ 3091 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3092 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3093 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3094 hasR := TRUE; .) ]
|
|
|
+ 3095 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ 3096 (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3097 IF hasB THEN SemError(230) END;
|
|
|
+ 3098 lo := SymTab.SetBaseLo(vt);
|
|
|
+ 3099 span := SymTab.SetCount(vt);
|
|
|
+ 3100 IF (et = SymTab.InvalidType)
|
|
|
+ 3101 OR (hasR AND (et2 =
|
|
|
+ 3102 SymTab.InvalidType)) THEN
|
|
|
+ 3103 ELSE cl :=
|
|
|
+ 3104 SymTab.ClassOf(et);
|
|
|
+ 3105 IF hasR THEN
|
|
|
+ 3106 cl2 :=
|
|
|
+ 3107 SymTab.ClassOf(et2)
|
|
|
+ 3108 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3109 END;
|
|
|
+ 3110 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3111 OR (hasR AND NOT
|
|
|
+ 3112 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3113 THEN
|
|
|
+ 3114 SemError(222)
|
|
|
+ 3115 ELSIF hasR
|
|
|
+ 3116 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3117 AND SymTab.ConstInt(q2,
|
|
|
+ 3118 v2)
|
|
|
+ 3119 AND ((v < lo)
|
|
|
+ 3120 OR (v2 < lo)
|
|
|
+ 3121 OR (v >= lo +
|
|
|
+ 3122 VAL(INTEGER, span))
|
|
|
+ 3123 OR (v2 >= lo +
|
|
|
+ 3124 VAL(INTEGER, span))
|
|
|
+ 3125 OR (v > v2)) THEN
|
|
|
+ 3126 SemError(222)
|
|
|
+ 3127 ELSIF hasR THEN
|
|
|
+ 3128 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3129 lo, span)
|
|
|
+ 3130 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3131 v)
|
|
|
+ 3132 AND ((v < lo)
|
|
|
+ 3133 OR (v >= lo +
|
|
|
+ 3134 VAL(INTEGER,
|
|
|
+ 3135 span))) THEN
|
|
|
+ 3136 SemError(222)
|
|
|
+ 3137 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3138 lo, span)
|
|
|
+ 3139 END
|
|
|
+ 3140 END
|
|
|
+ 3141 ELSIF (braceCls = SymTab.ClArray)
|
|
|
+ 3142 OR (braceCls =
|
|
|
+ 3143 SymTab.ClRecord)
|
|
|
+ 3144 OR (braceCls =
|
|
|
+ 3145 SymTab.ClClass) THEN
|
|
|
+ 3146 IF hasR THEN SemError(230) END;
|
|
|
+ 3147 reps := 1;
|
|
|
+ 3148 IF hasB THEN
|
|
|
+ 3149 IF SymTab.ConstInt(q2, v2)
|
|
|
+ 3150 AND (v2 >= 1) THEN
|
|
|
+ 3151 reps := v2
|
|
|
+ 3152 ELSE SemError(230)
|
|
|
+ 3153 END
|
|
|
+ 3154 END;
|
|
|
+ 3155 k := 0;
|
|
|
+ 3156 WHILE k < reps DO
|
|
|
+ 3157 QbeGen.CtorElem(qe);
|
|
|
+ 3158 INC(k)
|
|
|
+ 3159 END
|
|
|
+ 3160 END; .)
|
|
|
+ 3161 (. (* the BY form repeats the
|
|
|
+ 3162 element; keep the AST in
|
|
|
+ 3163 step with CtorElem *)
|
|
|
+ 3164 k := 0;
|
|
|
+ 3165 WHILE k < reps DO
|
|
|
+ 3166 AstAppend(AST.NkBlock,
|
|
|
+ 3167 node, tail, astEl);
|
|
|
+ 3168 INC(k)
|
|
|
+ 3169 END; .) .
|
|
|
+ 3170 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3171 qe, q2: QbeGen.QVal;
|
|
|
+ 3172 v, v2: INTEGER;
|
|
|
+ 3173 lo: INTEGER;
|
|
|
+ 3174 span: CARDINAL;
|
|
|
+ 3175 cl, cl2: INTEGER;
|
|
|
+ 3176 hasR: BOOLEAN;
|
|
|
+ 3177 astEl: AST.Node; .)
|
|
|
+ 3178 = (. hasR := FALSE; .)
|
|
|
+ 3179 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3180 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3181 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3182 hasR := TRUE; .) ]
|
|
|
+ 3183 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 3184 span := SymTab.SetCount(st);
|
|
|
+ 3185 IF (et = SymTab.InvalidType)
|
|
|
+ 3186 OR (hasR AND (et2 =
|
|
|
+ 3187 SymTab.InvalidType)) THEN
|
|
|
+ 3188 ELSE cl :=
|
|
|
+ 3189 SymTab.ClassOf(et);
|
|
|
+ 3190 IF hasR THEN
|
|
|
+ 3191 cl2 :=
|
|
|
+ 3192 SymTab.ClassOf(et2)
|
|
|
+ 3193 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3194 END;
|
|
|
+ 3195 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3196 OR (hasR AND NOT
|
|
|
+ 3197 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3198 THEN
|
|
|
+ 3199 SemError(222)
|
|
|
+ 3200 ELSIF hasR
|
|
|
+ 3201 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3202 AND SymTab.ConstInt(q2,
|
|
|
+ 3203 v2)
|
|
|
+ 3204 AND ((v < lo)
|
|
|
+ 3205 OR (v2 < lo)
|
|
|
+ 3206 OR (v >= lo +
|
|
|
+ 3207 VAL(INTEGER, span))
|
|
|
+ 3208 OR (v2 >= lo +
|
|
|
+ 3209 VAL(INTEGER, span))
|
|
|
+ 3210 OR (v > v2)) THEN
|
|
|
+ 3211 SemError(222)
|
|
|
+ 3212 ELSIF hasR THEN
|
|
|
+ 3213 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3214 lo, span)
|
|
|
+ 3215 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3216 v)
|
|
|
+ 3217 AND ((v < lo)
|
|
|
+ 3218 OR (v >= lo +
|
|
|
+ 3219 VAL(INTEGER,
|
|
|
+ 3220 span))) THEN
|
|
|
+ 3221 SemError(222)
|
|
|
+ 3222 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3223 lo, span)
|
|
|
+ 3224 END
|
|
|
+ 3225 END; .)
|
|
|
+ 3226 (. AST.SetChild(node,
|
|
|
+ 3227 AST.NChild(node), astEl); .) .
|
|
|
+ 3228 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 3229 = ident (. LexName(n); .) .
|
|
|
+ 3230
|
|
|
+ 3231 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|