(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: LongrealExpr.m3 *) (* Last modified on Tue Apr 10 22:36:18 1990 by muller *) (* modified on Sat Feb 10 17:36:38 1990 by kalsow *) MODULE LongrealExpr; IMPORT Expr, ExprRep, String, Longreal, Reel, Emit, Error; IMPORT Temp, Wr, Type, Fmt; CONST NOVALUE = -1.223456789d+31; TYPE P = Expr.T OBJECT str : String.T; val : LONGREAL; METHODS bind := ExprRep.NoBind; check := ExprRep.NoCheck; compile := Compile; evaluate := ExprRep.Self; fprint := FPrinter; write := Writer; isEqual := EqCheck; getBounds := ExprRep.NoBounds; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := IsZeroes; genLiteral := GenLiteral; END; PROCEDURE NewS (value: String.T): Expr.T = VAR p: P; BEGIN p := NEW (P); ExprRep.Init (p); p.str := value; p.val := NOVALUE; p.type := Longreal.T; p.bound := TRUE; p.checked := TRUE; RETURN p; END NewS; PROCEDURE New (value: LONGREAL): Expr.T = VAR p: P; BEGIN p := NEW (P); ExprRep.Init (p); p.str := NIL; p.val := value; p.type := Longreal.T; p.bound := TRUE; p.checked := TRUE; RETURN p; END New; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN ((a.str = b.str) AND (a.str # NIL)) OR ((a.val = b.val) AND (a.val # NOVALUE)); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = BEGIN RETURN Temp.FromExpr (p); END Compile; PROCEDURE Writer (p: P; <*UNUSED*> t1, t2: Temp.T) = BEGIN IF (p.str # NIL) THEN Emit.OpS (" @ ", p.str); ELSE Emit.OpR (" @ ", p.val); END; END Writer; PROCEDURE Split (e: Expr.T; VAR r: LONGREAL): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(p) => IF (p.val = NOVALUE) THEN p.val := Reel.Flt (p.str) END; r := p.val; RETURN TRUE; ELSE RETURN FALSE; END; END Split; PROCEDURE Compare (a, b: Expr.T; VAR sign: INTEGER): BOOLEAN = VAR x, y: LONGREAL; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF (x < y) THEN sign := -1 ELSIF (x > y) THEN sign := 1 ELSE sign := 0 END; RETURN TRUE; END Compare; PROCEDURE Add (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: LONGREAL; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; c := New (x + y); RETURN TRUE; END Add; PROCEDURE Subtract (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: LONGREAL; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; c := New (x - y); RETURN TRUE; END Subtract; PROCEDURE Multiply (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: LONGREAL; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; c := New (x * y); RETURN TRUE; END Multiply; PROCEDURE Divide (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: LONGREAL; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF (y = 0.0d+0) THEN Error.Msg ("attempt to divide by 0.0D+0"); RETURN FALSE; END; c := New (x / y); RETURN TRUE; END Divide; PROCEDURE Negate (a: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x: LONGREAL; BEGIN IF NOT Split (a, x) THEN RETURN FALSE END; c := New (-x); RETURN TRUE; END Negate; PROCEDURE SplitPair (a, b: Expr.T; VAR x, y: LONGREAL): BOOLEAN = BEGIN RETURN Split (a, x) AND Split (b, y); END SplitPair; PROCEDURE FPrinter (p: P; <*UNUSED*> map: Type.Map; wr: Wr.T) = BEGIN IF (p.str # NIL) THEN String.Put (wr, p.str); ELSE Wr.PutText (wr, Fmt.LongReal (p.val, 13, Fmt.Style.Sci)); END; END FPrinter; PROCEDURE IsZeroes (p: P): BOOLEAN = BEGIN IF (p.val = NOVALUE) THEN p.val := Reel.Flt (p.str) END; RETURN (p.val = 0.0d+0); END IsZeroes; PROCEDURE GenLiteral (p: P) = BEGIN IF (p.str # NIL) THEN Emit.OpS ("@", p.str); ELSE Emit.OpR ("@", p.val); END; END GenLiteral; BEGIN END LongrealExpr.