(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: SubtractExpr.m3 *) (* Last modified on Fri Apr 27 23:48:43 1990 by muller *) (* modified on Sat Feb 10 20:16:52 1990 by kalsow *) MODULE SubtractExpr; IMPORT Expr, ExprAB, ExprRep, Type, Error, Int, Reel; IMPORT SetType, Address, Emit, Void, Module, AddressExpr, Temp; IMPORT IntegerExpr, RealExpr, LongrealExpr, SetExpr, Wr, Longreal; TYPE Class = { cINT, cREAL, cLONG, cADDR, cSET }; TYPE P = ExprAB.T OBJECT class: Class; METHODS bind := Bind; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := ExprRep.NoWriter; isEqual := ExprAB.EqCheck; getBounds := ExprRep.NoBounds; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := ExprRep.IsNever; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (a, b: Expr.T): Expr.T = VAR p: P; BEGIN p := NEW (P); ExprRep.Init (p); p.a := a; p.b := b; RETURN p; END New; PROCEDURE Bind (p: P) = VAR ta, tb, range: Type.T; BEGIN Expr.Bind (p.a); Expr.Bind (p.b); ta := Type.Base (Expr.TypeOf (p.a)); tb := Type.Base (Expr.TypeOf (p.b)); IF (ta = Int.T) AND (tb = Int.T) THEN p.class := Class.cINT; ELSIF (ta = Reel.T) AND (tb = Reel.T) THEN p.class := Class.cREAL; ELSIF (ta = Longreal.T) AND (tb = Longreal.T) THEN p.class := Class.cLONG; ELSIF SetType.Split (ta, range) THEN p.class := Class.cSET; ELSIF (tb = Int.T) THEN p.class := Class.cADDR; ta := Address.T; ELSE p.class := Class.cADDR; ta := Int.T; END; p.type := ta; END Bind; PROCEDURE Check (p: P) = VAR ta, tb: Type.T; BEGIN Expr.TypeCheck (p.a); Expr.TypeCheck (p.b); CASE p.class OF | Class.cINT, Class.cREAL, Class.cLONG => (* ok *) | Class.cSET => ta := Type.Base (Expr.TypeOf (p.a)); tb := Type.Base (Expr.TypeOf (p.b)); IF NOT Type.IsEqual (ta, tb) THEN Err () END; | Class.cADDR => ta := Type.Base (Expr.TypeOf (p.a)); tb := Type.Base (Expr.TypeOf (p.b)); IF NOT Type.IsSubtype (ta, Address.T) THEN Err (); ELSIF Module.IsSafe () THEN Error.Msg ("unsafe"); ELSIF (tb = Int.T) THEN (* ok *) ELSIF Type.IsSubtype (tb, Address.T) THEN (* ok *) ELSE Err (); END; END; END Check; PROCEDURE Err () = BEGIN Error.Msg ("illegal operands for \'-\'"); END Err; PROCEDURE Compile (p: P): Temp.T = VAR t1, t2, t3: Temp.T; BEGIN t1 := Expr.Compile (p.a); t2 := Expr.Compile (p.b); t3 := Temp.Alloc (p); CASE p.class OF | Class.cSET => SetExpr.CompileDiff (t1, t2, t3, p.type); | Class.cADDR => Emit.OpTI ("@ = (t@) (((char*)", t3, Type.Name (p.type)); Emit.OpTT ("@) - ((char *)@));\n", t1, t2); ELSE Emit.OpTTT ("@ = @ - @;\n", t3, t1, t2); END; Temp.Free (t1); Temp.Free (t2); RETURN t3; END Compile; PROCEDURE Fold (p: P): Expr.T = VAR e1, e2, e3: Expr.T; BEGIN e1 := Expr.ConstValue (p.a); e2 := Expr.ConstValue (p.b); e3 := NIL; IF (e1 = NIL) OR (e2 = NIL) THEN ELSIF IntegerExpr.Subtract (e1, e2, e3) THEN ELSIF RealExpr.Subtract (e1, e2, e3) THEN ELSIF LongrealExpr.Subtract (e1, e2, e3) THEN ELSIF AddressExpr.Subtract (e1, e2, e3) THEN ELSIF SetExpr.Difference (e1, e2, e3) THEN END; RETURN e3; END Fold; PROCEDURE FPrinter (p: P; map: Type.Map; wr: Wr.T) = BEGIN Wr.PutText (wr, "- "); Expr.Fingerprint (p.a, map, wr); Expr.Fingerprint (p.b, map, wr); END FPrinter; BEGIN END SubtractExpr.