(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: ConsExpr.m3 *) (* Last modified on Tue Feb 4 16:41:36 PST 1992 by kalsow *) (* modified on Fri Dec 14 21:41:11 1990 by muller *) MODULE ConsExpr; IMPORT Expr, ExprRep, Error, Type, Scope, RecordType, ArrayType, Temp; IMPORT SetType, TypeExpr, SetExpr, RecordExpr, ArrayExpr, MBuf, PackedType; TYPE Kind = { Unknown, Record, Set, Array }; TYPE P = Expr.T BRANDED "ConsExpr.P" OBJECT tipe : Expr.T; args : Expr.List; dots : BOOLEAN; base : Expr.T; kind : Kind; OVERRIDES typeOf := TypeOf; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := ExprRep.NoWriter; isEqual := EqCheck; getBounds := ExprRep.NoBounds; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := ExprRep.IsNever; note_write := ExprRep.NotWritable; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (type: Expr.T; args: Expr.List; dots: BOOLEAN): Expr.T = VAR p := NEW (P); BEGIN ExprRep.Init (p); p.tipe := type; p.args := args; p.dots := dots; p.base := NIL; p.kind := Kind.Unknown; RETURN p; END New; PROCEDURE TypeOf (p: P): Type.T = VAR ta: Type.T; BEGIN IF TypeExpr.Split (p.tipe, ta) THEN RETURN ta; ELSE RETURN Expr.TypeOf (p.tipe); END; END TypeOf; PROCEDURE Seal (p: P) = VAR ta, range, index, element: Type.T; fields: Scope.T; BEGIN IF (p.base # NIL) THEN RETURN END; IF NOT TypeExpr.Split (p.tipe, ta) THEN RETURN END; ta := PackedType.Strip (ta); IF RecordType.Split (ta, fields) THEN p.base := RecordExpr.New (ta, p.args); p.kind := Kind.Record; ELSIF SetType.Split (ta, range) THEN p.base := SetExpr.New (ta, p.args); p.kind := Kind.Set; ELSIF ArrayType.Split (ta, index, element) THEN p.base := ArrayExpr.New (ta, p.args, p.dots); p.kind := Kind.Array; END; END Seal; PROCEDURE Check (p: P; VAR cs: Expr.CheckState) = BEGIN Seal (p); Expr.TypeCheck (p.tipe, cs); p.type := TypeOf (p); IF (p.kind = Kind.Unknown) THEN Error.Msg ("constructor type must be array, record, or set type"); ELSIF (p.dots) AND (p.kind # Kind.Array) THEN Error.Msg ("tailing \'..\' in constructor, ignored"); END; FOR i := 0 TO LAST (p.args^) DO Expr.TypeCheck (p.args[i], cs) END; Expr.TypeCheck (p.base, cs); END Check; PROCEDURE EqCheck (a: P; e: Expr.T): BOOLEAN = BEGIN Seal (a); TYPECASE e OF | NULL => RETURN FALSE; | P(b) => Seal (b); RETURN Expr.IsEqual (a.base, b.base); ELSE RETURN Expr.IsEqual (a.base, e); END; END EqCheck; PROCEDURE Compile (p: P): Temp.T = VAR t: Type.T; BEGIN Seal (p); IF TypeExpr.Split (p.tipe, t) THEN Type.Compile (t) END; RETURN Expr.Compile (p.base); END Compile; PROCEDURE Fold (p: P): Expr.T = BEGIN Seal (p); RETURN Expr.ConstValue (p.base); END Fold; PROCEDURE FPrinter (p: P; map: Type.FPMap; wr: MBuf.T) = BEGIN Seal (p); MBuf.PutText (wr, "{} "); Expr.Fingerprint (p.base, map, wr); END FPrinter; BEGIN END ConsExpr.