(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: CastExpr.m3 *) (* Last Modified On Tue Jun 30 08:33:41 PDT 1992 By kalsow *) (* Modified On Sun Dec 23 08:07:22 1990 By muller *) MODULE CastExpr; IMPORT Expr, ExprRep, Type, Emit, Error, Temp, MBuf, OpenArrayType; TYPE P = Expr.T BRANDED "CastExpr" OBJECT expr : Expr.T; tipe : Type.T; lvalue : BOOLEAN; OVERRIDES typeOf := ExprRep.NoType; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := Writer; isEqual := EqCheck; getBounds := Bounder; isWritable := IsWritable; isDesignator := IsDesignator; isZeroes := ExprRep.IsNever; note_write := NoteWrites; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (a: Expr.T; t: Type.T; lvalue: BOOLEAN): Expr.T = VAR p: P; BEGIN p := NEW (P); ExprRep.Init (p); p.origin := a.origin; p.expr := a; p.tipe := t; p.type := t; p.lvalue := lvalue; RETURN p; END New; PROCEDURE Check (p: P; VAR cs: Expr.CheckState) = VAR u, elt, elt2: Type.T; sz0, sz1: INTEGER; BEGIN Expr.TypeCheck (p.expr, cs); Type.Check (p.tipe); u := Expr.TypeOf (p.expr); IF OpenArrayType.Is (u) THEN Error.Msg ("LOOPHOLE: first argument cannot be an open array"); END; sz0 := Type.Size (u); IF OpenArrayType.Split (p.tipe, elt) THEN (* open array type *) IF OpenArrayType.Split (elt, elt2) THEN Error.Msg ("LOOPHOLE: two dimensional open arrays not supported"); END; sz1 := Type.Size (elt); IF (sz1 <= 0) OR ((sz0 MOD sz1) # 0) THEN Error.Msg ("LOOPHOLE: expression\'s size incompatible with type\'s"); END; ELSE (* fixed size type *) sz1 := Type.Size (p.tipe); IF (sz0 # sz1) THEN Error.Msg ("LOOPHOLE: expression\'s size differs from type\'s"); END; 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) AND (a.lvalue = b.lvalue); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = VAR t, u, elt: Type.T; e: Expr.T; t1, t2, t3: Temp.T; BEGIN e := p.expr; u := Expr.TypeOf (e); t := p.tipe; Type.Compile (t); IF OpenArrayType.Split (t, elt) THEN (* loophole to an open array type *) t2 := Expr.Compile (e); IF NOT Expr.IsDesignator (e) THEN (* copy the value to a temporary *) t1 := Temp.Alloc (e); Emit.OpTT ("@ = @;\n", t1, t2); Temp.Free (t2); t2 := t1; END; t1 := Temp.AllocEmpty (t, TRUE); Emit.OpT ("@.elts = ", t1); Emit.OpFT ("(@*)(& @);\n", elt, t2); Emit.OpTI ("@.size[0] = @;\n", t1, Type.Size (u) DIV Type.Size (elt)); Temp.Free (t2); RETURN t1; ELSIF NOT p.lvalue THEN t1 := Expr.Compile (e); t3 := Temp.AllocMacro (p, TRUE); Temp.Depend (t3, t1); RETURN t3; ELSIF NOT Expr.IsDesignator (e) THEN t2 := Expr.Compile (e); t1 := Temp.Alloc (e); Emit.OpTT ("@ = @;\n", t1, t2); Temp.Free (t2); t3 := Temp.AllocMacro (p, TRUE); Temp.Depend (t3, t1); RETURN t3; ELSE t1 := Expr.Compile (e); t3 := Temp.AllocMacro (p, TRUE); Temp.Depend (t3, t1); RETURN t3; END; END Compile; PROCEDURE Writer (p: P; t1: Temp.T; <*UNUSED*> t2: Temp.T) = BEGIN IF (p.lvalue) THEN Emit.OpFT ("(*((@*)(& @)))", p.tipe, t1); ELSE Emit.OpFT ("((@)@)", p.tipe, t1); END; END Writer; PROCEDURE Fold (p: P): Expr.T = VAR e: Expr.T; BEGIN e := Expr.ConstValue (p.expr); IF (e = NIL) THEN RETURN NIL END; p.expr := e; RETURN p; 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 p.lvalue AND Expr.IsDesignator (p.expr); END IsDesignator; PROCEDURE IsWritable (p: P): BOOLEAN = BEGIN RETURN p.lvalue AND 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, "LOOPHOLE "); Expr.Fingerprint (p.expr, map, wr); Type.Fingerprint (p.tipe, map, wr); END FPrinter; BEGIN END CastExpr.