SaffronEnvironmentsImpl.Mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Sturgis, August 13, 1987 10:15:22 am PDT
Bill Jackson (bj) August 11, 1987 2:25:50 pm PDT
DIRECTORY
Rope USING[Equal, ROPE],
SaffronContext USING[ErrorSignal],
SaffronContextPrivateTypes USING [ AccessValNode, ContextTreeNode, InterfaceTGN, InterfaceTGNBody, LocalContextNode, TypeGraphNodeNode, VisibleNames ],
SaffronGenericDef USING [ IdNode ];
SaffronEnvironmentsImpl: CEDAR PROGRAM IMPORTS Rope, SaffronContext ~ {
OPEN SaffronContext, SaffronContextPrivateTypes, SaffronGenericDef;
An environment supplies an interface for each short file name (with no extension). There will be a recursive function (MakeInterface) that is supplied an environment and the parse tree of a definitions file, and returns with the interface defined by the definitions file, and a new environment. The new environment will contain all the interfaces of the given environment, the interface for the given definitions file, and an interface for any definition files that were directly or indirectly referenced by the given file, and not already in the given environment.
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]];
};
damages lc
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]];
ErrorSignal[];
END;
NameSequence
NameSequenceNode: TYPE = LIST OF IdNode;
EmptyNameSequence: PUBLIC PROC RETURNS[NameSequenceNode] =
{RETURN[NIL]};
InsertNameOnNameSequence: PUBLIC PROC[name: IdNode, ns: NameSequenceNode] RETURNS[NameSequenceNode] =
{RETURN[CONS[name, ns]]};
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 ErrorSignal[];
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];
}.