(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: NarrowExpr.m3 *) (* Last Modified On Tue Jun 30 09:39:21 PDT 1992 by kalsow *) (* Modified On Fri Feb 15 04:03:39 1991 by muller *) MODULE NarrowExpr; IMPORT Expr, ExprRep, Type, Emit, Error, Host, Frame; IMPORT Reff, Null, ObjectType, Temp, MBuf, RefType, Fault; TYPE P = Expr.T BRANDED "NarrowExpr.P" OBJECT expr : Expr.T; tipe : Type.T; OVERRIDES typeOf := ExprRep.NoType; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := ExprRep.NoWriter; isEqual := EqCheck; getBounds := Bounder; isWritable := IsWritable; isDesignator := ExprRep.IsNever; isZeroes := ExprRep.IsNever; note_write := NoteWrites; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (a: Expr.T; t: Type.T; implicit: BOOLEAN): Expr.T = VAR p: P; BEGIN IF (implicit) AND (NOT Host.doNarrowChk) THEN RETURN a END; p := NEW (P); ExprRep.Init (p); p.expr := a; p.tipe := t; p.type := t; RETURN p; END New; PROCEDURE Check (p: P; VAR cs: Expr.CheckState) = VAR t, u: Type.T; BEGIN Expr.TypeCheck (p.expr, cs); Type.Check (p.tipe); p.type := p.tipe; u := Expr.TypeOf (p.expr); t := Type.Base (p.tipe); IF ObjectType.Is (t) THEN (* ok *) ELSIF ( NOT Type.IsSubtype (t, Reff.T)) THEN Error.Msg ("NARROW: must be a traced reference type"); ELSIF ( NOT Type.IsAssignable (t, u)) THEN Error.Msg ("NARROW: types must be assignable"); ELSE (* REF type *) (* ok *) END; END Check; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN TYPECASE e OF | NULL => RETURN FALSE; | P(b) => RETURN Type.IsEqual (a.tipe, b.tipe, NIL) AND Expr.IsEqual (a.expr, b.expr); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = VAR t, u, z: Type.T; e: Expr.T; t1, t2: Temp.T; block: INTEGER; BEGIN e := p.expr; u := Expr.TypeOf (e); t := p.tipe; z := Type.Base (t); Type.Compile (t); IF (Type.IsSubtype (u, t)) THEN t2 := Expr.Compile (e); ELSIF (Type.IsEqual (t, Null.T, NIL)) THEN t1 := Expr.Compile (e); t2 := Temp.Alloc (p); Emit.OpTT ("@ = ((_ADDRESS) @) == _NIL ? _NIL : ", t2, t1); Emit.OpF (" (@) ", t); Fault.Narrow (); Temp.Free (t1); ELSIF RefType.Is (t) THEN t1 := Expr.Compile (e); t2 := Temp.Alloc (p); Emit.OpT ("@ = ", t2); Emit.OpFT ("(@)@;\n", t, t1); Emit.OpT ("if (!_ISTYPE (@, ", t2); Emit.OpF ("@_TC)) ", t); Fault.Narrow (); Temp.Free (t1); ELSE t1 := Expr.Compile (e); t2 := Temp.Alloc (p); Emit.OpT ("@ = ", t2); Emit.OpFT ("(@)@;\n", t, t1); Emit.OpT ("if (@ != 0) ", t1); Frame.PushBlock (block, 1); Emit.OpT ("register int _tc = _TYPECODZ (@);\n", t2); Emit.OpF ("if (!_ISSUBTYPZ (_tc, @_TC)) ", t); Fault.Narrow (); Frame.PopBlock (block); Temp.Free (t1); END; RETURN t2; END Compile; PROCEDURE Fold (p: P): Expr.T = BEGIN RETURN Expr.ConstValue (p.expr); END Fold; PROCEDURE Bounder (p: P; VAR min, max: INTEGER) = VAR min1, max1: INTEGER; BEGIN Expr.GetBounds (p.expr, min, max); EVAL Type.GetBounds (p.tipe, min1, max1); min := MAX (min, min1); max := MIN (max, max1); END Bounder; (**************************************** PROCEDURE IsDesignator (p: P): BOOLEAN = BEGIN RETURN Expr.IsDesignator (p.expr); END IsDesignator; ******************************************) PROCEDURE IsWritable (p: P): BOOLEAN = BEGIN RETURN Expr.IsWritable (p.expr); END IsWritable; PROCEDURE NoteWrites (p: P) = BEGIN Expr.NoteWrite (p.expr); END NoteWrites; PROCEDURE FPrinter (p: P; map: Type.FPMap; wr: MBuf.T) = BEGIN MBuf.PutText (wr, "NARROW "); Expr.Fingerprint (p.expr, map, wr); Type.Fingerprint (p.tipe, map, wr); END FPrinter; BEGIN END NarrowExpr.