(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: CastExpr.m3 *) (* Last Modified On Tue Apr 10 11:24:33 1990 By muller *) (* Modified On Sat Feb 10 17:31:12 1990 By kalsow *) MODULE CastExpr; IMPORT Expr, ExprRep, Type, String, Emit, Error; IMPORT Temp, Wr, ArrayType; TYPE P = Expr.T OBJECT expr : Expr.T; tipe : Type.T; METHODS bind := Bind; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := Writer; isEqual := EqCheck; getBounds := Bounder; isWritable := IsWritable; isDesignator := IsDesignator; isZeroes := ExprRep.IsNever; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (a: Expr.T; t: Type.T): Expr.T = VAR p: P; BEGIN p := NEW (P); ExprRep.Init (p); p.expr := a; p.tipe := t; RETURN p; END New; PROCEDURE Bind (p: P) = BEGIN Expr.Bind (p.expr); p.tipe := Type.Bind (p.tipe); p.type := p.tipe; END Bind; PROCEDURE Check (p: P) = VAR u, index, elt, elt2: Type.T; sz0, sz1: INTEGER; BEGIN Expr.TypeCheck (p.expr); Type.Check (p.tipe); u := Expr.TypeOf (p.expr); IF (ArrayType.Split (u, index, elt)) AND (index = NIL) THEN Error.Msg ("LOOPHOLE: first argument cannot be an open array"); END; sz0 := Type.Size (u); IF (ArrayType.Split (p.tipe, index, elt)) AND (index = NIL) THEN (* open array type *) IF (ArrayType.Split (elt, index, elt2)) AND (index = NIL) 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: expresion\'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) AND Expr.IsEqual (a.expr, b.expr); ELSE RETURN FALSE; END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = VAR t, u, index, elt: Type.T; e: Expr.T; t1, t2, t3: Temp.T; BEGIN e := p.expr; u := Expr.TypeOf (e); t := p.tipe; IF Type.SameImpl (u, t) THEN RETURN Expr.Compile (e); ELSIF (ArrayType.Split (t, index, elt)) AND (index = NIL) THEN (* loophole to an open array type *) t2 := Expr.Compile (e); t1 := Temp.AllocEmpty (ArrayType.OpenImpl (t), TRUE); Emit.OpTT ("@.elts = (char*) (& @);\n", t1, t2); Emit.OpTI ("@.size[0] = @;\n", t1, Type.Size (u) DIV Type.Size (elt)); Temp.Free (t2); RETURN t1; 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 Emit.OpIT ("(*((t@*)(& @)))", Type.Name (p.tipe), t1); 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); 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 FPrinter (p: P; map: Type.Map; wr: Wr.T) = BEGIN Wr.PutText (wr, "LOOPHOLE "); Expr.Fingerprint (p.expr, map, wr); Type.Fingerprint (p.tipe, map, wr); END FPrinter; BEGIN END CastExpr.