(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: IntegerExpr.m3 *) (* Last modified on Fri Dec 13 08:36:09 PST 1991 by kalsow *) (* modified on Tue Apr 10 22:35:24 1990 by muller *) MODULE IntegerExpr; IMPORT Expr, ExprRep, Type, Int, Emit, Error, Temp, MBuf; TYPE P = Expr.T BRANDED "IntegerExpr.T" OBJECT value: INTEGER; OVERRIDES typeOf := ExprRep.NoType; check := ExprRep.NoCheck; compile := Compile; evaluate := ExprRep.Self; fprint := FPrinter; write := Writer; isEqual := EqCheck; getBounds := Bounder; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := IsZeroes; note_write := ExprRep.NotWritable; genLiteral := GenLiteral; END; VAR cache: ARRAY [-7 .. 31] OF P; PROCEDURE New (value: INTEGER): Expr.T = VAR p: P; BEGIN IF (FIRST (cache) <= value) AND (value <= LAST (cache)) AND (cache[value] # NIL) THEN RETURN cache[value]; END; p := NEW (P); ExprRep.Init (p); p.value := value; p.type := Int.T; p.checked := TRUE; IF (FIRST (cache) <= value) AND (value <= LAST (cache)) THEN cache[value] := p; END; RETURN p; END New; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN (a.value = b.value); 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 Emit.OpI (" @ ", p.value); END Writer; PROCEDURE Bounder (p: P; VAR min, max: INTEGER) = BEGIN min := p.value; max := p.value; END Bounder; PROCEDURE Compare (a, b: Expr.T; VAR sign: INTEGER): BOOLEAN = VAR x, y: INTEGER; 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: INTEGER; 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: INTEGER; 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: INTEGER; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; c := New (x * y); RETURN TRUE; END Multiply; PROCEDURE Div (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: INTEGER; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF (y = 0) THEN Error.Msg ("attempt to DIV by 0"); RETURN FALSE END; c := New (x DIV y); RETURN TRUE; END Div; PROCEDURE Mod (a, b: Expr.T; VAR c: Expr.T): BOOLEAN = VAR x, y: INTEGER; BEGIN IF NOT SplitPair (a, b, x, y) THEN RETURN FALSE END; IF (y = 0) THEN Error.Msg ("attempt to MOD by 0"); RETURN FALSE END; c := New (x MOD y); RETURN TRUE; END Mod; PROCEDURE Negate (a: Expr.T; VAR c: Expr.T): BOOLEAN = BEGIN TYPECASE a OF | NULL => RETURN FALSE; | P(p) => c := New (-p.value); RETURN TRUE; ELSE RETURN FALSE; END; END Negate; PROCEDURE SplitPair (a, b: Expr.T; VAR x, y: INTEGER): BOOLEAN = BEGIN TYPECASE a OF | NULL => RETURN FALSE; | P(p) => x := p.value; ELSE RETURN FALSE; END; TYPECASE b OF | NULL => RETURN FALSE; | P(p) => y := p.value; RETURN TRUE; ELSE RETURN FALSE; END; END SplitPair; PROCEDURE Split (e: Expr.T; VAR value: INTEGER): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(p) => value := p.value; RETURN TRUE; ELSE RETURN FALSE; END; END Split; PROCEDURE FPrinter (p: P; <*UNUSED*> map: Type.FPMap; wr: MBuf.T) = BEGIN MBuf.PutInt (wr, p.value); END FPrinter; PROCEDURE IsZeroes (p: P): BOOLEAN = BEGIN RETURN (p.value = 0); END IsZeroes; PROCEDURE GenLiteral (p: P) = BEGIN Emit.OpI ("@", p.value); END GenLiteral; BEGIN FOR i := FIRST (cache) TO LAST (cache) DO cache[i] := NIL END; END IntegerExpr.