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