(* Copyright (C) 1989, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: Value.m3 *) (* Last modified on Thu May 17 01:30:38 1990 by muller *) (* modified on Tue Feb 27 08:29:16 1990 by kalsow *) MODULE Value EXPORTS Value, ValueRep; IMPORT Type, Expr, Error, Constant, Exceptionz, EnumElt, Wr, Text; IMPORT Field, Method, Module, Procedure, Formal, Temp, Emit; IMPORT Tipe, Variable, Ident, Token, Void, Scanner, Host, FPrint; IMPORT String, Revelation, TextWr, Scope; PROCEDURE Bind (t: T) = VAR save: INTEGER; BEGIN IF (t = NIL) THEN RETURN END; IF (t.bound) THEN RETURN END; t.bound := TRUE; save := Scanner.offset; Scanner.offset := t.origin; t.bind (); Scanner.offset := save; END Bind; PROCEDURE TypeOf (t: T): Type.T = BEGIN IF (t = NIL) THEN RETURN Void.T END; <* ASSERT t.bound *> RETURN t.type; END TypeOf; PROCEDURE TypeCheck (t: T) = VAR save: INTEGER; BEGIN IF (t = NIL) THEN RETURN END; IF (t.checked) THEN RETURN END; IF (t.incheck) THEN Error.Str (t.name, "recursive declaration"); RETURN; END; save := Scanner.offset; Scanner.offset := t.origin; t.incheck := TRUE; t.typeCheck (); t.incheck := FALSE; t.checked := TRUE; Scanner.offset := save; END TypeCheck; PROCEDURE Load (t: T): Temp.T = BEGIN IF (t = NIL) THEN RETURN Temp.FromValue (NIL) END; <* ASSERT t.checked *> RETURN t.load (); END Load; PROCEDURE Write (t: T) = BEGIN IF (t # NIL) THEN <* ASSERT t.checked *> t.write (); END; END Write; PROCEDURE SelectOne (a, b: T): T = BEGIN IF (a = NIL) THEN RETURN b END; IF (b = NIL) THEN RETURN a END; Scanner.offset := b.origin; RETURN a.select (b); END SelectOne; PROCEDURE ToExpr (t: T): Expr.T = BEGIN IF (t = NIL) THEN RETURN NIL END; RETURN t.toExpr (); END ToExpr; PROCEDURE ToType (t: T): Type.T = BEGIN IF (t = NIL) THEN RETURN NIL END; RETURN t.toType (); END ToType; PROCEDURE ClassOf (t: T): Class = BEGIN IF (t = NIL) THEN RETURN Class.Error END; RETURN t.class (); END ClassOf; PROCEDURE StorageClass (t: T): [0..3] = BEGIN IF (t.imported) THEN <* ASSERT NOT t.exported *> RETURN 1; ELSIF (t.exported) THEN <* ASSERT NOT t.imported *> IF (t.class() # Class.Procedure) OR Procedure.HasBody (t) THEN RETURN 0; ELSE RETURN 1; END; ELSIF Scope.OuterMost (t.scope) THEN RETURN 2; ELSE RETURN 3; END; END StorageClass; PROCEDURE GenStorageClass (t: T; considerExternal: BOOLEAN := TRUE) = BEGIN IF t.external THEN IF considerExternal OR (NOT t.exported) THEN Emit.Op ("IMPORT "); ELSE Emit.Op ("EXPORT "); END; ELSE CASE StorageClass (t) OF | 0 => IF Host.incrementalVersion > 0 THEN Emit.Op ("PRIVATE "); ELSE Emit.Op ("EXPORT "); END; | 1 => Emit.Op ("IMPORT "); | 2 => Emit.Op ("PRIVATE "); | 3 => IF t.class() = Class.Procedure THEN Emit.Op ("PRIVATE "); ELSE Emit.Op ("auto "); END; END; END; END GenStorageClass; VAR typeMap : Type.Map := NIL; fpWriter : Wr.T; fpBusy : BOOLEAN; PROCEDURE Declare0 (t: T) = VAR class: INTEGER; fpText: Text.T; BEGIN IF (t = NIL) THEN RETURN END; IF (t.declared) THEN RETURN END; class := StorageClass (t); IF (NOT t.used) AND (class = 1) THEN RETURN END; t.declared := TRUE; IF t.declare0 () AND (class # 2) AND (class # 3) AND Host.versionStamps THEN <* ASSERT NOT fpBusy *> fpBusy := TRUE; IF (typeMap = NIL) THEN typeMap := Type.NewMap (); fpWriter := TextWr.New (); END; FOR i := 0 TO LAST (typeMap^) DO typeMap[i] := 0 END; Fingerprint (t, typeMap, fpWriter); fpText := TextWr.ToText (fpWriter); t.fprint := FPrint.FromText (fpText); GenStorageClass (t, FALSE); Emit.OpN ("char VS@__", t); Emit.OpHH ("@@", t.fprint[0], t.fprint[1]); IF (class = 0) THEN Emit.Op (" = \'\\0\'") END; Emit.Op (";\n"); IF (Host.verbose) THEN Emit.Comment (fpText) END; fpBusy := FALSE; END; END Declare0; PROCEDURE Declare1 (t: T) = VAR save: INTEGER; BEGIN IF (t = NIL) THEN RETURN END; IF (t.compiled) THEN RETURN END; <* ASSERT t.checked *> t.compiled := TRUE; save := Scanner.offset; Scanner.offset := t.origin; t.declare1 (); Scanner.offset := save; END Declare1; PROCEDURE Declare2 (t: T) = VAR save: INTEGER; BEGIN IF (t = NIL) THEN RETURN; END; save := Scanner.offset; Scanner.offset := t.origin; t.declare2 (); Scanner.offset := save; END Declare2; PROCEDURE Fingerprint (t: T; map: Type.Map; wr: Wr.T) = BEGIN IF (t = NIL) THEN RETURN END; Wr.PutText (wr, "<"); String.Put (wr, t.name); Wr.PutText (wr, ": "); t.fingerprint (map, wr); Wr.PutText (wr, ">"); END Fingerprint; PROCEDURE NoteUse (t: T) = BEGIN IF (t = NIL) THEN RETURN END; IF (t.used) AND (NOT t.external) AND (StorageClass (t) = 1) (* imported *) AND (t.needsDecl ()) AND Host.versionStamps THEN (* make sure the version stamp is referenced *) Emit.OpN ("&VS@__", t); Emit.OpHH ("@@,\n", t.fprint[0], t.fprint[1]); END; END NoteUse; PROCEDURE Init (t: T; name: String.T) = BEGIN t.origin := Scanner.offset; t.name := name; t.scope := NIL; t.checked := FALSE; t.incheck := FALSE; t.readonly := FALSE; t.declared := FALSE; t.bound := FALSE; t.compiled := FALSE; t.imported := (Module.depth # 1); t.external := FALSE; t.exported := FALSE; t.used := FALSE; t.usedAtTop := FALSE; t.unused := FALSE; t.obsolete := FALSE; t.inFrame := FALSE; t.fprint[0] := 0; t.fprint[1] := 0; END Init; PROCEDURE NoDuplicates (a, b: T): T = BEGIN Error.Str (b.name, "symbol redefined"); RETURN a; END NoDuplicates; PROCEDURE NoExpr (<*UNUSED*> t: T): Expr.T = BEGIN <* ASSERT FALSE *> END NoExpr; PROCEDURE NoType (<*UNUSED*> t: T): Type.T = BEGIN <* ASSERT FALSE *> END NoType; PROCEDURE NoLoader (<*UNUSED*> t: T): Temp.T = BEGIN <* ASSERT FALSE *> END NoLoader; PROCEDURE NoWriter (<*UNUSED*> t: T) = BEGIN <* ASSERT FALSE *> END NoWriter; PROCEDURE NoDeclarer (<*UNUSED*> t: T) = BEGIN END NoDeclarer; PROCEDURE Never (<*UNUSED*> t: T): BOOLEAN = BEGIN RETURN FALSE; END Never; PROCEDURE Always (<*UNUSED*> t: T): BOOLEAN = BEGIN RETURN TRUE; END Always; PROCEDURE Initialize () = BEGIN Variable.Initialize (); Revelation.Initialize (); END Initialize; PROCEDURE IsExternal (t: T): BOOLEAN = BEGIN RETURN (t.external); END IsExternal; BEGIN END Value.