|
|
@@ -49,6 +49,84 @@ PROCEDURE SelType (n: AST.Node; VAR t: SymTab.TypeIndex);
|
|
|
END
|
|
|
END SelType;
|
|
|
|
|
|
+PROCEDURE RelOp (op: INTEGER; VAR sop: INTEGER): BOOLEAN;
|
|
|
+(* AST relation operator -> SymTab relation operator. *)
|
|
|
+BEGIN
|
|
|
+ IF op = AST.OpEq THEN sop := SymTab.OpEq; RETURN TRUE
|
|
|
+ ELSIF op = AST.OpNe THEN sop := SymTab.OpNeq1; RETURN TRUE
|
|
|
+ ELSIF op = AST.OpLt THEN sop := SymTab.OpLt; RETURN TRUE
|
|
|
+ ELSIF op = AST.OpLe THEN sop := SymTab.OpLe; RETURN TRUE
|
|
|
+ ELSIF op = AST.OpGt THEN sop := SymTab.OpGt; RETURN TRUE
|
|
|
+ ELSIF op = AST.OpGe THEN sop := SymTab.OpGe; RETURN TRUE
|
|
|
+ END;
|
|
|
+ RETURN FALSE
|
|
|
+END RelOp;
|
|
|
+
|
|
|
+PROCEDURE EvalExpr (n: AST.Node): SymTab.TypeIndex;
|
|
|
+(* The type of an expression node: its stored type when known, else the
|
|
|
+ result of combining its (now typed) operands by the operator rules.
|
|
|
+ Mirrors the grammar's typing; set operators are left unknown. *)
|
|
|
+ VAR t, t2, res: SymTab.TypeIndex; op, k, sop: INTEGER;
|
|
|
+BEGIN
|
|
|
+ IF n < 0 THEN RETURN SymTab.InvalidType END;
|
|
|
+ t := AST.Ty(n);
|
|
|
+ IF t # -1 THEN RETURN t END;
|
|
|
+ k := AST.Kind(n);
|
|
|
+ op := AST.Op(n);
|
|
|
+ IF k = AST.NkBinExpr THEN
|
|
|
+ IF AST.Child(n, 0) < 0 THEN RETURN SymTab.InvalidType END;
|
|
|
+ t := EvalExpr(AST.Child(n, 0));
|
|
|
+ t2 := EvalExpr(AST.Child(n, 1));
|
|
|
+ IF (t = SymTab.InvalidType) OR (t2 = SymTab.InvalidType) THEN
|
|
|
+ RETURN SymTab.InvalidType
|
|
|
+ END;
|
|
|
+ IF (op = AST.OpAnd) OR (op = AST.OpOr) THEN
|
|
|
+ IF SymTab.BoolCheck(t) AND SymTab.BoolCheck(t2) THEN
|
|
|
+ RETURN SymTab.BoolType()
|
|
|
+ END
|
|
|
+ ELSIF op = AST.OpIn THEN
|
|
|
+ IF SymTab.InCheck(t, t2) THEN RETURN SymTab.BoolType() END
|
|
|
+ ELSIF RelOp(op, sop) THEN
|
|
|
+ IF SymTab.RelCheck(t, t2, sop) THEN RETURN SymTab.BoolType() END
|
|
|
+ ELSIF SymTab.ArithCheck(t, t2, (op = AST.OpDiv) OR (op = AST.OpMod),
|
|
|
+ res) THEN
|
|
|
+ RETURN res
|
|
|
+ END;
|
|
|
+ RETURN SymTab.InvalidType
|
|
|
+ ELSIF k = AST.NkUnary THEN
|
|
|
+ IF AST.Child(n, 0) < 0 THEN RETURN SymTab.InvalidType END;
|
|
|
+ t := EvalExpr(AST.Child(n, 0));
|
|
|
+ IF t = SymTab.InvalidType THEN RETURN t END;
|
|
|
+ IF op = AST.OpNot THEN
|
|
|
+ IF SymTab.BoolCheck(t) THEN RETURN SymTab.BoolType() END;
|
|
|
+ RETURN SymTab.InvalidType
|
|
|
+ END;
|
|
|
+ RETURN t
|
|
|
+ END;
|
|
|
+ RETURN t
|
|
|
+END EvalExpr;
|
|
|
+
|
|
|
+PROCEDURE PropNode (n: AST.Node);
|
|
|
+(* Post-order: re-type any expression node whose type is still unknown
|
|
|
+ (i.e. one whose operands included a forward reference). *)
|
|
|
+ VAR i: CARDINAL; k: INTEGER; t: SymTab.TypeIndex;
|
|
|
+BEGIN
|
|
|
+ IF n < 0 THEN RETURN END;
|
|
|
+ k := AST.Kind(n);
|
|
|
+ IF (k >= AST.NkIdent) AND (k <= AST.NkCharLit) THEN
|
|
|
+ RETURN (* a leaf: child 0 is a text index, not a node *)
|
|
|
+ END;
|
|
|
+ i := 0;
|
|
|
+ WHILE i < AST.NChild(n) DO
|
|
|
+ PropNode(AST.Child(n, i)); INC(i)
|
|
|
+ END;
|
|
|
+ IF (k >= AST.NkBinExpr) AND (k <= AST.NkSetLit)
|
|
|
+ AND (AST.Ty(n) = -1) THEN
|
|
|
+ t := EvalExpr(n);
|
|
|
+ IF t # -1 THEN AST.SetTy(n, t) END
|
|
|
+ END
|
|
|
+END PropNode;
|
|
|
+
|
|
|
PROCEDURE BeginSession (progName: ARRAY OF CHAR);
|
|
|
BEGIN
|
|
|
nFwd := 0
|
|
|
@@ -93,7 +171,8 @@ END FlushForward;
|
|
|
|
|
|
PROCEDURE Resolve (unit: AST.Node);
|
|
|
BEGIN
|
|
|
- FlushForward
|
|
|
+ FlushForward;
|
|
|
+ PropNode(unit)
|
|
|
END Resolve;
|
|
|
|
|
|
PROCEDURE EndSession;
|