(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: CheckExpr.m3 *) (* Last Modified On Mon Mar 2 10:41:38 PST 1992 By kalsow *) (* Modified On Fri Feb 15 04:03:38 1991 By muller *) MODULE CheckExpr; IMPORT Expr, ExprRep, Type, Emit, IntegerExpr, EnumExpr, Temp, MBuf; IMPORT Host, Fault; TYPE Class = { cLOWER, cUPPER, cBOTH }; TYPE P = Expr.T OBJECT expr : Expr.T; min : INTEGER; max : INTEGER; class : Class; OVERRIDES typeOf := TypeOf; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := ExprRep.NoWriter; isEqual := EqCheck; getBounds := Bounder; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := ExprRep.IsNever; note_write := ExprRep.NotWritable; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (a: Expr.T; min, max: INTEGER): Expr.T = BEGIN RETURN Create (a, min, max, Class.cBOTH); END New; PROCEDURE NewLower (a: Expr.T; min: INTEGER): Expr.T = BEGIN RETURN Create (a, min, 0, Class.cLOWER); END NewLower; PROCEDURE NewUpper (a: Expr.T; max: INTEGER): Expr.T = BEGIN RETURN Create (a, 0, max, Class.cUPPER); END NewUpper; PROCEDURE Create (a: Expr.T; min, max: INTEGER; c: Class): Expr.T = VAR p: P; BEGIN IF (NOT Host.doRangeChk) THEN RETURN a END; p := NEW (P); ExprRep.Init (p); p.expr := a; p.min := min; p.max := max; p.class := c; p.origin := a.origin; RETURN p; END Create; PROCEDURE TypeOf (p: P): Type.T = BEGIN RETURN Expr.TypeOf (p.expr); END TypeOf; PROCEDURE Check (p: P; VAR cs: Expr.CheckState) = BEGIN Expr.TypeCheck (p.expr, cs); END Check; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN (a.class = b.class) AND (a.min = b.min) AND (a.max = b.max) AND Expr.IsEqual (a.expr, b.expr); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = VAR t1, t2: Temp.T; BEGIN t1 := Expr.Compile (p.expr); t2 := Temp.Alloc (p); Emit.OpTT ("@ = @;\nif ", t2, t1); CASE p.class OF | Class.cLOWER => Emit.OpTI ("(@ < @) ", t2, p.min); | Class.cUPPER => Emit.OpTI ("(@ > @) ", t2, p.max); | Class.cBOTH => Emit.OpTI ("((@ < @) ", t2, p.min); Emit.OpIT ("|| (@ < @)) ", p.max, t2); END; Fault.Range (); Temp.Free (t1); RETURN t2; END Compile; PROCEDURE Fold (p: P): Expr.T = VAR e: Expr.T; i: INTEGER; t: Type.T; BEGIN e := Expr.ConstValue (p.expr); IF (e = NIL) THEN RETURN NIL END; IF (NOT IntegerExpr.Split (e, i)) AND (NOT EnumExpr.Split (e, i, t)) THEN RETURN NIL; END; CASE p.class OF | Class.cLOWER => IF (p.min > i) THEN RETURN NIL END; | Class.cUPPER => IF (p.max < i) THEN RETURN NIL END; | Class.cBOTH => IF (i < p.min) OR (p.max < i) THEN RETURN NIL END; END; RETURN e; END Fold; PROCEDURE Bounder (p: P; VAR min, max: INTEGER) = BEGIN Expr.GetBounds (p.expr, min, max); CASE p.class OF | Class.cLOWER => min := MAX (min, p.min); | Class.cUPPER => max := MIN (max, p.max); | Class.cBOTH => min := MAX (min, p.min); max := MIN (max, p.max); END; END Bounder; PROCEDURE FPrinter (p: P; map: Type.FPMap; wr: MBuf.T) = BEGIN CASE p.class OF | Class.cLOWER => MBuf.PutText (wr, "CHKL "); MBuf.PutInt (wr, p.min); MBuf.PutText (wr, " "); | Class.cUPPER => MBuf.PutText (wr, "CHKH "); MBuf.PutInt (wr, p.max); MBuf.PutText (wr, " "); | Class.cBOTH => MBuf.PutText (wr, "CHKR "); MBuf.PutInt (wr, p.min); MBuf.PutText (wr, " "); MBuf.PutInt (wr, p.max); MBuf.PutText (wr, " "); END; Expr.Fingerprint (p.expr, map, wr); END FPrinter; BEGIN END CheckExpr.