File: ReelExpr.m3 Last modified on Fri Feb 24 16:46:45 PST 1995 by kalsow modified on Tue Apr 10 22:38:17 1990 by muller
MODULE; IMPORT M3, CG, Expr, ExprRep, Type, Target, TInt, TFloat; IMPORT M3Buf, Int, LInt, Reel, LReel, EReel, IntegerExpr; TYPE P = Expr.T OBJECT val : Target.Float; OVERRIDES typeOf := ExprRep.NoType; check := ExprRep.NoCheck; need_addr := ExprRep.NotAddressable; prep := ExprRep.NoPrep; compile := Compile; prepLV := ExprRep.NotLValue; compileLV := ExprRep.NotLValue; prepBR := ExprRep.NotBoolean; compileBR := ExprRep.NotBoolean; evaluate := ExprRep.Self; isEqual := EqCheck; getBounds := ExprRep.NoBounds; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := IsZeroes; genFPLiteral := GenFPLiteral; prepLiteral := ExprRep.NoPrepLiteral; genLiteral := GenLiteral; note_write := ExprRep.NotWritable; END; PROCEDURE ReelExpr New (READONLY value: Target.Float): Expr.T = VAR p := NEW (P); BEGIN ExprRep.Init (p); p.val := value; p.checked := TRUE; CASE TFloat.Prec (value) OF | Target.Precision.Short => p.type := Reel.T; | Target.Precision.Long => p.type := LReel.T; | Target.Precision.Extended => p.type := EReel.T; END; RETURN p; END New; PROCEDUREEqCheck (a: P; e: Expr.T; <*UNUSED*> x: M3.EqAssumption): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN TFloat.EQ (a.val, b.val); ELSE RETURN FALSE; END; END EqCheck; PROCEDURECompile (p: P) = BEGIN CG.Load_float (p.val); END Compile; PROCEDURECompare (a, b: Expr.T; VAR sign: INTEGER): BOOLEAN = VAR x, y: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF TFloat.LT (x, y) THEN sign := -1 ELSIF TFloat.LT (y, x) THEN sign := +1 ELSE sign := 0 END; RETURN TRUE; END Compare; PROCEDUREAdd (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y, res: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF NOT TFloat.Add (x, y, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Add; PROCEDURESubtract (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y, res: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF NOT TFloat.Subtract (x, y, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Subtract; PROCEDUREMultiply (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y, res: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF NOT TFloat.Multiply (x, y, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Multiply; PROCEDUREDivide (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y, res: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF NOT TFloat.Divide (x, y, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Divide; PROCEDUREMod (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y, res: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF NOT TFloat.Mod (x, y, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Mod; PROCEDUREMin (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF TFloat.LT (x, y) THEN c := a; ELSE c := b; END; RETURN TRUE; END Min; PROCEDUREMax (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: Target.Float; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF TFloat.LT (x, y) THEN c := b; ELSE c := a; END; RETURN TRUE; END Max; PROCEDURENegate (a: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, zero, res: Target.Float; BEGIN IF NOT Split (a, x) THEN RETURN FALSE END; CASE TFloat.Prec (x) OF | Target.Precision.Short => zero := TFloat.ZeroR; | Target.Precision.Long => zero := TFloat.ZeroL; | Target.Precision.Extended => zero := TFloat.ZeroX; END; IF NOT TFloat.Subtract (zero, x, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Negate; PROCEDUREAbs (a: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, zero, res: Target.Float; BEGIN IF NOT Split (a, x) THEN RETURN FALSE END; CASE TFloat.Prec (x) OF | Target.Precision.Short => zero := TFloat.ZeroR; | Target.Precision.Long => zero := TFloat.ZeroL; | Target.Precision.Extended => zero := TFloat.ZeroX; END; IF NOT TFloat.LT (x, zero) THEN c := a; RETURN TRUE END; IF NOT TFloat.Subtract (zero, x, res) THEN RETURN FALSE END; c := New (res); RETURN TRUE; END Abs; PROCEDUREFloor (a: Expr.T; t: Type.T; VAR c: Expr.T): BOOLEAN = VAR x: Target.Float; res: Target.Int; n: CARDINAL; BEGIN IF t = Int.T THEN n := Target.Integer.bytes; ELSIF t = LInt.T THEN n := Target.Longint.bytes; ELSE RETURN FALSE END; IF NOT Split (a, x) THEN RETURN FALSE END; IF NOT TInt.FromInt (TFloat.Floor (x), n, res) THEN RETURN FALSE END; c := IntegerExpr.New (t, res); RETURN TRUE; END Floor; PROCEDURECeiling (a: Expr.T; t: Type.T; VAR c: Expr.T): BOOLEAN = VAR x: Target.Float; res: Target.Int; n: CARDINAL; BEGIN IF t = Int.T THEN n := Target.Integer.bytes; ELSIF t = LInt.T THEN n := Target.Longint.bytes; ELSE RETURN FALSE END; IF NOT Split (a, x) THEN RETURN FALSE END; IF NOT TInt.FromInt (TFloat.Ceiling (x), n, res) THEN RETURN FALSE END; c := IntegerExpr.New (t, res); RETURN TRUE; END Ceiling; PROCEDURETrunc (a: Expr.T; t: Type.T; VAR c: Expr.T): BOOLEAN = VAR x: Target.Float; res: Target.Int; n: CARDINAL; BEGIN IF t = Int.T THEN n := Target.Integer.bytes; ELSIF t = LInt.T THEN n := Target.Longint.bytes; ELSE RETURN FALSE END; IF NOT Split (a, x) THEN RETURN FALSE END; IF NOT TInt.FromInt (TFloat.Trunc (x), n, res) THEN RETURN FALSE END; c := IntegerExpr.New (t, res); RETURN TRUE; END Trunc; PROCEDURERound (a: Expr.T; t: Type.T; VAR c: Expr.T): BOOLEAN = VAR x: Target.Float; res: Target.Int; n: CARDINAL; BEGIN IF t = Int.T THEN n := Target.Integer.bytes; ELSIF t = LInt.T THEN n := Target.Longint.bytes; ELSE RETURN FALSE END; IF NOT Split (a, x) THEN RETURN FALSE END; IF NOT TInt.FromInt (TFloat.Round (x), n, res) THEN RETURN FALSE END; c := IntegerExpr.New (t, res); RETURN TRUE; END Round; PROCEDUREFloat (a: Expr.T; t: Type.T; VAR c: Expr.T): BOOLEAN = VAR i: INTEGER; x, res: Target.Float; new_pre: Target.Precision; BEGIN IF (t = Reel.T) THEN new_pre := Target.Precision.Short; ELSIF (t = LReel.T) THEN new_pre := Target.Precision.Long; ELSIF (t = EReel.T) THEN new_pre := Target.Precision.Extended; ELSE RETURN FALSE END; IF Split (a, x) THEN IF NOT TFloat.FloatF (x, new_pre, res) THEN RETURN FALSE END; ELSIF IntegerExpr.ToInt (a, i) THEN IF NOT TFloat.FloatI (i, new_pre, res) THEN RETURN FALSE END; ELSE RETURN FALSE; END; c := New (res); RETURN TRUE; END Float; PROCEDURESplitPair (a, b: Expr.T; VAR x, y: Target.Float): BOOLEAN = VAR t: Type.T; BEGIN TYPECASE a OF | NULL => RETURN FALSE; | P(p) => x := p.val; t := p.type; ELSE RETURN FALSE; END; TYPECASE b OF | NULL => RETURN FALSE; | P(p) => y := p.val; RETURN t = p.type; ELSE RETURN FALSE; END; END SplitPair; PROCEDURESplit (e: Expr.T; VAR x: Target.Float): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(p) => x := p.val; RETURN TRUE; ELSE RETURN FALSE; END; END Split; PROCEDUREIsZeroes (p: P; <*UNUSED*> lhs: BOOLEAN): BOOLEAN = BEGIN RETURN TFloat.EQ (TFloat.ZeroR, p.val) OR TFloat.EQ (TFloat.ZeroL, p.val) OR TFloat.EQ (TFloat.ZeroX, p.val); END IsZeroes; PROCEDUREGenFPLiteral (p: P; buf: M3Buf.T) = BEGIN IF p.type = Reel.T THEN M3Buf.PutText (buf, "REAL<"); ELSIF p.type = LReel.T THEN M3Buf.PutText (buf, "LREAL<"); ELSIF p.type = EReel.T THEN M3Buf.PutText (buf, "EREAL<"); ELSE <*ASSERT FALSE*> END; M3Buf.PutFloat (buf, p.val); M3Buf.PutChar (buf, '>'); END GenFPLiteral; PROCEDUREGenLiteral (p: P; offset: INTEGER; <*UNUSED*>type: Type.T; is_const: BOOLEAN) = BEGIN CG.Init_float (offset, p.val, is_const); END GenLiteral; BEGIN END ReelExpr.