|
|
@@ -1141,2777 +1141,2778 @@ Listing:
|
|
|
1123 (* a forward-typed global:
|
|
|
1124 defer emission until the
|
|
|
1125 TYPE block completes *)
|
|
|
- 1126 WHILE i < SymTab.PendCount() DO
|
|
|
- 1127 SymTab.PendName(i, nm);
|
|
|
- 1128 IF nPendVar <=
|
|
|
- 1129 HIGH(pendVarName) THEN
|
|
|
- 1130 pendVarName[nPendVar] := nm;
|
|
|
- 1131 pendVarT[nPendVar] := t;
|
|
|
- 1132 INC(nPendVar)
|
|
|
- 1133 END;
|
|
|
- 1134 INC(i)
|
|
|
- 1135 END
|
|
|
- 1136 ELSE
|
|
|
- 1137 WHILE i < SymTab.PendCount() DO
|
|
|
- 1138 SymTab.PendName(i, nm);
|
|
|
- 1139 QbeGen.DeclVar(nm, t);
|
|
|
- 1140 INC(i)
|
|
|
- 1141 END
|
|
|
- 1142 END;
|
|
|
- 1143 (* a plain VAR list, not a
|
|
|
- 1144 heading: the signature
|
|
|
- 1145 result is discarded *)
|
|
|
- 1146 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1147 END; .) .
|
|
|
- 1148 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
- 1149 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1150 SymTab.KindVar) THEN
|
|
|
- 1151 SemError(200) END; .)
|
|
|
- 1152 { ","
|
|
|
- 1153 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
- 1154 SymTab.KindVar) THEN
|
|
|
- 1155 SemError(200) END; .) } .
|
|
|
- 1156 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
- 1157 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1158 SemError(200) END; .)
|
|
|
- 1159 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
- 1160 SemError(200) END; .) } .
|
|
|
- 1161 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
- 1162 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
- 1163 FORWARD marks; the body heading re-enters (signature compare
|
|
|
- 1164 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
- 1165 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
- 1166 (. VAR t: SymTab.TypeIndex;
|
|
|
- 1167 mg: QbeGen.QVal; .)
|
|
|
- 1168 = "PROCEDURE"
|
|
|
- 1169 GetIdent<pn> (. IF methCls #
|
|
|
- 1170 SymTab.InvalidType THEN
|
|
|
- 1171 (* a method: resume the
|
|
|
- 1172 declared symbol (reuse
|
|
|
- 1173 its uid) *)
|
|
|
- 1174 IF NOT SymTab.ResumeMethod(
|
|
|
- 1175 methCls, pn) THEN
|
|
|
- 1176 SemError(200) END
|
|
|
- 1177 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
- 1178 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
- 1179 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
- 1180 SemError(200) END
|
|
|
- 1181 END
|
|
|
- 1182 END;
|
|
|
- 1183 Lower.ScopeEnter;
|
|
|
- 1184 Lower.NoteProc(pn,
|
|
|
- 1185 SymTab.ProcUid(pn),
|
|
|
- 1186 SymTab.InvalidType,
|
|
|
- 1187 SymTab.ProcDepthOf(pn),
|
|
|
- 1188 FALSE);
|
|
|
- 1189 IF methCls #
|
|
|
- 1190 SymTab.InvalidType THEN
|
|
|
- 1191 QbeGen.Mangled(pn,
|
|
|
- 1192 SymTab.MethUid(), mg)
|
|
|
- 1193 ELSE
|
|
|
- 1194 QbeGen.Mangled(pn,
|
|
|
- 1195 SymTab.ProcUid(pn), mg)
|
|
|
- 1196 END;
|
|
|
- 1197 QbeGen.BeginFunc(mg);
|
|
|
- 1198 IF methCls #
|
|
|
- 1199 SymTab.InvalidType THEN
|
|
|
- 1200 (* hidden THIS receiver:
|
|
|
- 1201 a VAR param of the
|
|
|
- 1202 class type, pushed as
|
|
|
- 1203 the WITH base *)
|
|
|
- 1204 IF NOT SymTab.EnterThisParam(
|
|
|
- 1205 methCls) THEN
|
|
|
- 1206 SemError(200) END;
|
|
|
- 1207 IF NOT QbeGen.FuncParam(
|
|
|
- 1208 "THIS", TRUE,
|
|
|
- 1209 methCls) THEN
|
|
|
- 1210 SemError(233) END
|
|
|
- 1211 END; .)
|
|
|
- 1212 [ FormalParams ]
|
|
|
- 1213 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
- 1214 SemError(235) END;
|
|
|
- 1215 Lower.SetProcRes(t);
|
|
|
- 1216 QbeGen.SetFuncRes(t);
|
|
|
- 1217 IF (t #
|
|
|
- 1218 SymTab.InvalidType)
|
|
|
- 1219 AND ((SymTab.ClassOf(t)
|
|
|
- 1220 = SymTab.ClArray)
|
|
|
- 1221 OR (SymTab.ClassOf(t)
|
|
|
- 1222 = SymTab.ClRecord)
|
|
|
- 1223 OR (SymTab.ClassOf(t)
|
|
|
- 1224 = SymTab.ClSet)
|
|
|
- 1225 OR (SymTab.ClassOf(t)
|
|
|
- 1226 = SymTab.ClClass)) THEN
|
|
|
- 1227 SemError(230) END; .) ] .
|
|
|
- 1228 FormalParams
|
|
|
- 1229 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
- 1230 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
- 1231 nm: SymTab.Name;
|
|
|
- 1232 i: CARDINAL;
|
|
|
- 1233 isV: BOOLEAN; .)
|
|
|
- 1234 = (. isV := FALSE; .)
|
|
|
- 1235 [ "VAR" (. isV := TRUE; .) ]
|
|
|
- 1236 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
- 1237 WHILE i < SymTab.PendCount() DO
|
|
|
- 1238 SymTab.PendName(i, nm);
|
|
|
- 1239 Lower.NoteParam(nm, t, isV);
|
|
|
- 1240 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
- 1241 (* value open arrays are
|
|
|
- 1242 passed as descriptor
|
|
|
- 1243 addresses (no copy):
|
|
|
- 1244 same representation as
|
|
|
- 1245 VAR formals *)
|
|
|
- 1246 IF NOT QbeGen.FuncParam(nm,
|
|
|
- 1247 isV
|
|
|
- 1248 OR SymTab.IsOpenArray(t),
|
|
|
- 1249 t) THEN
|
|
|
- 1250 SemError(233) END;
|
|
|
- 1251 INC(i)
|
|
|
- 1252 END;
|
|
|
- 1253 IF NOT SymTab.FixPending(t) THEN
|
|
|
- 1254 SemError(235) END; .) .
|
|
|
- 1255 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
- 1256 static link gives them their parent's frame. Methods keep
|
|
|
- 1257 parse-now/230-later. *)
|
|
|
- 1258 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
- 1259 astNode: AST.Node; .)
|
|
|
- 1260 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
- 1261 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
- 1262 AST.SetOp(astNode, 0);
|
|
|
- 1263 AST.SetChild(astNode, 0,
|
|
|
- 1264 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
- 1265 Lower.NoteProcNode(astNode); .)
|
|
|
- 1266 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
- 1267 astDecl := astNode;
|
|
|
- 1268 Lower.ScopeLeave;
|
|
|
- 1269 SymTab.MarkFwd;
|
|
|
- 1270 SymTab.CloseProc;
|
|
|
- 1271 QbeGen.AbortFunc; .)
|
|
|
- 1272 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
- 1273 astDecl := astNode;
|
|
|
- 1274 Lower.MarkProcExternal;
|
|
|
- 1275 Lower.ScopeLeave;
|
|
|
- 1276 SymTab.MarkExternal("");
|
|
|
- 1277 SymTab.CloseProc;
|
|
|
- 1278 QbeGen.AbortFunc; .)
|
|
|
- 1279 | (. QbeGen.EndFuncHeader; .)
|
|
|
- 1280 Block<pn> (. AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1281 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
- 1282 astDecl := astNode;
|
|
|
- 1283 Lower.ScopeLeave;
|
|
|
- 1284 SymTab.CloseProc;
|
|
|
- 1285 QbeGen.EndFunc(
|
|
|
- 1286 SymTab.ProcRes(pn)); .) ) .
|
|
|
- 1287 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
- 1288 = DeclSeq (. astBlkDecls := astDecl;
|
|
|
- 1289 astStmt := AST.NoNode; .)
|
|
|
- 1290 [ "BEGIN" (. (* an empty body is still a
|
|
|
- 1291 body: mark it so Lower
|
|
|
- 1292 does not read it as a
|
|
|
- 1293 definition heading *)
|
|
|
- 1294 IF astStmt = AST.NoNode THEN
|
|
|
- 1295 astStmt :=
|
|
|
- 1296 AST.MakeNode(AST.NkBlock)
|
|
|
- 1297 END; .)
|
|
|
- 1298 [ StatSeq ] ]
|
|
|
- 1299 "END"
|
|
|
- 1300 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
- 1301 SemError(202) END; .) .
|
|
|
- 1302 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
- 1303 = (. astSeq := AST.NoNode;
|
|
|
- 1304 astTail := AST.NoNode; .)
|
|
|
- 1305 Statement (. AstAppend(AST.NkBlock,
|
|
|
- 1306 astSeq, astTail, astStmt); .)
|
|
|
- 1307 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
- 1308 astSeq, astTail, astStmt); .) ] }
|
|
|
- 1309 (. astStmt := astSeq; .) .
|
|
|
- 1310 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
- 1311 are accepted: the statement after ';' is optional. *)
|
|
|
- 1312 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
- 1313 = (. astStmt := AST.NoNode; .)
|
|
|
- 1314 ( AssOrCall
|
|
|
- 1315 | IfStat
|
|
|
- 1316 | WhileStat
|
|
|
- 1317 | RepeatStat
|
|
|
- 1318 | LoopStat
|
|
|
- 1319 | ForStat
|
|
|
- 1320 | CaseStat
|
|
|
- 1321 | WithStat
|
|
|
- 1322 | ReturnStat
|
|
|
- 1323 | HaltStat
|
|
|
- 1324 | NewStat
|
|
|
- 1325 | DisposeStat
|
|
|
- 1326 | IncDecStat
|
|
|
- 1327 | InclExclStat
|
|
|
- 1328 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
- 1329 QbeGen.Jmp(lx)
|
|
|
- 1330 ELSE SemError(230) END;
|
|
|
- 1331 astStmt := AST.MakeNode(AST.NkExit); .) ) .
|
|
|
- 1332 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
- 1333 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
- 1334 dk: INTEGER;
|
|
|
- 1335 qd, qe: QbeGen.QVal;
|
|
|
- 1336 qn: SymTab.Name;
|
|
|
- 1337 sfx, isInc: BOOLEAN;
|
|
|
- 1338 astNode, astD: AST.Node; .)
|
|
|
- 1339 = ( "INCL" (. isInc := TRUE; .)
|
|
|
- 1340 | "EXCL" (. isInc := FALSE; .) )
|
|
|
- 1341 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
- 1342 Expr<et2, qe> ")"
|
|
|
- 1343 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1344 IF isInc THEN
|
|
|
- 1345 AST.SetChild(astNode, 0,
|
|
|
- 1346 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
- 1347 ELSE AST.SetChild(astNode, 0,
|
|
|
- 1348 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
- 1349 END;
|
|
|
- 1350 IF astD # AST.NoNode THEN
|
|
|
- 1351 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1352 IF astCur # AST.NoNode THEN
|
|
|
- 1353 AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 1354 astStmt := astNode; .)
|
|
|
- 1355 (. IF at = SymTab.InvalidType THEN
|
|
|
- 1356 ELSIF SymTab.ClassOf(at) #
|
|
|
- 1357 SymTab.ClSet THEN
|
|
|
- 1358 SemError(222)
|
|
|
- 1359 ELSE
|
|
|
- 1360 IF isInc THEN
|
|
|
- 1361 QbeGen.SetBit(qd, qe,
|
|
|
- 1362 SymTab.SetBaseLo(at),
|
|
|
- 1363 SymTab.SetCount(at))
|
|
|
- 1364 ELSE
|
|
|
- 1365 QbeGen.SetClearBit(qd, qe,
|
|
|
- 1366 SymTab.SetBaseLo(at),
|
|
|
- 1367 SymTab.SetCount(at))
|
|
|
- 1368 END
|
|
|
- 1369 END; .) .
|
|
|
- 1370 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
- 1371 integer designator. *)
|
|
|
- 1372 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
- 1373 dk: INTEGER;
|
|
|
- 1374 qd, qv, qn2, qstep:
|
|
|
- 1375 QbeGen.QVal;
|
|
|
- 1376 qn: SymTab.Name;
|
|
|
- 1377 sfx, isInc: BOOLEAN;
|
|
|
- 1378 astNode, astD, astStep:
|
|
|
- 1379 AST.Node; .)
|
|
|
- 1380 = (. isInc := TRUE; .)
|
|
|
- 1381 ( "INC" (. isInc := TRUE; .)
|
|
|
- 1382 | "DEC" (. isInc := FALSE; .) )
|
|
|
- 1383 "(" (. QbeGen.CopyOp("1", qstep); astStep := AST.NoNode; .)
|
|
|
- 1384 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
- 1385 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
- 1386 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1387 IF isInc THEN
|
|
|
- 1388 AST.SetChild(astNode, 0,
|
|
|
- 1389 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
- 1390 ELSE AST.SetChild(astNode, 0,
|
|
|
- 1391 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
- 1392 END;
|
|
|
- 1393 IF astD # AST.NoNode THEN
|
|
|
- 1394 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1395 IF astStep # AST.NoNode THEN
|
|
|
- 1396 AST.SetChild(astNode, 2, astStep) END;
|
|
|
- 1397 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1398 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1399 AND (dk # SymTab.KindParam)
|
|
|
- 1400 AND (dk # SymTab.KindField) THEN
|
|
|
- 1401 SemError(210)
|
|
|
- 1402 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
- 1403 SemError(211)
|
|
|
- 1404 ELSE
|
|
|
- 1405 IF sfx
|
|
|
- 1406 OR (dk = SymTab.KindField) THEN
|
|
|
- 1407 QbeGen.ElemLoad(qd, dt, qv)
|
|
|
- 1408 ELSE QbeGen.LoadVar(qn,
|
|
|
- 1409 FALSE, qv)
|
|
|
- 1410 END;
|
|
|
- 1411 QbeGen.NewTemp(qn2);
|
|
|
- 1412 IF isInc THEN
|
|
|
- 1413 QbeGen.Op3("add", qn2, qv,
|
|
|
- 1414 qstep, FALSE)
|
|
|
- 1415 ELSE QbeGen.Op3("sub", qn2, qv,
|
|
|
- 1416 qstep, FALSE)
|
|
|
- 1417 END;
|
|
|
- 1418 IF sfx
|
|
|
- 1419 OR (dk = SymTab.KindField) THEN
|
|
|
- 1420 QbeGen.ElemStore(qd, qn2,
|
|
|
- 1421 dt)
|
|
|
- 1422 ELSE QbeGen.StoreVar(qn,
|
|
|
- 1423 qn2, FALSE)
|
|
|
- 1424 END
|
|
|
- 1425 END; .) .
|
|
|
- 1426 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
- 1427 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
- 1428 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
- 1429 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1430 dk: INTEGER;
|
|
|
- 1431 qd, qm: QbeGen.QVal;
|
|
|
- 1432 qn: SymTab.Name;
|
|
|
- 1433 sfx: BOOLEAN;
|
|
|
- 1434 bt: SymTab.TypeIndex;
|
|
|
- 1435 astNode, astD: AST.Node; .)
|
|
|
- 1436 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 1437 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1438 AST.SetChild(astNode, 0,
|
|
|
- 1439 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
- 1440 IF astD # AST.NoNode THEN
|
|
|
- 1441 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1442 astStmt := astNode; .)
|
|
|
- 1443 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1444 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1445 AND (dk # SymTab.KindParam)
|
|
|
- 1446 AND (dk # SymTab.KindField) THEN
|
|
|
- 1447 SemError(210)
|
|
|
- 1448 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1449 SymTab.ClPtr THEN
|
|
|
- 1450 SemError(219)
|
|
|
- 1451 ELSE bt := SymTab.PtrBase(dt);
|
|
|
- 1452 IF bt #
|
|
|
- 1453 SymTab.InvalidType THEN
|
|
|
- 1454 QbeGen.NewHeap(bt, qm);
|
|
|
- 1455 QbeGen.InitHeap(qm, bt);
|
|
|
- 1456 IF sfx
|
|
|
- 1457 OR (dk =
|
|
|
- 1458 SymTab.KindField) THEN
|
|
|
- 1459 QbeGen.ElemStore(qd, qm,
|
|
|
- 1460 dt)
|
|
|
- 1461 ELSE QbeGen.StorePtr(qn,
|
|
|
- 1462 qm)
|
|
|
- 1463 END
|
|
|
- 1464 END
|
|
|
- 1465 END; .) .
|
|
|
- 1466 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1467 dk: INTEGER;
|
|
|
- 1468 qd, qv: QbeGen.QVal;
|
|
|
- 1469 qn: SymTab.Name;
|
|
|
- 1470 sfx: BOOLEAN;
|
|
|
- 1471 astNode, astD: AST.Node; .)
|
|
|
- 1472 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
- 1473 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 1474 AST.SetChild(astNode, 0,
|
|
|
- 1475 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
- 1476 IF astD # AST.NoNode THEN
|
|
|
- 1477 AST.SetChild(astNode, 1, astD) END;
|
|
|
- 1478 astStmt := astNode; .)
|
|
|
- 1479 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 1480 ELSIF (dk # SymTab.KindVar)
|
|
|
- 1481 AND (dk # SymTab.KindParam)
|
|
|
- 1482 AND (dk # SymTab.KindField) THEN
|
|
|
- 1483 SemError(210)
|
|
|
- 1484 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 1485 SymTab.ClPtr THEN
|
|
|
- 1486 SemError(219)
|
|
|
- 1487 ELSE
|
|
|
- 1488 IF sfx
|
|
|
- 1489 OR (dk =
|
|
|
- 1490 SymTab.KindField) THEN
|
|
|
- 1491 QbeGen.ElemLoad(qd, dt,
|
|
|
- 1492 qv)
|
|
|
- 1493 ELSE QbeGen.LoadPtr(qn, qv)
|
|
|
- 1494 END;
|
|
|
- 1495 QbeGen.FreeHeap(qv);
|
|
|
- 1496 IF sfx
|
|
|
- 1497 OR (dk =
|
|
|
- 1498 SymTab.KindField) THEN
|
|
|
- 1499 QbeGen.ElemStore(qd, "0",
|
|
|
- 1500 dt)
|
|
|
- 1501 ELSE QbeGen.StorePtr(qn,
|
|
|
- 1502 "0")
|
|
|
- 1503 END
|
|
|
- 1504 END; .) .
|
|
|
- 1505 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
- 1506 address; field designators resolve through both stacks. *)
|
|
|
- 1507 WithStat (. VAR nW: CARDINAL;
|
|
|
- 1508 astNode: AST.Node; .)
|
|
|
- 1509 = "WITH" (. nW := 0;
|
|
|
- 1510 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
- 1511 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
- 1512 "DO" (. astStmt := AST.NoNode; .)
|
|
|
- 1513 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
- 1514 AST.NChild(astNode), astStmt);
|
|
|
- 1515 astStmt := astNode;
|
|
|
- 1516 WHILE nW > 0 DO
|
|
|
- 1517 SymTab.PopScope;
|
|
|
- 1518 QbeGen.PopWith;
|
|
|
- 1519 DEC(nW)
|
|
|
- 1520 END; .) .
|
|
|
- 1521 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
- 1522 (. VAR dt: SymTab.TypeIndex;
|
|
|
- 1523 dk: INTEGER;
|
|
|
- 1524 qd, qe: QbeGen.QVal;
|
|
|
- 1525 qn: SymTab.Name;
|
|
|
- 1526 sfx: BOOLEAN; .)
|
|
|
- 1527 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 1528 (. IF astCur # AST.NoNode THEN
|
|
|
- 1529 AST.SetChild(wnode,
|
|
|
- 1530 AST.NChild(wnode), astCur) END;
|
|
|
- 1531 IF dt = SymTab.InvalidType THEN
|
|
|
- 1532 ELSIF (SymTab.ClassOf(dt) #
|
|
|
- 1533 SymTab.ClRecord)
|
|
|
- 1534 AND (SymTab.ClassOf(dt) #
|
|
|
- 1535 SymTab.ClClass) THEN
|
|
|
- 1536 SemError(215)
|
|
|
- 1537 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
- 1538 QbeGen.PushWith(qd);
|
|
|
- 1539 INC(nW)
|
|
|
- 1540 END; .) .
|
|
|
- 1541 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
- 1542 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
- 1543 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
- 1544 dk: INTEGER;
|
|
|
- 1545 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
- 1546 qn: SymTab.Name;
|
|
|
- 1547 ct2, res0: SymTab.TypeIndex;
|
|
|
- 1548 q2, mg0: QbeGen.QVal;
|
|
|
- 1549 isR, conv, wconv: BOOLEAN;
|
|
|
- 1550 called, sfx: BOOLEAN;
|
|
|
- 1551 astLhs: AST.Node; .)
|
|
|
- 1552 = Design<dt, dk, qd, qn, sfx>
|
|
|
- 1553 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
- 1554 ( ":="
|
|
|
- 1555 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
- 1556 AST.NkAssign, 0, astLhs, astCur);
|
|
|
- 1557 IF (dt # SymTab.InvalidType)
|
|
|
- 1558 AND (dk # SymTab.KindVar)
|
|
|
- 1559 AND (dk # SymTab.KindParam)
|
|
|
- 1560 AND (dk # SymTab.KindField) THEN
|
|
|
- 1561 SemError(210)
|
|
|
- 1562 ELSIF NOT SymTab.Assignable(et,
|
|
|
- 1563 dt) THEN
|
|
|
- 1564 SemError(210)
|
|
|
- 1565 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 1566 AND (SymTab.ClassOf(dt) =
|
|
|
- 1567 SymTab.ClClass) THEN
|
|
|
- 1568 SemError(230) END;
|
|
|
- 1569 isR := (dt #
|
|
|
- 1570 SymTab.InvalidType)
|
|
|
- 1571 AND (SymTab.ClassOf(dt)
|
|
|
- 1572 = SymTab.ClReal);
|
|
|
- 1573 conv := isR
|
|
|
- 1574 AND SymTab.IsIntFamily(et);
|
|
|
- 1575 wconv := (dt #
|
|
|
- 1576 SymTab.InvalidType)
|
|
|
- 1577 AND SymTab.IsLongFamily(dt)
|
|
|
- 1578 AND SymTab.IsIntFamily(et);
|
|
|
- 1579 IF ((dk = SymTab.KindVar)
|
|
|
- 1580 OR (dk = SymTab.KindParam)
|
|
|
- 1581 OR (dk = SymTab.KindField))
|
|
|
- 1582 AND (dt # SymTab.InvalidType)
|
|
|
- 1583 AND (et # SymTab.InvalidType)
|
|
|
- 1584 AND (SymTab.ClassOf(dt) #
|
|
|
- 1585 SymTab.ClClass) THEN
|
|
|
- 1586 IF sfx
|
|
|
- 1587 OR (dk = SymTab.KindField) THEN
|
|
|
- 1588 IF SymTab.ClassOf(dt) =
|
|
|
- 1589 SymTab.ClArray THEN
|
|
|
- 1590 IF (et # SymTab.InvalidType)
|
|
|
- 1591 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
- 1592 AND SymTab.IsUCharArray(dt) THEN
|
|
|
- 1593 QbeGen.UAssign(qd, qe)
|
|
|
- 1594 ELSIF SymTab.StrCompat(dt,
|
|
|
- 1595 et) THEN
|
|
|
- 1596 QbeGen.StrAssign(qd,
|
|
|
- 1597 qe)
|
|
|
- 1598 ELSE
|
|
|
- 1599 QbeGen.CopyArray(qd,
|
|
|
- 1600 qe, dt)
|
|
|
- 1601 END
|
|
|
- 1602 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 1603 SymTab.ClSet THEN
|
|
|
- 1604 QbeGen.CopySet(qd, qe,
|
|
|
- 1605 SymTab.SetWords(dt),
|
|
|
- 1606 SymTab.SetWords(et))
|
|
|
- 1607 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 1608 SymTab.ClRecord THEN
|
|
|
- 1609 QbeGen.CopyRecord(qd, qe,
|
|
|
- 1610 dt)
|
|
|
- 1611 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
- 1612 IF wconv THEN
|
|
|
- 1613 QbeGen.WidenLong(qe, ql);
|
|
|
- 1614 QbeGen.ElemStore(qd, ql,
|
|
|
- 1615 dt)
|
|
|
- 1616 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
- 1617 dt)
|
|
|
- 1618 END
|
|
|
- 1619 ELSIF conv THEN
|
|
|
- 1620 QbeGen.ConvIR(qe, qt);
|
|
|
- 1621 QbeGen.ElemStore(qd, qt,
|
|
|
- 1622 dt)
|
|
|
- 1623 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
- 1624 dt)
|
|
|
- 1625 END
|
|
|
- 1626 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 1627 SymTab.ClArray THEN
|
|
|
- 1628 IF (et # SymTab.InvalidType)
|
|
|
- 1629 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
- 1630 AND SymTab.IsUCharArray(dt) THEN
|
|
|
- 1631 QbeGen.UAssign(qd, qe)
|
|
|
- 1632 ELSIF SymTab.StrCompat(dt,
|
|
|
- 1633 et) THEN
|
|
|
- 1634 QbeGen.StrAssign(qd, qe)
|
|
|
- 1635 ELSE
|
|
|
- 1636 QbeGen.CopyArray(qd, qe,
|
|
|
- 1637 dt)
|
|
|
- 1638 END
|
|
|
- 1639 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 1640 SymTab.ClSet THEN
|
|
|
- 1641 QbeGen.CopySet(qd, qe,
|
|
|
- 1642 SymTab.SetWords(dt),
|
|
|
- 1643 SymTab.SetWords(et))
|
|
|
- 1644 ELSIF SymTab.ClassOf(dt) =
|
|
|
- 1645 SymTab.ClRecord THEN
|
|
|
- 1646 QbeGen.CopyRecord(qd, qe, dt)
|
|
|
- 1647 ELSIF (SymTab.ClassOf(dt) =
|
|
|
- 1648 SymTab.ClPtr)
|
|
|
- 1649 OR (SymTab.ClassOf(dt) =
|
|
|
- 1650 SymTab.ClProc) THEN
|
|
|
- 1651 QbeGen.StorePtr(qn, qe)
|
|
|
- 1652 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
- 1653 IF wconv THEN
|
|
|
- 1654 QbeGen.WidenLong(qe, ql);
|
|
|
- 1655 QbeGen.StoreLong(qn, ql)
|
|
|
- 1656 ELSE QbeGen.StoreLong(qn, qe)
|
|
|
- 1657 END
|
|
|
- 1658 ELSIF conv THEN
|
|
|
- 1659 QbeGen.ConvIR(qe, qt);
|
|
|
- 1660 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
- 1661 ELSE
|
|
|
- 1662 QbeGen.StoreVar(qn, qe, isR)
|
|
|
- 1663 END
|
|
|
- 1664 END; .)
|
|
|
- 1665 | ArgList<qn, dt, qd, FALSE, FALSE, methCls, ct2, q2, called>
|
|
|
- 1666 (. astStmt := AstCallNode(astLhs); .)
|
|
|
- 1667 | (* bare `P;`: proper parameterless
|
|
|
- 1668 procedure call; anything else
|
|
|
- 1669 here is 233 (was a bare syntax
|
|
|
- 1670 error before 4.2) *)
|
|
|
- 1671 (. astStmt := AstCallNode(astLhs);
|
|
|
- 1672 IF (dk = SymTab.KindProc)
|
|
|
- 1673 AND NOT sfx THEN
|
|
|
- 1674 res0 := SymTab.ProcRes(qn);
|
|
|
- 1675 IF res0 #
|
|
|
- 1676 SymTab.InvalidType THEN
|
|
|
- 1677 SemError(233)
|
|
|
- 1678 ELSIF SymTab.ProcNPar(qn) #
|
|
|
- 1679 0 THEN
|
|
|
- 1680 SemError(233)
|
|
|
- 1681 ELSE QbeGen.Mangled(qn,
|
|
|
- 1682 SymTab.ProcUid(qn), mg0);
|
|
|
- 1683 QbeGen.CallBegin(mg0,
|
|
|
- 1684 res0,
|
|
|
- 1685 SymTab.ProcDepthOf(qn),
|
|
|
- 1686 SymTab.IsExternal(qn));
|
|
|
- 1687 QbeGen.CallEnd(FALSE, q2)
|
|
|
- 1688 END
|
|
|
- 1689 ELSE SemError(233)
|
|
|
- 1690 END; .) ) .
|
|
|
- 1691 (* Actual-parameter list shared by statement and expression calls.
|
|
|
- 1692 want selects CallEnd's result handling; t/q carry the call
|
|
|
- 1693 value (statement calls discard). Arity/type failures are 233;
|
|
|
- 1694 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
- 1695 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
- 1696 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
- 1697 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 1698 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
- 1699 vs: INTEGER;
|
|
|
- 1700 res: SymTab.TypeIndex;
|
|
|
- 1701 mg: QbeGen.QVal;
|
|
|
- 1702 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
- 1703 = "(" (. called := TRUE;
|
|
|
- 1704 ok := TRUE;
|
|
|
- 1705 ind := FALSE;
|
|
|
- 1706 isMeth := methCls #
|
|
|
- 1707 SymTab.InvalidType;
|
|
|
- 1708 IF isMeth THEN
|
|
|
- 1709 (* class method: the
|
|
|
- 1710 receiver is armed.
|
|
|
- 1711 Virtual -> dispatch
|
|
|
- 1712 through the vtable;
|
|
|
- 1713 otherwise a static
|
|
|
- 1714 call. *)
|
|
|
- 1715 res := SymTab.ClassMethodRes(
|
|
|
- 1716 methCls, pn);
|
|
|
- 1717 vs := SymTab.VirtSlot(
|
|
|
- 1718 methCls, pn);
|
|
|
- 1719 IF vs >= 0 THEN
|
|
|
- 1720 QbeGen.VirtCallBegin(
|
|
|
- 1721 callee, vs, res)
|
|
|
- 1722 ELSE
|
|
|
- 1723 QbeGen.Mangled(pn,
|
|
|
- 1724 SymTab.ClassMethodUid(
|
|
|
- 1725 methCls, pn), mg);
|
|
|
- 1726 QbeGen.CallBegin(mg, res, 0,
|
|
|
- 1727 FALSE)
|
|
|
- 1728 END
|
|
|
- 1729 ELSIF SymTab.SymKind(pn) =
|
|
|
- 1730 SymTab.KindProc THEN
|
|
|
- 1731 res := SymTab.ProcRes(pn);
|
|
|
- 1732 QbeGen.Mangled(pn,
|
|
|
- 1733 SymTab.ProcUid(pn), mg);
|
|
|
- 1734 QbeGen.CallBegin(mg, res,
|
|
|
- 1735 SymTab.ProcDepthOf(pn),
|
|
|
- 1736 SymTab.IsExternal(pn))
|
|
|
- 1737 ELSIF (pt # SymTab.InvalidType)
|
|
|
- 1738 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
- 1739 ind := TRUE;
|
|
|
- 1740 res :=
|
|
|
- 1741 SymTab.ProcTypeRes(pt);
|
|
|
- 1742 QbeGen.CallBeginInd(callee,
|
|
|
- 1743 res, FALSE)
|
|
|
- 1744 ELSE SemError(233);
|
|
|
- 1745 ok := FALSE;
|
|
|
- 1746 res := SymTab.InvalidType
|
|
|
- 1747 END;
|
|
|
- 1748 i := 0; .)
|
|
|
- 1749 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
- 1750 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
- 1751 ")" (. IF ok THEN
|
|
|
- 1752 IF isMeth THEN
|
|
|
- 1753 np := SymTab.ClassMethodNPar(
|
|
|
- 1754 methCls, pn)
|
|
|
- 1755 ELSIF ind THEN
|
|
|
- 1756 np := SymTab.ProcTypeNPar(pt)
|
|
|
- 1757 ELSE np := SymTab.ProcNPar(pn)
|
|
|
- 1758 END;
|
|
|
- 1759 va := (NOT isMeth) AND (NOT ind)
|
|
|
- 1760 AND (SymTab.SymKind(pn) =
|
|
|
- 1761 SymTab.KindProc)
|
|
|
- 1762 AND SymTab.Varargs(pn);
|
|
|
- 1763 IF (i # np) AND NOT va THEN
|
|
|
- 1764 SemError(233); ok := FALSE
|
|
|
- 1765 END
|
|
|
- 1766 END;
|
|
|
- 1767 IF NOT ok THEN
|
|
|
- 1768 t := SymTab.InvalidType;
|
|
|
- 1769 QbeGen.CopyOp("0", q)
|
|
|
- 1770 ELSIF want THEN
|
|
|
- 1771 IF res =
|
|
|
- 1772 SymTab.InvalidType THEN
|
|
|
- 1773 SemError(233);
|
|
|
- 1774 t := SymTab.InvalidType;
|
|
|
- 1775 QbeGen.CopyOp("0", q)
|
|
|
- 1776 ELSE t := res;
|
|
|
- 1777 QbeGen.CallEnd(TRUE, q)
|
|
|
- 1778 END
|
|
|
- 1779 ELSE
|
|
|
- 1780 IF res #
|
|
|
- 1781 SymTab.InvalidType THEN
|
|
|
- 1782 SemError(233)
|
|
|
- 1783 END;
|
|
|
- 1784 t := SymTab.InvalidType;
|
|
|
- 1785 QbeGen.CopyOp("0", q);
|
|
|
- 1786 QbeGen.CallEnd(FALSE, q)
|
|
|
- 1787 END; .) .
|
|
|
- 1788 (* One actual: VAR formals take recorded designator addresses
|
|
|
- 1789 (233 otherwise); value formals take converted expressions. *)
|
|
|
- 1790 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
- 1791 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
- 1792 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
- 1793 qe, qa, qt: QbeGen.QVal;
|
|
|
- 1794 isV, conv, va: BOOLEAN;
|
|
|
- 1795 cl: CHAR;
|
|
|
- 1796 savedN, aj: CARDINAL;
|
|
|
- 1797 savedArgs: ARRAY [0 .. 31]
|
|
|
- 1798 OF AST.Node; .)
|
|
|
- 1799 = (. (* Parsing the actual can clobber
|
|
|
- 1800 the enclosing call's argument
|
|
|
- 1801 list (Factor resets astNArgs),
|
|
|
- 1802 so save/restore it. *)
|
|
|
- 1803 savedN := astNArgs; aj := 0;
|
|
|
- 1804 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 1805 savedArgs[aj] := astArgs[aj];
|
|
|
- 1806 INC(aj)
|
|
|
- 1807 END; .)
|
|
|
- 1808 Expr<at, qe> (. astNArgs := savedN; aj := 0;
|
|
|
- 1809 WHILE aj <= HIGH(astArgs) DO
|
|
|
- 1810 astArgs[aj] := savedArgs[aj];
|
|
|
- 1811 INC(aj)
|
|
|
- 1812 END;
|
|
|
- 1813 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
- 1814 astArgs[astNArgs] := astCur;
|
|
|
- 1815 INC(astNArgs)
|
|
|
- 1816 END;
|
|
|
- 1817 va := (NOT ind)
|
|
|
- 1818 AND (methCls =
|
|
|
- 1819 SymTab.InvalidType)
|
|
|
- 1820 AND (SymTab.SymKind(pn) =
|
|
|
- 1821 SymTab.KindProc)
|
|
|
- 1822 AND SymTab.Varargs(pn);
|
|
|
- 1823 IF ind THEN
|
|
|
- 1824 ft :=
|
|
|
- 1825 SymTab.ProcTypeParamType(pt,
|
|
|
- 1826 i);
|
|
|
- 1827 isV :=
|
|
|
- 1828 SymTab.ProcTypeParamIsVar(pt,
|
|
|
- 1829 i)
|
|
|
- 1830 ELSIF methCls #
|
|
|
- 1831 SymTab.InvalidType THEN
|
|
|
- 1832 ft :=
|
|
|
- 1833 SymTab.ClassMethodParamType(
|
|
|
- 1834 methCls, pn, i);
|
|
|
- 1835 isV :=
|
|
|
- 1836 SymTab.ClassMethodParamIsVar(
|
|
|
- 1837 methCls, pn, i)
|
|
|
- 1838 ELSE
|
|
|
- 1839 ft := SymTab.ParamType(pn, i);
|
|
|
- 1840 isV := SymTab.ParamIsVar(pn, i)
|
|
|
- 1841 END;
|
|
|
- 1842 IF (at = SymTab.InvalidType) THEN
|
|
|
- 1843 ELSIF ft = SymTab.InvalidType THEN
|
|
|
- 1844 IF va THEN
|
|
|
- 1845 QbeGen.CArgAdd(qe, at, qa, cl)
|
|
|
- 1846 END
|
|
|
- 1847 ELSIF isV THEN
|
|
|
- 1848 IF (SymTab.ClassOf(at)
|
|
|
- 1849 = SymTab.ClChar)
|
|
|
- 1850 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1851 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
- 1852 = SymTab.ClChar)
|
|
|
- 1853 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1854 (* 1-char string
|
|
|
- 1855 literal passed to
|
|
|
- 1856 a VAR ARRAY OF CHAR *)
|
|
|
- 1857 QbeGen.DeclCharStr(qe,
|
|
|
- 1858 qa);
|
|
|
- 1859 IF NOT QbeGen.CallArg(qa,
|
|
|
- 1860 "l") THEN
|
|
|
- 1861 SemError(233)
|
|
|
- 1862 END
|
|
|
- 1863 ELSIF NOT QbeGen.AddrOfVal(qe,
|
|
|
- 1864 qa) THEN
|
|
|
- 1865 SemError(233)
|
|
|
- 1866 ELSIF NOT SymTab.VarParamOk(at,
|
|
|
- 1867 ft) THEN
|
|
|
- 1868 SemError(233)
|
|
|
- 1869 ELSIF NOT QbeGen.CallArg(qa,
|
|
|
- 1870 "l") THEN
|
|
|
- 1871 SemError(233)
|
|
|
- 1872 END
|
|
|
- 1873 ELSE
|
|
|
- 1874 IF (SymTab.ClassOf(at)
|
|
|
- 1875 = SymTab.ClChar)
|
|
|
- 1876 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
- 1877 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
- 1878 = SymTab.ClChar)
|
|
|
- 1879 AND QbeGen.IsImm(qe) THEN
|
|
|
- 1880 (* 1-char string
|
|
|
- 1881 literal passed to
|
|
|
- 1882 ARRAY OF CHAR *)
|
|
|
- 1883 QbeGen.DeclCharStr(qe,
|
|
|
- 1884 qa);
|
|
|
- 1885 IF NOT QbeGen.CallArg(qa,
|
|
|
- 1886 "l") THEN
|
|
|
- 1887 SemError(233)
|
|
|
- 1888 END
|
|
|
- 1889 ELSIF NOT SymTab.Assignable(at,
|
|
|
- 1890 ft) THEN
|
|
|
- 1891 SemError(233)
|
|
|
- 1892 ELSE
|
|
|
- 1893 conv := (SymTab.ClassOf(
|
|
|
- 1894 ft) = SymTab.ClReal)
|
|
|
- 1895 AND SymTab.IsIntFamily(at);
|
|
|
- 1896 IF conv THEN
|
|
|
- 1897 QbeGen.ConvIR(qe, qt);
|
|
|
- 1898 IF NOT QbeGen.CallArg(qt,
|
|
|
- 1899 "d") THEN
|
|
|
- 1900 SemError(233)
|
|
|
- 1901 END
|
|
|
- 1902 ELSIF NOT QbeGen.CallArg(qe,
|
|
|
- 1903 QbeGen.ArgClass(ft)) THEN
|
|
|
- 1904 SemError(233)
|
|
|
- 1905 END
|
|
|
- 1906 END
|
|
|
- 1907 END; .) .
|
|
|
- 1908 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1909 q, lThen, lElse, lEnd:
|
|
|
- 1910 QbeGen.QVal;
|
|
|
- 1911 hasElse: BOOLEAN;
|
|
|
- 1912 astCond, astIf, astLast,
|
|
|
- 1913 astNode: AST.Node; .)
|
|
|
- 1914 = "IF" (. hasElse := FALSE; .)
|
|
|
- 1915 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 1916 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1917 SemError(214) END;
|
|
|
- 1918 QbeGen.NewLabel(lThen);
|
|
|
- 1919 QbeGen.NewLabel(lElse);
|
|
|
- 1920 QbeGen.NewLabel(lEnd);
|
|
|
- 1921 QbeGen.Jnz(q, lThen, lElse);
|
|
|
- 1922 QbeGen.EmitLabel(lThen); .)
|
|
|
- 1923 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 1924 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1925 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1926 astIf := astNode;
|
|
|
- 1927 astLast := astNode;
|
|
|
- 1928 QbeGen.Jmp(lEnd); .)
|
|
|
- 1929 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
- 1930 QbeGen.NewLabel(lElse); .)
|
|
|
- 1931 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
- 1932 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1933 SemError(214) END;
|
|
|
- 1934 QbeGen.NewLabel(lThen);
|
|
|
- 1935 QbeGen.Jnz(q, lThen, lElse);
|
|
|
- 1936 QbeGen.EmitLabel(lThen); .)
|
|
|
- 1937 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
- 1938 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1939 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1940 AST.SetChild(astLast, 2, astNode);
|
|
|
- 1941 astLast := astNode;
|
|
|
- 1942 QbeGen.Jmp(lEnd); .) }
|
|
|
- 1943 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
- 1944 hasElse := TRUE;
|
|
|
- 1945 astStmt := AST.NoNode; .)
|
|
|
- 1946 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- 1947 "END" (. astStmt := astIf;
|
|
|
- 1948 IF hasElse THEN
|
|
|
- 1949 QbeGen.EmitLabel(lEnd)
|
|
|
- 1950 ELSE QbeGen.EmitLabel(lElse);
|
|
|
- 1951 QbeGen.EmitLabel(lEnd)
|
|
|
- 1952 END; .) .
|
|
|
- 1953 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1954 q, lTop, lBody, lEnd:
|
|
|
- 1955 QbeGen.QVal;
|
|
|
- 1956 astCond, astNode: AST.Node; .)
|
|
|
- 1957 = "WHILE" (. astStmt := AST.NoNode;
|
|
|
- 1958 QbeGen.NewLabel(lTop);
|
|
|
- 1959 QbeGen.NewLabel(lBody);
|
|
|
- 1960 QbeGen.NewLabel(lEnd);
|
|
|
- 1961 QbeGen.EmitLabel(lTop); .)
|
|
|
- 1962 Expr<t, q> (. astCond := astCur;
|
|
|
- 1963 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1964 SemError(214) END;
|
|
|
- 1965 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
- 1966 QbeGen.EmitLabel(lBody); .)
|
|
|
- 1967 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
- 1968 AST.SetChild(astNode, 0, astCond);
|
|
|
- 1969 AST.SetChild(astNode, 1, astStmt);
|
|
|
- 1970 astStmt := astNode;
|
|
|
- 1971 QbeGen.Jmp(lTop); .)
|
|
|
- 1972 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1973 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 1974 q, lTop, lEnd: QbeGen.QVal;
|
|
|
- 1975 astCond, astBody, astNode:
|
|
|
- 1976 AST.Node; .)
|
|
|
- 1977 = "REPEAT" (. astStmt := AST.NoNode;
|
|
|
- 1978 QbeGen.NewLabel(lTop);
|
|
|
- 1979 QbeGen.NewLabel(lEnd);
|
|
|
- 1980 QbeGen.EmitLabel(lTop); .)
|
|
|
- 1981 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
- 1982 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
- 1983 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
- 1984 AST.SetChild(astNode, 0, astBody);
|
|
|
- 1985 AST.SetChild(astNode, 1, astCond);
|
|
|
- 1986 astStmt := astNode;
|
|
|
- 1987 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- 1988 SemError(214) END;
|
|
|
- 1989 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
- 1990 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 1991 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- 1992 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
- 1993 astStmt := AST.NoNode;
|
|
|
- 1994 QbeGen.NewLabel(lEnd);
|
|
|
- 1995 QbeGen.PushLoop(lEnd);
|
|
|
- 1996 QbeGen.EmitLabel(lTop); .)
|
|
|
- 1997 [ StatSeq ]
|
|
|
- 1998 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
- 1999 AST.SetChild(astNode, 0, astStmt);
|
|
|
- 2000 astStmt := astNode;
|
|
|
- 2001 QbeGen.Jmp(lTop);
|
|
|
- 2002 QbeGen.PopLoop;
|
|
|
- 2003 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 2004 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
- 2005 Runtime direction would need a compare-select; the literal
|
|
|
- 2006 sign picks cslew/csegew at "DO" time. *)
|
|
|
- 2007 ForStat (. VAR lv: SymTab.Name;
|
|
|
- 2008 tlo, thi, tby:
|
|
|
- 2009 SymTab.TypeIndex;
|
|
|
- 2010 qlo, qhi, qby, qt, qk, qb:
|
|
|
- 2011 QbeGen.QVal;
|
|
|
- 2012 lTop, lBody, lEnd:
|
|
|
- 2013 QbeGen.QVal;
|
|
|
- 2014 by: INTEGER;
|
|
|
- 2015 ok: BOOLEAN;
|
|
|
- 2016 astVar, astLo, astHi, astBy,
|
|
|
- 2017 astNode: AST.Node; .)
|
|
|
- 2018 = "FOR" (. by := 1; .)
|
|
|
- 2019 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
- 2020 astStmt := AST.NoNode;
|
|
|
- 2021 astBy := AST.NoNode;
|
|
|
- 2022 ok := SymTab.Lookup(lv);
|
|
|
- 2023 IF NOT ok THEN
|
|
|
- 2024 SemError(201)
|
|
|
- 2025 ELSIF (SymTab.SymKind(lv) #
|
|
|
- 2026 SymTab.KindVar)
|
|
|
- 2027 AND (SymTab.SymKind(lv) #
|
|
|
- 2028 SymTab.KindParam) THEN
|
|
|
- 2029 SemError(220); ok := FALSE
|
|
|
- 2030 ELSIF NOT SymTab.IsIntFamily(
|
|
|
- 2031 SymTab.SymType(lv)) THEN
|
|
|
- 2032 SemError(220); ok := FALSE
|
|
|
- 2033 END; .)
|
|
|
- 2034 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
- 2035 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
- 2036 SemError(220); ok := FALSE
|
|
|
- 2037 END; .)
|
|
|
- 2038 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
- 2039 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
- 2040 SemError(220); ok := FALSE
|
|
|
- 2041 END; .)
|
|
|
- 2042 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
- 2043 IF (tby #
|
|
|
- 2044 SymTab.InvalidType)
|
|
|
- 2045 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
- 2046 SemError(220); ok := FALSE
|
|
|
- 2047 END;
|
|
|
- 2048 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
- 2049 SemError(230); by := 1
|
|
|
- 2050 ELSIF by = 0 THEN
|
|
|
- 2051 SemError(220); by := 1
|
|
|
- 2052 END; .) ]
|
|
|
- 2053 "DO" (. IF ok THEN
|
|
|
- 2054 QbeGen.StoreVar(lv, qlo,
|
|
|
- 2055 FALSE) END;
|
|
|
- 2056 QbeGen.NewLabel(lTop);
|
|
|
- 2057 QbeGen.NewLabel(lBody);
|
|
|
- 2058 QbeGen.NewLabel(lEnd);
|
|
|
- 2059 QbeGen.EmitLabel(lTop);
|
|
|
- 2060 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
- 2061 QbeGen.NewTemp(qk);
|
|
|
- 2062 IF by > 0 THEN
|
|
|
- 2063 QbeGen.Op3("cslew", qk,
|
|
|
- 2064 qt, qhi, FALSE)
|
|
|
- 2065 ELSE QbeGen.Op3("csgew", qk,
|
|
|
- 2066 qt, qhi, FALSE)
|
|
|
- 2067 END;
|
|
|
- 2068 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
- 2069 QbeGen.EmitLabel(lBody); .)
|
|
|
- 2070 [ StatSeq ]
|
|
|
- 2071 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
- 2072 AST.SetChild(astNode, 0, astVar);
|
|
|
- 2073 AST.SetChild(astNode, 1, astLo);
|
|
|
- 2074 AST.SetChild(astNode, 2, astHi);
|
|
|
- 2075 AST.SetChild(astNode, 3, astBy);
|
|
|
- 2076 AST.SetChild(astNode, 4, astStmt);
|
|
|
- 2077 astStmt := astNode;
|
|
|
- 2078 IF ok THEN
|
|
|
- 2079 QbeGen.LoadVar(lv, FALSE,
|
|
|
- 2080 qt);
|
|
|
- 2081 QbeGen.IntStr(by, qb);
|
|
|
- 2082 QbeGen.NewTemp(qk);
|
|
|
- 2083 QbeGen.Op3("add", qk,
|
|
|
- 2084 qt, qb, FALSE);
|
|
|
- 2085 QbeGen.StoreVar(lv, qk,
|
|
|
- 2086 FALSE) END;
|
|
|
- 2087 QbeGen.Jmp(lTop);
|
|
|
- 2088 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 2089 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
- 2090 qsel, lEnd: QbeGen.QVal;
|
|
|
- 2091 arm, astNode, astArms,
|
|
|
- 2092 astArmsTail: AST.Node; .)
|
|
|
- 2093 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
- 2094 AST.SetChild(astNode, 0, astCur);
|
|
|
- 2095 astArms := AST.NoNode;
|
|
|
- 2096 astArmsTail := AST.NoNode;
|
|
|
- 2097 QbeGen.NewLabel(lEnd); .)
|
|
|
- 2098 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
- 2099 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
- 2100 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
- 2101 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 2102 AST.SetOp(arm, 1);
|
|
|
- 2103 AST.SetChild(arm, 0, astStmt);
|
|
|
- 2104 AstAppend(AST.NkBlock,
|
|
|
- 2105 astArms, astArmsTail, arm); .) ]
|
|
|
- 2106 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
- 2107 astStmt := astNode;
|
|
|
- 2108 QbeGen.EmitLabel(lEnd); .) .
|
|
|
- 2109 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
- 2110 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
- 2111 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
- 2112 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
- 2113 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2114 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- 2115 (. VAR lBody, lAfter: QbeGen.QVal;
|
|
|
- 2116 arm: AST.Node; .)
|
|
|
- 2117 = (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- 2118 QbeGen.NewLabel(lBody);
|
|
|
- 2119 QbeGen.NewLabel(lAfter); .)
|
|
|
- 2120 CaseLabel<tsel, qsel, lBody, arm>
|
|
|
- 2121 { "," CaseLabel<tsel, qsel, lBody, arm> }
|
|
|
- 2122 ":" (. astStmt := AST.NoNode;
|
|
|
- 2123 QbeGen.Jmp(lAfter);
|
|
|
- 2124 QbeGen.EmitLabel(lBody); .)
|
|
|
- 2125 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
- 2126 astStmt);
|
|
|
- 2127 AstAppend(AST.NkBlock,
|
|
|
- 2128 arms, armsTail, arm);
|
|
|
- 2129 QbeGen.Jmp(lEnd);
|
|
|
- 2130 QbeGen.EmitLabel(lAfter); .) .
|
|
|
- 2131 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- 2132 lBody: QbeGen.QVal; arm: AST.Node>
|
|
|
- 2133 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
- 2134 q2, q3, qc, qd, qe:
|
|
|
- 2135 QbeGen.QVal;
|
|
|
- 2136 astLab: AST.Node;
|
|
|
- 2137 lNext: QbeGen.QVal; .)
|
|
|
- 2138 = Expr<t2, q2> (. astLab := astCur;
|
|
|
- 2139 IF (t2 #
|
|
|
- 2140 SymTab.InvalidType)
|
|
|
- 2141 AND (tsel #
|
|
|
- 2142 SymTab.InvalidType)
|
|
|
- 2143 AND ((SymTab.ClassOf(t2) =
|
|
|
- 2144 SymTab.ClSet)
|
|
|
- 2145 OR (SymTab.ClassOf(tsel) =
|
|
|
- 2146 SymTab.ClSet)) THEN
|
|
|
- 2147 SemError(230)
|
|
|
- 2148 ELSIF (t2 #
|
|
|
- 2149 SymTab.InvalidType)
|
|
|
- 2150 AND (tsel #
|
|
|
- 2151 SymTab.InvalidType)
|
|
|
- 2152 AND NOT SymTab.EqCheck(t2,
|
|
|
- 2153 tsel) THEN
|
|
|
- 2154 SemError(213) END;
|
|
|
- 2155 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- 2156 SemError(230);
|
|
|
- 2157 QbeGen.CopyOp("0", q2)
|
|
|
- 2158 END;
|
|
|
- 2159 QbeGen.NewLabel(lNext);
|
|
|
- 2160 QbeGen.Cmp(SymTab.OpEq,
|
|
|
- 2161 qsel, q2, qc, FALSE);
|
|
|
- 2162 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
- 2163 QbeGen.EmitLabel(lNext); .)
|
|
|
- 2164 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
- 2165 AST.NkSubrange, 0, astLab, astCur);
|
|
|
- 2166 IF (t3 #
|
|
|
- 2167 SymTab.InvalidType)
|
|
|
- 2168 AND (tsel #
|
|
|
- 2169 SymTab.InvalidType)
|
|
|
- 2170 AND NOT SymTab.EqCheck(t3,
|
|
|
- 2171 tsel) THEN
|
|
|
- 2172 SemError(213) END;
|
|
|
- 2173 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- 2174 SemError(230);
|
|
|
- 2175 QbeGen.CopyOp("0", q3)
|
|
|
- 2176 END;
|
|
|
- 2177 QbeGen.Cmp(SymTab.OpGe,
|
|
|
- 2178 qsel, q2, qc, FALSE);
|
|
|
- 2179 QbeGen.Cmp(SymTab.OpLe,
|
|
|
- 2180 qsel, q3, qd, FALSE);
|
|
|
- 2181 QbeGen.NewTemp(qe);
|
|
|
- 2182 QbeGen.Op3("and", qe, qc, qd,
|
|
|
- 2183 FALSE);
|
|
|
- 2184 QbeGen.NewLabel(lNext);
|
|
|
- 2185 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
- 2186 QbeGen.EmitLabel(lNext); .) ]
|
|
|
- 2187 (. AST.SetChild(arm,
|
|
|
- 2188 AST.NChild(arm), astLab); .) .
|
|
|
- 2189 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2190 q, qt: QbeGen.QVal;
|
|
|
- 2191 res: SymTab.TypeIndex;
|
|
|
- 2192 hadE, conv: BOOLEAN;
|
|
|
- 2193 astVal, astNode: AST.Node; .)
|
|
|
- 2194 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
- 2195 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
- 2196 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
- 2197 IF hadE THEN
|
|
|
- 2198 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2199 END;
|
|
|
- 2200 astStmt := astNode;
|
|
|
- 2201 conv := FALSE;
|
|
|
- 2202 IF NOT SymTab.InProc() THEN
|
|
|
- 2203 SemError(232)
|
|
|
- 2204 ELSE res := SymTab.CurRes();
|
|
|
- 2205 IF NOT hadE THEN
|
|
|
- 2206 IF res #
|
|
|
- 2207 SymTab.InvalidType THEN
|
|
|
- 2208 SemError(232)
|
|
|
- 2209 ELSE QbeGen.EmitRet(q,
|
|
|
- 2210 FALSE)
|
|
|
- 2211 END
|
|
|
- 2212 ELSIF (res =
|
|
|
- 2213 SymTab.InvalidType)
|
|
|
- 2214 OR (t #
|
|
|
- 2215 SymTab.InvalidType)
|
|
|
- 2216 AND NOT SymTab.Assignable(t,
|
|
|
- 2217 res) THEN
|
|
|
- 2218 SemError(232)
|
|
|
- 2219 ELSE
|
|
|
- 2220 conv := (SymTab.ClassOf(
|
|
|
- 2221 res) = SymTab.ClReal)
|
|
|
- 2222 AND SymTab.IsIntFamily(t);
|
|
|
- 2223 IF conv THEN
|
|
|
- 2224 QbeGen.ConvIR(q, qt);
|
|
|
- 2225 QbeGen.EmitRet(qt, TRUE)
|
|
|
- 2226 ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
- 2227 END
|
|
|
- 2228 END
|
|
|
- 2229 END; .) .
|
|
|
- 2230 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
- 2231 q: QbeGen.QVal;
|
|
|
- 2232 astVal, astNode: AST.Node; .)
|
|
|
- 2233 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
- 2234 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
- 2235 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
- 2236 IF astVal # AST.NoNode THEN
|
|
|
- 2237 AST.SetChild(astNode, 0, astVal)
|
|
|
- 2238 END;
|
|
|
- 2239 astStmt := astNode;
|
|
|
- 2240 QbeGen.HaltQ; .) .
|
|
|
- 2241 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
- 2242 Each index descends one level (bounds-checked, trap on breach);
|
|
|
- 2243 nested levels reload the inner descriptor address. q ends as the
|
|
|
- 2244 value (scalars), the descriptor address (plain arrays), or the
|
|
|
- 2245 element address (indexed); sfx marks the indexed form. *)
|
|
|
- 2246 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
- 2247 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
- 2248 (. VAR n, fn, mal: SymTab.Name;
|
|
|
- 2249 cls: INTEGER;
|
|
|
- 2250 ic: SymTab.TypeIndex;
|
|
|
- 2251 curT, it, eT, bt:
|
|
|
- 2252 SymTab.TypeIndex;
|
|
|
- 2253 iq, ql, qlo, qhi, qe:
|
|
|
- 2254 QbeGen.QVal;
|
|
|
- 2255 lo, hi: INTEGER;
|
|
|
- 2256 fo: INTEGER;
|
|
|
- 2257 isOpen: BOOLEAN;
|
|
|
- 2258 qb, cv: QbeGen.QVal;
|
|
|
- 2259 fid, fref, slot: INTEGER;
|
|
|
- 2260 r: BOOLEAN;
|
|
|
- 2261 astDes, astSel: AST.Node; .)
|
|
|
- 2262 = GetIdent<n> (. methCls := SymTab.InvalidType;
|
|
|
- 2263 QbeGen.CopyOp(n, qn);
|
|
|
- 2264 sfx := FALSE;
|
|
|
- 2265 fid := 0; fref := 0; slot := 0;
|
|
|
- 2266 IF NOT SymTab.Lookup(n) THEN
|
|
|
- 2267 (* a bare method name inside
|
|
|
- 2268 a CLASS IMPLEMENTATION
|
|
|
- 2269 is a sibling call on
|
|
|
- 2270 THIS *)
|
|
|
- 2271 ic := SymTab.CurImplClass();
|
|
|
- 2272 IF (ic #
|
|
|
- 2273 SymTab.InvalidType)
|
|
|
- 2274 AND SymTab.MethodExists(ic, n) THEN
|
|
|
- 2275 sfx := FALSE;
|
|
|
- 2276 QbeGen.ThisBase(q);
|
|
|
- 2277 QbeGen.ArmRecv(q);
|
|
|
- 2278 methCls := ic;
|
|
|
- 2279 k := SymTab.KindProc;
|
|
|
- 2280 t := SymTab.InvalidType
|
|
|
- 2281 ELSIF SymTab.InProc() THEN
|
|
|
- 2282 (* not declared yet: a
|
|
|
- 2283 forward reference to a
|
|
|
- 2284 module-level variable
|
|
|
- 2285 declared further down. *)
|
|
|
- 2286 k := SymTab.KindVar;
|
|
|
- 2287 r := SymTab.FwdVarRef(n, k,
|
|
|
- 2288 fref, t);
|
|
|
- 2289 slot := QbeGen.FwdDesignator();
|
|
|
- 2290 FwdVarNote(fref, slot);
|
|
|
- 2291 fid := slot;
|
|
|
- 2292 QbeGen.FwdAddrOper(fid, q);
|
|
|
- 2293 sfx := TRUE
|
|
|
- 2294 ELSE
|
|
|
- 2295 SemError(201);
|
|
|
- 2296 t :=
|
|
|
- 2297 SymTab.InvalidType;
|
|
|
- 2298 k := -1;
|
|
|
- 2299 QbeGen.CopyOp("0", q)
|
|
|
- 2300 END
|
|
|
- 2301 ELSE
|
|
|
- 2302 t := SymTab.SymType(n);
|
|
|
- 2303 k := SymTab.SymKind(n);
|
|
|
- 2304 IF k = SymTab.KindConst THEN
|
|
|
- 2305 IF SymTab.Equal(n,
|
|
|
- 2306 "TRUE") THEN
|
|
|
- 2307 t := SymTab.BoolType();
|
|
|
- 2308 QbeGen.CopyOp("1", q)
|
|
|
- 2309 ELSIF SymTab.Equal(n,
|
|
|
- 2310 "FALSE") THEN
|
|
|
- 2311 t := SymTab.BoolType();
|
|
|
- 2312 QbeGen.CopyOp("0", q)
|
|
|
- 2313 ELSIF SymTab.Equal(n,
|
|
|
- 2314 "NIL") THEN
|
|
|
- 2315 QbeGen.CopyOp("0", q)
|
|
|
- 2316 ELSE
|
|
|
- 2317 cls :=
|
|
|
- 2318 SymTab.ClassOf(t);
|
|
|
- 2319 IF (t #
|
|
|
- 2320 SymTab.InvalidType)
|
|
|
- 2321 AND ((cls = SymTab.ClInt)
|
|
|
- 2322 OR (cls
|
|
|
- 2323 = SymTab.ClChar)
|
|
|
- 2324 OR (cls
|
|
|
- 2325 = SymTab.ClEnum)
|
|
|
- 2326 OR (cls
|
|
|
- 2327 = SymTab.ClReal)
|
|
|
- 2328 OR (cls
|
|
|
- 2329 = SymTab.ClLong)
|
|
|
- 2330 OR (cls
|
|
|
- 2331 = SymTab.ClNil)) THEN
|
|
|
- 2332 IF cls = SymTab.ClNil THEN
|
|
|
- 2333 QbeGen.CopyOp("0", q)
|
|
|
- 2334 ELSIF ((cls
|
|
|
- 2335 = SymTab.ClInt)
|
|
|
- 2336 OR (cls
|
|
|
- 2337 = SymTab.ClChar)
|
|
|
- 2338 OR (cls
|
|
|
- 2339 = SymTab.ClEnum)
|
|
|
- 2340 OR (cls
|
|
|
- 2341 = SymTab.ClLong))
|
|
|
- 2342 AND SymTab.GetSymVal(n, cv)
|
|
|
- 2343 AND QbeGen.IsImm(cv) THEN
|
|
|
- 2344 QbeGen.CopyOp(cv, q)
|
|
|
- 2345 ELSE
|
|
|
- 2346 QbeGen.LoadVar(n,
|
|
|
- 2347 cls = SymTab.ClReal,
|
|
|
- 2348 q)
|
|
|
- 2349 END
|
|
|
- 2350 ELSIF (cls = SymTab.ClArray)
|
|
|
- 2351 OR (cls = SymTab.ClRecord)
|
|
|
- 2352 OR (cls = SymTab.ClClass)
|
|
|
- 2353 OR (cls = SymTab.ClStr)
|
|
|
- 2354 OR (cls = SymTab.ClUStr) THEN
|
|
|
- 2355 (* aggregate constant:
|
|
|
- 2356 its value IS the
|
|
|
- 2357 descriptor address *)
|
|
|
- 2358 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
- 2359 QbeGen.CopyOp(cv, q)
|
|
|
- 2360 ELSE
|
|
|
- 2361 QbeGen.CopyOp("0", q)
|
|
|
- 2362 END
|
|
|
- 2363 ELSE
|
|
|
- 2364 IF t #
|
|
|
- 2365 SymTab.InvalidType THEN
|
|
|
- 2366 SemError(230)
|
|
|
- 2367 END;
|
|
|
- 2368 QbeGen.CopyOp("0", q)
|
|
|
- 2369 END
|
|
|
- 2370 END
|
|
|
- 2371 ELSIF (k = SymTab.KindVar)
|
|
|
- 2372 OR (k = SymTab.KindParam) THEN
|
|
|
- 2373 cls :=
|
|
|
- 2374 SymTab.ClassOf(t);
|
|
|
- 2375 IF (cls = SymTab.ClInt)
|
|
|
- 2376 OR (cls = SymTab.ClBool)
|
|
|
- 2377 OR (cls = SymTab.ClChar)
|
|
|
- 2378 OR (cls = SymTab.ClUChar)
|
|
|
- 2379 OR (cls = SymTab.ClEnum)
|
|
|
- 2380 OR (cls
|
|
|
- 2381 = SymTab.ClReal) THEN
|
|
|
- 2382 QbeGen.LoadVar(n,
|
|
|
- 2383 cls = SymTab.ClReal, q)
|
|
|
- 2384 ELSIF (cls = SymTab.ClPtr)
|
|
|
- 2385 OR (cls = SymTab.ClProc) THEN
|
|
|
- 2386 QbeGen.LoadPtr(n, q)
|
|
|
- 2387 ELSIF cls = SymTab.ClLong THEN
|
|
|
- 2388 QbeGen.LoadLong(n, q)
|
|
|
- 2389 ELSIF (cls
|
|
|
- 2390 = SymTab.ClArray)
|
|
|
- 2391 OR (cls
|
|
|
- 2392 = SymTab.ClSet)
|
|
|
- 2393 OR (cls
|
|
|
- 2394 = SymTab.ClRecord)
|
|
|
- 2395 OR (cls
|
|
|
- 2396 = SymTab.ClUStr)
|
|
|
- 2397 OR (cls
|
|
|
- 2398 = SymTab.ClClass) THEN
|
|
|
- 2399 QbeGen.AddrOf(n, q)
|
|
|
- 2400 ELSE SemError(230);
|
|
|
- 2401 QbeGen.CopyOp("0", q)
|
|
|
- 2402 END
|
|
|
- 2403 ELSE QbeGen.CopyOp("0", q);
|
|
|
- 2404 IF k = SymTab.KindImport THEN
|
|
|
- 2405 SemError(230)
|
|
|
- 2406 ELSIF k =
|
|
|
- 2407 SymTab.KindProc THEN
|
|
|
- 2408 (* bare procedure name:
|
|
|
- 2409 a following ArgList
|
|
|
- 2410 makes it a call;
|
|
|
- 2411 otherwise Fact
|
|
|
- 2412 reports 230 *)
|
|
|
- 2413 ELSE
|
|
|
- 2414 IF k = SymTab.KindField THEN
|
|
|
- 2415 IF QbeGen.TopWith(qb) THEN
|
|
|
- 2416 fo :=
|
|
|
- 2417 SymTab.FieldOffset(
|
|
|
- 2418 SymTab.FieldOwner(n),
|
|
|
- 2419 n);
|
|
|
- 2420 QbeGen.FieldAddr(qb,
|
|
|
- 2421 fo, q);
|
|
|
- 2422 sfx := TRUE
|
|
|
- 2423 ELSE SemError(230);
|
|
|
- 2424 QbeGen.CopyOp("0", q)
|
|
|
- 2425 END
|
|
|
- 2426 END
|
|
|
- 2427 END
|
|
|
- 2428 END
|
|
|
- 2429 END; .)
|
|
|
- 2430 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
- 2431 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
- 2432 { "[" Expr<it, iq>
|
|
|
- 2433 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2434 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2435 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2436 SymTab.ClArray THEN
|
|
|
- 2437 SemError(217);
|
|
|
- 2438 t := SymTab.InvalidType
|
|
|
- 2439 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2440 AND (SymTab.ClassOf(it) #
|
|
|
- 2441 SymTab.ClChar)
|
|
|
- 2442 AND (SymTab.ClassOf(it) #
|
|
|
- 2443 SymTab.ClEnum) THEN
|
|
|
- 2444 SemError(218);
|
|
|
- 2445 t := SymTab.InvalidType
|
|
|
- 2446 ELSE
|
|
|
- 2447 QbeGen.WidenIndex(iq, ql);
|
|
|
- 2448 isOpen :=
|
|
|
- 2449 SymTab.IsOpenArray(t);
|
|
|
- 2450 IF isOpen THEN
|
|
|
- 2451 QbeGen.CopyOp("0", qlo);
|
|
|
- 2452 IF SymTab.IsCharArray(t)
|
|
|
- 2453 OR SymTab.IsUCharArray(t) THEN
|
|
|
- 2454 QbeGen.OpenHiChar(q, qhi)
|
|
|
- 2455 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
- 2456 END
|
|
|
- 2457 ELSE
|
|
|
- 2458 lo := SymTab.ArrayLo(t);
|
|
|
- 2459 hi := SymTab.ArrayHi(t);
|
|
|
- 2460 IF SymTab.IsCharArray(t)
|
|
|
- 2461 OR SymTab.IsUCharArray(t) THEN
|
|
|
- 2462 hi := hi + 1
|
|
|
- 2463 END;
|
|
|
- 2464 QbeGen.IntStr(lo, qlo);
|
|
|
- 2465 QbeGen.IntStr(hi, qhi)
|
|
|
- 2466 END;
|
|
|
- 2467 QbeGen.CheckRange(ql, qlo,
|
|
|
- 2468 qhi);
|
|
|
- 2469 eT := SymTab.ArrayElem(t);
|
|
|
- 2470 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 2471 t, qe);
|
|
|
- 2472 IF SymTab.ClassOf(eT) =
|
|
|
- 2473 SymTab.ClArray THEN
|
|
|
- 2474 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 2475 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 2476 END;
|
|
|
- 2477 t := eT; sfx := TRUE
|
|
|
- 2478 END; .)
|
|
|
- 2479 { "," Expr<it, iq>
|
|
|
- 2480 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
- 2481 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2482 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2483 SymTab.ClArray THEN
|
|
|
- 2484 SemError(217);
|
|
|
- 2485 t := SymTab.InvalidType
|
|
|
- 2486 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2487 AND (SymTab.ClassOf(it) #
|
|
|
- 2488 SymTab.ClChar)
|
|
|
- 2489 AND (SymTab.ClassOf(it) #
|
|
|
- 2490 SymTab.ClEnum) THEN
|
|
|
- 2491 SemError(218);
|
|
|
- 2492 t := SymTab.InvalidType
|
|
|
- 2493 ELSE
|
|
|
- 2494 QbeGen.WidenIndex(iq, ql);
|
|
|
- 2495 isOpen :=
|
|
|
- 2496 SymTab.IsOpenArray(t);
|
|
|
- 2497 IF isOpen THEN
|
|
|
- 2498 QbeGen.CopyOp("0", qlo);
|
|
|
- 2499 IF SymTab.IsCharArray(t)
|
|
|
- 2500 OR SymTab.IsUCharArray(t) THEN
|
|
|
- 2501 QbeGen.OpenHiChar(q, qhi)
|
|
|
- 2502 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
- 2503 END
|
|
|
- 2504 ELSE
|
|
|
- 2505 lo := SymTab.ArrayLo(t);
|
|
|
- 2506 hi := SymTab.ArrayHi(t);
|
|
|
- 2507 IF SymTab.IsCharArray(t)
|
|
|
- 2508 OR SymTab.IsUCharArray(t) THEN
|
|
|
- 2509 hi := hi + 1
|
|
|
- 2510 END;
|
|
|
- 2511 QbeGen.IntStr(lo, qlo);
|
|
|
- 2512 QbeGen.IntStr(hi, qhi)
|
|
|
- 2513 END;
|
|
|
- 2514 QbeGen.CheckRange(ql, qlo,
|
|
|
- 2515 qhi);
|
|
|
- 2516 eT := SymTab.ArrayElem(t);
|
|
|
- 2517 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 2518 t, qe);
|
|
|
- 2519 IF SymTab.ClassOf(eT) =
|
|
|
- 2520 SymTab.ClArray THEN
|
|
|
- 2521 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 2522 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 2523 END;
|
|
|
- 2524 t := eT; sfx := TRUE
|
|
|
- 2525 END; .) }
|
|
|
- 2526 "]"
|
|
|
- 2527 | "." GetIdent<fn>
|
|
|
- 2528 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2529 AST.SetOp(astSel, AST.SelField);
|
|
|
- 2530 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
- 2531 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
- 2532 (* qualified L.x: materialize
|
|
|
- 2533 the export, then load it *)
|
|
|
- 2534 IF NOT SymTab.MaterializeAlias(n,
|
|
|
- 2535 fn, mal) THEN
|
|
|
- 2536 SemError(201);
|
|
|
- 2537 t := SymTab.InvalidType;
|
|
|
- 2538 QbeGen.CopyOp("0", q)
|
|
|
- 2539 ELSE
|
|
|
- 2540 QbeGen.CopyOp(mal, qn);
|
|
|
- 2541 t := SymTab.SymType(mal);
|
|
|
- 2542 k := SymTab.SymKind(mal);
|
|
|
- 2543 sfx := FALSE;
|
|
|
- 2544 IF k = SymTab.KindProc THEN
|
|
|
- 2545 (* call: ArgList supplies
|
|
|
- 2546 the value *)
|
|
|
- 2547 QbeGen.CopyOp("0", q)
|
|
|
- 2548 ELSIF NOT QbeGen.LoadDesignator(
|
|
|
- 2549 mal, t, k, q) THEN
|
|
|
- 2550 SemError(230);
|
|
|
- 2551 QbeGen.CopyOp("0", q)
|
|
|
- 2552 END
|
|
|
- 2553 END
|
|
|
- 2554 ELSIF t = SymTab.InvalidType THEN
|
|
|
- 2555 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2556 SymTab.ClRecord)
|
|
|
- 2557 AND (SymTab.ClassOf(t) #
|
|
|
- 2558 SymTab.ClClass) THEN
|
|
|
- 2559 SemError(215);
|
|
|
- 2560 t := SymTab.InvalidType
|
|
|
- 2561 ELSIF (SymTab.ClassOf(t) =
|
|
|
- 2562 SymTab.ClClass)
|
|
|
- 2563 AND SymTab.MethodExists(t, fn) THEN
|
|
|
- 2564 (* obj.Method: bind the
|
|
|
- 2565 method and pass obj as
|
|
|
- 2566 the hidden receiver; q
|
|
|
- 2567 already holds the
|
|
|
- 2568 object's address *)
|
|
|
- 2569 QbeGen.ArmRecv(q);
|
|
|
- 2570 QbeGen.CopyOp(fn, n);
|
|
|
- 2571 QbeGen.CopyOp(fn, qn);
|
|
|
- 2572 methCls := t;
|
|
|
- 2573 k := SymTab.KindProc;
|
|
|
- 2574 t := SymTab.InvalidType
|
|
|
- 2575 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2576 fn) THEN
|
|
|
- 2577 SemError(216);
|
|
|
- 2578 t := SymTab.InvalidType
|
|
|
- 2579 ELSE
|
|
|
- 2580 fo := SymTab.FieldOffset(t,
|
|
|
- 2581 fn);
|
|
|
- 2582 t := SymTab.FieldType(t, fn);
|
|
|
- 2583 QbeGen.FieldAddr(q, fo, qe);
|
|
|
- 2584 (* array fields are inline:
|
|
|
- 2585 the field address is the
|
|
|
- 2586 descriptor, like records *)
|
|
|
- 2587 QbeGen.CopyOp(qe, q);
|
|
|
- 2588 sfx := TRUE
|
|
|
- 2589 END; .)
|
|
|
- 2590 | "^"
|
|
|
- 2591 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2592 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2593 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2594 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2595 SymTab.ClPtr THEN
|
|
|
- 2596 SemError(219);
|
|
|
- 2597 t := SymTab.InvalidType
|
|
|
- 2598 ELSE
|
|
|
- 2599 bt := SymTab.PtrBase(t);
|
|
|
- 2600 IF bt = SymTab.InvalidType THEN
|
|
|
- 2601 ELSE
|
|
|
- 2602 IF sfx THEN
|
|
|
- 2603 QbeGen.ElemLoad(q, t,
|
|
|
- 2604 qb);
|
|
|
- 2605 QbeGen.CopyOp(qb, q)
|
|
|
- 2606 END;
|
|
|
- 2607 t := bt;
|
|
|
- 2608 (* q holds the pointee
|
|
|
- 2609 address: Fact loads
|
|
|
- 2610 scalars/pointers and uses
|
|
|
- 2611 the address for
|
|
|
- 2612 aggregates; the VAR-actual
|
|
|
- 2613 note is q itself. *)
|
|
|
- 2614 sfx := TRUE
|
|
|
- 2615 END
|
|
|
- 2616 END; .) } (. astCur := astDes; .) .
|
|
|
- 2617 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
- 2618 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
- 2619 (a value, or a descriptor address for aggregates); each component
|
|
|
- 2620 descends one level exactly like the Design components. *)
|
|
|
- 2621 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
- 2622 VAR sfx: BOOLEAN; VAR node: AST.Node> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
- 2623 iq, ql, qlo, qhi, qe, qb:
|
|
|
- 2624 QbeGen.QVal;
|
|
|
- 2625 lo, hi, fo: INTEGER;
|
|
|
- 2626 isOpen: BOOLEAN;
|
|
|
- 2627 fname: SymTab.Name;
|
|
|
- 2628 astWrap, astSel: AST.Node; .)
|
|
|
- 2629 = "[" Expr<it, iq>
|
|
|
- 2630 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2631 astWrap := AST.MakeNode(
|
|
|
- 2632 AST.NkDesignator);
|
|
|
- 2633 AST.SetChild(astWrap, 0, node);
|
|
|
- 2634 node := astWrap
|
|
|
- 2635 END;
|
|
|
- 2636 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2637 AST.MakeUn(AST.NkSelector,
|
|
|
- 2638 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
- 2639 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2640 SymTab.ClArray THEN
|
|
|
- 2641 SemError(217);
|
|
|
- 2642 t := SymTab.InvalidType
|
|
|
- 2643 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
- 2644 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
- 2645 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
- 2646 SemError(218);
|
|
|
- 2647 t := SymTab.InvalidType
|
|
|
- 2648 ELSE
|
|
|
- 2649 QbeGen.WidenIndex(iq, ql);
|
|
|
- 2650 isOpen :=
|
|
|
- 2651 SymTab.IsOpenArray(t);
|
|
|
- 2652 IF isOpen THEN
|
|
|
- 2653 QbeGen.CopyOp("0", qlo);
|
|
|
- 2654 IF SymTab.IsCharArray(t)
|
|
|
- 2655 OR SymTab.IsUCharArray(t) THEN
|
|
|
- 2656 QbeGen.OpenHiChar(q, qhi)
|
|
|
- 2657 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
- 2658 END
|
|
|
- 2659 ELSE
|
|
|
- 2660 lo := SymTab.ArrayLo(t);
|
|
|
- 2661 hi := SymTab.ArrayHi(t);
|
|
|
- 2662 IF SymTab.IsCharArray(t)
|
|
|
- 2663 OR SymTab.IsUCharArray(t) THEN
|
|
|
- 2664 hi := hi + 1
|
|
|
- 2665 END;
|
|
|
- 2666 QbeGen.IntStr(lo, qlo);
|
|
|
- 2667 QbeGen.IntStr(hi, qhi)
|
|
|
- 2668 END;
|
|
|
- 2669 QbeGen.CheckRange(ql, qlo,
|
|
|
- 2670 qhi);
|
|
|
- 2671 eT := SymTab.ArrayElem(t);
|
|
|
- 2672 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
- 2673 t, qe);
|
|
|
- 2674 IF SymTab.ClassOf(eT) =
|
|
|
- 2675 SymTab.ClArray THEN
|
|
|
- 2676 QbeGen.ElemLoad(qe, eT, q)
|
|
|
- 2677 ELSE QbeGen.CopyOp(qe, q)
|
|
|
- 2678 END;
|
|
|
- 2679 t := eT; sfx := TRUE
|
|
|
- 2680 END; .)
|
|
|
- 2681 "]"
|
|
|
- 2682 | "." GetIdent<fname>
|
|
|
- 2683 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2684 astWrap := AST.MakeNode(
|
|
|
- 2685 AST.NkDesignator);
|
|
|
- 2686 AST.SetChild(astWrap, 0, node);
|
|
|
- 2687 node := astWrap
|
|
|
- 2688 END;
|
|
|
- 2689 AST.SetChild(node, AST.NChild(node),
|
|
|
- 2690 AST.MakeUn(AST.NkSelector,
|
|
|
- 2691 AST.SelField,
|
|
|
- 2692 AST.MakeLeaf(AST.NkIdent,
|
|
|
- 2693 fname))); IF t = SymTab.InvalidType THEN
|
|
|
- 2694 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 2695 SymTab.ClRecord)
|
|
|
- 2696 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 2697 SemError(215);
|
|
|
- 2698 t := SymTab.InvalidType
|
|
|
- 2699 ELSIF NOT SymTab.FieldExists(t,
|
|
|
- 2700 fname) THEN
|
|
|
- 2701 SemError(216);
|
|
|
- 2702 t := SymTab.InvalidType
|
|
|
- 2703 ELSE
|
|
|
- 2704 fo := SymTab.FieldOffset(t,
|
|
|
- 2705 fname);
|
|
|
- 2706 t := SymTab.FieldType(t, fname);
|
|
|
- 2707 QbeGen.FieldAddr(q, fo, qe);
|
|
|
- 2708 QbeGen.CopyOp(qe, q);
|
|
|
- 2709 sfx := TRUE
|
|
|
- 2710 END; .)
|
|
|
- 2711 | "^" (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
- 2712 astWrap := AST.MakeNode(
|
|
|
- 2713 AST.NkDesignator);
|
|
|
- 2714 AST.SetChild(astWrap, 0, node);
|
|
|
- 2715 node := astWrap
|
|
|
- 2716 END;
|
|
|
- 2717 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
- 2718 AST.SetOp(astSel, AST.SelDeref);
|
|
|
- 2719 AST.SetChild(node,
|
|
|
- 2720 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
- 2721 ELSIF SymTab.ClassOf(t) #
|
|
|
- 2722 SymTab.ClPtr THEN
|
|
|
- 2723 SemError(219);
|
|
|
- 2724 t := SymTab.InvalidType
|
|
|
- 2725 ELSE
|
|
|
- 2726 bt := SymTab.PtrBase(t);
|
|
|
- 2727 IF bt # SymTab.InvalidType THEN
|
|
|
- 2728 IF sfx THEN
|
|
|
- 2729 QbeGen.ElemLoad(q, t, qb);
|
|
|
- 2730 QbeGen.CopyOp(qb, q)
|
|
|
- 2731 END;
|
|
|
- 2732 t := bt; sfx := TRUE
|
|
|
- 2733 END
|
|
|
- 2734 END; .) .
|
|
|
- 2735 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2736 (. VAR t2: SymTab.TypeIndex;
|
|
|
- 2737 op: INTEGER;
|
|
|
- 2738 q2, qt, wl: QbeGen.QVal;
|
|
|
- 2739 astA, astB: AST.Node;
|
|
|
- 2740 astOp: INTEGER;
|
|
|
- 2741 astMade: BOOLEAN;
|
|
|
- 2742 isR: BOOLEAN; .)
|
|
|
- 2743 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
- 2744 [ Rel<op> SimExpr<t2, q2>
|
|
|
- 2745 (. astB := astCur; astMade := TRUE;
|
|
|
- 2746 astOp := AST.OpEq;
|
|
|
- 2747 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
- 2748 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
- 2749 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
- 2750 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
- 2751 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
- 2752 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
- 2753 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
- 2754 END;
|
|
|
- 2755 IF op = SymTab.OpIn THEN
|
|
|
- 2756 IF SymTab.InCheck(t, t2) THEN
|
|
|
- 2757 IF (t = SymTab.InvalidType)
|
|
|
- 2758 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 2759 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 2760 ELSE
|
|
|
- 2761 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
- 2762 SymTab.SetCount(t2), qt);
|
|
|
- 2763 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2764 END
|
|
|
- 2765 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
- 2766 QbeGen.CopyOp("0", q)
|
|
|
- 2767 END
|
|
|
- 2768 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
- 2769 IF (t = SymTab.InvalidType)
|
|
|
- 2770 OR (t2 = SymTab.InvalidType) THEN
|
|
|
- 2771 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
- 2772 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
- 2773 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
- 2774 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
|
|
|
- 2775 QbeGen.Cmp(op, q, q2, qt, FALSE);
|
|
|
- 2776 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2777 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
- 2778 AND (op # SymTab.OpNeq2) THEN
|
|
|
- 2779 SemError(213); t := SymTab.InvalidType;
|
|
|
- 2780 QbeGen.CopyOp("0", q)
|
|
|
- 2781 ELSE
|
|
|
- 2782 QbeGen.CmpL(op, q, q2, qt);
|
|
|
- 2783 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2784 END
|
|
|
- 2785 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2786 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2787 QbeGen.CmpSet(op, q, q2,
|
|
|
- 2788 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
- 2789 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2790 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
- 2791 QbeGen.StrEq(op, q, q2, qt);
|
|
|
- 2792 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2793 ELSIF SymTab.IsLongFamily(t)
|
|
|
- 2794 OR SymTab.IsLongFamily(t2) THEN
|
|
|
- 2795 IF SymTab.IsIntFamily(t) THEN
|
|
|
- 2796 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
|
|
|
- 2797 END;
|
|
|
- 2798 IF SymTab.IsIntFamily(t2) THEN
|
|
|
- 2799 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
|
|
|
- 2800 END;
|
|
|
- 2801 QbeGen.CmpLong(op, q, q2, qt);
|
|
|
- 2802 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
- 2803 ELSE
|
|
|
- 2804 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 2805 t := SymTab.BoolType();
|
|
|
- 2806 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
- 2807 QbeGen.CopyOp(qt, q)
|
|
|
- 2808 END
|
|
|
- 2809 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
- 2810 QbeGen.CopyOp("0", q)
|
|
|
- 2811 END;
|
|
|
- 2812 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
- 2813 (. IF NOT astMade THEN astCur := astA END; .) .
|
|
|
- 2814 Rel<VAR op: INTEGER>
|
|
|
- 2815 = "=" (. op := SymTab.OpEq; .)
|
|
|
- 2816 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
- 2817 | "<" (. op := SymTab.OpLt; .)
|
|
|
- 2818 | "<=" (. op := SymTab.OpLe; .)
|
|
|
- 2819 | ">" (. op := SymTab.OpGt; .)
|
|
|
- 2820 | ">=" (. op := SymTab.OpGe; .)
|
|
|
- 2821 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
- 2822 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2823 (. VAR t2, res2, lt, rt:
|
|
|
- 2824 SymTab.TypeIndex;
|
|
|
- 2825 op: INTEGER;
|
|
|
- 2826 q2, qt, wq, qf, q2a, q2b:
|
|
|
- 2827 QbeGen.QVal;
|
|
|
- 2828 neg, isR, isL, folded:
|
|
|
- 2829 BOOLEAN;
|
|
|
- 2830 fok: BOOLEAN;
|
|
|
- 2831 lw, rw, mw: CARDINAL;
|
|
|
- 2832 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 2833 astA, astB: AST.Node;
|
|
|
- 2834 astSign, astOp: INTEGER; .)
|
|
|
- 2835 = (. neg := FALSE; astSign := 0; .)
|
|
|
- 2836 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
- 2837 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
- 2838 Term<t, q> (. astA := astCur; IF neg THEN
|
|
|
- 2839 IF QbeGen.IsImm(q) THEN
|
|
|
- 2840 QbeGen.NegFold(q, q)
|
|
|
- 2841 ELSE QbeGen.NewTemp(qt);
|
|
|
- 2842 QbeGen.NegQ(q, qt,
|
|
|
- 2843 SymTab.ClassOf(t)
|
|
|
- 2844 = SymTab.ClReal);
|
|
|
- 2845 QbeGen.CopyOp(qt, q)
|
|
|
- 2846 END
|
|
|
- 2847 END;
|
|
|
- 2848 IF astSign < 0 THEN
|
|
|
- 2849 astCur := AST.MakeUn(
|
|
|
- 2850 AST.NkUnary, AST.OpSub, astA);
|
|
|
- 2851 astA := astCur
|
|
|
- 2852 END; .)
|
|
|
- 2853 { AddOp<op> (. IF op = SymTab.OpOr THEN
|
|
|
- 2854 QbeGen.DelayBegin END; .)
|
|
|
- 2855 Term<t2, q2> (. astB := astCur; IF op = SymTab.OpOr THEN
|
|
|
- 2856 QbeGen.DelayEnd END; .)
|
|
|
- 2857 (. astOp := AST.OpAdd;
|
|
|
- 2858 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
- 2859 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
- 2860 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 2861 astCur := astA;
|
|
|
- 2862 IF op = SymTab.OpOr THEN
|
|
|
- 2863 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
- 2864 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 2865 t := SymTab.BoolType()
|
|
|
- 2866 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 2867 IF t # SymTab.InvalidType THEN
|
|
|
- 2868 QbeGen.Slot4(qs);
|
|
|
- 2869 QbeGen.NewLabel(lTrue);
|
|
|
- 2870 QbeGen.NewLabel(lNext);
|
|
|
- 2871 QbeGen.NewLabel(lDone);
|
|
|
- 2872 QbeGen.Jnz(q, lTrue, lNext);
|
|
|
- 2873 QbeGen.EmitLabel(lTrue);
|
|
|
- 2874 QbeGen.StoreW(qs, "1");
|
|
|
- 2875 QbeGen.Jmp(lDone);
|
|
|
- 2876 QbeGen.EmitLabel(lNext);
|
|
|
- 2877 QbeGen.DelayFlush;
|
|
|
- 2878 QbeGen.StoreW(qs, q2);
|
|
|
- 2879 QbeGen.Jmp(lDone);
|
|
|
- 2880 QbeGen.EmitLabel(lDone);
|
|
|
- 2881 QbeGen.LoadW(qs, qr);
|
|
|
- 2882 QbeGen.CopyOp(qr, q)
|
|
|
- 2883 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
- 2884 END
|
|
|
- 2885 ELSIF (op = SymTab.OpAdd)
|
|
|
- 2886 AND (SymTab.UStrCompat(t, t2)
|
|
|
- 2887 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 2888 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
- 2889 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
- 2890 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
- 2891 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
- 2892 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
- 2893 (* UString concatenation: a UCHAR operand becomes a
|
|
|
- 2894 1-codepoint UString; the result is a descriptor in the
|
|
|
- 2895 shim's concat buffer. Work on copies so neither
|
|
|
- 2896 operand is clobbered. *)
|
|
|
- 2897 IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
|
|
|
- 2898 QbeGen.CopyOp(q, q2a)
|
|
|
- 2899 ELSE
|
|
|
- 2900 QbeGen.UStrFrom(q, q2a)
|
|
|
- 2901 END;
|
|
|
- 2902 IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
|
|
|
- 2903 QbeGen.UStrCat(q2a, q2, qt)
|
|
|
- 2904 ELSE
|
|
|
- 2905 QbeGen.UStrFrom(q2, q2b);
|
|
|
- 2906 QbeGen.UStrCat(q2a, q2b, qt)
|
|
|
- 2907 END;
|
|
|
- 2908 t := SymTab.NewUStr();
|
|
|
- 2909 QbeGen.CopyOp(qt, q)
|
|
|
- 2910 ELSIF (op = SymTab.OpAdd)
|
|
|
- 2911 AND (SymTab.StrCompat(t, t2)
|
|
|
- 2912 OR (SymTab.IsStrType(t)
|
|
|
- 2913 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
- 2914 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
- 2915 AND SymTab.IsStrType(t2))) THEN
|
|
|
- 2916 (* string concatenation; a CHAR operand becomes a
|
|
|
- 2917 1-character string literal. When both operands are
|
|
|
- 2918 constants, fold to a single string literal so a
|
|
|
- 2919 constructor element stays compile-time. *)
|
|
|
- 2920 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
- 2921 qt, fok);
|
|
|
- 2922 IF NOT fok THEN
|
|
|
- 2923 IF SymTab.StrCompat(t, t2) THEN
|
|
|
- 2924 QbeGen.StrCat(q, q2, qt)
|
|
|
- 2925 ELSIF SymTab.IsStrType(t) THEN
|
|
|
- 2926 QbeGen.DeclCharStr(q2, qs);
|
|
|
- 2927 QbeGen.StrCat(q, qs, qt)
|
|
|
- 2928 ELSE
|
|
|
- 2929 QbeGen.DeclCharStr(q, qs);
|
|
|
- 2930 QbeGen.StrCat(qs, q2, qt)
|
|
|
- 2931 END
|
|
|
- 2932 END;
|
|
|
- 2933 t := SymTab.NewStr();
|
|
|
- 2934 QbeGen.CopyOp(qt, q)
|
|
|
- 2935 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 2936 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 2937 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 2938 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 2939 mw := lw;
|
|
|
- 2940 IF rw > mw THEN mw := rw END;
|
|
|
- 2941 IF op = SymTab.OpAdd THEN
|
|
|
- 2942 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
- 2943 ELSE
|
|
|
- 2944 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
- 2945 END;
|
|
|
- 2946 t := SymTab.NewSet(
|
|
|
- 2947 SymTab.NewSubR(0,
|
|
|
- 2948 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 2949 QbeGen.CopyOp(qt, q)
|
|
|
- 2950 ELSE
|
|
|
- 2951 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
- 2952 lt := t; rt := t2; t := res2
|
|
|
- 2953 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 2954 IF t # SymTab.InvalidType THEN
|
|
|
- 2955 isL := SymTab.IsLongFamily(t);
|
|
|
- 2956 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 2957 folded := FALSE;
|
|
|
- 2958 IF (NOT isL) AND (NOT isR)
|
|
|
- 2959 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 2960 IF op = SymTab.OpAdd THEN
|
|
|
- 2961 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
- 2962 ELSE
|
|
|
- 2963 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
- 2964 END
|
|
|
- 2965 END;
|
|
|
- 2966 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 2967 ELSE
|
|
|
- 2968 IF isL THEN
|
|
|
- 2969 IF SymTab.IsIntFamily(lt) THEN
|
|
|
- 2970 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
- 2971 END;
|
|
|
- 2972 IF SymTab.IsIntFamily(rt) THEN
|
|
|
- 2973 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
- 2974 END;
|
|
|
- 2975 QbeGen.NewTemp(qt);
|
|
|
- 2976 IF op = SymTab.OpAdd THEN
|
|
|
- 2977 QbeGen.Op3L("add", qt, q, q2)
|
|
|
- 2978 ELSE
|
|
|
- 2979 QbeGen.Op3L("sub", qt, q, q2)
|
|
|
- 2980 END
|
|
|
- 2981 ELSE
|
|
|
- 2982 QbeGen.NewTemp(qt);
|
|
|
- 2983 IF op = SymTab.OpAdd THEN
|
|
|
- 2984 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
- 2985 ELSE
|
|
|
- 2986 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
- 2987 END
|
|
|
- 2988 END;
|
|
|
- 2989 QbeGen.CopyOp(qt, q)
|
|
|
- 2990 END
|
|
|
- 2991 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 2992 END
|
|
|
- 2993 END; .) } .
|
|
|
- 2994 AddOp<VAR op: INTEGER>
|
|
|
- 2995 = "+" (. op := SymTab.OpAdd; .)
|
|
|
- 2996 | "-" (. op := SymTab.OpSub; .)
|
|
|
- 2997 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
- 2998 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 2999 (. VAR t2, res2, lt, rt:
|
|
|
- 3000 SymTab.TypeIndex;
|
|
|
- 3001 op: INTEGER;
|
|
|
- 3002 q2, qt, wq, qf:
|
|
|
- 3003 QbeGen.QVal;
|
|
|
- 3004 isR, isL, folded: BOOLEAN;
|
|
|
- 3005 lw, rw, mw: CARDINAL;
|
|
|
- 3006 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
- 3007 astA, astB: AST.Node;
|
|
|
- 3008 astOp: INTEGER; .)
|
|
|
- 3009 = Fact<t, q> (. astA := astCur; .) { MulOp<op> (. IF op = SymTab.OpAnd THEN
|
|
|
- 3010 QbeGen.DelayBegin END; .)
|
|
|
- 3011 Fact<t2, q2> (. astB := astCur; IF op = SymTab.OpAnd THEN
|
|
|
- 3012 QbeGen.DelayEnd END; .)
|
|
|
- 3013 (. astOp := AST.OpMul;
|
|
|
- 3014 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
- 3015 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
- 3016 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
- 3017 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
- 3018 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
- 3019 astCur := astA;
|
|
|
- 3020 IF op = SymTab.OpAnd THEN
|
|
|
- 3021 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
- 3022 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
- 3023 t := SymTab.BoolType()
|
|
|
- 3024 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
- 3025 IF t # SymTab.InvalidType THEN
|
|
|
- 3026 QbeGen.Slot4(qs);
|
|
|
- 3027 QbeGen.NewLabel(lNext);
|
|
|
- 3028 QbeGen.NewLabel(lFalse);
|
|
|
- 3029 QbeGen.NewLabel(lDone);
|
|
|
- 3030 QbeGen.Jnz(q, lNext, lFalse);
|
|
|
- 3031 QbeGen.EmitLabel(lNext);
|
|
|
- 3032 QbeGen.DelayFlush;
|
|
|
- 3033 QbeGen.StoreW(qs, q2);
|
|
|
- 3034 QbeGen.Jmp(lDone);
|
|
|
- 3035 QbeGen.EmitLabel(lFalse);
|
|
|
- 3036 QbeGen.StoreW(qs, "0");
|
|
|
- 3037 QbeGen.Jmp(lDone);
|
|
|
- 3038 QbeGen.EmitLabel(lDone);
|
|
|
- 3039 QbeGen.LoadW(qs, qr);
|
|
|
- 3040 QbeGen.CopyOp(qr, q)
|
|
|
- 3041 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
- 3042 END
|
|
|
- 3043 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
- 3044 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
- 3045 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
- 3046 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
- 3047 mw := lw;
|
|
|
- 3048 IF rw > mw THEN mw := rw END;
|
|
|
- 3049 IF op = SymTab.OpTimes THEN
|
|
|
- 3050 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
- 3051 ELSE
|
|
|
- 3052 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
- 3053 END;
|
|
|
- 3054 t := SymTab.NewSet(
|
|
|
- 3055 SymTab.NewSubR(0,
|
|
|
- 3056 VAL(INTEGER, mw) * 32 - 1));
|
|
|
- 3057 QbeGen.CopyOp(qt, q)
|
|
|
- 3058 ELSE
|
|
|
- 3059 IF SymTab.ArithCheck(t, t2,
|
|
|
- 3060 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
- 3061 res2) THEN
|
|
|
- 3062 lt := t; rt := t2; t := res2
|
|
|
- 3063 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
- 3064 IF t # SymTab.InvalidType THEN
|
|
|
- 3065 isL := SymTab.IsLongFamily(t);
|
|
|
- 3066 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
- 3067 folded := FALSE;
|
|
|
- 3068 IF (NOT isL) AND (NOT isR)
|
|
|
- 3069 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- 3070 IF op = SymTab.OpTimes THEN
|
|
|
- 3071 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
- 3072 ELSIF op = SymTab.OpDiv THEN
|
|
|
- 3073 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
- 3074 ELSIF op = SymTab.OpMod THEN
|
|
|
- 3075 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
- 3076 END
|
|
|
- 3077 END;
|
|
|
- 3078 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
- 3079 ELSE
|
|
|
- 3080 IF isL THEN
|
|
|
- 3081 IF SymTab.IsIntFamily(lt) THEN
|
|
|
- 3082 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
- 3083 END;
|
|
|
- 3084 IF SymTab.IsIntFamily(rt) THEN
|
|
|
- 3085 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
- 3086 END;
|
|
|
- 3087 QbeGen.NewTemp(qt);
|
|
|
- 3088 IF op = SymTab.OpTimes THEN
|
|
|
- 3089 QbeGen.Op3L("mul", qt, q, q2)
|
|
|
- 3090 ELSIF (op = SymTab.OpDiv)
|
|
|
- 3091 OR (op = SymTab.OpSlash) THEN
|
|
|
- 3092 QbeGen.Op3L("div", qt, q, q2)
|
|
|
- 3093 ELSE
|
|
|
- 3094 QbeGen.Op3L("rem", qt, q, q2)
|
|
|
- 3095 END
|
|
|
- 3096 ELSE
|
|
|
- 3097 QbeGen.NewTemp(qt);
|
|
|
- 3098 IF op = SymTab.OpTimes THEN
|
|
|
- 3099 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
- 3100 ELSIF (op = SymTab.OpDiv)
|
|
|
- 3101 OR (op = SymTab.OpSlash) THEN
|
|
|
- 3102 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
- 3103 ELSE
|
|
|
- 3104 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
- 3105 END
|
|
|
- 3106 END;
|
|
|
- 3107 QbeGen.CopyOp(qt, q)
|
|
|
- 3108 END
|
|
|
- 3109 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3110 END
|
|
|
- 3111 END; .) } .
|
|
|
- 3112 MulOp<VAR op: INTEGER>
|
|
|
- 3113 = "*" (. op := SymTab.OpTimes; .)
|
|
|
- 3114 | "/" (. op := SymTab.OpSlash; .)
|
|
|
- 3115 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
- 3116 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
- 3117 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
- 3118 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3119 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
- 3120 et, dt, t2, st, ct2, et2:
|
|
|
- 3121 SymTab.TypeIndex;
|
|
|
- 3122 dk: INTEGER;
|
|
|
- 3123 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
- 3124 QbeGen.QVal;
|
|
|
- 3125 qn, vn: SymTab.Name;
|
|
|
- 3126 vt: SymTab.TypeIndex;
|
|
|
- 3127 c1, c2: INTEGER;
|
|
|
- 3128 lo, hi: INTEGER;
|
|
|
- 3129 isMax: BOOLEAN;
|
|
|
- 3130 called, isHigh, sfx, isCh,
|
|
|
- 3131 isU, uok, isStr: BOOLEAN;
|
|
|
- 3132 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
- 3133 astD: AST.Node;
|
|
|
- 3134 astCall: BOOLEAN;
|
|
|
- 3135 astNode, astNot: AST.Node;
|
|
|
- 3136 j: CARDINAL;
|
|
|
- 3137 astArg2: AST.Node;
|
|
|
- 3138 astBrace: AST.Node;
|
|
|
- 3139 astRes: AST.Node; .)
|
|
|
- 3140 = (. astIsLit := FALSE; .)
|
|
|
- 3141 ( integer (. LexString(s);
|
|
|
- 3142 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
- 3143 t := SymTab.IntType(); .)
|
|
|
- 3144 | charConst (. LexString(s);
|
|
|
- 3145 QbeGen.NormLit(s, q, isCh);
|
|
|
- 3146 IF twoPhase THEN
|
|
|
- 3147 astIsLit := TRUE;
|
|
|
- 3148 astCur := AST.MakeLeaf(
|
|
|
- 3149 AST.NkCharLit, s)
|
|
|
- 3150 END;
|
|
|
- 3151 t := SymTab.CharType(); .)
|
|
|
- 3152 | real (. LexString(s);
|
|
|
- 3153 QbeGen.NormReal(s, q);
|
|
|
- 3154 IF twoPhase THEN
|
|
|
- 3155 astIsLit := TRUE;
|
|
|
- 3156 astCur := AST.MakeLeaf(
|
|
|
- 3157 AST.NkRealLit, s)
|
|
|
- 3158 END;
|
|
|
- 3159 t := SymTab.RealType(); .)
|
|
|
- 3160 | string (. LexString(s);
|
|
|
- 3161 IF twoPhase THEN
|
|
|
- 3162 astIsLit := TRUE;
|
|
|
- 3163 astCur := AST.MakeLeaf(
|
|
|
- 3164 AST.NkStrLit, s)
|
|
|
- 3165 END;
|
|
|
- 3166 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3167 t := SymTab.CharType();
|
|
|
- 3168 QbeGen.IntStr(
|
|
|
- 3169 QbeGen.CharVal(s), q)
|
|
|
- 3170 ELSE t := SymTab.NewStr();
|
|
|
- 3171 QbeGen.DeclStr(s, q);
|
|
|
- 3172 (* a literal's value IS its
|
|
|
- 3173 static descriptor address *)
|
|
|
- 3174 QbeGen.NoteAddr(q, q)
|
|
|
- 3175 END; .)
|
|
|
- 3176 | ustring (. LexString(s);
|
|
|
- 3177 IF twoPhase THEN
|
|
|
- 3178 astIsLit := TRUE;
|
|
|
- 3179 astCur := AST.MakeLeaf(
|
|
|
- 3180 AST.NkStrLit, s)
|
|
|
- 3181 END;
|
|
|
- 3182 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
- 3183 uok);
|
|
|
- 3184 IF NOT uok THEN
|
|
|
- 3185 SemError(234);
|
|
|
- 3186 t := SymTab.InvalidType
|
|
|
- 3187 ELSIF isU THEN
|
|
|
- 3188 t := SymTab.UCharType();
|
|
|
- 3189 QbeGen.IntStr(ucp, q)
|
|
|
- 3190 ELSE
|
|
|
- 3191 t := SymTab.NewUStr();
|
|
|
- 3192 QbeGen.NoteAddr(q, q)
|
|
|
- 3193 END; .)
|
|
|
- 3194 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
- 3195 astNArgs := 0; called := FALSE;
|
|
|
- 3196 t := dt;
|
|
|
- 3197 IF sfx THEN
|
|
|
- 3198 IF dt =
|
|
|
- 3199 SymTab.InvalidType THEN
|
|
|
- 3200 QbeGen.CopyOp("0", q)
|
|
|
- 3201 ELSIF (SymTab.ClassOf(dt) =
|
|
|
- 3202 SymTab.ClRecord)
|
|
|
- 3203 OR (SymTab.ClassOf(dt) =
|
|
|
- 3204 SymTab.ClSet)
|
|
|
- 3205 OR (SymTab.ClassOf(dt) =
|
|
|
- 3206 SymTab.ClArray)
|
|
|
- 3207 OR (SymTab.ClassOf(dt) =
|
|
|
- 3208 SymTab.ClClass) THEN
|
|
|
- 3209 QbeGen.CopyOp(qd, q)
|
|
|
- 3210 ELSE QbeGen.ElemLoad(qd, dt,
|
|
|
- 3211 q)
|
|
|
- 3212 END
|
|
|
- 3213 ELSE QbeGen.CopyOp(qd, q)
|
|
|
- 3214 END;
|
|
|
- 3215 IF (dk = SymTab.KindVar)
|
|
|
- 3216 OR (dk = SymTab.KindParam)
|
|
|
- 3217 OR (dk =
|
|
|
- 3218 SymTab.KindField) THEN
|
|
|
- 3219 IF sfx THEN
|
|
|
- 3220 QbeGen.NoteAddr(q, qd)
|
|
|
- 3221 ELSE
|
|
|
- 3222 QbeGen.AddrOf(qn, qa);
|
|
|
- 3223 QbeGen.NoteAddr(q, qa)
|
|
|
- 3224 END
|
|
|
- 3225 ELSIF sfx
|
|
|
- 3226 AND (dt #
|
|
|
- 3227 SymTab.InvalidType)
|
|
|
- 3228 AND ((SymTab.ClassOf(dt) =
|
|
|
- 3229 SymTab.ClArray)
|
|
|
- 3230 OR (SymTab.ClassOf(dt) =
|
|
|
- 3231 SymTab.ClSet)
|
|
|
- 3232 OR (SymTab.ClassOf(dt) =
|
|
|
- 3233 SymTab.ClRecord)) THEN
|
|
|
- 3234 QbeGen.NoteAddr(qd, qd)
|
|
|
- 3235 END; .)
|
|
|
- 3236 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
- 3237 astBrace := astCur; .) ]
|
|
|
- 3238 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
- 3239 (. astCall := TRUE;
|
|
|
- 3240 astNode := AstCallNode(astD);
|
|
|
- 3241 astRes := astNode;
|
|
|
- 3242 t := ct2;
|
|
|
- 3243 QbeGen.CopyOp(q2, q);
|
|
|
- 3244 sfx := FALSE; .)
|
|
|
- 3245 { ResultComp<t, q, sfx, astRes> }
|
|
|
- 3246 (. IF sfx THEN
|
|
|
- 3247 IF t = SymTab.InvalidType THEN
|
|
|
- 3248 QbeGen.CopyOp("0", q)
|
|
|
- 3249 ELSIF (SymTab.ClassOf(t) #
|
|
|
- 3250 SymTab.ClRecord)
|
|
|
- 3251 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
- 3252 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
- 3253 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
- 3254 QbeGen.ElemLoad(q, t, q2);
|
|
|
- 3255 QbeGen.CopyOp(q2, q)
|
|
|
- 3256 END
|
|
|
- 3257 END; .) ]
|
|
|
- 3258 (. IF called THEN
|
|
|
- 3259 astCur := astRes
|
|
|
- 3260 ELSIF astCall THEN
|
|
|
- 3261 astCur := astBrace
|
|
|
- 3262 ELSE astCur := astD
|
|
|
- 3263 END;
|
|
|
- 3264 astIsLit := TRUE;
|
|
|
- 3265 IF NOT called
|
|
|
- 3266 AND (dk = SymTab.KindProc) THEN
|
|
|
- 3267 (* bare zero-arg function
|
|
|
- 3268 call (parentheses may be
|
|
|
- 3269 omitted); a proper or
|
|
|
- 3270 parameterised proc here
|
|
|
- 3271 is 230 *)
|
|
|
- 3272 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
- 3273 AND (SymTab.ProcRes(qn) #
|
|
|
- 3274 SymTab.InvalidType) THEN
|
|
|
- 3275 QbeGen.Mangled(qn,
|
|
|
- 3276 SymTab.ProcUid(qn), qm0);
|
|
|
- 3277 QbeGen.CallBegin(qm0,
|
|
|
- 3278 SymTab.ProcRes(qn),
|
|
|
- 3279 SymTab.ProcDepthOf(qn),
|
|
|
- 3280 SymTab.IsExternal(qn));
|
|
|
- 3281 QbeGen.CallEnd(TRUE, q);
|
|
|
- 3282 t := SymTab.ProcRes(qn)
|
|
|
- 3283 ELSE
|
|
|
- 3284 (* procedure used as a
|
|
|
- 3285 value (assign to a
|
|
|
- 3286 procedure variable):
|
|
|
- 3287 its code address *)
|
|
|
- 3288 t := SymTab.ProcTypeOf(qn);
|
|
|
- 3289 QbeGen.Mangled(qn,
|
|
|
- 3290 SymTab.ProcUid(qn), qm0);
|
|
|
- 3291 QbeGen.ProcAddr(qm0, q)
|
|
|
- 3292 END
|
|
|
- 3293 END; .)
|
|
|
- 3294 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
- 3295 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
- 3296 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
- 3297 isU := FALSE; .)
|
|
|
- 3298 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3299 isStr := TRUE;
|
|
|
- 3300 isU := FALSE;
|
|
|
- 3301 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3302 dt := SymTab.CharType();
|
|
|
- 3303 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
- 3304 qd)
|
|
|
- 3305 ELSE
|
|
|
- 3306 dt := SymTab.NewStr();
|
|
|
- 3307 QbeGen.DeclStr(s, qd);
|
|
|
- 3308 QbeGen.NoteAddr(qd, qd)
|
|
|
- 3309 END;
|
|
|
- 3310 dk := -1;
|
|
|
- 3311 qn[0] := CHR(0); .)
|
|
|
- 3312 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
- 3313 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
- 3314 uok);
|
|
|
- 3315 isStr := FALSE;
|
|
|
- 3316 IF NOT uok THEN
|
|
|
- 3317 SemError(234);
|
|
|
- 3318 dt := SymTab.InvalidType
|
|
|
- 3319 ELSIF isU THEN
|
|
|
- 3320 (* one codepoint: a UCHAR;
|
|
|
- 3321 LEN is 1, HIGH is 0 *)
|
|
|
- 3322 dt := SymTab.UCharType();
|
|
|
- 3323 QbeGen.IntStr(ucp, qd)
|
|
|
- 3324 ELSE
|
|
|
- 3325 dt := SymTab.NewUStr();
|
|
|
- 3326 QbeGen.NoteAddr(qd, qd)
|
|
|
- 3327 END;
|
|
|
- 3328 dk := -1;
|
|
|
- 3329 qn[0] := CHR(0); .) )
|
|
|
- 3330 ")"
|
|
|
- 3331 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3332 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
- 3333 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
- 3334 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3335 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
- 3336 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3337 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3338 IF (dt # SymTab.InvalidType)
|
|
|
- 3339 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
- 3340 (* UString: the count is
|
|
|
- 3341 the descriptor header *)
|
|
|
- 3342 IF isHigh THEN
|
|
|
- 3343 QbeGen.UStrLen(qd, qr);
|
|
|
- 3344 QbeGen.DecQ(qr)
|
|
|
- 3345 ELSE
|
|
|
- 3346 QbeGen.UStrLen(qd, qr)
|
|
|
- 3347 END;
|
|
|
- 3348 t := SymTab.IntType();
|
|
|
- 3349 QbeGen.CopyOp(qr, q)
|
|
|
- 3350 ELSIF (dt # SymTab.InvalidType)
|
|
|
- 3351 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
- 3352 (* single UCHAR codepoint *)
|
|
|
- 3353 IF isHigh THEN
|
|
|
- 3354 QbeGen.CopyOp("0", qr)
|
|
|
- 3355 ELSE
|
|
|
- 3356 QbeGen.CopyOp("1", qr)
|
|
|
- 3357 END;
|
|
|
- 3358 t := SymTab.IntType();
|
|
|
- 3359 QbeGen.CopyOp(qr, q)
|
|
|
- 3360 ELSIF isStr THEN
|
|
|
- 3361 (* fold: content length at
|
|
|
- 3362 compile time *)
|
|
|
- 3363 IF SymTab.StrLen(s) = 3 THEN
|
|
|
- 3364 c1 := 1
|
|
|
- 3365 ELSE
|
|
|
- 3366 c1 :=
|
|
|
- 3367 SymTab.StrLen(s) - 2
|
|
|
- 3368 END;
|
|
|
- 3369 IF isHigh THEN
|
|
|
- 3370 DEC(c1)
|
|
|
- 3371 END;
|
|
|
- 3372 QbeGen.IntStr(c1, qr);
|
|
|
- 3373 t := SymTab.IntType();
|
|
|
- 3374 QbeGen.CopyOp(qr, q)
|
|
|
- 3375 ELSIF dt = SymTab.InvalidType THEN
|
|
|
- 3376 t := SymTab.InvalidType;
|
|
|
- 3377 QbeGen.CopyOp("0", q)
|
|
|
- 3378 ELSIF SymTab.ClassOf(dt) #
|
|
|
- 3379 SymTab.ClArray THEN
|
|
|
- 3380 SemError(217);
|
|
|
- 3381 t := SymTab.InvalidType;
|
|
|
- 3382 QbeGen.CopyOp("0", q)
|
|
|
- 3383 ELSE
|
|
|
- 3384 IF isHigh THEN
|
|
|
- 3385 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 3386 QbeGen.OpenHi(qd, qr)
|
|
|
- 3387 ELSE
|
|
|
- 3388 QbeGen.IntStr(
|
|
|
- 3389 SymTab.ArrayHi(dt), qr)
|
|
|
- 3390 END
|
|
|
- 3391 ELSE
|
|
|
- 3392 IF SymTab.IsOpenArray(dt) THEN
|
|
|
- 3393 QbeGen.LoadCount(qd, qr)
|
|
|
- 3394 ELSE
|
|
|
- 3395 QbeGen.IntStr(VAL(
|
|
|
- 3396 INTEGER,
|
|
|
- 3397 SymTab.ArrayLen(dt)),
|
|
|
- 3398 qr)
|
|
|
- 3399 END
|
|
|
- 3400 END;
|
|
|
- 3401 t := SymTab.IntType();
|
|
|
- 3402 QbeGen.CopyOp(qr, q)
|
|
|
- 3403 END; .)
|
|
|
- 3404 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3405 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3406 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
- 3407 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3408 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3409 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3410 t := SymTab.InvalidType;
|
|
|
- 3411 QbeGen.CopyOp("0", q)
|
|
|
- 3412 ELSE
|
|
|
- 3413 QbeGen.IntStr(VAL(INTEGER,
|
|
|
- 3414 SymTab.ObjectSize(dt)), q);
|
|
|
- 3415 t := SymTab.IntType()
|
|
|
- 3416 END; .)
|
|
|
- 3417 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
- 3418 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
- 3419 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
- 3420 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3421 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3422 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
- 3423 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3424 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
- 3425 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3426 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3427 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3428 (* set shift/rotate: isMax
|
|
|
- 3429 doubles as "rotate" *)
|
|
|
- 3430 IF (et # SymTab.InvalidType)
|
|
|
- 3431 AND (SymTab.ClassOf(et) =
|
|
|
- 3432 SymTab.ClSet) THEN
|
|
|
- 3433 QbeGen.SetShift(q, q2,
|
|
|
- 3434 SymTab.SetWords(et),
|
|
|
- 3435 SymTab.SetCount(et), isMax,
|
|
|
- 3436 qt);
|
|
|
- 3437 t := et;
|
|
|
- 3438 QbeGen.CopyOp(qt, q)
|
|
|
- 3439 ELSE SemError(230);
|
|
|
- 3440 t := SymTab.InvalidType;
|
|
|
- 3441 QbeGen.CopyOp("0", q)
|
|
|
- 3442 END; .)
|
|
|
- 3443 | ( "MIN" (. isMax := FALSE; .)
|
|
|
- 3444 | "MAX" (. isMax := TRUE; .) )
|
|
|
- 3445 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3446 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3447 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
- 3448 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
- 3449 ELSE AST.SetChild(astNode, 0,
|
|
|
- 3450 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
- 3451 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3452 astCur := astNode; astIsLit := TRUE;
|
|
|
- 3453 IF (dt # SymTab.InvalidType)
|
|
|
- 3454 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
- 3455 (* REAL/LONGREAL: the
|
|
|
- 3456 implementation bounds *)
|
|
|
- 3457 IF isMax THEN
|
|
|
- 3458 QbeGen.NormReal(
|
|
|
- 3459 "3.402823e38", q)
|
|
|
- 3460 ELSE QbeGen.NormReal(
|
|
|
- 3461 "-3.402823e38", q)
|
|
|
- 3462 END;
|
|
|
- 3463 t := SymTab.RealType()
|
|
|
- 3464 ELSIF (dt #
|
|
|
- 3465 SymTab.InvalidType)
|
|
|
- 3466 AND (SymTab.ClassOf(dt) =
|
|
|
- 3467 SymTab.ClLong) THEN
|
|
|
- 3468 IF isMax THEN
|
|
|
- 3469 QbeGen.CopyOp(
|
|
|
- 3470 "9223372036854775807", q)
|
|
|
- 3471 ELSE QbeGen.CopyOp(
|
|
|
- 3472 "-9223372036854775808", q)
|
|
|
- 3473 END;
|
|
|
- 3474 t := SymTab.LongType()
|
|
|
- 3475 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
- 3476 hi) THEN
|
|
|
- 3477 IF isMax THEN
|
|
|
- 3478 QbeGen.IntStr(hi, q)
|
|
|
- 3479 ELSE QbeGen.IntStr(lo, q)
|
|
|
- 3480 END;
|
|
|
- 3481 t := SymTab.IntType()
|
|
|
- 3482 ELSE SemError(230);
|
|
|
- 3483 t := SymTab.InvalidType;
|
|
|
- 3484 QbeGen.CopyOp("0", q)
|
|
|
- 3485 END; .)
|
|
|
- 3486 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
- 3487 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3488 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
- 3489 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3490 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3491 (. IF dt = SymTab.InvalidType THEN
|
|
|
- 3492 t := SymTab.InvalidType;
|
|
|
- 3493 QbeGen.CopyOp("0", q)
|
|
|
- 3494 ELSE
|
|
|
- 3495 IF sfx THEN
|
|
|
- 3496 QbeGen.CopyOp(qd, q)
|
|
|
- 3497 ELSIF (dk = SymTab.KindVar)
|
|
|
- 3498 OR (dk = SymTab.KindParam) THEN
|
|
|
- 3499 QbeGen.AddrOf(qn, q)
|
|
|
- 3500 ELSE SemError(230);
|
|
|
- 3501 QbeGen.CopyOp("0", q)
|
|
|
- 3502 END;
|
|
|
- 3503 t := SymTab.AddrType()
|
|
|
- 3504 END; .)
|
|
|
- 3505 | "CHR" "(" Expr<et, q> ")"
|
|
|
- 3506 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3507 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
- 3508 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3509 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3510 (. IF (et # SymTab.InvalidType)
|
|
|
- 3511 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3512 SemError(211) END;
|
|
|
- 3513 t := SymTab.CharType(); .)
|
|
|
- 3514 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
- 3515 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3516 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
- 3517 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3518 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3519 (. IF et # SymTab.InvalidType THEN
|
|
|
- 3520 IF (SymTab.ClassOf(et) #
|
|
|
- 3521 SymTab.ClChar)
|
|
|
- 3522 AND (SymTab.ClassOf(et) #
|
|
|
- 3523 SymTab.ClBool)
|
|
|
- 3524 AND (SymTab.ClassOf(et) #
|
|
|
- 3525 SymTab.ClEnum)
|
|
|
- 3526 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3527 SemError(211) END
|
|
|
- 3528 END;
|
|
|
- 3529 t := SymTab.IntType(); .)
|
|
|
- 3530 | "CAP" "(" Expr<et, q> ")"
|
|
|
- 3531 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3532 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
- 3533 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3534 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3535 (. QbeGen.CapQ(q, qa);
|
|
|
- 3536 QbeGen.CopyOp(qa, q);
|
|
|
- 3537 t := SymTab.CharType(); .)
|
|
|
- 3538 | "UCHR" "(" Expr<et, q> ")"
|
|
|
- 3539 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3540 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
- 3541 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3542 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3543 (. (* UCHR: the UCHAR constructor.
|
|
|
- 3544 CHAR -> UCHAR (identity);
|
|
|
- 3545 INTEGER familly -> UCHAR
|
|
|
- 3546 (codepoint value). *)
|
|
|
- 3547 IF (et # SymTab.InvalidType)
|
|
|
- 3548 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
- 3549 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
- 3550 SemError(211) END;
|
|
|
- 3551 t := SymTab.UCharType(); .)
|
|
|
- 3552 | "CHR8" "(" Expr<et, q> ")"
|
|
|
- 3553 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3554 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
- 3555 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3556 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3557 (. IF (et # SymTab.InvalidType)
|
|
|
- 3558 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3559 SemError(211) END;
|
|
|
- 3560 QbeGen.WidenLong(q, qa);
|
|
|
- 3561 QbeGen.CheckRange(qa, "0", "255");
|
|
|
- 3562 t := SymTab.CharType(); .)
|
|
|
- 3563 | "UORD" "(" Expr<et, q> ")"
|
|
|
- 3564 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3565 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
- 3566 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3567 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3568 (. (* UORD(u): the codepoint as a
|
|
|
- 3569 32-bit ordinal (INTEGER),
|
|
|
- 3570 cf. ORD for CHAR. *)
|
|
|
- 3571 IF (et # SymTab.InvalidType)
|
|
|
- 3572 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
- 3573 SemError(211) END;
|
|
|
- 3574 t := SymTab.IntType(); .)
|
|
|
- 3575 | "ABS" "(" Expr<et, q> ")"
|
|
|
- 3576 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3577 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
- 3578 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
- 3579 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3580 (. IF (et # SymTab.InvalidType)
|
|
|
- 3581 AND NOT SymTab.IsIntFamily(et)
|
|
|
- 3582 AND (SymTab.ClassOf(et) #
|
|
|
- 3583 SymTab.ClReal) THEN
|
|
|
- 3584 SemError(211)
|
|
|
- 3585 ELSE QbeGen.AbsQ(q, qa,
|
|
|
- 3586 SymTab.ClassOf(et) =
|
|
|
- 3587 SymTab.ClReal);
|
|
|
- 3588 QbeGen.CopyOp(qa, q)
|
|
|
- 3589 END;
|
|
|
- 3590 t := et; .)
|
|
|
- 3591 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
- 3592 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
- 3593 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
- 3594 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
- 3595 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
- 3596 astCur := astNode; astIsLit := TRUE; .)
|
|
|
- 3597 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
- 3598 SemError(201);
|
|
|
- 3599 t := SymTab.InvalidType
|
|
|
- 3600 ELSE vt := SymTab.SymType(vn);
|
|
|
- 3601 IF vt = SymTab.InvalidType THEN
|
|
|
- 3602 t := SymTab.InvalidType
|
|
|
- 3603 ELSIF et =
|
|
|
- 3604 SymTab.InvalidType THEN
|
|
|
- 3605 t := vt
|
|
|
- 3606 ELSE
|
|
|
- 3607 c1 := SymTab.ClassOf(et);
|
|
|
- 3608 c2 := SymTab.ClassOf(vt);
|
|
|
- 3609 IF (c1 = SymTab.ClInt)
|
|
|
- 3610 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3611 QbeGen.WidenLong(q, qa);
|
|
|
- 3612 QbeGen.CopyOp(qa, q);
|
|
|
- 3613 t := vt
|
|
|
- 3614 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3615 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3616 QbeGen.NarrowLong(q, qa);
|
|
|
- 3617 QbeGen.CopyOp(qa, q);
|
|
|
- 3618 t := vt
|
|
|
- 3619 ELSIF (c1 = SymTab.ClInt)
|
|
|
- 3620 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3621 QbeGen.ConvIR(q, qa);
|
|
|
- 3622 QbeGen.CopyOp(qa, q);
|
|
|
- 3623 t := vt
|
|
|
- 3624 ELSIF (c1 = SymTab.ClLong)
|
|
|
- 3625 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3626 QbeGen.ConvLR(q, qa);
|
|
|
- 3627 QbeGen.CopyOp(qa, q);
|
|
|
- 3628 t := vt
|
|
|
- 3629 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3630 AND (c2 = SymTab.ClInt) THEN
|
|
|
- 3631 QbeGen.ConvRI(q, qa);
|
|
|
- 3632 QbeGen.CopyOp(qa, q);
|
|
|
- 3633 t := vt
|
|
|
- 3634 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3635 AND (c2 = SymTab.ClLong) THEN
|
|
|
- 3636 QbeGen.ConvRL(q, qa);
|
|
|
- 3637 QbeGen.CopyOp(qa, q);
|
|
|
- 3638 t := vt
|
|
|
- 3639 ELSIF ((c1 = SymTab.ClInt)
|
|
|
- 3640 OR (c1 =
|
|
|
- 3641 SymTab.ClChar)
|
|
|
- 3642 OR (c1 =
|
|
|
- 3643 SymTab.ClBool)
|
|
|
- 3644 OR (c1 =
|
|
|
- 3645 SymTab.ClEnum))
|
|
|
- 3646 AND ((c2 = SymTab.ClInt)
|
|
|
- 3647 OR (c2 =
|
|
|
- 3648 SymTab.ClChar)
|
|
|
- 3649 OR (c2 =
|
|
|
- 3650 SymTab.ClBool)
|
|
|
- 3651 OR (c2 =
|
|
|
- 3652 SymTab.ClEnum)) THEN
|
|
|
- 3653 t := vt
|
|
|
- 3654 ELSIF (c1 = SymTab.ClPtr)
|
|
|
- 3655 AND (c2 = SymTab.ClPtr) THEN
|
|
|
- 3656 t := vt
|
|
|
- 3657 ELSIF (c1 = SymTab.ClReal)
|
|
|
- 3658 AND (c2 = SymTab.ClReal) THEN
|
|
|
- 3659 t := vt
|
|
|
- 3660 ELSE SemError(230);
|
|
|
- 3661 t := SymTab.InvalidType
|
|
|
- 3662 END
|
|
|
- 3663 END
|
|
|
- 3664 END; .)
|
|
|
- 3665 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
- 3666 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
- 3667 QbeGen.CopyOp(sq, q); .)
|
|
|
- 3668 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
- 3669 IF SymTab.BoolCheck(t2) THEN
|
|
|
- 3670 t := SymTab.BoolType()
|
|
|
- 3671 ELSE SemError(212);
|
|
|
- 3672 t := SymTab.InvalidType END;
|
|
|
- 3673 IF t # SymTab.InvalidType THEN
|
|
|
- 3674 QbeGen.NotQ(q2, q)
|
|
|
- 3675 ELSE QbeGen.CopyOp("0", q)
|
|
|
- 3676 END;
|
|
|
- 3677 astIsLit := TRUE;
|
|
|
- 3678 astCur := AST.MakeUn(
|
|
|
- 3679 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
- 3680 )
|
|
|
- 3681 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
|
|
|
- 3682 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
- 3683 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
- 3684 for computed elements. Ranges always lower via SetRange. *)
|
|
|
- 3685 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3686 (. VAR astNode: AST.Node; .)
|
|
|
- 3687 = "{" (. t := SymTab.NewSet(
|
|
|
- 3688 SymTab.NewSubR(0, 255));
|
|
|
- 3689 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
- 3690 QbeGen.NewSetTemp(8, q);
|
|
|
- 3691 QbeGen.SetZero(q, 8); .)
|
|
|
- 3692 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
- 3693 "}" (. astCur := astNode; .) .
|
|
|
- 3694 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
- 3695 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
- 3696 declared type sets the width (set) or element type (array). *)
|
|
|
- 3697 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
- 3698 (. VAR nw: CARDINAL;
|
|
|
- 3699 astNode, astTail: AST.Node;
|
|
|
- 3700 savedCls: INTEGER; .)
|
|
|
- 3701 = "{" (. savedCls := braceCls;
|
|
|
- 3702 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
- 3703 AST.SetTy(astNode, vt);
|
|
|
- 3704 astTail := astNode;
|
|
|
- 3705 IF vt = SymTab.InvalidType THEN
|
|
|
- 3706 braceCls := -1
|
|
|
- 3707 ELSE braceCls :=
|
|
|
- 3708 SymTab.ClassOf(vt)
|
|
|
- 3709 END;
|
|
|
- 3710 IF braceCls = SymTab.ClSet THEN
|
|
|
- 3711 IF vt = SymTab.InvalidType THEN
|
|
|
- 3712 nw := 8
|
|
|
- 3713 ELSE nw := SymTab.SetWords(vt);
|
|
|
- 3714 IF nw = 0 THEN nw := 8 END
|
|
|
- 3715 END;
|
|
|
- 3716 QbeGen.NewSetTemp(nw, q);
|
|
|
- 3717 QbeGen.SetZero(q, nw)
|
|
|
- 3718 ELSIF (braceCls =
|
|
|
- 3719 SymTab.ClArray)
|
|
|
- 3720 OR (braceCls =
|
|
|
- 3721 SymTab.ClRecord)
|
|
|
- 3722 OR (braceCls =
|
|
|
- 3723 SymTab.ClClass) THEN
|
|
|
- 3724 QbeGen.CtorBegin(vt)
|
|
|
- 3725 ELSE
|
|
|
- 3726 IF vt # SymTab.InvalidType THEN
|
|
|
- 3727 SemError(230) END;
|
|
|
- 3728 braceCls := -1
|
|
|
- 3729 END; .)
|
|
|
- 3730 [ BraceElem<vt, q, astNode, astTail>
|
|
|
- 3731 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
- 3732 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
- 3733 OR (braceCls =
|
|
|
- 3734 SymTab.ClRecord)
|
|
|
- 3735 OR (braceCls =
|
|
|
- 3736 SymTab.ClClass) THEN
|
|
|
- 3737 QbeGen.CtorEnd(q)
|
|
|
- 3738 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
- 3739 QbeGen.CopyOp("0", q)
|
|
|
- 3740 END;
|
|
|
- 3741 braceCls := savedCls; .)
|
|
|
- 3742 (. astCur := astNode; .) .
|
|
|
- 3743 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
- 3744 VAR node, tail: AST.Node>
|
|
|
- 3745 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3746 qe, q2: QbeGen.QVal;
|
|
|
- 3747 v, v2, reps, k: INTEGER;
|
|
|
- 3748 elem: SymTab.TypeIndex;
|
|
|
- 3749 lo: INTEGER;
|
|
|
- 3750 span: CARDINAL;
|
|
|
- 3751 cl, cl2: INTEGER;
|
|
|
- 3752 hasR, hasB: BOOLEAN;
|
|
|
- 3753 astEl: AST.Node; .)
|
|
|
- 3754 = (. hasR := FALSE; hasB := FALSE;
|
|
|
- 3755 reps := 1; .)
|
|
|
- 3756 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3757 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3758 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3759 hasR := TRUE; .) ]
|
|
|
- 3760 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
- 3761 (. IF braceCls = SymTab.ClSet THEN
|
|
|
- 3762 IF hasB THEN SemError(230) END;
|
|
|
- 3763 lo := SymTab.SetBaseLo(vt);
|
|
|
- 3764 span := SymTab.SetCount(vt);
|
|
|
- 3765 IF (et = SymTab.InvalidType)
|
|
|
- 3766 OR (hasR AND (et2 =
|
|
|
- 3767 SymTab.InvalidType)) THEN
|
|
|
- 3768 ELSE cl :=
|
|
|
- 3769 SymTab.ClassOf(et);
|
|
|
- 3770 IF hasR THEN
|
|
|
- 3771 cl2 :=
|
|
|
- 3772 SymTab.ClassOf(et2)
|
|
|
- 3773 ELSE cl2 := SymTab.ClInt
|
|
|
- 3774 END;
|
|
|
- 3775 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3776 OR (hasR AND NOT
|
|
|
- 3777 SymTab.SetElemClassOk(cl2))
|
|
|
- 3778 THEN
|
|
|
- 3779 SemError(222)
|
|
|
- 3780 ELSIF hasR
|
|
|
- 3781 AND SymTab.ConstInt(qe, v)
|
|
|
- 3782 AND SymTab.ConstInt(q2,
|
|
|
- 3783 v2)
|
|
|
- 3784 AND ((v < lo)
|
|
|
- 3785 OR (v2 < lo)
|
|
|
- 3786 OR (v >= lo +
|
|
|
- 3787 VAL(INTEGER, span))
|
|
|
- 3788 OR (v2 >= lo +
|
|
|
- 3789 VAL(INTEGER, span))
|
|
|
- 3790 OR (v > v2)) THEN
|
|
|
- 3791 SemError(222)
|
|
|
- 3792 ELSIF hasR THEN
|
|
|
- 3793 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3794 lo, span)
|
|
|
- 3795 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3796 v)
|
|
|
- 3797 AND ((v < lo)
|
|
|
- 3798 OR (v >= lo +
|
|
|
- 3799 VAL(INTEGER,
|
|
|
- 3800 span))) THEN
|
|
|
- 3801 SemError(222)
|
|
|
- 3802 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3803 lo, span)
|
|
|
- 3804 END
|
|
|
- 3805 END
|
|
|
- 3806 ELSIF (braceCls = SymTab.ClArray)
|
|
|
- 3807 OR (braceCls =
|
|
|
- 3808 SymTab.ClRecord)
|
|
|
- 3809 OR (braceCls =
|
|
|
- 3810 SymTab.ClClass) THEN
|
|
|
- 3811 IF hasR THEN SemError(230) END;
|
|
|
- 3812 reps := 1;
|
|
|
- 3813 IF hasB THEN
|
|
|
- 3814 IF SymTab.ConstInt(q2, v2)
|
|
|
- 3815 AND (v2 >= 1) THEN
|
|
|
- 3816 reps := v2
|
|
|
- 3817 ELSE SemError(230)
|
|
|
- 3818 END
|
|
|
- 3819 END;
|
|
|
- 3820 k := 0;
|
|
|
- 3821 WHILE k < reps DO
|
|
|
- 3822 QbeGen.CtorElem(qe);
|
|
|
- 3823 INC(k)
|
|
|
- 3824 END
|
|
|
- 3825 END; .)
|
|
|
- 3826 (. (* the BY form repeats the
|
|
|
- 3827 element; keep the AST in
|
|
|
- 3828 step with CtorElem *)
|
|
|
- 3829 k := 0;
|
|
|
- 3830 WHILE k < reps DO
|
|
|
- 3831 AstAppend(AST.NkBlock,
|
|
|
- 3832 node, tail, astEl);
|
|
|
- 3833 INC(k)
|
|
|
- 3834 END; .) .
|
|
|
- 3835 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
- 3836 qe, q2: QbeGen.QVal;
|
|
|
- 3837 v, v2: INTEGER;
|
|
|
- 3838 lo: INTEGER;
|
|
|
- 3839 span: CARDINAL;
|
|
|
- 3840 cl, cl2: INTEGER;
|
|
|
- 3841 hasR: BOOLEAN;
|
|
|
- 3842 astEl: AST.Node; .)
|
|
|
- 3843 = (. hasR := FALSE; .)
|
|
|
- 3844 Expr<et, qe> (. astEl := astCur; .)
|
|
|
- 3845 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
- 3846 AST.NkSubrange, 0, astEl, astCur);
|
|
|
- 3847 hasR := TRUE; .) ]
|
|
|
- 3848 (. lo := SymTab.SetBaseLo(st);
|
|
|
- 3849 span := SymTab.SetCount(st);
|
|
|
- 3850 IF (et = SymTab.InvalidType)
|
|
|
- 3851 OR (hasR AND (et2 =
|
|
|
- 3852 SymTab.InvalidType)) THEN
|
|
|
- 3853 ELSE cl :=
|
|
|
- 3854 SymTab.ClassOf(et);
|
|
|
- 3855 IF hasR THEN
|
|
|
- 3856 cl2 :=
|
|
|
- 3857 SymTab.ClassOf(et2)
|
|
|
- 3858 ELSE cl2 := SymTab.ClInt
|
|
|
- 3859 END;
|
|
|
- 3860 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
- 3861 OR (hasR AND NOT
|
|
|
- 3862 SymTab.SetElemClassOk(cl2))
|
|
|
- 3863 THEN
|
|
|
- 3864 SemError(222)
|
|
|
- 3865 ELSIF hasR
|
|
|
- 3866 AND SymTab.ConstInt(qe, v)
|
|
|
- 3867 AND SymTab.ConstInt(q2,
|
|
|
- 3868 v2)
|
|
|
- 3869 AND ((v < lo)
|
|
|
- 3870 OR (v2 < lo)
|
|
|
- 3871 OR (v >= lo +
|
|
|
- 3872 VAL(INTEGER, span))
|
|
|
- 3873 OR (v2 >= lo +
|
|
|
- 3874 VAL(INTEGER, span))
|
|
|
- 3875 OR (v > v2)) THEN
|
|
|
- 3876 SemError(222)
|
|
|
- 3877 ELSIF hasR THEN
|
|
|
- 3878 QbeGen.SetRange(sq, qe, q2,
|
|
|
- 3879 lo, span)
|
|
|
- 3880 ELSIF SymTab.ConstInt(qe,
|
|
|
- 3881 v)
|
|
|
- 3882 AND ((v < lo)
|
|
|
- 3883 OR (v >= lo +
|
|
|
- 3884 VAL(INTEGER,
|
|
|
- 3885 span))) THEN
|
|
|
- 3886 SemError(222)
|
|
|
- 3887 ELSE QbeGen.SetBit(sq, qe,
|
|
|
- 3888 lo, span)
|
|
|
- 3889 END
|
|
|
- 3890 END; .)
|
|
|
- 3891 (. AST.SetChild(node,
|
|
|
- 3892 AST.NChild(node), astEl); .) .
|
|
|
- 3893 GetIdent<VAR n: SymTab.Name>
|
|
|
- 3894 = ident (. LexName(n); .) .
|
|
|
- 3895
|
|
|
- 3896 END M2.
|
|
|
+ 1126 AST.SetOp(astNode, 1);
|
|
|
+ 1127 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1128 SymTab.PendName(i, nm);
|
|
|
+ 1129 IF nPendVar <=
|
|
|
+ 1130 HIGH(pendVarName) THEN
|
|
|
+ 1131 pendVarName[nPendVar] := nm;
|
|
|
+ 1132 pendVarT[nPendVar] := t;
|
|
|
+ 1133 INC(nPendVar)
|
|
|
+ 1134 END;
|
|
|
+ 1135 INC(i)
|
|
|
+ 1136 END
|
|
|
+ 1137 ELSE
|
|
|
+ 1138 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1139 SymTab.PendName(i, nm);
|
|
|
+ 1140 QbeGen.DeclVar(nm, t);
|
|
|
+ 1141 INC(i)
|
|
|
+ 1142 END
|
|
|
+ 1143 END;
|
|
|
+ 1144 (* a plain VAR list, not a
|
|
|
+ 1145 heading: the signature
|
|
|
+ 1146 result is discarded *)
|
|
|
+ 1147 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1148 END; .) .
|
|
|
+ 1149 VarIdents (. VAR n: SymTab.Name; .)
|
|
|
+ 1150 = GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1151 SymTab.KindVar) THEN
|
|
|
+ 1152 SemError(200) END; .)
|
|
|
+ 1153 { ","
|
|
|
+ 1154 GetIdent<n> (. IF NOT SymTab.EnterPending(n,
|
|
|
+ 1155 SymTab.KindVar) THEN
|
|
|
+ 1156 SemError(200) END; .) } .
|
|
|
+ 1157 ParIdents<isV: BOOLEAN> (. VAR n: SymTab.Name; .)
|
|
|
+ 1158 = GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1159 SemError(200) END; .)
|
|
|
+ 1160 { "," GetIdent<n> (. IF NOT SymTab.EnterParam(n, isV) THEN
|
|
|
+ 1161 SemError(200) END; .) } .
|
|
|
+ 1162 (* Procedure headings enter scopes/params/result and buffer the
|
|
|
+ 1163 QBE header; bodies lower to functions (4.1, module level only).
|
|
|
+ 1164 FORWARD marks; the body heading re-enters (signature compare
|
|
|
+ 1165 deferred). Nested procedures parse + check, lowering = 4.2. *)
|
|
|
+ 1166 ProcHeading<VAR pn: SymTab.Name; methCls: SymTab.TypeIndex>
|
|
|
+ 1167 (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1168 mg: QbeGen.QVal; .)
|
|
|
+ 1169 = "PROCEDURE"
|
|
|
+ 1170 GetIdent<pn> (. IF methCls #
|
|
|
+ 1171 SymTab.InvalidType THEN
|
|
|
+ 1172 (* a method: resume the
|
|
|
+ 1173 declared symbol (reuse
|
|
|
+ 1174 its uid) *)
|
|
|
+ 1175 IF NOT SymTab.ResumeMethod(
|
|
|
+ 1176 methCls, pn) THEN
|
|
|
+ 1177 SemError(200) END
|
|
|
+ 1178 ELSIF NOT SymTab.EnterProc(pn) THEN
|
|
|
+ 1179 IF NOT SymTab.ReenterProc(pn) THEN
|
|
|
+ 1180 IF NOT SymTab.ResumeProc(pn) THEN
|
|
|
+ 1181 SemError(200) END
|
|
|
+ 1182 END
|
|
|
+ 1183 END;
|
|
|
+ 1184 Lower.ScopeEnter;
|
|
|
+ 1185 Lower.NoteProc(pn,
|
|
|
+ 1186 SymTab.ProcUid(pn),
|
|
|
+ 1187 SymTab.InvalidType,
|
|
|
+ 1188 SymTab.ProcDepthOf(pn),
|
|
|
+ 1189 FALSE);
|
|
|
+ 1190 IF methCls #
|
|
|
+ 1191 SymTab.InvalidType THEN
|
|
|
+ 1192 QbeGen.Mangled(pn,
|
|
|
+ 1193 SymTab.MethUid(), mg)
|
|
|
+ 1194 ELSE
|
|
|
+ 1195 QbeGen.Mangled(pn,
|
|
|
+ 1196 SymTab.ProcUid(pn), mg)
|
|
|
+ 1197 END;
|
|
|
+ 1198 QbeGen.BeginFunc(mg);
|
|
|
+ 1199 IF methCls #
|
|
|
+ 1200 SymTab.InvalidType THEN
|
|
|
+ 1201 (* hidden THIS receiver:
|
|
|
+ 1202 a VAR param of the
|
|
|
+ 1203 class type, pushed as
|
|
|
+ 1204 the WITH base *)
|
|
|
+ 1205 IF NOT SymTab.EnterThisParam(
|
|
|
+ 1206 methCls) THEN
|
|
|
+ 1207 SemError(200) END;
|
|
|
+ 1208 IF NOT QbeGen.FuncParam(
|
|
|
+ 1209 "THIS", TRUE,
|
|
|
+ 1210 methCls) THEN
|
|
|
+ 1211 SemError(233) END
|
|
|
+ 1212 END; .)
|
|
|
+ 1213 [ FormalParams ]
|
|
|
+ 1214 [ ":" TypeIdent<t> (. IF NOT SymTab.SetProcRes(t) THEN
|
|
|
+ 1215 SemError(235) END;
|
|
|
+ 1216 Lower.SetProcRes(t);
|
|
|
+ 1217 QbeGen.SetFuncRes(t);
|
|
|
+ 1218 IF (t #
|
|
|
+ 1219 SymTab.InvalidType)
|
|
|
+ 1220 AND ((SymTab.ClassOf(t)
|
|
|
+ 1221 = SymTab.ClArray)
|
|
|
+ 1222 OR (SymTab.ClassOf(t)
|
|
|
+ 1223 = SymTab.ClRecord)
|
|
|
+ 1224 OR (SymTab.ClassOf(t)
|
|
|
+ 1225 = SymTab.ClSet)
|
|
|
+ 1226 OR (SymTab.ClassOf(t)
|
|
|
+ 1227 = SymTab.ClClass)) THEN
|
|
|
+ 1228 SemError(230) END; .) ] .
|
|
|
+ 1229 FormalParams
|
|
|
+ 1230 = "(" [ ParamSection { ";" ParamSection } ] ")" .
|
|
|
+ 1231 ParamSection (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1232 nm: SymTab.Name;
|
|
|
+ 1233 i: CARDINAL;
|
|
|
+ 1234 isV: BOOLEAN; .)
|
|
|
+ 1235 = (. isV := FALSE; .)
|
|
|
+ 1236 [ "VAR" (. isV := TRUE; .) ]
|
|
|
+ 1237 ParIdents<isV> ":" Type<t, TRUE> (. i := 0;
|
|
|
+ 1238 WHILE i < SymTab.PendCount() DO
|
|
|
+ 1239 SymTab.PendName(i, nm);
|
|
|
+ 1240 Lower.NoteParam(nm, t, isV);
|
|
|
+ 1241 Lower.NoteVar(nm, SymTab.KindParam, t);
|
|
|
+ 1242 (* value open arrays are
|
|
|
+ 1243 passed as descriptor
|
|
|
+ 1244 addresses (no copy):
|
|
|
+ 1245 same representation as
|
|
|
+ 1246 VAR formals *)
|
|
|
+ 1247 IF NOT QbeGen.FuncParam(nm,
|
|
|
+ 1248 isV
|
|
|
+ 1249 OR SymTab.IsOpenArray(t),
|
|
|
+ 1250 t) THEN
|
|
|
+ 1251 SemError(233) END;
|
|
|
+ 1252 INC(i)
|
|
|
+ 1253 END;
|
|
|
+ 1254 IF NOT SymTab.FixPending(t) THEN
|
|
|
+ 1255 SemError(235) END; .) .
|
|
|
+ 1256 (* Nested procedures lower like top-level ones (4.2): the
|
|
|
+ 1257 static link gives them their parent's frame. Methods keep
|
|
|
+ 1258 parse-now/230-later. *)
|
|
|
+ 1259 ProcDecl (. VAR pn: SymTab.Name;
|
|
|
+ 1260 astNode: AST.Node; .)
|
|
|
+ 1261 = ProcHeading<pn, SymTab.InvalidType> ";"
|
|
|
+ 1262 (. astNode := AST.MakeNode(AST.NkProcDecl);
|
|
|
+ 1263 AST.SetOp(astNode, 0);
|
|
|
+ 1264 AST.SetChild(astNode, 0,
|
|
|
+ 1265 AST.MakeLeaf(AST.NkIdent, pn));
|
|
|
+ 1266 Lower.NoteProcNode(astNode); .)
|
|
|
+ 1267 ( "FORWARD" (. AST.SetOp(astNode, 1);
|
|
|
+ 1268 astDecl := astNode;
|
|
|
+ 1269 Lower.ScopeLeave;
|
|
|
+ 1270 SymTab.MarkFwd;
|
|
|
+ 1271 SymTab.CloseProc;
|
|
|
+ 1272 QbeGen.AbortFunc; .)
|
|
|
+ 1273 | "EXTERNAL" (. AST.SetOp(astNode, 2);
|
|
|
+ 1274 astDecl := astNode;
|
|
|
+ 1275 Lower.MarkProcExternal;
|
|
|
+ 1276 Lower.ScopeLeave;
|
|
|
+ 1277 SymTab.MarkExternal("");
|
|
|
+ 1278 SymTab.CloseProc;
|
|
|
+ 1279 QbeGen.AbortFunc; .)
|
|
|
+ 1280 | (. QbeGen.EndFuncHeader; .)
|
|
|
+ 1281 Block<pn> (. AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1282 AST.SetChild(astNode, 2, astBlkDecls);
|
|
|
+ 1283 astDecl := astNode;
|
|
|
+ 1284 Lower.ScopeLeave;
|
|
|
+ 1285 SymTab.CloseProc;
|
|
|
+ 1286 QbeGen.EndFunc(
|
|
|
+ 1287 SymTab.ProcRes(pn)); .) ) .
|
|
|
+ 1288 Block<pn: SymTab.Name> (. VAR m2: SymTab.Name; .)
|
|
|
+ 1289 = DeclSeq (. astBlkDecls := astDecl;
|
|
|
+ 1290 astStmt := AST.NoNode; .)
|
|
|
+ 1291 [ "BEGIN" (. (* an empty body is still a
|
|
|
+ 1292 body: mark it so Lower
|
|
|
+ 1293 does not read it as a
|
|
|
+ 1294 definition heading *)
|
|
|
+ 1295 IF astStmt = AST.NoNode THEN
|
|
|
+ 1296 astStmt :=
|
|
|
+ 1297 AST.MakeNode(AST.NkBlock)
|
|
|
+ 1298 END; .)
|
|
|
+ 1299 [ StatSeq ] ]
|
|
|
+ 1300 "END"
|
|
|
+ 1301 GetIdent<m2> (. IF NOT SymTab.Equal(pn, m2) THEN
|
|
|
+ 1302 SemError(202) END; .) .
|
|
|
+ 1303 StatSeq (. VAR astSeq, astTail: AST.Node; .)
|
|
|
+ 1304 = (. astSeq := AST.NoNode;
|
|
|
+ 1305 astTail := AST.NoNode; .)
|
|
|
+ 1306 Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 1307 astSeq, astTail, astStmt); .)
|
|
|
+ 1308 { ";" [ Statement (. AstAppend(AST.NkBlock,
|
|
|
+ 1309 astSeq, astTail, astStmt); .) ] }
|
|
|
+ 1310 (. astStmt := astSeq; .) .
|
|
|
+ 1311 (* Trailing/empty statements (`a; ; b`, Coco/R's generated `;;`)
|
|
|
+ 1312 are accepted: the statement after ';' is optional. *)
|
|
|
+ 1313 Statement (. VAR lx: QbeGen.QVal; .)
|
|
|
+ 1314 = (. astStmt := AST.NoNode; .)
|
|
|
+ 1315 ( AssOrCall
|
|
|
+ 1316 | IfStat
|
|
|
+ 1317 | WhileStat
|
|
|
+ 1318 | RepeatStat
|
|
|
+ 1319 | LoopStat
|
|
|
+ 1320 | ForStat
|
|
|
+ 1321 | CaseStat
|
|
|
+ 1322 | WithStat
|
|
|
+ 1323 | ReturnStat
|
|
|
+ 1324 | HaltStat
|
|
|
+ 1325 | NewStat
|
|
|
+ 1326 | DisposeStat
|
|
|
+ 1327 | IncDecStat
|
|
|
+ 1328 | InclExclStat
|
|
|
+ 1329 | "EXIT" (. IF QbeGen.TopLoop(lx) THEN
|
|
|
+ 1330 QbeGen.Jmp(lx)
|
|
|
+ 1331 ELSE SemError(230) END;
|
|
|
+ 1332 astStmt := AST.MakeNode(AST.NkExit); .) ) .
|
|
|
+ 1333 (* INCL(set, elem) / EXCL(set, elem): PIM set-element builtins. *)
|
|
|
+ 1334 InclExclStat (. VAR at, et2: SymTab.TypeIndex;
|
|
|
+ 1335 dk: INTEGER;
|
|
|
+ 1336 qd, qe: QbeGen.QVal;
|
|
|
+ 1337 qn: SymTab.Name;
|
|
|
+ 1338 sfx, isInc: BOOLEAN;
|
|
|
+ 1339 astNode, astD: AST.Node; .)
|
|
|
+ 1340 = ( "INCL" (. isInc := TRUE; .)
|
|
|
+ 1341 | "EXCL" (. isInc := FALSE; .) )
|
|
|
+ 1342 "(" Design<at, dk, qd, qn, sfx> (. astD := astCur; .) ","
|
|
|
+ 1343 Expr<et2, qe> ")"
|
|
|
+ 1344 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1345 IF isInc THEN
|
|
|
+ 1346 AST.SetChild(astNode, 0,
|
|
|
+ 1347 AST.MakeLeaf(AST.NkIdent, "INCL"))
|
|
|
+ 1348 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 1349 AST.MakeLeaf(AST.NkIdent, "EXCL"))
|
|
|
+ 1350 END;
|
|
|
+ 1351 IF astD # AST.NoNode THEN
|
|
|
+ 1352 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1353 IF astCur # AST.NoNode THEN
|
|
|
+ 1354 AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 1355 astStmt := astNode; .)
|
|
|
+ 1356 (. IF at = SymTab.InvalidType THEN
|
|
|
+ 1357 ELSIF SymTab.ClassOf(at) #
|
|
|
+ 1358 SymTab.ClSet THEN
|
|
|
+ 1359 SemError(222)
|
|
|
+ 1360 ELSE
|
|
|
+ 1361 IF isInc THEN
|
|
|
+ 1362 QbeGen.SetBit(qd, qe,
|
|
|
+ 1363 SymTab.SetBaseLo(at),
|
|
|
+ 1364 SymTab.SetCount(at))
|
|
|
+ 1365 ELSE
|
|
|
+ 1366 QbeGen.SetClearBit(qd, qe,
|
|
|
+ 1367 SymTab.SetBaseLo(at),
|
|
|
+ 1368 SymTab.SetCount(at))
|
|
|
+ 1369 END
|
|
|
+ 1370 END; .) .
|
|
|
+ 1371 (* INC(v [,step]) / DEC(v [,step]) as builtin statements over an
|
|
|
+ 1372 integer designator. *)
|
|
|
+ 1373 IncDecStat (. VAR dt, et2: SymTab.TypeIndex;
|
|
|
+ 1374 dk: INTEGER;
|
|
|
+ 1375 qd, qv, qn2, qstep:
|
|
|
+ 1376 QbeGen.QVal;
|
|
|
+ 1377 qn: SymTab.Name;
|
|
|
+ 1378 sfx, isInc: BOOLEAN;
|
|
|
+ 1379 astNode, astD, astStep:
|
|
|
+ 1380 AST.Node; .)
|
|
|
+ 1381 = (. isInc := TRUE; .)
|
|
|
+ 1382 ( "INC" (. isInc := TRUE; .)
|
|
|
+ 1383 | "DEC" (. isInc := FALSE; .) )
|
|
|
+ 1384 "(" (. QbeGen.CopyOp("1", qstep); astStep := AST.NoNode; .)
|
|
|
+ 1385 Design<dt, dk, qd, qn, sfx> (. astD := astCur; .)
|
|
|
+ 1386 [ "," Expr<et2, qstep> (. astStep := astCur; .) ]
|
|
|
+ 1387 ")" (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1388 IF isInc THEN
|
|
|
+ 1389 AST.SetChild(astNode, 0,
|
|
|
+ 1390 AST.MakeLeaf(AST.NkIdent, "INC"))
|
|
|
+ 1391 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 1392 AST.MakeLeaf(AST.NkIdent, "DEC"))
|
|
|
+ 1393 END;
|
|
|
+ 1394 IF astD # AST.NoNode THEN
|
|
|
+ 1395 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1396 IF astStep # AST.NoNode THEN
|
|
|
+ 1397 AST.SetChild(astNode, 2, astStep) END;
|
|
|
+ 1398 astStmt := astNode; .) (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1399 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1400 AND (dk # SymTab.KindParam)
|
|
|
+ 1401 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1402 SemError(210)
|
|
|
+ 1403 ELSIF NOT SymTab.IsIntFamily(dt) THEN
|
|
|
+ 1404 SemError(211)
|
|
|
+ 1405 ELSE
|
|
|
+ 1406 IF sfx
|
|
|
+ 1407 OR (dk = SymTab.KindField) THEN
|
|
|
+ 1408 QbeGen.ElemLoad(qd, dt, qv)
|
|
|
+ 1409 ELSE QbeGen.LoadVar(qn,
|
|
|
+ 1410 FALSE, qv)
|
|
|
+ 1411 END;
|
|
|
+ 1412 QbeGen.NewTemp(qn2);
|
|
|
+ 1413 IF isInc THEN
|
|
|
+ 1414 QbeGen.Op3("add", qn2, qv,
|
|
|
+ 1415 qstep, FALSE)
|
|
|
+ 1416 ELSE QbeGen.Op3("sub", qn2, qv,
|
|
|
+ 1417 qstep, FALSE)
|
|
|
+ 1418 END;
|
|
|
+ 1419 IF sfx
|
|
|
+ 1420 OR (dk = SymTab.KindField) THEN
|
|
|
+ 1421 QbeGen.ElemStore(qd, qn2,
|
|
|
+ 1422 dt)
|
|
|
+ 1423 ELSE QbeGen.StoreVar(qn,
|
|
|
+ 1424 qn2, FALSE)
|
|
|
+ 1425 END
|
|
|
+ 1426 END; .) .
|
|
|
+ 1427 (* NEW/DISPOSE as builtin statements (no call syntax until step 4).
|
|
|
+ 1428 Targets are pointer designators; DISPOSE nils afterwards (safer
|
|
|
+ 1429 than Wirth-undefined; documented). DISPOSE is shallow. *)
|
|
|
+ 1430 NewStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1431 dk: INTEGER;
|
|
|
+ 1432 qd, qm: QbeGen.QVal;
|
|
|
+ 1433 qn: SymTab.Name;
|
|
|
+ 1434 sfx: BOOLEAN;
|
|
|
+ 1435 bt: SymTab.TypeIndex;
|
|
|
+ 1436 astNode, astD: AST.Node; .)
|
|
|
+ 1437 = "NEW" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 1438 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1439 AST.SetChild(astNode, 0,
|
|
|
+ 1440 AST.MakeLeaf(AST.NkIdent, "NEW"));
|
|
|
+ 1441 IF astD # AST.NoNode THEN
|
|
|
+ 1442 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1443 astStmt := astNode; .)
|
|
|
+ 1444 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1445 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1446 AND (dk # SymTab.KindParam)
|
|
|
+ 1447 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1448 SemError(210)
|
|
|
+ 1449 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1450 SymTab.ClPtr THEN
|
|
|
+ 1451 SemError(219)
|
|
|
+ 1452 ELSE bt := SymTab.PtrBase(dt);
|
|
|
+ 1453 IF bt #
|
|
|
+ 1454 SymTab.InvalidType THEN
|
|
|
+ 1455 QbeGen.NewHeap(bt, qm);
|
|
|
+ 1456 QbeGen.InitHeap(qm, bt);
|
|
|
+ 1457 IF sfx
|
|
|
+ 1458 OR (dk =
|
|
|
+ 1459 SymTab.KindField) THEN
|
|
|
+ 1460 QbeGen.ElemStore(qd, qm,
|
|
|
+ 1461 dt)
|
|
|
+ 1462 ELSE QbeGen.StorePtr(qn,
|
|
|
+ 1463 qm)
|
|
|
+ 1464 END
|
|
|
+ 1465 END
|
|
|
+ 1466 END; .) .
|
|
|
+ 1467 DisposeStat (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1468 dk: INTEGER;
|
|
|
+ 1469 qd, qv: QbeGen.QVal;
|
|
|
+ 1470 qn: SymTab.Name;
|
|
|
+ 1471 sfx: BOOLEAN;
|
|
|
+ 1472 astNode, astD: AST.Node; .)
|
|
|
+ 1473 = "DISPOSE" "(" Design<dt, dk, qd, qn, sfx> (. astD := astCur; .) ")"
|
|
|
+ 1474 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 1475 AST.SetChild(astNode, 0,
|
|
|
+ 1476 AST.MakeLeaf(AST.NkIdent, "DISPOSE"));
|
|
|
+ 1477 IF astD # AST.NoNode THEN
|
|
|
+ 1478 AST.SetChild(astNode, 1, astD) END;
|
|
|
+ 1479 astStmt := astNode; .)
|
|
|
+ 1480 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 1481 ELSIF (dk # SymTab.KindVar)
|
|
|
+ 1482 AND (dk # SymTab.KindParam)
|
|
|
+ 1483 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1484 SemError(210)
|
|
|
+ 1485 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 1486 SymTab.ClPtr THEN
|
|
|
+ 1487 SemError(219)
|
|
|
+ 1488 ELSE
|
|
|
+ 1489 IF sfx
|
|
|
+ 1490 OR (dk =
|
|
|
+ 1491 SymTab.KindField) THEN
|
|
|
+ 1492 QbeGen.ElemLoad(qd, dt,
|
|
|
+ 1493 qv)
|
|
|
+ 1494 ELSE QbeGen.LoadPtr(qn, qv)
|
|
|
+ 1495 END;
|
|
|
+ 1496 QbeGen.FreeHeap(qv);
|
|
|
+ 1497 IF sfx
|
|
|
+ 1498 OR (dk =
|
|
|
+ 1499 SymTab.KindField) THEN
|
|
|
+ 1500 QbeGen.ElemStore(qd, "0",
|
|
|
+ 1501 dt)
|
|
|
+ 1502 ELSE QbeGen.StorePtr(qn,
|
|
|
+ 1503 "0")
|
|
|
+ 1504 END
|
|
|
+ 1505 END; .) .
|
|
|
+ 1506 (* WITH pushes each record's fields (inner wins) plus its base
|
|
|
+ 1507 address; field designators resolve through both stacks. *)
|
|
|
+ 1508 WithStat (. VAR nW: CARDINAL;
|
|
|
+ 1509 astNode: AST.Node; .)
|
|
|
+ 1510 = "WITH" (. nW := 0;
|
|
|
+ 1511 astNode := AST.MakeNode(AST.NkWith); .)
|
|
|
+ 1512 WithItem<nW, astNode> { "," WithItem<nW, astNode> }
|
|
|
+ 1513 "DO" (. astStmt := AST.NoNode; .)
|
|
|
+ 1514 [ StatSeq ] "END" (. AST.SetChild(astNode,
|
|
|
+ 1515 AST.NChild(astNode), astStmt);
|
|
|
+ 1516 astStmt := astNode;
|
|
|
+ 1517 WHILE nW > 0 DO
|
|
|
+ 1518 SymTab.PopScope;
|
|
|
+ 1519 QbeGen.PopWith;
|
|
|
+ 1520 DEC(nW)
|
|
|
+ 1521 END; .) .
|
|
|
+ 1522 WithItem<VAR nW: CARDINAL; wnode: AST.Node>
|
|
|
+ 1523 (. VAR dt: SymTab.TypeIndex;
|
|
|
+ 1524 dk: INTEGER;
|
|
|
+ 1525 qd, qe: QbeGen.QVal;
|
|
|
+ 1526 qn: SymTab.Name;
|
|
|
+ 1527 sfx: BOOLEAN; .)
|
|
|
+ 1528 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 1529 (. IF astCur # AST.NoNode THEN
|
|
|
+ 1530 AST.SetChild(wnode,
|
|
|
+ 1531 AST.NChild(wnode), astCur) END;
|
|
|
+ 1532 IF dt = SymTab.InvalidType THEN
|
|
|
+ 1533 ELSIF (SymTab.ClassOf(dt) #
|
|
|
+ 1534 SymTab.ClRecord)
|
|
|
+ 1535 AND (SymTab.ClassOf(dt) #
|
|
|
+ 1536 SymTab.ClClass) THEN
|
|
|
+ 1537 SemError(215)
|
|
|
+ 1538 ELSIF SymTab.PushRecord(dt) THEN
|
|
|
+ 1539 QbeGen.PushWith(qd);
|
|
|
+ 1540 INC(nW)
|
|
|
+ 1541 END; .) .
|
|
|
+ 1542 (* Assignment or procedure-statement call (4.1, module level).
|
|
|
+ 1543 Bare `P;` is a syntax error; function-as-statement is 233. *)
|
|
|
+ 1544 AssOrCall (. VAR dt, et: SymTab.TypeIndex;
|
|
|
+ 1545 dk: INTEGER;
|
|
|
+ 1546 qd, qe, qt, ql: QbeGen.QVal;
|
|
|
+ 1547 qn: SymTab.Name;
|
|
|
+ 1548 ct2, res0: SymTab.TypeIndex;
|
|
|
+ 1549 q2, mg0: QbeGen.QVal;
|
|
|
+ 1550 isR, conv, wconv: BOOLEAN;
|
|
|
+ 1551 called, sfx: BOOLEAN;
|
|
|
+ 1552 astLhs: AST.Node; .)
|
|
|
+ 1553 = Design<dt, dk, qd, qn, sfx>
|
|
|
+ 1554 (. astLhs := astCur; astNArgs := 0; .)
|
|
|
+ 1555 ( ":="
|
|
|
+ 1556 Expr<et, qe> (. astStmt := AST.MakeBin(
|
|
|
+ 1557 AST.NkAssign, 0, astLhs, astCur);
|
|
|
+ 1558 IF (dt # SymTab.InvalidType)
|
|
|
+ 1559 AND (dk # SymTab.KindVar)
|
|
|
+ 1560 AND (dk # SymTab.KindParam)
|
|
|
+ 1561 AND (dk # SymTab.KindField) THEN
|
|
|
+ 1562 SemError(210)
|
|
|
+ 1563 ELSIF NOT SymTab.Assignable(et,
|
|
|
+ 1564 dt) THEN
|
|
|
+ 1565 SemError(210)
|
|
|
+ 1566 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 1567 AND (SymTab.ClassOf(dt) =
|
|
|
+ 1568 SymTab.ClClass) THEN
|
|
|
+ 1569 SemError(230) END;
|
|
|
+ 1570 isR := (dt #
|
|
|
+ 1571 SymTab.InvalidType)
|
|
|
+ 1572 AND (SymTab.ClassOf(dt)
|
|
|
+ 1573 = SymTab.ClReal);
|
|
|
+ 1574 conv := isR
|
|
|
+ 1575 AND SymTab.IsIntFamily(et);
|
|
|
+ 1576 wconv := (dt #
|
|
|
+ 1577 SymTab.InvalidType)
|
|
|
+ 1578 AND SymTab.IsLongFamily(dt)
|
|
|
+ 1579 AND SymTab.IsIntFamily(et);
|
|
|
+ 1580 IF ((dk = SymTab.KindVar)
|
|
|
+ 1581 OR (dk = SymTab.KindParam)
|
|
|
+ 1582 OR (dk = SymTab.KindField))
|
|
|
+ 1583 AND (dt # SymTab.InvalidType)
|
|
|
+ 1584 AND (et # SymTab.InvalidType)
|
|
|
+ 1585 AND (SymTab.ClassOf(dt) #
|
|
|
+ 1586 SymTab.ClClass) THEN
|
|
|
+ 1587 IF sfx
|
|
|
+ 1588 OR (dk = SymTab.KindField) THEN
|
|
|
+ 1589 IF SymTab.ClassOf(dt) =
|
|
|
+ 1590 SymTab.ClArray THEN
|
|
|
+ 1591 IF (et # SymTab.InvalidType)
|
|
|
+ 1592 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
+ 1593 AND SymTab.IsUCharArray(dt) THEN
|
|
|
+ 1594 QbeGen.UAssign(qd, qe)
|
|
|
+ 1595 ELSIF SymTab.StrCompat(dt,
|
|
|
+ 1596 et) THEN
|
|
|
+ 1597 QbeGen.StrAssign(qd,
|
|
|
+ 1598 qe)
|
|
|
+ 1599 ELSE
|
|
|
+ 1600 QbeGen.CopyArray(qd,
|
|
|
+ 1601 qe, dt)
|
|
|
+ 1602 END
|
|
|
+ 1603 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 1604 SymTab.ClSet THEN
|
|
|
+ 1605 QbeGen.CopySet(qd, qe,
|
|
|
+ 1606 SymTab.SetWords(dt),
|
|
|
+ 1607 SymTab.SetWords(et))
|
|
|
+ 1608 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 1609 SymTab.ClRecord THEN
|
|
|
+ 1610 QbeGen.CopyRecord(qd, qe,
|
|
|
+ 1611 dt)
|
|
|
+ 1612 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
+ 1613 IF wconv THEN
|
|
|
+ 1614 QbeGen.WidenLong(qe, ql);
|
|
|
+ 1615 QbeGen.ElemStore(qd, ql,
|
|
|
+ 1616 dt)
|
|
|
+ 1617 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
+ 1618 dt)
|
|
|
+ 1619 END
|
|
|
+ 1620 ELSIF conv THEN
|
|
|
+ 1621 QbeGen.ConvIR(qe, qt);
|
|
|
+ 1622 QbeGen.ElemStore(qd, qt,
|
|
|
+ 1623 dt)
|
|
|
+ 1624 ELSE QbeGen.ElemStore(qd, qe,
|
|
|
+ 1625 dt)
|
|
|
+ 1626 END
|
|
|
+ 1627 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 1628 SymTab.ClArray THEN
|
|
|
+ 1629 IF (et # SymTab.InvalidType)
|
|
|
+ 1630 AND (SymTab.ClassOf(et) = SymTab.ClUStr)
|
|
|
+ 1631 AND SymTab.IsUCharArray(dt) THEN
|
|
|
+ 1632 QbeGen.UAssign(qd, qe)
|
|
|
+ 1633 ELSIF SymTab.StrCompat(dt,
|
|
|
+ 1634 et) THEN
|
|
|
+ 1635 QbeGen.StrAssign(qd, qe)
|
|
|
+ 1636 ELSE
|
|
|
+ 1637 QbeGen.CopyArray(qd, qe,
|
|
|
+ 1638 dt)
|
|
|
+ 1639 END
|
|
|
+ 1640 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 1641 SymTab.ClSet THEN
|
|
|
+ 1642 QbeGen.CopySet(qd, qe,
|
|
|
+ 1643 SymTab.SetWords(dt),
|
|
|
+ 1644 SymTab.SetWords(et))
|
|
|
+ 1645 ELSIF SymTab.ClassOf(dt) =
|
|
|
+ 1646 SymTab.ClRecord THEN
|
|
|
+ 1647 QbeGen.CopyRecord(qd, qe, dt)
|
|
|
+ 1648 ELSIF (SymTab.ClassOf(dt) =
|
|
|
+ 1649 SymTab.ClPtr)
|
|
|
+ 1650 OR (SymTab.ClassOf(dt) =
|
|
|
+ 1651 SymTab.ClProc) THEN
|
|
|
+ 1652 QbeGen.StorePtr(qn, qe)
|
|
|
+ 1653 ELSIF SymTab.IsLongFamily(dt) THEN
|
|
|
+ 1654 IF wconv THEN
|
|
|
+ 1655 QbeGen.WidenLong(qe, ql);
|
|
|
+ 1656 QbeGen.StoreLong(qn, ql)
|
|
|
+ 1657 ELSE QbeGen.StoreLong(qn, qe)
|
|
|
+ 1658 END
|
|
|
+ 1659 ELSIF conv THEN
|
|
|
+ 1660 QbeGen.ConvIR(qe, qt);
|
|
|
+ 1661 QbeGen.StoreVar(qn, qt, TRUE)
|
|
|
+ 1662 ELSE
|
|
|
+ 1663 QbeGen.StoreVar(qn, qe, isR)
|
|
|
+ 1664 END
|
|
|
+ 1665 END; .)
|
|
|
+ 1666 | ArgList<qn, dt, qd, FALSE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 1667 (. astStmt := AstCallNode(astLhs); .)
|
|
|
+ 1668 | (* bare `P;`: proper parameterless
|
|
|
+ 1669 procedure call; anything else
|
|
|
+ 1670 here is 233 (was a bare syntax
|
|
|
+ 1671 error before 4.2) *)
|
|
|
+ 1672 (. astStmt := AstCallNode(astLhs);
|
|
|
+ 1673 IF (dk = SymTab.KindProc)
|
|
|
+ 1674 AND NOT sfx THEN
|
|
|
+ 1675 res0 := SymTab.ProcRes(qn);
|
|
|
+ 1676 IF res0 #
|
|
|
+ 1677 SymTab.InvalidType THEN
|
|
|
+ 1678 SemError(233)
|
|
|
+ 1679 ELSIF SymTab.ProcNPar(qn) #
|
|
|
+ 1680 0 THEN
|
|
|
+ 1681 SemError(233)
|
|
|
+ 1682 ELSE QbeGen.Mangled(qn,
|
|
|
+ 1683 SymTab.ProcUid(qn), mg0);
|
|
|
+ 1684 QbeGen.CallBegin(mg0,
|
|
|
+ 1685 res0,
|
|
|
+ 1686 SymTab.ProcDepthOf(qn),
|
|
|
+ 1687 SymTab.IsExternal(qn));
|
|
|
+ 1688 QbeGen.CallEnd(FALSE, q2)
|
|
|
+ 1689 END
|
|
|
+ 1690 ELSE SemError(233)
|
|
|
+ 1691 END; .) ) .
|
|
|
+ 1692 (* Actual-parameter list shared by statement and expression calls.
|
|
|
+ 1693 want selects CallEnd's result handling; t/q carry the call
|
|
|
+ 1694 value (statement calls discard). Arity/type failures are 233;
|
|
|
+ 1695 evaluation code still emits so the .ssa stays assembleable. *)
|
|
|
+ 1696 ArgList<pn: SymTab.Name; pt: SymTab.TypeIndex; callee: QbeGen.QVal;
|
|
|
+ 1697 want: BOOLEAN; soft: BOOLEAN; methCls: SymTab.TypeIndex;
|
|
|
+ 1698 VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 1699 VAR called: BOOLEAN> (. VAR i, np: CARDINAL;
|
|
|
+ 1700 vs: INTEGER;
|
|
|
+ 1701 res: SymTab.TypeIndex;
|
|
|
+ 1702 mg: QbeGen.QVal;
|
|
|
+ 1703 ok, ind, isMeth, va: BOOLEAN; .)
|
|
|
+ 1704 = "(" (. called := TRUE;
|
|
|
+ 1705 ok := TRUE;
|
|
|
+ 1706 ind := FALSE;
|
|
|
+ 1707 isMeth := methCls #
|
|
|
+ 1708 SymTab.InvalidType;
|
|
|
+ 1709 IF isMeth THEN
|
|
|
+ 1710 (* class method: the
|
|
|
+ 1711 receiver is armed.
|
|
|
+ 1712 Virtual -> dispatch
|
|
|
+ 1713 through the vtable;
|
|
|
+ 1714 otherwise a static
|
|
|
+ 1715 call. *)
|
|
|
+ 1716 res := SymTab.ClassMethodRes(
|
|
|
+ 1717 methCls, pn);
|
|
|
+ 1718 vs := SymTab.VirtSlot(
|
|
|
+ 1719 methCls, pn);
|
|
|
+ 1720 IF vs >= 0 THEN
|
|
|
+ 1721 QbeGen.VirtCallBegin(
|
|
|
+ 1722 callee, vs, res)
|
|
|
+ 1723 ELSE
|
|
|
+ 1724 QbeGen.Mangled(pn,
|
|
|
+ 1725 SymTab.ClassMethodUid(
|
|
|
+ 1726 methCls, pn), mg);
|
|
|
+ 1727 QbeGen.CallBegin(mg, res, 0,
|
|
|
+ 1728 FALSE)
|
|
|
+ 1729 END
|
|
|
+ 1730 ELSIF SymTab.SymKind(pn) =
|
|
|
+ 1731 SymTab.KindProc THEN
|
|
|
+ 1732 res := SymTab.ProcRes(pn);
|
|
|
+ 1733 QbeGen.Mangled(pn,
|
|
|
+ 1734 SymTab.ProcUid(pn), mg);
|
|
|
+ 1735 QbeGen.CallBegin(mg, res,
|
|
|
+ 1736 SymTab.ProcDepthOf(pn),
|
|
|
+ 1737 SymTab.IsExternal(pn))
|
|
|
+ 1738 ELSIF (pt # SymTab.InvalidType)
|
|
|
+ 1739 AND (SymTab.ClassOf(pt) = SymTab.ClProc) THEN
|
|
|
+ 1740 ind := TRUE;
|
|
|
+ 1741 res :=
|
|
|
+ 1742 SymTab.ProcTypeRes(pt);
|
|
|
+ 1743 QbeGen.CallBeginInd(callee,
|
|
|
+ 1744 res, FALSE)
|
|
|
+ 1745 ELSE SemError(233);
|
|
|
+ 1746 ok := FALSE;
|
|
|
+ 1747 res := SymTab.InvalidType
|
|
|
+ 1748 END;
|
|
|
+ 1749 i := 0; .)
|
|
|
+ 1750 [ ActParam<pn, pt, ind, methCls, i> (. INC(i); .)
|
|
|
+ 1751 { "," ActParam<pn, pt, ind, methCls, i> (. INC(i); .) } ]
|
|
|
+ 1752 ")" (. IF ok THEN
|
|
|
+ 1753 IF isMeth THEN
|
|
|
+ 1754 np := SymTab.ClassMethodNPar(
|
|
|
+ 1755 methCls, pn)
|
|
|
+ 1756 ELSIF ind THEN
|
|
|
+ 1757 np := SymTab.ProcTypeNPar(pt)
|
|
|
+ 1758 ELSE np := SymTab.ProcNPar(pn)
|
|
|
+ 1759 END;
|
|
|
+ 1760 va := (NOT isMeth) AND (NOT ind)
|
|
|
+ 1761 AND (SymTab.SymKind(pn) =
|
|
|
+ 1762 SymTab.KindProc)
|
|
|
+ 1763 AND SymTab.Varargs(pn);
|
|
|
+ 1764 IF (i # np) AND NOT va THEN
|
|
|
+ 1765 SemError(233); ok := FALSE
|
|
|
+ 1766 END
|
|
|
+ 1767 END;
|
|
|
+ 1768 IF NOT ok THEN
|
|
|
+ 1769 t := SymTab.InvalidType;
|
|
|
+ 1770 QbeGen.CopyOp("0", q)
|
|
|
+ 1771 ELSIF want THEN
|
|
|
+ 1772 IF res =
|
|
|
+ 1773 SymTab.InvalidType THEN
|
|
|
+ 1774 SemError(233);
|
|
|
+ 1775 t := SymTab.InvalidType;
|
|
|
+ 1776 QbeGen.CopyOp("0", q)
|
|
|
+ 1777 ELSE t := res;
|
|
|
+ 1778 QbeGen.CallEnd(TRUE, q)
|
|
|
+ 1779 END
|
|
|
+ 1780 ELSE
|
|
|
+ 1781 IF res #
|
|
|
+ 1782 SymTab.InvalidType THEN
|
|
|
+ 1783 SemError(233)
|
|
|
+ 1784 END;
|
|
|
+ 1785 t := SymTab.InvalidType;
|
|
|
+ 1786 QbeGen.CopyOp("0", q);
|
|
|
+ 1787 QbeGen.CallEnd(FALSE, q)
|
|
|
+ 1788 END; .) .
|
|
|
+ 1789 (* One actual: VAR formals take recorded designator addresses
|
|
|
+ 1790 (233 otherwise); value formals take converted expressions. *)
|
|
|
+ 1791 ActParam<pn: SymTab.Name; pt: SymTab.TypeIndex; ind: BOOLEAN;
|
|
|
+ 1792 methCls: SymTab.TypeIndex; i: CARDINAL>
|
|
|
+ 1793 (. VAR at, ft: SymTab.TypeIndex;
|
|
|
+ 1794 qe, qa, qt: QbeGen.QVal;
|
|
|
+ 1795 isV, conv, va: BOOLEAN;
|
|
|
+ 1796 cl: CHAR;
|
|
|
+ 1797 savedN, aj: CARDINAL;
|
|
|
+ 1798 savedArgs: ARRAY [0 .. 31]
|
|
|
+ 1799 OF AST.Node; .)
|
|
|
+ 1800 = (. (* Parsing the actual can clobber
|
|
|
+ 1801 the enclosing call's argument
|
|
|
+ 1802 list (Factor resets astNArgs),
|
|
|
+ 1803 so save/restore it. *)
|
|
|
+ 1804 savedN := astNArgs; aj := 0;
|
|
|
+ 1805 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 1806 savedArgs[aj] := astArgs[aj];
|
|
|
+ 1807 INC(aj)
|
|
|
+ 1808 END; .)
|
|
|
+ 1809 Expr<at, qe> (. astNArgs := savedN; aj := 0;
|
|
|
+ 1810 WHILE aj <= HIGH(astArgs) DO
|
|
|
+ 1811 astArgs[aj] := savedArgs[aj];
|
|
|
+ 1812 INC(aj)
|
|
|
+ 1813 END;
|
|
|
+ 1814 IF astNArgs <= HIGH(astArgs) THEN
|
|
|
+ 1815 astArgs[astNArgs] := astCur;
|
|
|
+ 1816 INC(astNArgs)
|
|
|
+ 1817 END;
|
|
|
+ 1818 va := (NOT ind)
|
|
|
+ 1819 AND (methCls =
|
|
|
+ 1820 SymTab.InvalidType)
|
|
|
+ 1821 AND (SymTab.SymKind(pn) =
|
|
|
+ 1822 SymTab.KindProc)
|
|
|
+ 1823 AND SymTab.Varargs(pn);
|
|
|
+ 1824 IF ind THEN
|
|
|
+ 1825 ft :=
|
|
|
+ 1826 SymTab.ProcTypeParamType(pt,
|
|
|
+ 1827 i);
|
|
|
+ 1828 isV :=
|
|
|
+ 1829 SymTab.ProcTypeParamIsVar(pt,
|
|
|
+ 1830 i)
|
|
|
+ 1831 ELSIF methCls #
|
|
|
+ 1832 SymTab.InvalidType THEN
|
|
|
+ 1833 ft :=
|
|
|
+ 1834 SymTab.ClassMethodParamType(
|
|
|
+ 1835 methCls, pn, i);
|
|
|
+ 1836 isV :=
|
|
|
+ 1837 SymTab.ClassMethodParamIsVar(
|
|
|
+ 1838 methCls, pn, i)
|
|
|
+ 1839 ELSE
|
|
|
+ 1840 ft := SymTab.ParamType(pn, i);
|
|
|
+ 1841 isV := SymTab.ParamIsVar(pn, i)
|
|
|
+ 1842 END;
|
|
|
+ 1843 IF (at = SymTab.InvalidType) THEN
|
|
|
+ 1844 ELSIF ft = SymTab.InvalidType THEN
|
|
|
+ 1845 IF va THEN
|
|
|
+ 1846 QbeGen.CArgAdd(qe, at, qa, cl)
|
|
|
+ 1847 END
|
|
|
+ 1848 ELSIF isV THEN
|
|
|
+ 1849 IF (SymTab.ClassOf(at)
|
|
|
+ 1850 = SymTab.ClChar)
|
|
|
+ 1851 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1852 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
+ 1853 = SymTab.ClChar)
|
|
|
+ 1854 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1855 (* 1-char string
|
|
|
+ 1856 literal passed to
|
|
|
+ 1857 a VAR ARRAY OF CHAR *)
|
|
|
+ 1858 QbeGen.DeclCharStr(qe,
|
|
|
+ 1859 qa);
|
|
|
+ 1860 IF NOT QbeGen.CallArg(qa,
|
|
|
+ 1861 "l") THEN
|
|
|
+ 1862 SemError(233)
|
|
|
+ 1863 END
|
|
|
+ 1864 ELSIF NOT QbeGen.AddrOfVal(qe,
|
|
|
+ 1865 qa) THEN
|
|
|
+ 1866 SemError(233)
|
|
|
+ 1867 ELSIF NOT SymTab.VarParamOk(at,
|
|
|
+ 1868 ft) THEN
|
|
|
+ 1869 SemError(233)
|
|
|
+ 1870 ELSIF NOT QbeGen.CallArg(qa,
|
|
|
+ 1871 "l") THEN
|
|
|
+ 1872 SemError(233)
|
|
|
+ 1873 END
|
|
|
+ 1874 ELSE
|
|
|
+ 1875 IF (SymTab.ClassOf(at)
|
|
|
+ 1876 = SymTab.ClChar)
|
|
|
+ 1877 AND (SymTab.ClassOf(ft) = SymTab.ClArray)
|
|
|
+ 1878 AND (SymTab.ClassOf(SymTab.ArrayElem(ft))
|
|
|
+ 1879 = SymTab.ClChar)
|
|
|
+ 1880 AND QbeGen.IsImm(qe) THEN
|
|
|
+ 1881 (* 1-char string
|
|
|
+ 1882 literal passed to
|
|
|
+ 1883 ARRAY OF CHAR *)
|
|
|
+ 1884 QbeGen.DeclCharStr(qe,
|
|
|
+ 1885 qa);
|
|
|
+ 1886 IF NOT QbeGen.CallArg(qa,
|
|
|
+ 1887 "l") THEN
|
|
|
+ 1888 SemError(233)
|
|
|
+ 1889 END
|
|
|
+ 1890 ELSIF NOT SymTab.Assignable(at,
|
|
|
+ 1891 ft) THEN
|
|
|
+ 1892 SemError(233)
|
|
|
+ 1893 ELSE
|
|
|
+ 1894 conv := (SymTab.ClassOf(
|
|
|
+ 1895 ft) = SymTab.ClReal)
|
|
|
+ 1896 AND SymTab.IsIntFamily(at);
|
|
|
+ 1897 IF conv THEN
|
|
|
+ 1898 QbeGen.ConvIR(qe, qt);
|
|
|
+ 1899 IF NOT QbeGen.CallArg(qt,
|
|
|
+ 1900 "d") THEN
|
|
|
+ 1901 SemError(233)
|
|
|
+ 1902 END
|
|
|
+ 1903 ELSIF NOT QbeGen.CallArg(qe,
|
|
|
+ 1904 QbeGen.ArgClass(ft)) THEN
|
|
|
+ 1905 SemError(233)
|
|
|
+ 1906 END
|
|
|
+ 1907 END
|
|
|
+ 1908 END; .) .
|
|
|
+ 1909 IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1910 q, lThen, lElse, lEnd:
|
|
|
+ 1911 QbeGen.QVal;
|
|
|
+ 1912 hasElse: BOOLEAN;
|
|
|
+ 1913 astCond, astIf, astLast,
|
|
|
+ 1914 astNode: AST.Node; .)
|
|
|
+ 1915 = "IF" (. hasElse := FALSE; .)
|
|
|
+ 1916 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 1917 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1918 SemError(214) END;
|
|
|
+ 1919 QbeGen.NewLabel(lThen);
|
|
|
+ 1920 QbeGen.NewLabel(lElse);
|
|
|
+ 1921 QbeGen.NewLabel(lEnd);
|
|
|
+ 1922 QbeGen.Jnz(q, lThen, lElse);
|
|
|
+ 1923 QbeGen.EmitLabel(lThen); .)
|
|
|
+ 1924 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 1925 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1926 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1927 astIf := astNode;
|
|
|
+ 1928 astLast := astNode;
|
|
|
+ 1929 QbeGen.Jmp(lEnd); .)
|
|
|
+ 1930 { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
+ 1931 QbeGen.NewLabel(lElse); .)
|
|
|
+ 1932 Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
+ 1933 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1934 SemError(214) END;
|
|
|
+ 1935 QbeGen.NewLabel(lThen);
|
|
|
+ 1936 QbeGen.Jnz(q, lThen, lElse);
|
|
|
+ 1937 QbeGen.EmitLabel(lThen); .)
|
|
|
+ 1938 "THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
+ 1939 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1940 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1941 AST.SetChild(astLast, 2, astNode);
|
|
|
+ 1942 astLast := astNode;
|
|
|
+ 1943 QbeGen.Jmp(lEnd); .) }
|
|
|
+ 1944 [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
+ 1945 hasElse := TRUE;
|
|
|
+ 1946 astStmt := AST.NoNode; .)
|
|
|
+ 1947 [ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
+ 1948 "END" (. astStmt := astIf;
|
|
|
+ 1949 IF hasElse THEN
|
|
|
+ 1950 QbeGen.EmitLabel(lEnd)
|
|
|
+ 1951 ELSE QbeGen.EmitLabel(lElse);
|
|
|
+ 1952 QbeGen.EmitLabel(lEnd)
|
|
|
+ 1953 END; .) .
|
|
|
+ 1954 WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1955 q, lTop, lBody, lEnd:
|
|
|
+ 1956 QbeGen.QVal;
|
|
|
+ 1957 astCond, astNode: AST.Node; .)
|
|
|
+ 1958 = "WHILE" (. astStmt := AST.NoNode;
|
|
|
+ 1959 QbeGen.NewLabel(lTop);
|
|
|
+ 1960 QbeGen.NewLabel(lBody);
|
|
|
+ 1961 QbeGen.NewLabel(lEnd);
|
|
|
+ 1962 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 1963 Expr<t, q> (. astCond := astCur;
|
|
|
+ 1964 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1965 SemError(214) END;
|
|
|
+ 1966 QbeGen.Jnz(q, lBody, lEnd);
|
|
|
+ 1967 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 1968 "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ 1969 AST.SetChild(astNode, 0, astCond);
|
|
|
+ 1970 AST.SetChild(astNode, 1, astStmt);
|
|
|
+ 1971 astStmt := astNode;
|
|
|
+ 1972 QbeGen.Jmp(lTop); .)
|
|
|
+ 1973 "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1974 RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 1975 q, lTop, lEnd: QbeGen.QVal;
|
|
|
+ 1976 astCond, astBody, astNode:
|
|
|
+ 1977 AST.Node; .)
|
|
|
+ 1978 = "REPEAT" (. astStmt := AST.NoNode;
|
|
|
+ 1979 QbeGen.NewLabel(lTop);
|
|
|
+ 1980 QbeGen.NewLabel(lEnd);
|
|
|
+ 1981 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 1982 [ StatSeq ] (. astBody := astStmt; .)
|
|
|
+ 1983 "UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
+ 1984 astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
+ 1985 AST.SetChild(astNode, 0, astBody);
|
|
|
+ 1986 AST.SetChild(astNode, 1, astCond);
|
|
|
+ 1987 astStmt := astNode;
|
|
|
+ 1988 IF NOT SymTab.BoolCheck(t) THEN
|
|
|
+ 1989 SemError(214) END;
|
|
|
+ 1990 QbeGen.Jnz(q, lEnd, lTop);
|
|
|
+ 1991 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 1992 LoopStat (. VAR lTop, lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ 1993 = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
+ 1994 astStmt := AST.NoNode;
|
|
|
+ 1995 QbeGen.NewLabel(lEnd);
|
|
|
+ 1996 QbeGen.PushLoop(lEnd);
|
|
|
+ 1997 QbeGen.EmitLabel(lTop); .)
|
|
|
+ 1998 [ StatSeq ]
|
|
|
+ 1999 "END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
+ 2000 AST.SetChild(astNode, 0, astStmt);
|
|
|
+ 2001 astStmt := astNode;
|
|
|
+ 2002 QbeGen.Jmp(lTop);
|
|
|
+ 2003 QbeGen.PopLoop;
|
|
|
+ 2004 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 2005 (* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
+ 2006 Runtime direction would need a compare-select; the literal
|
|
|
+ 2007 sign picks cslew/csegew at "DO" time. *)
|
|
|
+ 2008 ForStat (. VAR lv: SymTab.Name;
|
|
|
+ 2009 tlo, thi, tby:
|
|
|
+ 2010 SymTab.TypeIndex;
|
|
|
+ 2011 qlo, qhi, qby, qt, qk, qb:
|
|
|
+ 2012 QbeGen.QVal;
|
|
|
+ 2013 lTop, lBody, lEnd:
|
|
|
+ 2014 QbeGen.QVal;
|
|
|
+ 2015 by: INTEGER;
|
|
|
+ 2016 ok: BOOLEAN;
|
|
|
+ 2017 astVar, astLo, astHi, astBy,
|
|
|
+ 2018 astNode: AST.Node; .)
|
|
|
+ 2019 = "FOR" (. by := 1; .)
|
|
|
+ 2020 GetIdent<lv> (. astVar := AST.MakeLeaf(AST.NkIdent, lv);
|
|
|
+ 2021 astStmt := AST.NoNode;
|
|
|
+ 2022 astBy := AST.NoNode;
|
|
|
+ 2023 ok := SymTab.Lookup(lv);
|
|
|
+ 2024 IF NOT ok THEN
|
|
|
+ 2025 SemError(201)
|
|
|
+ 2026 ELSIF (SymTab.SymKind(lv) #
|
|
|
+ 2027 SymTab.KindVar)
|
|
|
+ 2028 AND (SymTab.SymKind(lv) #
|
|
|
+ 2029 SymTab.KindParam) THEN
|
|
|
+ 2030 SemError(220); ok := FALSE
|
|
|
+ 2031 ELSIF NOT SymTab.IsIntFamily(
|
|
|
+ 2032 SymTab.SymType(lv)) THEN
|
|
|
+ 2033 SemError(220); ok := FALSE
|
|
|
+ 2034 END; .)
|
|
|
+ 2035 ":=" Expr<tlo, qlo> (. astLo := astCur;
|
|
|
+ 2036 IF NOT SymTab.IsIntFamily(tlo) THEN
|
|
|
+ 2037 SemError(220); ok := FALSE
|
|
|
+ 2038 END; .)
|
|
|
+ 2039 "TO" Expr<thi, qhi> (. astHi := astCur;
|
|
|
+ 2040 IF NOT SymTab.IsIntFamily(thi) THEN
|
|
|
+ 2041 SemError(220); ok := FALSE
|
|
|
+ 2042 END; .)
|
|
|
+ 2043 [ "BY" Expr<tby, qby> (. astBy := astCur;
|
|
|
+ 2044 IF (tby #
|
|
|
+ 2045 SymTab.InvalidType)
|
|
|
+ 2046 AND NOT SymTab.IsIntFamily(tby) THEN
|
|
|
+ 2047 SemError(220); ok := FALSE
|
|
|
+ 2048 END;
|
|
|
+ 2049 IF NOT SymTab.ConstInt(qby, by) THEN
|
|
|
+ 2050 SemError(230); by := 1
|
|
|
+ 2051 ELSIF by = 0 THEN
|
|
|
+ 2052 SemError(220); by := 1
|
|
|
+ 2053 END; .) ]
|
|
|
+ 2054 "DO" (. IF ok THEN
|
|
|
+ 2055 QbeGen.StoreVar(lv, qlo,
|
|
|
+ 2056 FALSE) END;
|
|
|
+ 2057 QbeGen.NewLabel(lTop);
|
|
|
+ 2058 QbeGen.NewLabel(lBody);
|
|
|
+ 2059 QbeGen.NewLabel(lEnd);
|
|
|
+ 2060 QbeGen.EmitLabel(lTop);
|
|
|
+ 2061 QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
+ 2062 QbeGen.NewTemp(qk);
|
|
|
+ 2063 IF by > 0 THEN
|
|
|
+ 2064 QbeGen.Op3("cslew", qk,
|
|
|
+ 2065 qt, qhi, FALSE)
|
|
|
+ 2066 ELSE QbeGen.Op3("csgew", qk,
|
|
|
+ 2067 qt, qhi, FALSE)
|
|
|
+ 2068 END;
|
|
|
+ 2069 QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
+ 2070 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 2071 [ StatSeq ]
|
|
|
+ 2072 "END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
+ 2073 AST.SetChild(astNode, 0, astVar);
|
|
|
+ 2074 AST.SetChild(astNode, 1, astLo);
|
|
|
+ 2075 AST.SetChild(astNode, 2, astHi);
|
|
|
+ 2076 AST.SetChild(astNode, 3, astBy);
|
|
|
+ 2077 AST.SetChild(astNode, 4, astStmt);
|
|
|
+ 2078 astStmt := astNode;
|
|
|
+ 2079 IF ok THEN
|
|
|
+ 2080 QbeGen.LoadVar(lv, FALSE,
|
|
|
+ 2081 qt);
|
|
|
+ 2082 QbeGen.IntStr(by, qb);
|
|
|
+ 2083 QbeGen.NewTemp(qk);
|
|
|
+ 2084 QbeGen.Op3("add", qk,
|
|
|
+ 2085 qt, qb, FALSE);
|
|
|
+ 2086 QbeGen.StoreVar(lv, qk,
|
|
|
+ 2087 FALSE) END;
|
|
|
+ 2088 QbeGen.Jmp(lTop);
|
|
|
+ 2089 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 2090 CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
+ 2091 qsel, lEnd: QbeGen.QVal;
|
|
|
+ 2092 arm, astNode, astArms,
|
|
|
+ 2093 astArmsTail: AST.Node; .)
|
|
|
+ 2094 = "CASE" Expr<tsel, qsel> (. astNode := AST.MakeNode(AST.NkCase);
|
|
|
+ 2095 AST.SetChild(astNode, 0, astCur);
|
|
|
+ 2096 astArms := AST.NoNode;
|
|
|
+ 2097 astArmsTail := AST.NoNode;
|
|
|
+ 2098 QbeGen.NewLabel(lEnd); .)
|
|
|
+ 2099 "OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
+ 2100 { "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
+ 2101 [ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
+ 2102 [ StatSeq ] (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 2103 AST.SetOp(arm, 1);
|
|
|
+ 2104 AST.SetChild(arm, 0, astStmt);
|
|
|
+ 2105 AstAppend(AST.NkBlock,
|
|
|
+ 2106 astArms, astArmsTail, arm); .) ]
|
|
|
+ 2107 "END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
+ 2108 astStmt := astNode;
|
|
|
+ 2109 QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ 2110 (* Compare-chain lowering: each alternative ends its match-tests
|
|
|
+ 2111 with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
+ 2112 "cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
+ 2113 lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
+ 2114 CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2115 lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
+ 2116 (. VAR lBody, lAfter: QbeGen.QVal;
|
|
|
+ 2117 arm: AST.Node; .)
|
|
|
+ 2118 = (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
+ 2119 QbeGen.NewLabel(lBody);
|
|
|
+ 2120 QbeGen.NewLabel(lAfter); .)
|
|
|
+ 2121 CaseLabel<tsel, qsel, lBody, arm>
|
|
|
+ 2122 { "," CaseLabel<tsel, qsel, lBody, arm> }
|
|
|
+ 2123 ":" (. astStmt := AST.NoNode;
|
|
|
+ 2124 QbeGen.Jmp(lAfter);
|
|
|
+ 2125 QbeGen.EmitLabel(lBody); .)
|
|
|
+ 2126 [ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
+ 2127 astStmt);
|
|
|
+ 2128 AstAppend(AST.NkBlock,
|
|
|
+ 2129 arms, armsTail, arm);
|
|
|
+ 2130 QbeGen.Jmp(lEnd);
|
|
|
+ 2131 QbeGen.EmitLabel(lAfter); .) .
|
|
|
+ 2132 CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
+ 2133 lBody: QbeGen.QVal; arm: AST.Node>
|
|
|
+ 2134 (. VAR t2, t3: SymTab.TypeIndex;
|
|
|
+ 2135 q2, q3, qc, qd, qe:
|
|
|
+ 2136 QbeGen.QVal;
|
|
|
+ 2137 astLab: AST.Node;
|
|
|
+ 2138 lNext: QbeGen.QVal; .)
|
|
|
+ 2139 = Expr<t2, q2> (. astLab := astCur;
|
|
|
+ 2140 IF (t2 #
|
|
|
+ 2141 SymTab.InvalidType)
|
|
|
+ 2142 AND (tsel #
|
|
|
+ 2143 SymTab.InvalidType)
|
|
|
+ 2144 AND ((SymTab.ClassOf(t2) =
|
|
|
+ 2145 SymTab.ClSet)
|
|
|
+ 2146 OR (SymTab.ClassOf(tsel) =
|
|
|
+ 2147 SymTab.ClSet)) THEN
|
|
|
+ 2148 SemError(230)
|
|
|
+ 2149 ELSIF (t2 #
|
|
|
+ 2150 SymTab.InvalidType)
|
|
|
+ 2151 AND (tsel #
|
|
|
+ 2152 SymTab.InvalidType)
|
|
|
+ 2153 AND NOT SymTab.EqCheck(t2,
|
|
|
+ 2154 tsel) THEN
|
|
|
+ 2155 SemError(213) END;
|
|
|
+ 2156 IF NOT QbeGen.IsImm(q2) THEN
|
|
|
+ 2157 SemError(230);
|
|
|
+ 2158 QbeGen.CopyOp("0", q2)
|
|
|
+ 2159 END;
|
|
|
+ 2160 QbeGen.NewLabel(lNext);
|
|
|
+ 2161 QbeGen.Cmp(SymTab.OpEq,
|
|
|
+ 2162 qsel, q2, qc, FALSE);
|
|
|
+ 2163 QbeGen.Jnz(qc, lBody, lNext);
|
|
|
+ 2164 QbeGen.EmitLabel(lNext); .)
|
|
|
+ 2165 [ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
+ 2166 AST.NkSubrange, 0, astLab, astCur);
|
|
|
+ 2167 IF (t3 #
|
|
|
+ 2168 SymTab.InvalidType)
|
|
|
+ 2169 AND (tsel #
|
|
|
+ 2170 SymTab.InvalidType)
|
|
|
+ 2171 AND NOT SymTab.EqCheck(t3,
|
|
|
+ 2172 tsel) THEN
|
|
|
+ 2173 SemError(213) END;
|
|
|
+ 2174 IF NOT QbeGen.IsImm(q3) THEN
|
|
|
+ 2175 SemError(230);
|
|
|
+ 2176 QbeGen.CopyOp("0", q3)
|
|
|
+ 2177 END;
|
|
|
+ 2178 QbeGen.Cmp(SymTab.OpGe,
|
|
|
+ 2179 qsel, q2, qc, FALSE);
|
|
|
+ 2180 QbeGen.Cmp(SymTab.OpLe,
|
|
|
+ 2181 qsel, q3, qd, FALSE);
|
|
|
+ 2182 QbeGen.NewTemp(qe);
|
|
|
+ 2183 QbeGen.Op3("and", qe, qc, qd,
|
|
|
+ 2184 FALSE);
|
|
|
+ 2185 QbeGen.NewLabel(lNext);
|
|
|
+ 2186 QbeGen.Jnz(qe, lBody, lNext);
|
|
|
+ 2187 QbeGen.EmitLabel(lNext); .) ]
|
|
|
+ 2188 (. AST.SetChild(arm,
|
|
|
+ 2189 AST.NChild(arm), astLab); .) .
|
|
|
+ 2190 ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2191 q, qt: QbeGen.QVal;
|
|
|
+ 2192 res: SymTab.TypeIndex;
|
|
|
+ 2193 hadE, conv: BOOLEAN;
|
|
|
+ 2194 astVal, astNode: AST.Node; .)
|
|
|
+ 2195 = "RETURN" (. hadE := FALSE; astStmt := AST.NoNode; .)
|
|
|
+ 2196 [ Expr<t, q> (. hadE := TRUE; astVal := astCur; .) ]
|
|
|
+ 2197 (. astNode := AST.MakeNode(AST.NkReturn);
|
|
|
+ 2198 IF hadE THEN
|
|
|
+ 2199 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2200 END;
|
|
|
+ 2201 astStmt := astNode;
|
|
|
+ 2202 conv := FALSE;
|
|
|
+ 2203 IF NOT SymTab.InProc() THEN
|
|
|
+ 2204 SemError(232)
|
|
|
+ 2205 ELSE res := SymTab.CurRes();
|
|
|
+ 2206 IF NOT hadE THEN
|
|
|
+ 2207 IF res #
|
|
|
+ 2208 SymTab.InvalidType THEN
|
|
|
+ 2209 SemError(232)
|
|
|
+ 2210 ELSE QbeGen.EmitRet(q,
|
|
|
+ 2211 FALSE)
|
|
|
+ 2212 END
|
|
|
+ 2213 ELSIF (res =
|
|
|
+ 2214 SymTab.InvalidType)
|
|
|
+ 2215 OR (t #
|
|
|
+ 2216 SymTab.InvalidType)
|
|
|
+ 2217 AND NOT SymTab.Assignable(t,
|
|
|
+ 2218 res) THEN
|
|
|
+ 2219 SemError(232)
|
|
|
+ 2220 ELSE
|
|
|
+ 2221 conv := (SymTab.ClassOf(
|
|
|
+ 2222 res) = SymTab.ClReal)
|
|
|
+ 2223 AND SymTab.IsIntFamily(t);
|
|
|
+ 2224 IF conv THEN
|
|
|
+ 2225 QbeGen.ConvIR(q, qt);
|
|
|
+ 2226 QbeGen.EmitRet(qt, TRUE)
|
|
|
+ 2227 ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
+ 2228 END
|
|
|
+ 2229 END
|
|
|
+ 2230 END; .) .
|
|
|
+ 2231 HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
+ 2232 q: QbeGen.QVal;
|
|
|
+ 2233 astVal, astNode: AST.Node; .)
|
|
|
+ 2234 = "HALT" (. astVal := AST.NoNode; .)
|
|
|
+ 2235 [ "(" Expr<t, q> (. astVal := astCur; .) ")" ]
|
|
|
+ 2236 (. astNode := AST.MakeNode(AST.NkHalt);
|
|
|
+ 2237 IF astVal # AST.NoNode THEN
|
|
|
+ 2238 AST.SetChild(astNode, 0, astVal)
|
|
|
+ 2239 END;
|
|
|
+ 2240 astStmt := astNode;
|
|
|
+ 2241 QbeGen.HaltQ; .) .
|
|
|
+ 2242 (* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
+ 2243 Each index descends one level (bounds-checked, trap on breach);
|
|
|
+ 2244 nested levels reload the inner descriptor address. q ends as the
|
|
|
+ 2245 value (scalars), the descriptor address (plain arrays), or the
|
|
|
+ 2246 element address (indexed); sfx marks the indexed form. *)
|
|
|
+ 2247 Design<VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
+ 2248 VAR q: QbeGen.QVal; VAR qn: SymTab.Name; VAR sfx: BOOLEAN>
|
|
|
+ 2249 (. VAR n, fn, mal: SymTab.Name;
|
|
|
+ 2250 cls: INTEGER;
|
|
|
+ 2251 ic: SymTab.TypeIndex;
|
|
|
+ 2252 curT, it, eT, bt:
|
|
|
+ 2253 SymTab.TypeIndex;
|
|
|
+ 2254 iq, ql, qlo, qhi, qe:
|
|
|
+ 2255 QbeGen.QVal;
|
|
|
+ 2256 lo, hi: INTEGER;
|
|
|
+ 2257 fo: INTEGER;
|
|
|
+ 2258 isOpen: BOOLEAN;
|
|
|
+ 2259 qb, cv: QbeGen.QVal;
|
|
|
+ 2260 fid, fref, slot: INTEGER;
|
|
|
+ 2261 r: BOOLEAN;
|
|
|
+ 2262 astDes, astSel: AST.Node; .)
|
|
|
+ 2263 = GetIdent<n> (. methCls := SymTab.InvalidType;
|
|
|
+ 2264 QbeGen.CopyOp(n, qn);
|
|
|
+ 2265 sfx := FALSE;
|
|
|
+ 2266 fid := 0; fref := 0; slot := 0;
|
|
|
+ 2267 IF NOT SymTab.Lookup(n) THEN
|
|
|
+ 2268 (* a bare method name inside
|
|
|
+ 2269 a CLASS IMPLEMENTATION
|
|
|
+ 2270 is a sibling call on
|
|
|
+ 2271 THIS *)
|
|
|
+ 2272 ic := SymTab.CurImplClass();
|
|
|
+ 2273 IF (ic #
|
|
|
+ 2274 SymTab.InvalidType)
|
|
|
+ 2275 AND SymTab.MethodExists(ic, n) THEN
|
|
|
+ 2276 sfx := FALSE;
|
|
|
+ 2277 QbeGen.ThisBase(q);
|
|
|
+ 2278 QbeGen.ArmRecv(q);
|
|
|
+ 2279 methCls := ic;
|
|
|
+ 2280 k := SymTab.KindProc;
|
|
|
+ 2281 t := SymTab.InvalidType
|
|
|
+ 2282 ELSIF SymTab.InProc() THEN
|
|
|
+ 2283 (* not declared yet: a
|
|
|
+ 2284 forward reference to a
|
|
|
+ 2285 module-level variable
|
|
|
+ 2286 declared further down. *)
|
|
|
+ 2287 k := SymTab.KindVar;
|
|
|
+ 2288 r := SymTab.FwdVarRef(n, k,
|
|
|
+ 2289 fref, t);
|
|
|
+ 2290 slot := QbeGen.FwdDesignator();
|
|
|
+ 2291 FwdVarNote(fref, slot);
|
|
|
+ 2292 fid := slot;
|
|
|
+ 2293 QbeGen.FwdAddrOper(fid, q);
|
|
|
+ 2294 sfx := TRUE
|
|
|
+ 2295 ELSE
|
|
|
+ 2296 SemError(201);
|
|
|
+ 2297 t :=
|
|
|
+ 2298 SymTab.InvalidType;
|
|
|
+ 2299 k := -1;
|
|
|
+ 2300 QbeGen.CopyOp("0", q)
|
|
|
+ 2301 END
|
|
|
+ 2302 ELSE
|
|
|
+ 2303 t := SymTab.SymType(n);
|
|
|
+ 2304 k := SymTab.SymKind(n);
|
|
|
+ 2305 IF k = SymTab.KindConst THEN
|
|
|
+ 2306 IF SymTab.Equal(n,
|
|
|
+ 2307 "TRUE") THEN
|
|
|
+ 2308 t := SymTab.BoolType();
|
|
|
+ 2309 QbeGen.CopyOp("1", q)
|
|
|
+ 2310 ELSIF SymTab.Equal(n,
|
|
|
+ 2311 "FALSE") THEN
|
|
|
+ 2312 t := SymTab.BoolType();
|
|
|
+ 2313 QbeGen.CopyOp("0", q)
|
|
|
+ 2314 ELSIF SymTab.Equal(n,
|
|
|
+ 2315 "NIL") THEN
|
|
|
+ 2316 QbeGen.CopyOp("0", q)
|
|
|
+ 2317 ELSE
|
|
|
+ 2318 cls :=
|
|
|
+ 2319 SymTab.ClassOf(t);
|
|
|
+ 2320 IF (t #
|
|
|
+ 2321 SymTab.InvalidType)
|
|
|
+ 2322 AND ((cls = SymTab.ClInt)
|
|
|
+ 2323 OR (cls
|
|
|
+ 2324 = SymTab.ClChar)
|
|
|
+ 2325 OR (cls
|
|
|
+ 2326 = SymTab.ClEnum)
|
|
|
+ 2327 OR (cls
|
|
|
+ 2328 = SymTab.ClReal)
|
|
|
+ 2329 OR (cls
|
|
|
+ 2330 = SymTab.ClLong)
|
|
|
+ 2331 OR (cls
|
|
|
+ 2332 = SymTab.ClNil)) THEN
|
|
|
+ 2333 IF cls = SymTab.ClNil THEN
|
|
|
+ 2334 QbeGen.CopyOp("0", q)
|
|
|
+ 2335 ELSIF ((cls
|
|
|
+ 2336 = SymTab.ClInt)
|
|
|
+ 2337 OR (cls
|
|
|
+ 2338 = SymTab.ClChar)
|
|
|
+ 2339 OR (cls
|
|
|
+ 2340 = SymTab.ClEnum)
|
|
|
+ 2341 OR (cls
|
|
|
+ 2342 = SymTab.ClLong))
|
|
|
+ 2343 AND SymTab.GetSymVal(n, cv)
|
|
|
+ 2344 AND QbeGen.IsImm(cv) THEN
|
|
|
+ 2345 QbeGen.CopyOp(cv, q)
|
|
|
+ 2346 ELSE
|
|
|
+ 2347 QbeGen.LoadVar(n,
|
|
|
+ 2348 cls = SymTab.ClReal,
|
|
|
+ 2349 q)
|
|
|
+ 2350 END
|
|
|
+ 2351 ELSIF (cls = SymTab.ClArray)
|
|
|
+ 2352 OR (cls = SymTab.ClRecord)
|
|
|
+ 2353 OR (cls = SymTab.ClClass)
|
|
|
+ 2354 OR (cls = SymTab.ClStr)
|
|
|
+ 2355 OR (cls = SymTab.ClUStr) THEN
|
|
|
+ 2356 (* aggregate constant:
|
|
|
+ 2357 its value IS the
|
|
|
+ 2358 descriptor address *)
|
|
|
+ 2359 IF SymTab.GetSymVal(n, cv) THEN
|
|
|
+ 2360 QbeGen.CopyOp(cv, q)
|
|
|
+ 2361 ELSE
|
|
|
+ 2362 QbeGen.CopyOp("0", q)
|
|
|
+ 2363 END
|
|
|
+ 2364 ELSE
|
|
|
+ 2365 IF t #
|
|
|
+ 2366 SymTab.InvalidType THEN
|
|
|
+ 2367 SemError(230)
|
|
|
+ 2368 END;
|
|
|
+ 2369 QbeGen.CopyOp("0", q)
|
|
|
+ 2370 END
|
|
|
+ 2371 END
|
|
|
+ 2372 ELSIF (k = SymTab.KindVar)
|
|
|
+ 2373 OR (k = SymTab.KindParam) THEN
|
|
|
+ 2374 cls :=
|
|
|
+ 2375 SymTab.ClassOf(t);
|
|
|
+ 2376 IF (cls = SymTab.ClInt)
|
|
|
+ 2377 OR (cls = SymTab.ClBool)
|
|
|
+ 2378 OR (cls = SymTab.ClChar)
|
|
|
+ 2379 OR (cls = SymTab.ClUChar)
|
|
|
+ 2380 OR (cls = SymTab.ClEnum)
|
|
|
+ 2381 OR (cls
|
|
|
+ 2382 = SymTab.ClReal) THEN
|
|
|
+ 2383 QbeGen.LoadVar(n,
|
|
|
+ 2384 cls = SymTab.ClReal, q)
|
|
|
+ 2385 ELSIF (cls = SymTab.ClPtr)
|
|
|
+ 2386 OR (cls = SymTab.ClProc) THEN
|
|
|
+ 2387 QbeGen.LoadPtr(n, q)
|
|
|
+ 2388 ELSIF cls = SymTab.ClLong THEN
|
|
|
+ 2389 QbeGen.LoadLong(n, q)
|
|
|
+ 2390 ELSIF (cls
|
|
|
+ 2391 = SymTab.ClArray)
|
|
|
+ 2392 OR (cls
|
|
|
+ 2393 = SymTab.ClSet)
|
|
|
+ 2394 OR (cls
|
|
|
+ 2395 = SymTab.ClRecord)
|
|
|
+ 2396 OR (cls
|
|
|
+ 2397 = SymTab.ClUStr)
|
|
|
+ 2398 OR (cls
|
|
|
+ 2399 = SymTab.ClClass) THEN
|
|
|
+ 2400 QbeGen.AddrOf(n, q)
|
|
|
+ 2401 ELSE SemError(230);
|
|
|
+ 2402 QbeGen.CopyOp("0", q)
|
|
|
+ 2403 END
|
|
|
+ 2404 ELSE QbeGen.CopyOp("0", q);
|
|
|
+ 2405 IF k = SymTab.KindImport THEN
|
|
|
+ 2406 SemError(230)
|
|
|
+ 2407 ELSIF k =
|
|
|
+ 2408 SymTab.KindProc THEN
|
|
|
+ 2409 (* bare procedure name:
|
|
|
+ 2410 a following ArgList
|
|
|
+ 2411 makes it a call;
|
|
|
+ 2412 otherwise Fact
|
|
|
+ 2413 reports 230 *)
|
|
|
+ 2414 ELSE
|
|
|
+ 2415 IF k = SymTab.KindField THEN
|
|
|
+ 2416 IF QbeGen.TopWith(qb) THEN
|
|
|
+ 2417 fo :=
|
|
|
+ 2418 SymTab.FieldOffset(
|
|
|
+ 2419 SymTab.FieldOwner(n),
|
|
|
+ 2420 n);
|
|
|
+ 2421 QbeGen.FieldAddr(qb,
|
|
|
+ 2422 fo, q);
|
|
|
+ 2423 sfx := TRUE
|
|
|
+ 2424 ELSE SemError(230);
|
|
|
+ 2425 QbeGen.CopyOp("0", q)
|
|
|
+ 2426 END
|
|
|
+ 2427 END
|
|
|
+ 2428 END
|
|
|
+ 2429 END
|
|
|
+ 2430 END; .)
|
|
|
+ 2431 (. astDes := AST.MakeNode(AST.NkDesignator);
|
|
|
+ 2432 AST.SetChild(astDes, AST.NChild(astDes), AST.MakeLeaf(AST.NkIdent, n)); .)
|
|
|
+ 2433 { "[" Expr<it, iq>
|
|
|
+ 2434 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2435 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2436 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2437 SymTab.ClArray THEN
|
|
|
+ 2438 SemError(217);
|
|
|
+ 2439 t := SymTab.InvalidType
|
|
|
+ 2440 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2441 AND (SymTab.ClassOf(it) #
|
|
|
+ 2442 SymTab.ClChar)
|
|
|
+ 2443 AND (SymTab.ClassOf(it) #
|
|
|
+ 2444 SymTab.ClEnum) THEN
|
|
|
+ 2445 SemError(218);
|
|
|
+ 2446 t := SymTab.InvalidType
|
|
|
+ 2447 ELSE
|
|
|
+ 2448 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 2449 isOpen :=
|
|
|
+ 2450 SymTab.IsOpenArray(t);
|
|
|
+ 2451 IF isOpen THEN
|
|
|
+ 2452 QbeGen.CopyOp("0", qlo);
|
|
|
+ 2453 IF SymTab.IsCharArray(t)
|
|
|
+ 2454 OR SymTab.IsUCharArray(t) THEN
|
|
|
+ 2455 QbeGen.OpenHiChar(q, qhi)
|
|
|
+ 2456 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
+ 2457 END
|
|
|
+ 2458 ELSE
|
|
|
+ 2459 lo := SymTab.ArrayLo(t);
|
|
|
+ 2460 hi := SymTab.ArrayHi(t);
|
|
|
+ 2461 IF SymTab.IsCharArray(t)
|
|
|
+ 2462 OR SymTab.IsUCharArray(t) THEN
|
|
|
+ 2463 hi := hi + 1
|
|
|
+ 2464 END;
|
|
|
+ 2465 QbeGen.IntStr(lo, qlo);
|
|
|
+ 2466 QbeGen.IntStr(hi, qhi)
|
|
|
+ 2467 END;
|
|
|
+ 2468 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 2469 qhi);
|
|
|
+ 2470 eT := SymTab.ArrayElem(t);
|
|
|
+ 2471 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 2472 t, qe);
|
|
|
+ 2473 IF SymTab.ClassOf(eT) =
|
|
|
+ 2474 SymTab.ClArray THEN
|
|
|
+ 2475 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 2476 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 2477 END;
|
|
|
+ 2478 t := eT; sfx := TRUE
|
|
|
+ 2479 END; .)
|
|
|
+ 2480 { "," Expr<it, iq>
|
|
|
+ 2481 (. AST.SetChild(astDes, AST.NChild(astDes),
|
|
|
+ 2482 AST.MakeUn(AST.NkSelector, AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2483 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2484 SymTab.ClArray THEN
|
|
|
+ 2485 SemError(217);
|
|
|
+ 2486 t := SymTab.InvalidType
|
|
|
+ 2487 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2488 AND (SymTab.ClassOf(it) #
|
|
|
+ 2489 SymTab.ClChar)
|
|
|
+ 2490 AND (SymTab.ClassOf(it) #
|
|
|
+ 2491 SymTab.ClEnum) THEN
|
|
|
+ 2492 SemError(218);
|
|
|
+ 2493 t := SymTab.InvalidType
|
|
|
+ 2494 ELSE
|
|
|
+ 2495 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 2496 isOpen :=
|
|
|
+ 2497 SymTab.IsOpenArray(t);
|
|
|
+ 2498 IF isOpen THEN
|
|
|
+ 2499 QbeGen.CopyOp("0", qlo);
|
|
|
+ 2500 IF SymTab.IsCharArray(t)
|
|
|
+ 2501 OR SymTab.IsUCharArray(t) THEN
|
|
|
+ 2502 QbeGen.OpenHiChar(q, qhi)
|
|
|
+ 2503 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
+ 2504 END
|
|
|
+ 2505 ELSE
|
|
|
+ 2506 lo := SymTab.ArrayLo(t);
|
|
|
+ 2507 hi := SymTab.ArrayHi(t);
|
|
|
+ 2508 IF SymTab.IsCharArray(t)
|
|
|
+ 2509 OR SymTab.IsUCharArray(t) THEN
|
|
|
+ 2510 hi := hi + 1
|
|
|
+ 2511 END;
|
|
|
+ 2512 QbeGen.IntStr(lo, qlo);
|
|
|
+ 2513 QbeGen.IntStr(hi, qhi)
|
|
|
+ 2514 END;
|
|
|
+ 2515 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 2516 qhi);
|
|
|
+ 2517 eT := SymTab.ArrayElem(t);
|
|
|
+ 2518 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 2519 t, qe);
|
|
|
+ 2520 IF SymTab.ClassOf(eT) =
|
|
|
+ 2521 SymTab.ClArray THEN
|
|
|
+ 2522 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 2523 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 2524 END;
|
|
|
+ 2525 t := eT; sfx := TRUE
|
|
|
+ 2526 END; .) }
|
|
|
+ 2527 "]"
|
|
|
+ 2528 | "." GetIdent<fn>
|
|
|
+ 2529 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2530 AST.SetOp(astSel, AST.SelField);
|
|
|
+ 2531 AST.SetChild(astSel, 0, AST.MakeLeaf(AST.NkIdent, fn));
|
|
|
+ 2532 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF k = SymTab.KindModule THEN
|
|
|
+ 2533 (* qualified L.x: materialize
|
|
|
+ 2534 the export, then load it *)
|
|
|
+ 2535 IF NOT SymTab.MaterializeAlias(n,
|
|
|
+ 2536 fn, mal) THEN
|
|
|
+ 2537 SemError(201);
|
|
|
+ 2538 t := SymTab.InvalidType;
|
|
|
+ 2539 QbeGen.CopyOp("0", q)
|
|
|
+ 2540 ELSE
|
|
|
+ 2541 QbeGen.CopyOp(mal, qn);
|
|
|
+ 2542 t := SymTab.SymType(mal);
|
|
|
+ 2543 k := SymTab.SymKind(mal);
|
|
|
+ 2544 sfx := FALSE;
|
|
|
+ 2545 IF k = SymTab.KindProc THEN
|
|
|
+ 2546 (* call: ArgList supplies
|
|
|
+ 2547 the value *)
|
|
|
+ 2548 QbeGen.CopyOp("0", q)
|
|
|
+ 2549 ELSIF NOT QbeGen.LoadDesignator(
|
|
|
+ 2550 mal, t, k, q) THEN
|
|
|
+ 2551 SemError(230);
|
|
|
+ 2552 QbeGen.CopyOp("0", q)
|
|
|
+ 2553 END
|
|
|
+ 2554 END
|
|
|
+ 2555 ELSIF t = SymTab.InvalidType THEN
|
|
|
+ 2556 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2557 SymTab.ClRecord)
|
|
|
+ 2558 AND (SymTab.ClassOf(t) #
|
|
|
+ 2559 SymTab.ClClass) THEN
|
|
|
+ 2560 SemError(215);
|
|
|
+ 2561 t := SymTab.InvalidType
|
|
|
+ 2562 ELSIF (SymTab.ClassOf(t) =
|
|
|
+ 2563 SymTab.ClClass)
|
|
|
+ 2564 AND SymTab.MethodExists(t, fn) THEN
|
|
|
+ 2565 (* obj.Method: bind the
|
|
|
+ 2566 method and pass obj as
|
|
|
+ 2567 the hidden receiver; q
|
|
|
+ 2568 already holds the
|
|
|
+ 2569 object's address *)
|
|
|
+ 2570 QbeGen.ArmRecv(q);
|
|
|
+ 2571 QbeGen.CopyOp(fn, n);
|
|
|
+ 2572 QbeGen.CopyOp(fn, qn);
|
|
|
+ 2573 methCls := t;
|
|
|
+ 2574 k := SymTab.KindProc;
|
|
|
+ 2575 t := SymTab.InvalidType
|
|
|
+ 2576 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2577 fn) THEN
|
|
|
+ 2578 SemError(216);
|
|
|
+ 2579 t := SymTab.InvalidType
|
|
|
+ 2580 ELSE
|
|
|
+ 2581 fo := SymTab.FieldOffset(t,
|
|
|
+ 2582 fn);
|
|
|
+ 2583 t := SymTab.FieldType(t, fn);
|
|
|
+ 2584 QbeGen.FieldAddr(q, fo, qe);
|
|
|
+ 2585 (* array fields are inline:
|
|
|
+ 2586 the field address is the
|
|
|
+ 2587 descriptor, like records *)
|
|
|
+ 2588 QbeGen.CopyOp(qe, q);
|
|
|
+ 2589 sfx := TRUE
|
|
|
+ 2590 END; .)
|
|
|
+ 2591 | "^"
|
|
|
+ 2592 (. astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2593 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2594 AST.SetChild(astDes, AST.NChild(astDes), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2595 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2596 SymTab.ClPtr THEN
|
|
|
+ 2597 SemError(219);
|
|
|
+ 2598 t := SymTab.InvalidType
|
|
|
+ 2599 ELSE
|
|
|
+ 2600 bt := SymTab.PtrBase(t);
|
|
|
+ 2601 IF bt = SymTab.InvalidType THEN
|
|
|
+ 2602 ELSE
|
|
|
+ 2603 IF sfx THEN
|
|
|
+ 2604 QbeGen.ElemLoad(q, t,
|
|
|
+ 2605 qb);
|
|
|
+ 2606 QbeGen.CopyOp(qb, q)
|
|
|
+ 2607 END;
|
|
|
+ 2608 t := bt;
|
|
|
+ 2609 (* q holds the pointee
|
|
|
+ 2610 address: Fact loads
|
|
|
+ 2611 scalars/pointers and uses
|
|
|
+ 2612 the address for
|
|
|
+ 2613 aggregates; the VAR-actual
|
|
|
+ 2614 note is q itself. *)
|
|
|
+ 2615 sfx := TRUE
|
|
|
+ 2616 END
|
|
|
+ 2617 END; .) } (. astCur := astDes; .) .
|
|
|
+ 2618 (* Result suffix (ISO component after a function call): `F()^`,
|
|
|
+ 2619 `F()[i]`, `F().field`. The call result is in t/q with sfx FALSE
|
|
|
+ 2620 (a value, or a descriptor address for aggregates); each component
|
|
|
+ 2621 descends one level exactly like the Design components. *)
|
|
|
+ 2622 ResultComp<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal;
|
|
|
+ 2623 VAR sfx: BOOLEAN; VAR node: AST.Node> (. VAR it, eT, bt: SymTab.TypeIndex;
|
|
|
+ 2624 iq, ql, qlo, qhi, qe, qb:
|
|
|
+ 2625 QbeGen.QVal;
|
|
|
+ 2626 lo, hi, fo: INTEGER;
|
|
|
+ 2627 isOpen: BOOLEAN;
|
|
|
+ 2628 fname: SymTab.Name;
|
|
|
+ 2629 astWrap, astSel: AST.Node; .)
|
|
|
+ 2630 = "[" Expr<it, iq>
|
|
|
+ 2631 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2632 astWrap := AST.MakeNode(
|
|
|
+ 2633 AST.NkDesignator);
|
|
|
+ 2634 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2635 node := astWrap
|
|
|
+ 2636 END;
|
|
|
+ 2637 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2638 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2639 AST.SelIndex, astCur)); IF t = SymTab.InvalidType THEN
|
|
|
+ 2640 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2641 SymTab.ClArray THEN
|
|
|
+ 2642 SemError(217);
|
|
|
+ 2643 t := SymTab.InvalidType
|
|
|
+ 2644 ELSIF NOT SymTab.IsIntFamily(it)
|
|
|
+ 2645 AND (SymTab.ClassOf(it) # SymTab.ClChar)
|
|
|
+ 2646 AND (SymTab.ClassOf(it) # SymTab.ClEnum) THEN
|
|
|
+ 2647 SemError(218);
|
|
|
+ 2648 t := SymTab.InvalidType
|
|
|
+ 2649 ELSE
|
|
|
+ 2650 QbeGen.WidenIndex(iq, ql);
|
|
|
+ 2651 isOpen :=
|
|
|
+ 2652 SymTab.IsOpenArray(t);
|
|
|
+ 2653 IF isOpen THEN
|
|
|
+ 2654 QbeGen.CopyOp("0", qlo);
|
|
|
+ 2655 IF SymTab.IsCharArray(t)
|
|
|
+ 2656 OR SymTab.IsUCharArray(t) THEN
|
|
|
+ 2657 QbeGen.OpenHiChar(q, qhi)
|
|
|
+ 2658 ELSE QbeGen.OpenHi(q, qhi)
|
|
|
+ 2659 END
|
|
|
+ 2660 ELSE
|
|
|
+ 2661 lo := SymTab.ArrayLo(t);
|
|
|
+ 2662 hi := SymTab.ArrayHi(t);
|
|
|
+ 2663 IF SymTab.IsCharArray(t)
|
|
|
+ 2664 OR SymTab.IsUCharArray(t) THEN
|
|
|
+ 2665 hi := hi + 1
|
|
|
+ 2666 END;
|
|
|
+ 2667 QbeGen.IntStr(lo, qlo);
|
|
|
+ 2668 QbeGen.IntStr(hi, qhi)
|
|
|
+ 2669 END;
|
|
|
+ 2670 QbeGen.CheckRange(ql, qlo,
|
|
|
+ 2671 qhi);
|
|
|
+ 2672 eT := SymTab.ArrayElem(t);
|
|
|
+ 2673 QbeGen.ElemAddr(q, ql, qlo,
|
|
|
+ 2674 t, qe);
|
|
|
+ 2675 IF SymTab.ClassOf(eT) =
|
|
|
+ 2676 SymTab.ClArray THEN
|
|
|
+ 2677 QbeGen.ElemLoad(qe, eT, q)
|
|
|
+ 2678 ELSE QbeGen.CopyOp(qe, q)
|
|
|
+ 2679 END;
|
|
|
+ 2680 t := eT; sfx := TRUE
|
|
|
+ 2681 END; .)
|
|
|
+ 2682 "]"
|
|
|
+ 2683 | "." GetIdent<fname>
|
|
|
+ 2684 (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2685 astWrap := AST.MakeNode(
|
|
|
+ 2686 AST.NkDesignator);
|
|
|
+ 2687 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2688 node := astWrap
|
|
|
+ 2689 END;
|
|
|
+ 2690 AST.SetChild(node, AST.NChild(node),
|
|
|
+ 2691 AST.MakeUn(AST.NkSelector,
|
|
|
+ 2692 AST.SelField,
|
|
|
+ 2693 AST.MakeLeaf(AST.NkIdent,
|
|
|
+ 2694 fname))); IF t = SymTab.InvalidType THEN
|
|
|
+ 2695 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 2696 SymTab.ClRecord)
|
|
|
+ 2697 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 2698 SemError(215);
|
|
|
+ 2699 t := SymTab.InvalidType
|
|
|
+ 2700 ELSIF NOT SymTab.FieldExists(t,
|
|
|
+ 2701 fname) THEN
|
|
|
+ 2702 SemError(216);
|
|
|
+ 2703 t := SymTab.InvalidType
|
|
|
+ 2704 ELSE
|
|
|
+ 2705 fo := SymTab.FieldOffset(t,
|
|
|
+ 2706 fname);
|
|
|
+ 2707 t := SymTab.FieldType(t, fname);
|
|
|
+ 2708 QbeGen.FieldAddr(q, fo, qe);
|
|
|
+ 2709 QbeGen.CopyOp(qe, q);
|
|
|
+ 2710 sfx := TRUE
|
|
|
+ 2711 END; .)
|
|
|
+ 2712 | "^" (. IF AST.Kind(node) # AST.NkDesignator THEN
|
|
|
+ 2713 astWrap := AST.MakeNode(
|
|
|
+ 2714 AST.NkDesignator);
|
|
|
+ 2715 AST.SetChild(astWrap, 0, node);
|
|
|
+ 2716 node := astWrap
|
|
|
+ 2717 END;
|
|
|
+ 2718 astSel := AST.MakeNode(AST.NkSelector);
|
|
|
+ 2719 AST.SetOp(astSel, AST.SelDeref);
|
|
|
+ 2720 AST.SetChild(node,
|
|
|
+ 2721 AST.NChild(node), astSel); IF t = SymTab.InvalidType THEN
|
|
|
+ 2722 ELSIF SymTab.ClassOf(t) #
|
|
|
+ 2723 SymTab.ClPtr THEN
|
|
|
+ 2724 SemError(219);
|
|
|
+ 2725 t := SymTab.InvalidType
|
|
|
+ 2726 ELSE
|
|
|
+ 2727 bt := SymTab.PtrBase(t);
|
|
|
+ 2728 IF bt # SymTab.InvalidType THEN
|
|
|
+ 2729 IF sfx THEN
|
|
|
+ 2730 QbeGen.ElemLoad(q, t, qb);
|
|
|
+ 2731 QbeGen.CopyOp(qb, q)
|
|
|
+ 2732 END;
|
|
|
+ 2733 t := bt; sfx := TRUE
|
|
|
+ 2734 END
|
|
|
+ 2735 END; .) .
|
|
|
+ 2736 Expr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2737 (. VAR t2: SymTab.TypeIndex;
|
|
|
+ 2738 op: INTEGER;
|
|
|
+ 2739 q2, qt, wl: QbeGen.QVal;
|
|
|
+ 2740 astA, astB: AST.Node;
|
|
|
+ 2741 astOp: INTEGER;
|
|
|
+ 2742 astMade: BOOLEAN;
|
|
|
+ 2743 isR: BOOLEAN; .)
|
|
|
+ 2744 = SimExpr<t, q> (. astA := astCur; astMade := FALSE; .)
|
|
|
+ 2745 [ Rel<op> SimExpr<t2, q2>
|
|
|
+ 2746 (. astB := astCur; astMade := TRUE;
|
|
|
+ 2747 astOp := AST.OpEq;
|
|
|
+ 2748 IF op = SymTab.OpNeq1 THEN astOp := AST.OpNe
|
|
|
+ 2749 ELSIF op = SymTab.OpNeq2 THEN astOp := AST.OpNe
|
|
|
+ 2750 ELSIF op = SymTab.OpLt THEN astOp := AST.OpLt
|
|
|
+ 2751 ELSIF op = SymTab.OpLe THEN astOp := AST.OpLe
|
|
|
+ 2752 ELSIF op = SymTab.OpGt THEN astOp := AST.OpGt
|
|
|
+ 2753 ELSIF op = SymTab.OpGe THEN astOp := AST.OpGe
|
|
|
+ 2754 ELSIF op = SymTab.OpIn THEN astOp := AST.OpIn
|
|
|
+ 2755 END;
|
|
|
+ 2756 IF op = SymTab.OpIn THEN
|
|
|
+ 2757 IF SymTab.InCheck(t, t2) THEN
|
|
|
+ 2758 IF (t = SymTab.InvalidType)
|
|
|
+ 2759 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 2760 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 2761 ELSE
|
|
|
+ 2762 QbeGen.InSet(q, q2, SymTab.SetBaseLo(t2),
|
|
|
+ 2763 SymTab.SetCount(t2), qt);
|
|
|
+ 2764 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2765 END
|
|
|
+ 2766 ELSE SemError(222); t := SymTab.InvalidType;
|
|
|
+ 2767 QbeGen.CopyOp("0", q)
|
|
|
+ 2768 END
|
|
|
+ 2769 ELSIF SymTab.RelCheck(t, t2, op) THEN
|
|
|
+ 2770 IF (t = SymTab.InvalidType)
|
|
|
+ 2771 OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ 2772 t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ 2773 ELSIF (SymTab.ClassOf(t) = SymTab.ClPtr)
|
|
|
+ 2774 OR (SymTab.ClassOf(t2) = SymTab.ClPtr) THEN
|
|
|
+ 2775 IF SymTab.IsFwdVar(t) OR SymTab.IsFwdVar(t2) THEN
|
|
|
+ 2776 QbeGen.Cmp(op, q, q2, qt, FALSE);
|
|
|
+ 2777 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2778 ELSIF (op # SymTab.OpEq) AND (op # SymTab.OpNeq1)
|
|
|
+ 2779 AND (op # SymTab.OpNeq2) THEN
|
|
|
+ 2780 SemError(213); t := SymTab.InvalidType;
|
|
|
+ 2781 QbeGen.CopyOp("0", q)
|
|
|
+ 2782 ELSE
|
|
|
+ 2783 QbeGen.CmpL(op, q, q2, qt);
|
|
|
+ 2784 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2785 END
|
|
|
+ 2786 ELSIF (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2787 OR (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2788 QbeGen.CmpSet(op, q, q2,
|
|
|
+ 2789 SymTab.SetWords(t), SymTab.SetWords(t2), qt);
|
|
|
+ 2790 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2791 ELSIF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 2792 QbeGen.StrEq(op, q, q2, qt);
|
|
|
+ 2793 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2794 ELSIF SymTab.IsLongFamily(t)
|
|
|
+ 2795 OR SymTab.IsLongFamily(t2) THEN
|
|
|
+ 2796 IF SymTab.IsIntFamily(t) THEN
|
|
|
+ 2797 QbeGen.WidenLong(q, wl); QbeGen.CopyOp(wl, q)
|
|
|
+ 2798 END;
|
|
|
+ 2799 IF SymTab.IsIntFamily(t2) THEN
|
|
|
+ 2800 QbeGen.WidenLong(q2, wl); QbeGen.CopyOp(wl, q2)
|
|
|
+ 2801 END;
|
|
|
+ 2802 QbeGen.CmpLong(op, q, q2, qt);
|
|
|
+ 2803 t := SymTab.BoolType(); QbeGen.CopyOp(qt, q)
|
|
|
+ 2804 ELSE
|
|
|
+ 2805 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 2806 t := SymTab.BoolType();
|
|
|
+ 2807 QbeGen.Cmp(op, q, q2, qt, isR);
|
|
|
+ 2808 QbeGen.CopyOp(qt, q)
|
|
|
+ 2809 END
|
|
|
+ 2810 ELSE SemError(213); t := SymTab.InvalidType;
|
|
|
+ 2811 QbeGen.CopyOp("0", q)
|
|
|
+ 2812 END;
|
|
|
+ 2813 astCur := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB); .) ]
|
|
|
+ 2814 (. IF NOT astMade THEN astCur := astA END; .) .
|
|
|
+ 2815 Rel<VAR op: INTEGER>
|
|
|
+ 2816 = "=" (. op := SymTab.OpEq; .)
|
|
|
+ 2817 | "#" (. op := SymTab.OpNeq1; .)
|
|
|
+ 2818 | "<" (. op := SymTab.OpLt; .)
|
|
|
+ 2819 | "<=" (. op := SymTab.OpLe; .)
|
|
|
+ 2820 | ">" (. op := SymTab.OpGt; .)
|
|
|
+ 2821 | ">=" (. op := SymTab.OpGe; .)
|
|
|
+ 2822 | "IN" (. op := SymTab.OpIn; .) .
|
|
|
+ 2823 SimExpr<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 2824 (. VAR t2, res2, lt, rt:
|
|
|
+ 2825 SymTab.TypeIndex;
|
|
|
+ 2826 op: INTEGER;
|
|
|
+ 2827 q2, qt, wq, qf, q2a, q2b:
|
|
|
+ 2828 QbeGen.QVal;
|
|
|
+ 2829 neg, isR, isL, folded:
|
|
|
+ 2830 BOOLEAN;
|
|
|
+ 2831 fok: BOOLEAN;
|
|
|
+ 2832 lw, rw, mw: CARDINAL;
|
|
|
+ 2833 lTrue, lNext, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 2834 astA, astB: AST.Node;
|
|
|
+ 2835 astSign, astOp: INTEGER; .)
|
|
|
+ 2836 = (. neg := FALSE; astSign := 0; .)
|
|
|
+ 2837 [ "+" (. neg := TRUE; astSign := 1; .)
|
|
|
+ 2838 | "-" (. neg := TRUE; astSign := -1; .) ]
|
|
|
+ 2839 Term<t, q> (. astA := astCur; IF neg THEN
|
|
|
+ 2840 IF QbeGen.IsImm(q) THEN
|
|
|
+ 2841 QbeGen.NegFold(q, q)
|
|
|
+ 2842 ELSE QbeGen.NewTemp(qt);
|
|
|
+ 2843 QbeGen.NegQ(q, qt,
|
|
|
+ 2844 SymTab.ClassOf(t)
|
|
|
+ 2845 = SymTab.ClReal);
|
|
|
+ 2846 QbeGen.CopyOp(qt, q)
|
|
|
+ 2847 END
|
|
|
+ 2848 END;
|
|
|
+ 2849 IF astSign < 0 THEN
|
|
|
+ 2850 astCur := AST.MakeUn(
|
|
|
+ 2851 AST.NkUnary, AST.OpSub, astA);
|
|
|
+ 2852 astA := astCur
|
|
|
+ 2853 END; .)
|
|
|
+ 2854 { AddOp<op> (. IF op = SymTab.OpOr THEN
|
|
|
+ 2855 QbeGen.DelayBegin END; .)
|
|
|
+ 2856 Term<t2, q2> (. astB := astCur; IF op = SymTab.OpOr THEN
|
|
|
+ 2857 QbeGen.DelayEnd END; .)
|
|
|
+ 2858 (. astOp := AST.OpAdd;
|
|
|
+ 2859 IF op = SymTab.OpSub THEN astOp := AST.OpSub
|
|
|
+ 2860 ELSIF op = SymTab.OpOr THEN astOp := AST.OpOr END;
|
|
|
+ 2861 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 2862 astCur := astA;
|
|
|
+ 2863 IF op = SymTab.OpOr THEN
|
|
|
+ 2864 (* short-circuit: if q is true the RHS is skipped *)
|
|
|
+ 2865 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 2866 t := SymTab.BoolType()
|
|
|
+ 2867 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 2868 IF t # SymTab.InvalidType THEN
|
|
|
+ 2869 QbeGen.Slot4(qs);
|
|
|
+ 2870 QbeGen.NewLabel(lTrue);
|
|
|
+ 2871 QbeGen.NewLabel(lNext);
|
|
|
+ 2872 QbeGen.NewLabel(lDone);
|
|
|
+ 2873 QbeGen.Jnz(q, lTrue, lNext);
|
|
|
+ 2874 QbeGen.EmitLabel(lTrue);
|
|
|
+ 2875 QbeGen.StoreW(qs, "1");
|
|
|
+ 2876 QbeGen.Jmp(lDone);
|
|
|
+ 2877 QbeGen.EmitLabel(lNext);
|
|
|
+ 2878 QbeGen.DelayFlush;
|
|
|
+ 2879 QbeGen.StoreW(qs, q2);
|
|
|
+ 2880 QbeGen.Jmp(lDone);
|
|
|
+ 2881 QbeGen.EmitLabel(lDone);
|
|
|
+ 2882 QbeGen.LoadW(qs, qr);
|
|
|
+ 2883 QbeGen.CopyOp(qr, q)
|
|
|
+ 2884 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
+ 2885 END
|
|
|
+ 2886 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 2887 AND (SymTab.UStrCompat(t, t2)
|
|
|
+ 2888 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 2889 AND (SymTab.ClassOf(t2) = SymTab.ClUStr))
|
|
|
+ 2890 OR ((SymTab.ClassOf(t) = SymTab.ClUStr)
|
|
|
+ 2891 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))
|
|
|
+ 2892 OR ((SymTab.ClassOf(t) = SymTab.ClUChar)
|
|
|
+ 2893 AND (SymTab.ClassOf(t2) = SymTab.ClUChar))) THEN
|
|
|
+ 2894 (* UString concatenation: a UCHAR operand becomes a
|
|
|
+ 2895 1-codepoint UString; the result is a descriptor in the
|
|
|
+ 2896 shim's concat buffer. Work on copies so neither
|
|
|
+ 2897 operand is clobbered. *)
|
|
|
+ 2898 IF SymTab.ClassOf(t) = SymTab.ClUStr THEN
|
|
|
+ 2899 QbeGen.CopyOp(q, q2a)
|
|
|
+ 2900 ELSE
|
|
|
+ 2901 QbeGen.UStrFrom(q, q2a)
|
|
|
+ 2902 END;
|
|
|
+ 2903 IF SymTab.ClassOf(t2) = SymTab.ClUStr THEN
|
|
|
+ 2904 QbeGen.UStrCat(q2a, q2, qt)
|
|
|
+ 2905 ELSE
|
|
|
+ 2906 QbeGen.UStrFrom(q2, q2b);
|
|
|
+ 2907 QbeGen.UStrCat(q2a, q2b, qt)
|
|
|
+ 2908 END;
|
|
|
+ 2909 t := SymTab.NewUStr();
|
|
|
+ 2910 QbeGen.CopyOp(qt, q)
|
|
|
+ 2911 ELSIF (op = SymTab.OpAdd)
|
|
|
+ 2912 AND (SymTab.StrCompat(t, t2)
|
|
|
+ 2913 OR (SymTab.IsStrType(t)
|
|
|
+ 2914 AND (SymTab.ClassOf(t2) = SymTab.ClChar))
|
|
|
+ 2915 OR ((SymTab.ClassOf(t) = SymTab.ClChar)
|
|
|
+ 2916 AND SymTab.IsStrType(t2))) THEN
|
|
|
+ 2917 (* string concatenation; a CHAR operand becomes a
|
|
|
+ 2918 1-character string literal. When both operands are
|
|
|
+ 2919 constants, fold to a single string literal so a
|
|
|
+ 2920 constructor element stays compile-time. *)
|
|
|
+ 2921 QbeGen.StrFold(q, q2, SymTab.ClassOf(t), SymTab.ClassOf(t2),
|
|
|
+ 2922 qt, fok);
|
|
|
+ 2923 IF NOT fok THEN
|
|
|
+ 2924 IF SymTab.StrCompat(t, t2) THEN
|
|
|
+ 2925 QbeGen.StrCat(q, q2, qt)
|
|
|
+ 2926 ELSIF SymTab.IsStrType(t) THEN
|
|
|
+ 2927 QbeGen.DeclCharStr(q2, qs);
|
|
|
+ 2928 QbeGen.StrCat(q, qs, qt)
|
|
|
+ 2929 ELSE
|
|
|
+ 2930 QbeGen.DeclCharStr(q, qs);
|
|
|
+ 2931 QbeGen.StrCat(qs, q2, qt)
|
|
|
+ 2932 END
|
|
|
+ 2933 END;
|
|
|
+ 2934 t := SymTab.NewStr();
|
|
|
+ 2935 QbeGen.CopyOp(qt, q)
|
|
|
+ 2936 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 2937 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 2938 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 2939 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 2940 mw := lw;
|
|
|
+ 2941 IF rw > mw THEN mw := rw END;
|
|
|
+ 2942 IF op = SymTab.OpAdd THEN
|
|
|
+ 2943 QbeGen.SetBinOp(0, q, q2, lw, rw, qt)
|
|
|
+ 2944 ELSE
|
|
|
+ 2945 QbeGen.SetBinOp(2, q, q2, lw, rw, qt)
|
|
|
+ 2946 END;
|
|
|
+ 2947 t := SymTab.NewSet(
|
|
|
+ 2948 SymTab.NewSubR(0,
|
|
|
+ 2949 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 2950 QbeGen.CopyOp(qt, q)
|
|
|
+ 2951 ELSE
|
|
|
+ 2952 IF SymTab.ArithCheck(t, t2, FALSE, res2) THEN
|
|
|
+ 2953 lt := t; rt := t2; t := res2
|
|
|
+ 2954 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 2955 IF t # SymTab.InvalidType THEN
|
|
|
+ 2956 isL := SymTab.IsLongFamily(t);
|
|
|
+ 2957 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 2958 folded := FALSE;
|
|
|
+ 2959 IF (NOT isL) AND (NOT isR)
|
|
|
+ 2960 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 2961 IF op = SymTab.OpAdd THEN
|
|
|
+ 2962 folded := QbeGen.Fold2(0, q, q2, qf)
|
|
|
+ 2963 ELSE
|
|
|
+ 2964 folded := QbeGen.Fold2(1, q, q2, qf)
|
|
|
+ 2965 END
|
|
|
+ 2966 END;
|
|
|
+ 2967 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 2968 ELSE
|
|
|
+ 2969 IF isL THEN
|
|
|
+ 2970 IF SymTab.IsIntFamily(lt) THEN
|
|
|
+ 2971 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
+ 2972 END;
|
|
|
+ 2973 IF SymTab.IsIntFamily(rt) THEN
|
|
|
+ 2974 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
+ 2975 END;
|
|
|
+ 2976 QbeGen.NewTemp(qt);
|
|
|
+ 2977 IF op = SymTab.OpAdd THEN
|
|
|
+ 2978 QbeGen.Op3L("add", qt, q, q2)
|
|
|
+ 2979 ELSE
|
|
|
+ 2980 QbeGen.Op3L("sub", qt, q, q2)
|
|
|
+ 2981 END
|
|
|
+ 2982 ELSE
|
|
|
+ 2983 QbeGen.NewTemp(qt);
|
|
|
+ 2984 IF op = SymTab.OpAdd THEN
|
|
|
+ 2985 QbeGen.Op3("add", qt, q, q2, isR)
|
|
|
+ 2986 ELSE
|
|
|
+ 2987 QbeGen.Op3("sub", qt, q, q2, isR)
|
|
|
+ 2988 END
|
|
|
+ 2989 END;
|
|
|
+ 2990 QbeGen.CopyOp(qt, q)
|
|
|
+ 2991 END
|
|
|
+ 2992 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 2993 END
|
|
|
+ 2994 END; .) } .
|
|
|
+ 2995 AddOp<VAR op: INTEGER>
|
|
|
+ 2996 = "+" (. op := SymTab.OpAdd; .)
|
|
|
+ 2997 | "-" (. op := SymTab.OpSub; .)
|
|
|
+ 2998 | "OR" (. op := SymTab.OpOr; .) .
|
|
|
+ 2999 Term<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3000 (. VAR t2, res2, lt, rt:
|
|
|
+ 3001 SymTab.TypeIndex;
|
|
|
+ 3002 op: INTEGER;
|
|
|
+ 3003 q2, qt, wq, qf:
|
|
|
+ 3004 QbeGen.QVal;
|
|
|
+ 3005 isR, isL, folded: BOOLEAN;
|
|
|
+ 3006 lw, rw, mw: CARDINAL;
|
|
|
+ 3007 lNext, lFalse, lDone, qr, qs: QbeGen.QVal;
|
|
|
+ 3008 astA, astB: AST.Node;
|
|
|
+ 3009 astOp: INTEGER; .)
|
|
|
+ 3010 = Fact<t, q> (. astA := astCur; .) { MulOp<op> (. IF op = SymTab.OpAnd THEN
|
|
|
+ 3011 QbeGen.DelayBegin END; .)
|
|
|
+ 3012 Fact<t2, q2> (. astB := astCur; IF op = SymTab.OpAnd THEN
|
|
|
+ 3013 QbeGen.DelayEnd END; .)
|
|
|
+ 3014 (. astOp := AST.OpMul;
|
|
|
+ 3015 IF op = SymTab.OpSlash THEN astOp := AST.OpDiv
|
|
|
+ 3016 ELSIF op = SymTab.OpDiv THEN astOp := AST.OpDiv
|
|
|
+ 3017 ELSIF op = SymTab.OpMod THEN astOp := AST.OpMod
|
|
|
+ 3018 ELSIF op = SymTab.OpAnd THEN astOp := AST.OpAnd END;
|
|
|
+ 3019 astA := AST.MakeBin(AST.NkBinExpr, astOp, astA, astB);
|
|
|
+ 3020 astCur := astA;
|
|
|
+ 3021 IF op = SymTab.OpAnd THEN
|
|
|
+ 3022 (* short-circuit: if q is false the RHS is skipped *)
|
|
|
+ 3023 IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ 3024 t := SymTab.BoolType()
|
|
|
+ 3025 ELSE SemError(212); t := SymTab.InvalidType END;
|
|
|
+ 3026 IF t # SymTab.InvalidType THEN
|
|
|
+ 3027 QbeGen.Slot4(qs);
|
|
|
+ 3028 QbeGen.NewLabel(lNext);
|
|
|
+ 3029 QbeGen.NewLabel(lFalse);
|
|
|
+ 3030 QbeGen.NewLabel(lDone);
|
|
|
+ 3031 QbeGen.Jnz(q, lNext, lFalse);
|
|
|
+ 3032 QbeGen.EmitLabel(lNext);
|
|
|
+ 3033 QbeGen.DelayFlush;
|
|
|
+ 3034 QbeGen.StoreW(qs, q2);
|
|
|
+ 3035 QbeGen.Jmp(lDone);
|
|
|
+ 3036 QbeGen.EmitLabel(lFalse);
|
|
|
+ 3037 QbeGen.StoreW(qs, "0");
|
|
|
+ 3038 QbeGen.Jmp(lDone);
|
|
|
+ 3039 QbeGen.EmitLabel(lDone);
|
|
|
+ 3040 QbeGen.LoadW(qs, qr);
|
|
|
+ 3041 QbeGen.CopyOp(qr, q)
|
|
|
+ 3042 ELSE QbeGen.DelayFlush; QbeGen.CopyOp("0", q)
|
|
|
+ 3043 END
|
|
|
+ 3044 ELSIF (t # SymTab.InvalidType) AND (t2 # SymTab.InvalidType)
|
|
|
+ 3045 AND (SymTab.ClassOf(t) = SymTab.ClSet)
|
|
|
+ 3046 AND (SymTab.ClassOf(t2) = SymTab.ClSet) THEN
|
|
|
+ 3047 lw := SymTab.SetWords(t); rw := SymTab.SetWords(t2);
|
|
|
+ 3048 mw := lw;
|
|
|
+ 3049 IF rw > mw THEN mw := rw END;
|
|
|
+ 3050 IF op = SymTab.OpTimes THEN
|
|
|
+ 3051 QbeGen.SetBinOp(1, q, q2, lw, rw, qt)
|
|
|
+ 3052 ELSE
|
|
|
+ 3053 QbeGen.SetBinOp(3, q, q2, lw, rw, qt)
|
|
|
+ 3054 END;
|
|
|
+ 3055 t := SymTab.NewSet(
|
|
|
+ 3056 SymTab.NewSubR(0,
|
|
|
+ 3057 VAL(INTEGER, mw) * 32 - 1));
|
|
|
+ 3058 QbeGen.CopyOp(qt, q)
|
|
|
+ 3059 ELSE
|
|
|
+ 3060 IF SymTab.ArithCheck(t, t2,
|
|
|
+ 3061 (op = SymTab.OpDiv) OR (op = SymTab.OpMod),
|
|
|
+ 3062 res2) THEN
|
|
|
+ 3063 lt := t; rt := t2; t := res2
|
|
|
+ 3064 ELSE SemError(211); t := SymTab.InvalidType END;
|
|
|
+ 3065 IF t # SymTab.InvalidType THEN
|
|
|
+ 3066 isL := SymTab.IsLongFamily(t);
|
|
|
+ 3067 isR := SymTab.ClassOf(t) = SymTab.ClReal;
|
|
|
+ 3068 folded := FALSE;
|
|
|
+ 3069 IF (NOT isL) AND (NOT isR)
|
|
|
+ 3070 AND QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ 3071 IF op = SymTab.OpTimes THEN
|
|
|
+ 3072 folded := QbeGen.Fold2(2, q, q2, qf)
|
|
|
+ 3073 ELSIF op = SymTab.OpDiv THEN
|
|
|
+ 3074 folded := QbeGen.Fold2(3, q, q2, qf)
|
|
|
+ 3075 ELSIF op = SymTab.OpMod THEN
|
|
|
+ 3076 folded := QbeGen.Fold2(4, q, q2, qf)
|
|
|
+ 3077 END
|
|
|
+ 3078 END;
|
|
|
+ 3079 IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ 3080 ELSE
|
|
|
+ 3081 IF isL THEN
|
|
|
+ 3082 IF SymTab.IsIntFamily(lt) THEN
|
|
|
+ 3083 QbeGen.WidenLong(q, wq); QbeGen.CopyOp(wq, q)
|
|
|
+ 3084 END;
|
|
|
+ 3085 IF SymTab.IsIntFamily(rt) THEN
|
|
|
+ 3086 QbeGen.WidenLong(q2, wq); QbeGen.CopyOp(wq, q2)
|
|
|
+ 3087 END;
|
|
|
+ 3088 QbeGen.NewTemp(qt);
|
|
|
+ 3089 IF op = SymTab.OpTimes THEN
|
|
|
+ 3090 QbeGen.Op3L("mul", qt, q, q2)
|
|
|
+ 3091 ELSIF (op = SymTab.OpDiv)
|
|
|
+ 3092 OR (op = SymTab.OpSlash) THEN
|
|
|
+ 3093 QbeGen.Op3L("div", qt, q, q2)
|
|
|
+ 3094 ELSE
|
|
|
+ 3095 QbeGen.Op3L("rem", qt, q, q2)
|
|
|
+ 3096 END
|
|
|
+ 3097 ELSE
|
|
|
+ 3098 QbeGen.NewTemp(qt);
|
|
|
+ 3099 IF op = SymTab.OpTimes THEN
|
|
|
+ 3100 QbeGen.Op3("mul", qt, q, q2, isR)
|
|
|
+ 3101 ELSIF (op = SymTab.OpDiv)
|
|
|
+ 3102 OR (op = SymTab.OpSlash) THEN
|
|
|
+ 3103 QbeGen.Op3("div", qt, q, q2, isR)
|
|
|
+ 3104 ELSE
|
|
|
+ 3105 QbeGen.Op3("rem", qt, q, q2, isR)
|
|
|
+ 3106 END
|
|
|
+ 3107 END;
|
|
|
+ 3108 QbeGen.CopyOp(qt, q)
|
|
|
+ 3109 END
|
|
|
+ 3110 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3111 END
|
|
|
+ 3112 END; .) } .
|
|
|
+ 3113 MulOp<VAR op: INTEGER>
|
|
|
+ 3114 = "*" (. op := SymTab.OpTimes; .)
|
|
|
+ 3115 | "/" (. op := SymTab.OpSlash; .)
|
|
|
+ 3116 | "DIV" (. op := SymTab.OpDiv; .)
|
|
|
+ 3117 | "MOD" (. op := SymTab.OpMod; .)
|
|
|
+ 3118 | ( "AND" | "&" ) (. op := SymTab.OpAnd; .) .
|
|
|
+ 3119 Fact<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3120 (. VAR s: ARRAY [0 .. 255] OF CHAR;
|
|
|
+ 3121 et, dt, t2, st, ct2, et2:
|
|
|
+ 3122 SymTab.TypeIndex;
|
|
|
+ 3123 dk: INTEGER;
|
|
|
+ 3124 qd, q2, sq, qa, qm0, qr, qt:
|
|
|
+ 3125 QbeGen.QVal;
|
|
|
+ 3126 qn, vn: SymTab.Name;
|
|
|
+ 3127 vt: SymTab.TypeIndex;
|
|
|
+ 3128 c1, c2: INTEGER;
|
|
|
+ 3129 lo, hi: INTEGER;
|
|
|
+ 3130 isMax: BOOLEAN;
|
|
|
+ 3131 called, isHigh, sfx, isCh,
|
|
|
+ 3132 isU, uok, isStr: BOOLEAN;
|
|
|
+ 3133 ucp: INTEGER; astIsLit: BOOLEAN;
|
|
|
+ 3134 astD: AST.Node;
|
|
|
+ 3135 astCall: BOOLEAN;
|
|
|
+ 3136 astNode, astNot: AST.Node;
|
|
|
+ 3137 j: CARDINAL;
|
|
|
+ 3138 astArg2: AST.Node;
|
|
|
+ 3139 astBrace: AST.Node;
|
|
|
+ 3140 astRes: AST.Node; .)
|
|
|
+ 3141 = (. astIsLit := FALSE; .)
|
|
|
+ 3142 ( integer (. LexString(s);
|
|
|
+ 3143 QbeGen.NormInt(s, q); IF twoPhase THEN astIsLit := TRUE; astCur := AST.MakeLeaf(AST.NkIntLit, s) END;
|
|
|
+ 3144 t := SymTab.IntType(); .)
|
|
|
+ 3145 | charConst (. LexString(s);
|
|
|
+ 3146 QbeGen.NormLit(s, q, isCh);
|
|
|
+ 3147 IF twoPhase THEN
|
|
|
+ 3148 astIsLit := TRUE;
|
|
|
+ 3149 astCur := AST.MakeLeaf(
|
|
|
+ 3150 AST.NkCharLit, s)
|
|
|
+ 3151 END;
|
|
|
+ 3152 t := SymTab.CharType(); .)
|
|
|
+ 3153 | real (. LexString(s);
|
|
|
+ 3154 QbeGen.NormReal(s, q);
|
|
|
+ 3155 IF twoPhase THEN
|
|
|
+ 3156 astIsLit := TRUE;
|
|
|
+ 3157 astCur := AST.MakeLeaf(
|
|
|
+ 3158 AST.NkRealLit, s)
|
|
|
+ 3159 END;
|
|
|
+ 3160 t := SymTab.RealType(); .)
|
|
|
+ 3161 | string (. LexString(s);
|
|
|
+ 3162 IF twoPhase THEN
|
|
|
+ 3163 astIsLit := TRUE;
|
|
|
+ 3164 astCur := AST.MakeLeaf(
|
|
|
+ 3165 AST.NkStrLit, s)
|
|
|
+ 3166 END;
|
|
|
+ 3167 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3168 t := SymTab.CharType();
|
|
|
+ 3169 QbeGen.IntStr(
|
|
|
+ 3170 QbeGen.CharVal(s), q)
|
|
|
+ 3171 ELSE t := SymTab.NewStr();
|
|
|
+ 3172 QbeGen.DeclStr(s, q);
|
|
|
+ 3173 (* a literal's value IS its
|
|
|
+ 3174 static descriptor address *)
|
|
|
+ 3175 QbeGen.NoteAddr(q, q)
|
|
|
+ 3176 END; .)
|
|
|
+ 3177 | ustring (. LexString(s);
|
|
|
+ 3178 IF twoPhase THEN
|
|
|
+ 3179 astIsLit := TRUE;
|
|
|
+ 3180 astCur := AST.MakeLeaf(
|
|
|
+ 3181 AST.NkStrLit, s)
|
|
|
+ 3182 END;
|
|
|
+ 3183 QbeGen.DeclUStr(s, q, isU, ucp,
|
|
|
+ 3184 uok);
|
|
|
+ 3185 IF NOT uok THEN
|
|
|
+ 3186 SemError(234);
|
|
|
+ 3187 t := SymTab.InvalidType
|
|
|
+ 3188 ELSIF isU THEN
|
|
|
+ 3189 t := SymTab.UCharType();
|
|
|
+ 3190 QbeGen.IntStr(ucp, q)
|
|
|
+ 3191 ELSE
|
|
|
+ 3192 t := SymTab.NewUStr();
|
|
|
+ 3193 QbeGen.NoteAddr(q, q)
|
|
|
+ 3194 END; .)
|
|
|
+ 3195 | Design<dt, dk, qd, qn, sfx> (. astD := astCur; astCall := FALSE; astBrace := AST.NoNode;
|
|
|
+ 3196 astNArgs := 0; called := FALSE;
|
|
|
+ 3197 t := dt;
|
|
|
+ 3198 IF sfx THEN
|
|
|
+ 3199 IF dt =
|
|
|
+ 3200 SymTab.InvalidType THEN
|
|
|
+ 3201 QbeGen.CopyOp("0", q)
|
|
|
+ 3202 ELSIF (SymTab.ClassOf(dt) =
|
|
|
+ 3203 SymTab.ClRecord)
|
|
|
+ 3204 OR (SymTab.ClassOf(dt) =
|
|
|
+ 3205 SymTab.ClSet)
|
|
|
+ 3206 OR (SymTab.ClassOf(dt) =
|
|
|
+ 3207 SymTab.ClArray)
|
|
|
+ 3208 OR (SymTab.ClassOf(dt) =
|
|
|
+ 3209 SymTab.ClClass) THEN
|
|
|
+ 3210 QbeGen.CopyOp(qd, q)
|
|
|
+ 3211 ELSE QbeGen.ElemLoad(qd, dt,
|
|
|
+ 3212 q)
|
|
|
+ 3213 END
|
|
|
+ 3214 ELSE QbeGen.CopyOp(qd, q)
|
|
|
+ 3215 END;
|
|
|
+ 3216 IF (dk = SymTab.KindVar)
|
|
|
+ 3217 OR (dk = SymTab.KindParam)
|
|
|
+ 3218 OR (dk =
|
|
|
+ 3219 SymTab.KindField) THEN
|
|
|
+ 3220 IF sfx THEN
|
|
|
+ 3221 QbeGen.NoteAddr(q, qd)
|
|
|
+ 3222 ELSE
|
|
|
+ 3223 QbeGen.AddrOf(qn, qa);
|
|
|
+ 3224 QbeGen.NoteAddr(q, qa)
|
|
|
+ 3225 END
|
|
|
+ 3226 ELSIF sfx
|
|
|
+ 3227 AND (dt #
|
|
|
+ 3228 SymTab.InvalidType)
|
|
|
+ 3229 AND ((SymTab.ClassOf(dt) =
|
|
|
+ 3230 SymTab.ClArray)
|
|
|
+ 3231 OR (SymTab.ClassOf(dt) =
|
|
|
+ 3232 SymTab.ClSet)
|
|
|
+ 3233 OR (SymTab.ClassOf(dt) =
|
|
|
+ 3234 SymTab.ClRecord)) THEN
|
|
|
+ 3235 QbeGen.NoteAddr(qd, qd)
|
|
|
+ 3236 END; .)
|
|
|
+ 3237 [ TypedBraceLit<dt, q> (. t := dt; astCall := TRUE;
|
|
|
+ 3238 astBrace := astCur; .) ]
|
|
|
+ 3239 [ ArgList<qn, dt, qd, TRUE, FALSE, methCls, ct2, q2, called>
|
|
|
+ 3240 (. astCall := TRUE;
|
|
|
+ 3241 astNode := AstCallNode(astD);
|
|
|
+ 3242 astRes := astNode;
|
|
|
+ 3243 t := ct2;
|
|
|
+ 3244 QbeGen.CopyOp(q2, q);
|
|
|
+ 3245 sfx := FALSE; .)
|
|
|
+ 3246 { ResultComp<t, q, sfx, astRes> }
|
|
|
+ 3247 (. IF sfx THEN
|
|
|
+ 3248 IF t = SymTab.InvalidType THEN
|
|
|
+ 3249 QbeGen.CopyOp("0", q)
|
|
|
+ 3250 ELSIF (SymTab.ClassOf(t) #
|
|
|
+ 3251 SymTab.ClRecord)
|
|
|
+ 3252 AND (SymTab.ClassOf(t) # SymTab.ClSet)
|
|
|
+ 3253 AND (SymTab.ClassOf(t) # SymTab.ClArray)
|
|
|
+ 3254 AND (SymTab.ClassOf(t) # SymTab.ClClass) THEN
|
|
|
+ 3255 QbeGen.ElemLoad(q, t, q2);
|
|
|
+ 3256 QbeGen.CopyOp(q2, q)
|
|
|
+ 3257 END
|
|
|
+ 3258 END; .) ]
|
|
|
+ 3259 (. IF called THEN
|
|
|
+ 3260 astCur := astRes
|
|
|
+ 3261 ELSIF astCall THEN
|
|
|
+ 3262 astCur := astBrace
|
|
|
+ 3263 ELSE astCur := astD
|
|
|
+ 3264 END;
|
|
|
+ 3265 astIsLit := TRUE;
|
|
|
+ 3266 IF NOT called
|
|
|
+ 3267 AND (dk = SymTab.KindProc) THEN
|
|
|
+ 3268 (* bare zero-arg function
|
|
|
+ 3269 call (parentheses may be
|
|
|
+ 3270 omitted); a proper or
|
|
|
+ 3271 parameterised proc here
|
|
|
+ 3272 is 230 *)
|
|
|
+ 3273 IF (SymTab.ProcNPar(qn) = 0)
|
|
|
+ 3274 AND (SymTab.ProcRes(qn) #
|
|
|
+ 3275 SymTab.InvalidType) THEN
|
|
|
+ 3276 QbeGen.Mangled(qn,
|
|
|
+ 3277 SymTab.ProcUid(qn), qm0);
|
|
|
+ 3278 QbeGen.CallBegin(qm0,
|
|
|
+ 3279 SymTab.ProcRes(qn),
|
|
|
+ 3280 SymTab.ProcDepthOf(qn),
|
|
|
+ 3281 SymTab.IsExternal(qn));
|
|
|
+ 3282 QbeGen.CallEnd(TRUE, q);
|
|
|
+ 3283 t := SymTab.ProcRes(qn)
|
|
|
+ 3284 ELSE
|
|
|
+ 3285 (* procedure used as a
|
|
|
+ 3286 value (assign to a
|
|
|
+ 3287 procedure variable):
|
|
|
+ 3288 its code address *)
|
|
|
+ 3289 t := SymTab.ProcTypeOf(qn);
|
|
|
+ 3290 QbeGen.Mangled(qn,
|
|
|
+ 3291 SymTab.ProcUid(qn), qm0);
|
|
|
+ 3292 QbeGen.ProcAddr(qm0, q)
|
|
|
+ 3293 END
|
|
|
+ 3294 END; .)
|
|
|
+ 3295 | ( "HIGH" (. isHigh := TRUE; .)
|
|
|
+ 3296 | ( "LEN" | "LENGTH" ) (. isHigh := FALSE; .) )
|
|
|
+ 3297 "(" ( Design<dt, dk, qd, qn, sfx> (. isStr := FALSE;
|
|
|
+ 3298 isU := FALSE; .)
|
|
|
+ 3299 | string (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3300 isStr := TRUE;
|
|
|
+ 3301 isU := FALSE;
|
|
|
+ 3302 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3303 dt := SymTab.CharType();
|
|
|
+ 3304 QbeGen.IntStr(QbeGen.CharVal(s),
|
|
|
+ 3305 qd)
|
|
|
+ 3306 ELSE
|
|
|
+ 3307 dt := SymTab.NewStr();
|
|
|
+ 3308 QbeGen.DeclStr(s, qd);
|
|
|
+ 3309 QbeGen.NoteAddr(qd, qd)
|
|
|
+ 3310 END;
|
|
|
+ 3311 dk := -1;
|
|
|
+ 3312 qn[0] := CHR(0); .)
|
|
|
+ 3313 | ustring (. LexString(s); astCur := AST.MakeLeaf(AST.NkStrLit, s);
|
|
|
+ 3314 QbeGen.DeclUStr(s, qd, isU, ucp,
|
|
|
+ 3315 uok);
|
|
|
+ 3316 isStr := FALSE;
|
|
|
+ 3317 IF NOT uok THEN
|
|
|
+ 3318 SemError(234);
|
|
|
+ 3319 dt := SymTab.InvalidType
|
|
|
+ 3320 ELSIF isU THEN
|
|
|
+ 3321 (* one codepoint: a UCHAR;
|
|
|
+ 3322 LEN is 1, HIGH is 0 *)
|
|
|
+ 3323 dt := SymTab.UCharType();
|
|
|
+ 3324 QbeGen.IntStr(ucp, qd)
|
|
|
+ 3325 ELSE
|
|
|
+ 3326 dt := SymTab.NewUStr();
|
|
|
+ 3327 QbeGen.NoteAddr(qd, qd)
|
|
|
+ 3328 END;
|
|
|
+ 3329 dk := -1;
|
|
|
+ 3330 qn[0] := CHR(0); .) )
|
|
|
+ 3331 ")"
|
|
|
+ 3332 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3333 IF isHigh THEN AST.SetChild(astNode, 0,
|
|
|
+ 3334 AST.MakeLeaf(AST.NkIdent, "HIGH"))
|
|
|
+ 3335 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3336 AST.MakeLeaf(AST.NkIdent, "LEN")) END;
|
|
|
+ 3337 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3338 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3339 IF (dt # SymTab.InvalidType)
|
|
|
+ 3340 AND (SymTab.ClassOf(dt) = SymTab.ClUStr) THEN
|
|
|
+ 3341 (* UString: the count is
|
|
|
+ 3342 the descriptor header *)
|
|
|
+ 3343 IF isHigh THEN
|
|
|
+ 3344 QbeGen.UStrLen(qd, qr);
|
|
|
+ 3345 QbeGen.DecQ(qr)
|
|
|
+ 3346 ELSE
|
|
|
+ 3347 QbeGen.UStrLen(qd, qr)
|
|
|
+ 3348 END;
|
|
|
+ 3349 t := SymTab.IntType();
|
|
|
+ 3350 QbeGen.CopyOp(qr, q)
|
|
|
+ 3351 ELSIF (dt # SymTab.InvalidType)
|
|
|
+ 3352 AND (SymTab.ClassOf(dt) = SymTab.ClUChar) THEN
|
|
|
+ 3353 (* single UCHAR codepoint *)
|
|
|
+ 3354 IF isHigh THEN
|
|
|
+ 3355 QbeGen.CopyOp("0", qr)
|
|
|
+ 3356 ELSE
|
|
|
+ 3357 QbeGen.CopyOp("1", qr)
|
|
|
+ 3358 END;
|
|
|
+ 3359 t := SymTab.IntType();
|
|
|
+ 3360 QbeGen.CopyOp(qr, q)
|
|
|
+ 3361 ELSIF isStr THEN
|
|
|
+ 3362 (* fold: content length at
|
|
|
+ 3363 compile time *)
|
|
|
+ 3364 IF SymTab.StrLen(s) = 3 THEN
|
|
|
+ 3365 c1 := 1
|
|
|
+ 3366 ELSE
|
|
|
+ 3367 c1 :=
|
|
|
+ 3368 SymTab.StrLen(s) - 2
|
|
|
+ 3369 END;
|
|
|
+ 3370 IF isHigh THEN
|
|
|
+ 3371 DEC(c1)
|
|
|
+ 3372 END;
|
|
|
+ 3373 QbeGen.IntStr(c1, qr);
|
|
|
+ 3374 t := SymTab.IntType();
|
|
|
+ 3375 QbeGen.CopyOp(qr, q)
|
|
|
+ 3376 ELSIF dt = SymTab.InvalidType THEN
|
|
|
+ 3377 t := SymTab.InvalidType;
|
|
|
+ 3378 QbeGen.CopyOp("0", q)
|
|
|
+ 3379 ELSIF SymTab.ClassOf(dt) #
|
|
|
+ 3380 SymTab.ClArray THEN
|
|
|
+ 3381 SemError(217);
|
|
|
+ 3382 t := SymTab.InvalidType;
|
|
|
+ 3383 QbeGen.CopyOp("0", q)
|
|
|
+ 3384 ELSE
|
|
|
+ 3385 IF isHigh THEN
|
|
|
+ 3386 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 3387 QbeGen.OpenHi(qd, qr)
|
|
|
+ 3388 ELSE
|
|
|
+ 3389 QbeGen.IntStr(
|
|
|
+ 3390 SymTab.ArrayHi(dt), qr)
|
|
|
+ 3391 END
|
|
|
+ 3392 ELSE
|
|
|
+ 3393 IF SymTab.IsOpenArray(dt) THEN
|
|
|
+ 3394 QbeGen.LoadCount(qd, qr)
|
|
|
+ 3395 ELSE
|
|
|
+ 3396 QbeGen.IntStr(VAL(
|
|
|
+ 3397 INTEGER,
|
|
|
+ 3398 SymTab.ArrayLen(dt)),
|
|
|
+ 3399 qr)
|
|
|
+ 3400 END
|
|
|
+ 3401 END;
|
|
|
+ 3402 t := SymTab.IntType();
|
|
|
+ 3403 QbeGen.CopyOp(qr, q)
|
|
|
+ 3404 END; .)
|
|
|
+ 3405 | ( "SIZE" | "TSIZE" ) "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3406 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3407 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "SIZE"));
|
|
|
+ 3408 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3409 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3410 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3411 t := SymTab.InvalidType;
|
|
|
+ 3412 QbeGen.CopyOp("0", q)
|
|
|
+ 3413 ELSE
|
|
|
+ 3414 QbeGen.IntStr(VAL(INTEGER,
|
|
|
+ 3415 SymTab.ObjectSize(dt)), q);
|
|
|
+ 3416 t := SymTab.IntType()
|
|
|
+ 3417 END; .)
|
|
|
+ 3418 | ( "SHIFT" (. isMax := FALSE; .)
|
|
|
+ 3419 | "ROTATE" (. isMax := TRUE; .) )
|
|
|
+ 3420 "(" Expr<et, q> (. astArg2 := astCur; .) "," Expr<et2, q2> ")"
|
|
|
+ 3421 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3422 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3423 AST.MakeLeaf(AST.NkIdent, "ROTATE"))
|
|
|
+ 3424 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3425 AST.MakeLeaf(AST.NkIdent, "SHIFT")) END;
|
|
|
+ 3426 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3427 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3428 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3429 (* set shift/rotate: isMax
|
|
|
+ 3430 doubles as "rotate" *)
|
|
|
+ 3431 IF (et # SymTab.InvalidType)
|
|
|
+ 3432 AND (SymTab.ClassOf(et) =
|
|
|
+ 3433 SymTab.ClSet) THEN
|
|
|
+ 3434 QbeGen.SetShift(q, q2,
|
|
|
+ 3435 SymTab.SetWords(et),
|
|
|
+ 3436 SymTab.SetCount(et), isMax,
|
|
|
+ 3437 qt);
|
|
|
+ 3438 t := et;
|
|
|
+ 3439 QbeGen.CopyOp(qt, q)
|
|
|
+ 3440 ELSE SemError(230);
|
|
|
+ 3441 t := SymTab.InvalidType;
|
|
|
+ 3442 QbeGen.CopyOp("0", q)
|
|
|
+ 3443 END; .)
|
|
|
+ 3444 | ( "MIN" (. isMax := FALSE; .)
|
|
|
+ 3445 | "MAX" (. isMax := TRUE; .) )
|
|
|
+ 3446 "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3447 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3448 IF isMax THEN AST.SetChild(astNode, 0,
|
|
|
+ 3449 AST.MakeLeaf(AST.NkIdent, "MAX"))
|
|
|
+ 3450 ELSE AST.SetChild(astNode, 0,
|
|
|
+ 3451 AST.MakeLeaf(AST.NkIdent, "MIN")) END;
|
|
|
+ 3452 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3453 astCur := astNode; astIsLit := TRUE;
|
|
|
+ 3454 IF (dt # SymTab.InvalidType)
|
|
|
+ 3455 AND (SymTab.ClassOf(dt) = SymTab.ClReal) THEN
|
|
|
+ 3456 (* REAL/LONGREAL: the
|
|
|
+ 3457 implementation bounds *)
|
|
|
+ 3458 IF isMax THEN
|
|
|
+ 3459 QbeGen.NormReal(
|
|
|
+ 3460 "3.402823e38", q)
|
|
|
+ 3461 ELSE QbeGen.NormReal(
|
|
|
+ 3462 "-3.402823e38", q)
|
|
|
+ 3463 END;
|
|
|
+ 3464 t := SymTab.RealType()
|
|
|
+ 3465 ELSIF (dt #
|
|
|
+ 3466 SymTab.InvalidType)
|
|
|
+ 3467 AND (SymTab.ClassOf(dt) =
|
|
|
+ 3468 SymTab.ClLong) THEN
|
|
|
+ 3469 IF isMax THEN
|
|
|
+ 3470 QbeGen.CopyOp(
|
|
|
+ 3471 "9223372036854775807", q)
|
|
|
+ 3472 ELSE QbeGen.CopyOp(
|
|
|
+ 3473 "-9223372036854775808", q)
|
|
|
+ 3474 END;
|
|
|
+ 3475 t := SymTab.LongType()
|
|
|
+ 3476 ELSIF SymTab.TypeBounds(dt, lo,
|
|
|
+ 3477 hi) THEN
|
|
|
+ 3478 IF isMax THEN
|
|
|
+ 3479 QbeGen.IntStr(hi, q)
|
|
|
+ 3480 ELSE QbeGen.IntStr(lo, q)
|
|
|
+ 3481 END;
|
|
|
+ 3482 t := SymTab.IntType()
|
|
|
+ 3483 ELSE SemError(230);
|
|
|
+ 3484 t := SymTab.InvalidType;
|
|
|
+ 3485 QbeGen.CopyOp("0", q)
|
|
|
+ 3486 END; .)
|
|
|
+ 3487 | "ADR" "(" Design<dt, dk, qd, qn, sfx> ")"
|
|
|
+ 3488 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3489 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ADR"));
|
|
|
+ 3490 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3491 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3492 (. IF dt = SymTab.InvalidType THEN
|
|
|
+ 3493 t := SymTab.InvalidType;
|
|
|
+ 3494 QbeGen.CopyOp("0", q)
|
|
|
+ 3495 ELSE
|
|
|
+ 3496 IF sfx THEN
|
|
|
+ 3497 QbeGen.CopyOp(qd, q)
|
|
|
+ 3498 ELSIF (dk = SymTab.KindVar)
|
|
|
+ 3499 OR (dk = SymTab.KindParam) THEN
|
|
|
+ 3500 QbeGen.AddrOf(qn, q)
|
|
|
+ 3501 ELSE SemError(230);
|
|
|
+ 3502 QbeGen.CopyOp("0", q)
|
|
|
+ 3503 END;
|
|
|
+ 3504 t := SymTab.AddrType()
|
|
|
+ 3505 END; .)
|
|
|
+ 3506 | "CHR" "(" Expr<et, q> ")"
|
|
|
+ 3507 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3508 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR"));
|
|
|
+ 3509 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3510 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3511 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3512 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3513 SemError(211) END;
|
|
|
+ 3514 t := SymTab.CharType(); .)
|
|
|
+ 3515 | ( "ORD" | "ORDL" ) "(" Expr<et, q> ")"
|
|
|
+ 3516 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3517 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ORD"));
|
|
|
+ 3518 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3519 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3520 (. IF et # SymTab.InvalidType THEN
|
|
|
+ 3521 IF (SymTab.ClassOf(et) #
|
|
|
+ 3522 SymTab.ClChar)
|
|
|
+ 3523 AND (SymTab.ClassOf(et) #
|
|
|
+ 3524 SymTab.ClBool)
|
|
|
+ 3525 AND (SymTab.ClassOf(et) #
|
|
|
+ 3526 SymTab.ClEnum)
|
|
|
+ 3527 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3528 SemError(211) END
|
|
|
+ 3529 END;
|
|
|
+ 3530 t := SymTab.IntType(); .)
|
|
|
+ 3531 | "CAP" "(" Expr<et, q> ")"
|
|
|
+ 3532 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3533 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CAP"));
|
|
|
+ 3534 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3535 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3536 (. QbeGen.CapQ(q, qa);
|
|
|
+ 3537 QbeGen.CopyOp(qa, q);
|
|
|
+ 3538 t := SymTab.CharType(); .)
|
|
|
+ 3539 | "UCHR" "(" Expr<et, q> ")"
|
|
|
+ 3540 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3541 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UCHR"));
|
|
|
+ 3542 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3543 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3544 (. (* UCHR: the UCHAR constructor.
|
|
|
+ 3545 CHAR -> UCHAR (identity);
|
|
|
+ 3546 INTEGER familly -> UCHAR
|
|
|
+ 3547 (codepoint value). *)
|
|
|
+ 3548 IF (et # SymTab.InvalidType)
|
|
|
+ 3549 AND (SymTab.ClassOf(et) # SymTab.ClChar)
|
|
|
+ 3550 AND NOT SymTab.IsIntFamily(et) THEN
|
|
|
+ 3551 SemError(211) END;
|
|
|
+ 3552 t := SymTab.UCharType(); .)
|
|
|
+ 3553 | "CHR8" "(" Expr<et, q> ")"
|
|
|
+ 3554 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3555 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "CHR8"));
|
|
|
+ 3556 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3557 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3558 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3559 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3560 SemError(211) END;
|
|
|
+ 3561 QbeGen.WidenLong(q, qa);
|
|
|
+ 3562 QbeGen.CheckRange(qa, "0", "255");
|
|
|
+ 3563 t := SymTab.CharType(); .)
|
|
|
+ 3564 | "UORD" "(" Expr<et, q> ")"
|
|
|
+ 3565 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3566 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "UORD"));
|
|
|
+ 3567 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3568 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3569 (. (* UORD(u): the codepoint as a
|
|
|
+ 3570 32-bit ordinal (INTEGER),
|
|
|
+ 3571 cf. ORD for CHAR. *)
|
|
|
+ 3572 IF (et # SymTab.InvalidType)
|
|
|
+ 3573 AND (SymTab.ClassOf(et) # SymTab.ClUChar) THEN
|
|
|
+ 3574 SemError(211) END;
|
|
|
+ 3575 t := SymTab.IntType(); .)
|
|
|
+ 3576 | "ABS" "(" Expr<et, q> ")"
|
|
|
+ 3577 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3578 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "ABS"));
|
|
|
+ 3579 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 1, astCur) END;
|
|
|
+ 3580 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3581 (. IF (et # SymTab.InvalidType)
|
|
|
+ 3582 AND NOT SymTab.IsIntFamily(et)
|
|
|
+ 3583 AND (SymTab.ClassOf(et) #
|
|
|
+ 3584 SymTab.ClReal) THEN
|
|
|
+ 3585 SemError(211)
|
|
|
+ 3586 ELSE QbeGen.AbsQ(q, qa,
|
|
|
+ 3587 SymTab.ClassOf(et) =
|
|
|
+ 3588 SymTab.ClReal);
|
|
|
+ 3589 QbeGen.CopyOp(qa, q)
|
|
|
+ 3590 END;
|
|
|
+ 3591 t := et; .)
|
|
|
+ 3592 | "VAL" "(" GetIdent<vn> (. astArg2 := AST.MakeLeaf(AST.NkIdent, vn); .) "," Expr<et, q> ")"
|
|
|
+ 3593 (. astNode := AST.MakeNode(AST.NkCall);
|
|
|
+ 3594 AST.SetChild(astNode, 0, AST.MakeLeaf(AST.NkIdent, "VAL"));
|
|
|
+ 3595 IF astArg2 # AST.NoNode THEN AST.SetChild(astNode, 1, astArg2) END;
|
|
|
+ 3596 IF astCur # AST.NoNode THEN AST.SetChild(astNode, 2, astCur) END;
|
|
|
+ 3597 astCur := astNode; astIsLit := TRUE; .)
|
|
|
+ 3598 (. IF NOT SymTab.Lookup(vn) THEN
|
|
|
+ 3599 SemError(201);
|
|
|
+ 3600 t := SymTab.InvalidType
|
|
|
+ 3601 ELSE vt := SymTab.SymType(vn);
|
|
|
+ 3602 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3603 t := SymTab.InvalidType
|
|
|
+ 3604 ELSIF et =
|
|
|
+ 3605 SymTab.InvalidType THEN
|
|
|
+ 3606 t := vt
|
|
|
+ 3607 ELSE
|
|
|
+ 3608 c1 := SymTab.ClassOf(et);
|
|
|
+ 3609 c2 := SymTab.ClassOf(vt);
|
|
|
+ 3610 IF (c1 = SymTab.ClInt)
|
|
|
+ 3611 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3612 QbeGen.WidenLong(q, qa);
|
|
|
+ 3613 QbeGen.CopyOp(qa, q);
|
|
|
+ 3614 t := vt
|
|
|
+ 3615 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3616 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3617 QbeGen.NarrowLong(q, qa);
|
|
|
+ 3618 QbeGen.CopyOp(qa, q);
|
|
|
+ 3619 t := vt
|
|
|
+ 3620 ELSIF (c1 = SymTab.ClInt)
|
|
|
+ 3621 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3622 QbeGen.ConvIR(q, qa);
|
|
|
+ 3623 QbeGen.CopyOp(qa, q);
|
|
|
+ 3624 t := vt
|
|
|
+ 3625 ELSIF (c1 = SymTab.ClLong)
|
|
|
+ 3626 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3627 QbeGen.ConvLR(q, qa);
|
|
|
+ 3628 QbeGen.CopyOp(qa, q);
|
|
|
+ 3629 t := vt
|
|
|
+ 3630 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3631 AND (c2 = SymTab.ClInt) THEN
|
|
|
+ 3632 QbeGen.ConvRI(q, qa);
|
|
|
+ 3633 QbeGen.CopyOp(qa, q);
|
|
|
+ 3634 t := vt
|
|
|
+ 3635 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3636 AND (c2 = SymTab.ClLong) THEN
|
|
|
+ 3637 QbeGen.ConvRL(q, qa);
|
|
|
+ 3638 QbeGen.CopyOp(qa, q);
|
|
|
+ 3639 t := vt
|
|
|
+ 3640 ELSIF ((c1 = SymTab.ClInt)
|
|
|
+ 3641 OR (c1 =
|
|
|
+ 3642 SymTab.ClChar)
|
|
|
+ 3643 OR (c1 =
|
|
|
+ 3644 SymTab.ClBool)
|
|
|
+ 3645 OR (c1 =
|
|
|
+ 3646 SymTab.ClEnum))
|
|
|
+ 3647 AND ((c2 = SymTab.ClInt)
|
|
|
+ 3648 OR (c2 =
|
|
|
+ 3649 SymTab.ClChar)
|
|
|
+ 3650 OR (c2 =
|
|
|
+ 3651 SymTab.ClBool)
|
|
|
+ 3652 OR (c2 =
|
|
|
+ 3653 SymTab.ClEnum)) THEN
|
|
|
+ 3654 t := vt
|
|
|
+ 3655 ELSIF (c1 = SymTab.ClPtr)
|
|
|
+ 3656 AND (c2 = SymTab.ClPtr) THEN
|
|
|
+ 3657 t := vt
|
|
|
+ 3658 ELSIF (c1 = SymTab.ClReal)
|
|
|
+ 3659 AND (c2 = SymTab.ClReal) THEN
|
|
|
+ 3660 t := vt
|
|
|
+ 3661 ELSE SemError(230);
|
|
|
+ 3662 t := SymTab.InvalidType
|
|
|
+ 3663 END
|
|
|
+ 3664 END
|
|
|
+ 3665 END; .)
|
|
|
+ 3666 | "(" Expr<et, q> ")" (. t := et; astIsLit := TRUE; .)
|
|
|
+ 3667 | SetLit<st, sq> (. astIsLit := TRUE; t := st;
|
|
|
+ 3668 QbeGen.CopyOp(sq, q); .)
|
|
|
+ 3669 | ( "NOT" | "~" ) Fact<t2, q2> (. astNot := astCur;
|
|
|
+ 3670 IF SymTab.BoolCheck(t2) THEN
|
|
|
+ 3671 t := SymTab.BoolType()
|
|
|
+ 3672 ELSE SemError(212);
|
|
|
+ 3673 t := SymTab.InvalidType END;
|
|
|
+ 3674 IF t # SymTab.InvalidType THEN
|
|
|
+ 3675 QbeGen.NotQ(q2, q)
|
|
|
+ 3676 ELSE QbeGen.CopyOp("0", q)
|
|
|
+ 3677 END;
|
|
|
+ 3678 astIsLit := TRUE;
|
|
|
+ 3679 astCur := AST.MakeUn(
|
|
|
+ 3680 AST.NkUnary, AST.OpNot, astNot); .)
|
|
|
+ 3681 )
|
|
|
+ 3682 (. IF NOT astIsLit THEN astCur := AST.NoNode END; .) .
|
|
|
+ 3683 (* Set literals are SET OF [0..255] (8 words); elements validated
|
|
|
+ 3684 0..255 statically when foldable (222 otherwise), runtime trap
|
|
|
+ 3685 for computed elements. Ranges always lower via SetRange. *)
|
|
|
+ 3686 SetLit<VAR t: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3687 (. VAR astNode: AST.Node; .)
|
|
|
+ 3688 = "{" (. t := SymTab.NewSet(
|
|
|
+ 3689 SymTab.NewSubR(0, 255));
|
|
|
+ 3690 astNode := AST.MakeNode(AST.NkSetLit);
|
|
|
+ 3691 QbeGen.NewSetTemp(8, q);
|
|
|
+ 3692 QbeGen.SetZero(q, 8); .)
|
|
|
+ 3693 [ SetElem<t, q, astNode> { "," SetElem<t, q, astNode> } ]
|
|
|
+ 3694 "}" (. astCur := astNode; .) .
|
|
|
+ 3695 (* Typed brace constructor: TypeName{ elems } — BITSET{0} (a set)
|
|
|
+ 3696 or ArrayName{...} (an array constructor, GNU Modula-2). The
|
|
|
+ 3697 declared type sets the width (set) or element type (array). *)
|
|
|
+ 3698 TypedBraceLit<vt: SymTab.TypeIndex; VAR q: QbeGen.QVal>
|
|
|
+ 3699 (. VAR nw: CARDINAL;
|
|
|
+ 3700 astNode, astTail: AST.Node;
|
|
|
+ 3701 savedCls: INTEGER; .)
|
|
|
+ 3702 = "{" (. savedCls := braceCls;
|
|
|
+ 3703 astNode := AST.MakeNode(AST.NkBraceLit);
|
|
|
+ 3704 AST.SetTy(astNode, vt);
|
|
|
+ 3705 astTail := astNode;
|
|
|
+ 3706 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3707 braceCls := -1
|
|
|
+ 3708 ELSE braceCls :=
|
|
|
+ 3709 SymTab.ClassOf(vt)
|
|
|
+ 3710 END;
|
|
|
+ 3711 IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3712 IF vt = SymTab.InvalidType THEN
|
|
|
+ 3713 nw := 8
|
|
|
+ 3714 ELSE nw := SymTab.SetWords(vt);
|
|
|
+ 3715 IF nw = 0 THEN nw := 8 END
|
|
|
+ 3716 END;
|
|
|
+ 3717 QbeGen.NewSetTemp(nw, q);
|
|
|
+ 3718 QbeGen.SetZero(q, nw)
|
|
|
+ 3719 ELSIF (braceCls =
|
|
|
+ 3720 SymTab.ClArray)
|
|
|
+ 3721 OR (braceCls =
|
|
|
+ 3722 SymTab.ClRecord)
|
|
|
+ 3723 OR (braceCls =
|
|
|
+ 3724 SymTab.ClClass) THEN
|
|
|
+ 3725 QbeGen.CtorBegin(vt)
|
|
|
+ 3726 ELSE
|
|
|
+ 3727 IF vt # SymTab.InvalidType THEN
|
|
|
+ 3728 SemError(230) END;
|
|
|
+ 3729 braceCls := -1
|
|
|
+ 3730 END; .)
|
|
|
+ 3731 [ BraceElem<vt, q, astNode, astTail>
|
|
|
+ 3732 { "," BraceElem<vt, q, astNode, astTail> } ]
|
|
|
+ 3733 "}" (. IF (braceCls = SymTab.ClArray)
|
|
|
+ 3734 OR (braceCls =
|
|
|
+ 3735 SymTab.ClRecord)
|
|
|
+ 3736 OR (braceCls =
|
|
|
+ 3737 SymTab.ClClass) THEN
|
|
|
+ 3738 QbeGen.CtorEnd(q)
|
|
|
+ 3739 ELSIF braceCls # SymTab.ClSet THEN
|
|
|
+ 3740 QbeGen.CopyOp("0", q)
|
|
|
+ 3741 END;
|
|
|
+ 3742 braceCls := savedCls; .)
|
|
|
+ 3743 (. astCur := astNode; .) .
|
|
|
+ 3744 BraceElem<vt: SymTab.TypeIndex; VAR sq: QbeGen.QVal;
|
|
|
+ 3745 VAR node, tail: AST.Node>
|
|
|
+ 3746 (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3747 qe, q2: QbeGen.QVal;
|
|
|
+ 3748 v, v2, reps, k: INTEGER;
|
|
|
+ 3749 elem: SymTab.TypeIndex;
|
|
|
+ 3750 lo: INTEGER;
|
|
|
+ 3751 span: CARDINAL;
|
|
|
+ 3752 cl, cl2: INTEGER;
|
|
|
+ 3753 hasR, hasB: BOOLEAN;
|
|
|
+ 3754 astEl: AST.Node; .)
|
|
|
+ 3755 = (. hasR := FALSE; hasB := FALSE;
|
|
|
+ 3756 reps := 1; .)
|
|
|
+ 3757 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3758 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3759 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3760 hasR := TRUE; .) ]
|
|
|
+ 3761 [ "BY" Expr<et2, q2> (. hasB := TRUE; .) ]
|
|
|
+ 3762 (. IF braceCls = SymTab.ClSet THEN
|
|
|
+ 3763 IF hasB THEN SemError(230) END;
|
|
|
+ 3764 lo := SymTab.SetBaseLo(vt);
|
|
|
+ 3765 span := SymTab.SetCount(vt);
|
|
|
+ 3766 IF (et = SymTab.InvalidType)
|
|
|
+ 3767 OR (hasR AND (et2 =
|
|
|
+ 3768 SymTab.InvalidType)) THEN
|
|
|
+ 3769 ELSE cl :=
|
|
|
+ 3770 SymTab.ClassOf(et);
|
|
|
+ 3771 IF hasR THEN
|
|
|
+ 3772 cl2 :=
|
|
|
+ 3773 SymTab.ClassOf(et2)
|
|
|
+ 3774 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3775 END;
|
|
|
+ 3776 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3777 OR (hasR AND NOT
|
|
|
+ 3778 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3779 THEN
|
|
|
+ 3780 SemError(222)
|
|
|
+ 3781 ELSIF hasR
|
|
|
+ 3782 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3783 AND SymTab.ConstInt(q2,
|
|
|
+ 3784 v2)
|
|
|
+ 3785 AND ((v < lo)
|
|
|
+ 3786 OR (v2 < lo)
|
|
|
+ 3787 OR (v >= lo +
|
|
|
+ 3788 VAL(INTEGER, span))
|
|
|
+ 3789 OR (v2 >= lo +
|
|
|
+ 3790 VAL(INTEGER, span))
|
|
|
+ 3791 OR (v > v2)) THEN
|
|
|
+ 3792 SemError(222)
|
|
|
+ 3793 ELSIF hasR THEN
|
|
|
+ 3794 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3795 lo, span)
|
|
|
+ 3796 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3797 v)
|
|
|
+ 3798 AND ((v < lo)
|
|
|
+ 3799 OR (v >= lo +
|
|
|
+ 3800 VAL(INTEGER,
|
|
|
+ 3801 span))) THEN
|
|
|
+ 3802 SemError(222)
|
|
|
+ 3803 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3804 lo, span)
|
|
|
+ 3805 END
|
|
|
+ 3806 END
|
|
|
+ 3807 ELSIF (braceCls = SymTab.ClArray)
|
|
|
+ 3808 OR (braceCls =
|
|
|
+ 3809 SymTab.ClRecord)
|
|
|
+ 3810 OR (braceCls =
|
|
|
+ 3811 SymTab.ClClass) THEN
|
|
|
+ 3812 IF hasR THEN SemError(230) END;
|
|
|
+ 3813 reps := 1;
|
|
|
+ 3814 IF hasB THEN
|
|
|
+ 3815 IF SymTab.ConstInt(q2, v2)
|
|
|
+ 3816 AND (v2 >= 1) THEN
|
|
|
+ 3817 reps := v2
|
|
|
+ 3818 ELSE SemError(230)
|
|
|
+ 3819 END
|
|
|
+ 3820 END;
|
|
|
+ 3821 k := 0;
|
|
|
+ 3822 WHILE k < reps DO
|
|
|
+ 3823 QbeGen.CtorElem(qe);
|
|
|
+ 3824 INC(k)
|
|
|
+ 3825 END
|
|
|
+ 3826 END; .)
|
|
|
+ 3827 (. (* the BY form repeats the
|
|
|
+ 3828 element; keep the AST in
|
|
|
+ 3829 step with CtorElem *)
|
|
|
+ 3830 k := 0;
|
|
|
+ 3831 WHILE k < reps DO
|
|
|
+ 3832 AstAppend(AST.NkBlock,
|
|
|
+ 3833 node, tail, astEl);
|
|
|
+ 3834 INC(k)
|
|
|
+ 3835 END; .) .
|
|
|
+ 3836 SetElem<st: SymTab.TypeIndex; sq: QbeGen.QVal; node: AST.Node> (. VAR et, et2: SymTab.TypeIndex;
|
|
|
+ 3837 qe, q2: QbeGen.QVal;
|
|
|
+ 3838 v, v2: INTEGER;
|
|
|
+ 3839 lo: INTEGER;
|
|
|
+ 3840 span: CARDINAL;
|
|
|
+ 3841 cl, cl2: INTEGER;
|
|
|
+ 3842 hasR: BOOLEAN;
|
|
|
+ 3843 astEl: AST.Node; .)
|
|
|
+ 3844 = (. hasR := FALSE; .)
|
|
|
+ 3845 Expr<et, qe> (. astEl := astCur; .)
|
|
|
+ 3846 [ ".." Expr<et2, q2> (. astEl := AST.MakeBin(
|
|
|
+ 3847 AST.NkSubrange, 0, astEl, astCur);
|
|
|
+ 3848 hasR := TRUE; .) ]
|
|
|
+ 3849 (. lo := SymTab.SetBaseLo(st);
|
|
|
+ 3850 span := SymTab.SetCount(st);
|
|
|
+ 3851 IF (et = SymTab.InvalidType)
|
|
|
+ 3852 OR (hasR AND (et2 =
|
|
|
+ 3853 SymTab.InvalidType)) THEN
|
|
|
+ 3854 ELSE cl :=
|
|
|
+ 3855 SymTab.ClassOf(et);
|
|
|
+ 3856 IF hasR THEN
|
|
|
+ 3857 cl2 :=
|
|
|
+ 3858 SymTab.ClassOf(et2)
|
|
|
+ 3859 ELSE cl2 := SymTab.ClInt
|
|
|
+ 3860 END;
|
|
|
+ 3861 IF NOT SymTab.SetElemClassOk(cl)
|
|
|
+ 3862 OR (hasR AND NOT
|
|
|
+ 3863 SymTab.SetElemClassOk(cl2))
|
|
|
+ 3864 THEN
|
|
|
+ 3865 SemError(222)
|
|
|
+ 3866 ELSIF hasR
|
|
|
+ 3867 AND SymTab.ConstInt(qe, v)
|
|
|
+ 3868 AND SymTab.ConstInt(q2,
|
|
|
+ 3869 v2)
|
|
|
+ 3870 AND ((v < lo)
|
|
|
+ 3871 OR (v2 < lo)
|
|
|
+ 3872 OR (v >= lo +
|
|
|
+ 3873 VAL(INTEGER, span))
|
|
|
+ 3874 OR (v2 >= lo +
|
|
|
+ 3875 VAL(INTEGER, span))
|
|
|
+ 3876 OR (v > v2)) THEN
|
|
|
+ 3877 SemError(222)
|
|
|
+ 3878 ELSIF hasR THEN
|
|
|
+ 3879 QbeGen.SetRange(sq, qe, q2,
|
|
|
+ 3880 lo, span)
|
|
|
+ 3881 ELSIF SymTab.ConstInt(qe,
|
|
|
+ 3882 v)
|
|
|
+ 3883 AND ((v < lo)
|
|
|
+ 3884 OR (v >= lo +
|
|
|
+ 3885 VAL(INTEGER,
|
|
|
+ 3886 span))) THEN
|
|
|
+ 3887 SemError(222)
|
|
|
+ 3888 ELSE QbeGen.SetBit(sq, qe,
|
|
|
+ 3889 lo, span)
|
|
|
+ 3890 END
|
|
|
+ 3891 END; .)
|
|
|
+ 3892 (. AST.SetChild(node,
|
|
|
+ 3893 AST.NChild(node), astEl); .) .
|
|
|
+ 3894 GetIdent<VAR n: SymTab.Name>
|
|
|
+ 3895 = ident (. LexName(n); .) .
|
|
|
+ 3896
|
|
|
+ 3897 END M2.
|
|
|
|
|
|
0 errors
|
|
|
|