Environment
EnvironmentNode: TYPE ~ REF EnvironmentNodeBody;
EnvironmentNodeBody:
TYPE ~
RECORD [
interfaces: RopeNames
];
we use the same old data structure, hope to change it at some later date
CreateEmptyEnvironment:
PUBLIC
PROC
RETURNS [EnvironmentNode] ~ {
RETURN[NEW [EnvironmentNodeBody ← [CreateEmptyRopeNames[]] ]];
};
damages env and ifc
AddInterfaceToEnvironment:
PUBLIC
PROC [env: EnvironmentNode, fileName: Rope.ROPE,
ifc: InterfaceNode]
RETURNS [EnvironmentNode] ~ {
RecordRopeName[env.interfaces, fileName, ifc];
RETURN[env];
};
LookupInterfaceInEnv:
PUBLIC
PROC [env: EnvironmentNode, fileName: Rope.ROPE]
RETURNS [InterfaceNode] ~ {
RETURN[NARROW[LookupRopeName[env.interfaces, fileName]]];
};
IsInterfaceInEnv:
PROC [env: EnvironmentNode, fileName: Rope.ROPE]
RETURNS [
BOOLEAN] ~ {
RETURN[LookupRopeName[env.interfaces, fileName] # NIL];
};
Interfaces
Interfaces are not InterfaceTGNs. InterfaceTGNs occur inside type graphs, and point out to other contexts. Interfaces occur outside type graphs (and contexts) and point into contexts.
NOTE: We almost had to use proto and frozen interfaces, because we wanted to beable to have more than one module name for an interface. If this were implemented by adding the names one at a time, to the interface, this would make the interface a modifiable data structure, which must then be frozen when placed in an environment. However, by using NameSequences (see below), which are built non-destructively, and building the interface directly from the NameSequence and a contextTree, we avoid having malleable interfaces.
InterfaceNode: TYPE ~ REF InterfaceNodeBody;
InterfaceNodeBody:
TYPE ~
RECORD [
entries: VisibleNames
];
this procedure must be called after forming the context tree that contains the body of the definitions file. i.e., the names occurring in the locally visible names must be the names one expects to see in the interface
It is a little bit of a crock at the moment, because I do not have the data structures quite like I would like them.
CreateInterfaceFromContextTree:
PUBLIC
PROC [ct: ContextTreeNode, ns: NameSequenceNode]
RETURNS [in: InterfaceNode] ~ {
entries: VisibleNames ← CreateEmptyVisibleNames[];
typeNames: VisibleNames ← ct.rib.lc.lvtn; -- herein lies the crock
EnterOneName:
PROC [name: IdNode, access: AccessValNode, value:
REF
ANY] ~ {
tgn: TypeGraphNodeNode ← NARROW[value]; -- check
RecordVisibleName[entries, name, access, tgn];
};
GenVisibleNames[typeNames, EnterOneName];
RETURN[NEW [InterfaceNodeBody ← [entries]]];
};
used to create an interfaceTGN whole hog
GenInterfaceEntries:
PROC [in: InterfaceNode,
for:
PROC [name: IdNode, access: AccessValNode, tgn: TypeGraphNodeNode] ] ~ {
SeeOne:
PROC [name: IdNode, access: AccessValNode, value:
REF
ANY] ~ {
for[name, access, NARROW[value]];
};
GenVisibleNames[in.entries, SeeOne];
};
LookupInterfaceEntry:
PUBLIC
PROC [in: InterfaceNode, name: IdNode]
RETURNS [access: AccessValNode, tgn: TypeGraphNodeNode] ~ {
value: REF ANY;
[access, value] ← LookupVisibleName[in.entries, name];
RETURN[access, NARROW[value]];
};
There are two ways to create interfaceTGNs. One is directly from an interface, using all the entries. (Corresponds to directory line without out a Using clause). The other is by putting the names in one at a time. (Corresponds to a directory line with a Using clause.)
CreateEmptyInterfaceTGN:
PUBLIC
PROC [lc: LocalContextNode]
RETURNS [lcp: LocalContextNode, tgn: TypeGraphNodeNode] ~ {
body: InterfaceTGN ← NEW [InterfaceTGNBody ← [FALSE, CreateEmptyVisibleNames[] ]];
RETURN[lc, CreateTGN[lc, body]];
};
AddTGNToInterfaceTGN:
PUBLIC
PROC [lc: LocalContextNode, if: TypeGraphNodeNode, name: IdNode, access: AccessValNode, entryTgn: TypeGraphNodeNode]
RETURNS [lcp: LocalContextNode] ~ {
iftgn: InterfaceTGN ← NARROW[if.body];
RecordVisibleName[iftgn.typeNames, name, access, entryTgn];
RETURN[lc];
};
CreateInterfaceTGNFromInterface:
PUBLIC
PROC [lc: LocalContextNode, if: InterfaceNode]
RETURNS [lcp: LocalContextNode, tgn: TypeGraphNodeNode] ~ {
AddOne:
PROC [name: IdNode, access: AccessValNode, tgn: TypeGraphNodeNode] ~ {
[] ← AddTGNToInterfaceTGN[lc, tgn, name, access, tgn];
};
tgn ← CreateEmptyInterfaceTGN[lc].tgn;
GenInterfaceEntries[if, AddOne];
RETURN[lc, tgn];
ExportLocallyVisibleTGN: PUBLIC
PROC[lc: LocalContextNode, name: IdNode]
RETURNS[AccessValNode, TypeGraphNodeNode] =
BEGIN
ratgn: REF ANY;
access: AccessValNode;
[access, ratgn] ← LookupVisibleName[lc.lvtn, name];
IF ratgn # NIL THEN RETURN[access, NARROW[ratgn]];
ERROR SaffronErrorHandling.InternalError["SaffronEnvironmentsImpl.ExportLocallyVisibleTGN"];
END;
RopeNames
RopeNames: TYPE = REF RopeNamesBody;
RopeNamesBody: TYPE = RECORD[
first: RNCell];
RNCell: TYPE = REF RNCellBody; RNCellBody: TYPE = RECORD[
name: Rope.ROPE, value: REF ANY, next: RNCell];
CreateEmptyRopeNames: PROC RETURNS[rns: RopeNames] =
BEGIN
rns ← NEW[RopeNamesBody ← [NIL]];
RETURN[rns];
END;
RecordRopeName: PROC[rns: RopeNames, name: Rope.ROPE, val: REF ANY] =
BEGIN
newCell: RNCell ← NEW[RNCellBody←[name, val, rns.first]];
IF (LookupRopeName[rns, name] # NIL) THEN ERROR SaffronErrorHandling.InternalError["SaffronEnvironmentsImpl.RecordRopeName"];
rns.first ← newCell;
END;
LookupRopeName: PROC[rns: RopeNames, name: Rope.ROPE] RETURNS[REF ANY] =
BEGIN
cell: RNCell ← rns.first;
WHILE cell # NIL DO
IF Rope.Equal[cell.name, name] THEN RETURN[cell.value];
cell ← cell.next;
ENDLOOP;
RETURN[NIL];
END;
Misc
The following items will be supplied through some suitable interface, e.g., SaffronContextPrivateTypes. The code currently exists in SaffronContextImpl, but of course that is being broken up.
CreateEmptyVisibleNames: PROC RETURNS [VisibleNames];
RecordVisibleName: PROC [vn: VisibleNames, name: IdNode, access: AccessValNode,
value: REF ANY];
LookupVisibleName: PROC [vn: VisibleNames, name: IdNode]
RETURNS [access: AccessValNode, value: REF ANY];
GenVisibleNames: PROC [vn: VisibleNames,
for: PROC [name: IdNode, access: AccessValNode, value: REF ANY] ];
CreateTGN: PROC [lc: LocalContextNode, body: REF ANY]
RETURNS [tgn: TypeGraphNodeNode];
}.