The module contains procedures to gain necessary imports to compile a type.
MODULE\subsection{Producing import lists} The proceuderes; IMPORT Atom, AtomRefTbl, Type; ImportList
Import...
maintain
a list modules necessary to represent a type. This list is a
AtomRefTbl.T
which is only used in a set like fashion. There are no
entries in the table (NIL
is inserted together with the interface).
The main module called from outside is FromType()
.
REVEAL T = AtomRefTbl.Default BRANDED OBJECT END; PROCEDURE\subsection{Procedure Add} Add an elementFromType (type: Type.Object; methods: MethodList): T = VAR obj : Type.Reference := type; importTbl: T := NEW(T).init(); BEGIN IF type.name # NIL AND type.name.intf # nullAtm THEN EVAL importTbl.put(type.name.intf, NIL); END; ImportRevelations(type, importTbl); FOR i := 0 TO LAST(methods^) DO WITH sig = methods[i].sig DO ImportFromSig(sig, importTbl); ImportRefsFromSig(sig, importTbl); (* Hmm. StableData.m3 will not actually handle the exceptions. FOR j := 0 TO LAST(sig.raises^) DO ImportFromType(sig.raises[j].arg, importTbl); END; *) END (*WITH*) END; (*FOR*) WHILE obj # NIL AND ISTYPE(obj, Type.Object) DO IF obj.revIntf # NIL THEN EVAL importTbl.put(obj.revIntf, NIL); END; obj := NARROW(obj, Type.Object).super; END; RETURN importTbl; END FromType; PROCEDUREImportRevelations (t: Type.Reference; importTbl: T) = (* Add to the table "importTbl" the names of interfaces that provide revelations of "t" or one of its supertypes. *) BEGIN IF t.revIntf # NIL THEN EVAL importTbl.put(t.revIntf, NIL); END; TYPECASE t OF | Type.Object (obj) => VAR o := obj; BEGIN WHILE TRUE DO TYPECASE o.super OF | Type.Opaque => EXIT | Type.Object => IF o.revIntf # NIL THEN EVAL importTbl.put(o.revIntf, NIL); END; o := o.super; ELSE <*ASSERT FALSE*> END; END; END; ELSE END; END ImportRevelations; PROCEDUREImportFromType (t: Type.T; importTbl: T; byName: BOOLEAN := TRUE) = BEGIN IF t = NIL THEN RETURN END; IF t.name # NIL AND t.name.intf # nullAtm THEN EVAL importTbl.put(t.name.intf, NIL); END; TYPECASE t OF | Type.Reference (ref) => ImportRevelations(ref, importTbl); ELSE END; IF byName AND t.name # NIL THEN RETURN; END; TYPECASE t OF | Type.Enumeration, Type.UserDefined, Type.Real, Type.LongReal, Type.Extended => | Type.Subrange (sr) => ImportFromType(sr.base, importTbl); | Type.Object (ob) => ImportFromFields(ob.fields, importTbl); FOR i := 0 TO LAST(ob.methods^) DO ImportFromSig(ob.methods[i].sig, importTbl); END; IF ob.revIntf # NIL THEN EVAL importTbl.put(ob.revIntf, NIL); END; | Type.Ref (r) => ImportFromType(r.target, importTbl); | Type.Opaque (op) => ImportFromType(op.revealedSuperType, importTbl); | Type.Array (a) => ImportFromType(a.index, importTbl); ImportFromType(a.element, importTbl); | Type.Packed (p) => ImportFromType(p.base, importTbl); | Type.Record (rec) => ImportFromFields(rec.fields, importTbl); | Type.Set (s) => ImportFromType(s.range, importTbl); | Type.Procedure (p) => ImportFromSig(p.sig, importTbl); ELSE <*ASSERT FALSE*> END; END ImportFromType; PROCEDUREImportFromFields (fields: REF ARRAY OF Type.Field; importTbl: T) = BEGIN IF fields = NIL THEN RETURN END; FOR i := 0 TO LAST(fields^) DO ImportFromType(fields[i].type, importTbl); END; END ImportFromFields; PROCEDUREImportFromSig (sig: Type.Signature; importTbl: T) = BEGIN FOR i := 0 TO LAST(sig.formals^) DO ImportFromType(sig.formals[i].type, importTbl); END; ImportFromType(sig.result, importTbl); IF sig.raises # NIL THEN FOR i := 0 TO LAST(sig.raises^) DO EVAL importTbl.put(sig.raises[i].qid.intf, NIL); END; END; END ImportFromSig; PROCEDUREImportRefsFromSig (sig: Type.Signature; importTbl: T) = BEGIN FOR i := 0 TO LAST(sig.formals^) DO ImportRefsFromType(sig.formals[i].type, importTbl); END; ImportRefsFromType(sig.result, importTbl); END ImportRefsFromSig; PROCEDUREImportRefsFromType (t: Type.T; importTbl: T) = BEGIN IF t = NIL THEN RETURN END; TYPECASE t OF | Type.Enumeration, Type.UserDefined, Type.Real, Type.LongReal, Type.Extended, Type.Subrange, Type.Set, Type.Procedure => | Type.Reference => IF NOT Type.MayBeRefAny(t) AND Type.NamedType(t) THEN ImportFromType(t, importTbl) END; | Type.Array (a) => ImportFromType(a.index, importTbl); ImportRefsFromType(a.element, importTbl); | Type.Packed (p) => ImportRefsFromType(p.base, importTbl); | Type.Record (rec) => IF rec.fields = NIL THEN RETURN END; FOR i := 0 TO LAST(rec.fields^) DO ImportRefsFromType(rec.fields[i].type, importTbl); END; ELSE <*ASSERT FALSE*> END; END ImportRefsFromType;
intf
to a import list.
PROCEDURE\subsection{Procedure ToText} Generate a comma separated list of interface names out ofAdd (importList: T; intf: Atom.T) = BEGIN EVAL importList.put(intf, NIL) END Add;
imports
. The output is suitable for an
IMPORT
statement.
Iterate over the table imports
and append to result
.
PROCEDUREToText (imports: T): TEXT = VAR intf : Atom.T; dummy : REFANY; iter := imports.iterate(); result := ""; BEGIN IF iter.next(intf, dummy) THEN result := Atom.ToText(intf); WHILE iter.next(intf, dummy) DO result := result & ", " & Atom.ToText(intf); END; END; RETURN result; END ToText; VAR nullAtm := Atom.FromText(""); BEGIN END ImportList.