CDImportsImpl.mesa (part of ChipNDale)
Copyright © 1984, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, March 20, 1984 5:50:51 pm PST
Last edited by: Christian Jacobi, September 2, 1986 5:09:06 pm PDT
DIRECTORY
CD,
CDBasics,
CDCallSpecific,
CDDirectory,
CDDirectoryOps,
CDEnvironment,
CDEvents,
CDGenerate,
CDRemote,
CDImports,
CDImportsExtras,
CDInstances,
CDIO,
CDOps,
CDOrient,
CDProperties,
CDValue,
Rope,
SymTab,
TerminalIO,
TokenIO,
UserProfile;
CDImportsImpl: CEDAR PROGRAM
IMPORTS CD, CDBasics, CDDirectory, CDDirectoryOps, CDEnvironment, CDEvents, CDGenerate, CDRemote, CDInstances, CDIO, CDOps, CDOrient, CDProperties, CDValue, Rope, SymTab, TerminalIO, TokenIO, UserProfile
EXPORTS CDImports, CDImportsExtras
SHARES CDDirectory, CDRemote =
BEGIN
ROPE: TYPE = Rope.ROPE;
BoolOrInteractive: TYPE = CDImports.BoolOrInteractive;
ImportPtr: TYPE = CDImports.ImportPtr;
ImportRep: TYPE = CDImports.ImportRep;
ImportList: TYPE = CDImports.ImportList;
ImportDesign: TYPE = CDImports.ImportDesign;
ImpList: TYPE = LIST OF REF ImportDesign;
importListKey: ATOM = $ImportList; -- for CDValue
importsClass: PUBLIC CD.ObjectClass = CD.RegisterObjectClass[$Import, [
drawMe: DrawForImport,
quickDrawMe: QuickDrawReference,
showMeSelected: DrawSelectionForImport,
internalRead: ReadImportOb,
internalWrite: WriteImportOb,
describe: DescribeImport,
interestRect: InterestRect
]];
ImpOfDesign: TYPE = REF ImpOfDesignRec;
ImpOfDesignRec: TYPE = RECORD [
d: CD.Design←NIL,
obTab: SymTab.Ref←
];
EachImpOb: PROC [priv: ImpOfDesign, proc: PROC [ob: CD.Object]] = {
EachPair: PROC [key: REF, val: REF] RETURNS [quit: BOOLFALSE] = {proc[NARROW[val]]};
[] ← SymTab.Pairs[priv.obTab, EachPair]
};
NewPerImpDesign: PROC RETURNS [handle: ImpOfDesign] = {
handle ← NEW[ImpOfDesignRec←[obTab: SymTab.Create[17]]]
};
EnumerateItsObjects: PROC [me: CD.Object, p: CDDirectory.EnumerateObjectsProc, x: REF] = {
dont !!!
the imported objects are not part of this design
};
ReplaceDirectChild: CDDirectory.ReplaceDChildsProc = {
-- PROC[me: CD.Object, design: CD.Design, replace: LIST OF REF ReplaceRec] --
dont, don't ERROR:
don't ERROR, because the client doese not know that imports cannot be changed
};
InternalCreateImport: PROC [into: CD.Design,
size: CD.Position←[1, 1], ir: CD.Rect ← [0, 0, -1, -1],
objectName, importeeName: ROPE,
autoLoad: BOOLFALSE, --loads file if neccessary; if loaded, import design is made
autoImport: BOOLFALSE, --import design even if not loaded successfully
autoCreateOb: BOOLFALSE, --creates ob if not found or design not loaded (but not if import not made)
allowConflicts: BoolOrInteractive�lse, --allow size conflicts on the object
include: BOOLTRUE]
RETURNS [ob: CD.Object ← NIL]
= {
referedOb: CD.Object ← NIL; iR: CD.Rect;
import: REF ImportDesign;
impPriv: ImpOfDesign;
probablySize: CD.Position ← CDBasics.MaxPoint[size, [1, 1]];
--make an import of the importee design
import ← GetImportEntry[into, importeeName, false];
IF (import=NIL OR ~import.loaded) AND autoLoad THEN {
loaded: BOOL ← Load[into: into, importeeName: importeeName, overload: false, allowConflicts: false];
IF loaded AND import=NIL THEN import ← GetImportEntry[into, importeeName, false];
};
IF import=NIL AND autoImport THEN import ← GetImportEntry[into, importeeName, true];
IF import=NIL THEN RETURN [NIL];
--search for an already existing import object
IF CDBasics.NonEmpty[ir] THEN iR ← ir ELSE iR ← CDBasics.RectAt[[0, 0], probablySize];
impPriv ← NARROW[import.reservedForCDImports];
WITH SymTab.Fetch[impPriv.obTab, objectName].val SELECT FROM
ob: CD.Object => {
IF ob.size=size AND (CD.InterestRect[ob]=iR OR ~CDBasics.NonEmpty[ir]) THEN
RETURN [ob];
IF allowConflicts=true THEN RETURN [ob];
IF allowConflicts=interactive AND TerminalIO.Confirm[choice: "ignore", label: "size conflicts"] THEN RETURN [ob];
RETURN [NIL]
};
ENDCASE => NULL;
--already existing imported object not found; make new object
--if not load, trust for the size... it is checked at binding time
IF import.loaded THEN referedOb ← CDDirectory.Fetch[impPriv.d, objectName].object;
IF referedOb=NIL AND ~autoCreateOb THEN RETURN [NIL];
IF allowConflicts=true AND referedOb#NIL THEN {
probablySize ← referedOb.size; iR ← CD.InterestRect[referedOb];
};
ob ← NEW[CD.ObjectRep←[
size: probablySize,
class: importsClass,
layer: CD.undefLayer,
specificRef: NEW[ImportRep ← [
objectName: objectName,
ir: iR,
designName: importeeName
]]
]];
[] ← SymTab.Store[impPriv.obTab, objectName, ob];
IF include THEN
[] ← CDDirectory.Include[design: into, object: ob, alternateName: Rope.Cat[importeeName, ".", objectName]];
IF import.loaded THEN [] ← BindObject[into, ob, impPriv.d, allowConflicts];
};
CreateImport: PUBLIC PROC [into: CD.Design, objectName, importeeName: ROPE] RETURNS [ob: CD.Object] = {
ob ← InternalCreateImport[into: into, objectName: objectName, importeeName: importeeName, autoCreateOb: FALSE, autoImport: FALSE, autoLoad: TRUE, allowConflicts: true, include: TRUE];
};
ShortName: PROC [me: CD.Object, iPtr: ImportPtr] RETURNS [n: ROPE] = INLINE {
n ← CDDirectory.Name[me];
IF Rope.IsEmpty[n] THEN n ← iPtr.objectName;
};
DescribeImport: PROC[me: CD.Object] RETURNS [ROPE] = {
iPtr: ImportPtr = NARROW[me.specificRef];
RETURN [Rope.Cat["reference to ", iPtr.designName, ".", iPtr.objectName]];
};
MapIR: PROC [ob: CD.Object, pos: CD.Position, orient: CD.Orientation] RETURNS [CD.Rect] = INLINE {
RETURN [CDOrient.MapRect[
itemInCell: CD.InterestRect[ob],
cellSize: ob.size,
cellInstOrient: orient,
cellInstPos: pos
]]
};
DrawForImport: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = {
iPtr: ImportPtr = NARROW[inst.ob.specificRef];
IF iPtr.boundInstance#NIL THEN
pr.drawChild[iPtr.boundInstance, pos, orient, pr]
ELSE {
r: CD.Rect = MapIR[inst.ob, pos, orient];
pr.drawRect[r, CD.shadeLayer, pr];
pr.drawComment[r, ShortName[inst.ob, iPtr], pr];
}
};
QuickDrawReference: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = {
iPtr: ImportPtr = NARROW[inst.ob.specificRef];
IF iPtr.boundInstance#NIL THEN
iPtr.boundInstance.ob.class.quickDrawMe[iPtr.boundInstance, pos, orient, pr]
ELSE {
r: CD.Rect = MapIR[inst.ob, pos, orient];
pr.drawRect[r, CD.shadeLayer, pr];
pr.drawComment[r, ShortName[inst.ob, iPtr], pr];
}
};
DrawSelectionForImport: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = {
iPtr: ImportPtr = NARROW[inst.ob.specificRef];
IF iPtr.boundInstance#NIL THEN
iPtr.boundInstance.ob.class.showMeSelected[iPtr.boundInstance, pos, orient, pr]
ELSE
pr.drawOutLine[MapIR[inst.ob, pos, orient], CD.selectionLayer, pr]
};
InterestRect: PROC [ob: CD.Object] RETURNS [CD.Rect] = {
RETURN [NARROW[ob.specificRef, ImportPtr].ir]
};
WriteImportOb: CD.InternalWriteProc -- PROC [me: Object] -- = {
iPtr: ImportPtr = NARROW[me.specificRef];
CDIO.WritePos[me.size];
CDIO.WriteRect[iPtr.ir];
TokenIO.WriteRope[iPtr.objectName];
TokenIO.WriteRope[iPtr.designName];
};
ReadImportOb: CD.InternalReadProc --PROC [] RETURNS [Object]-- = {
sz: CD.Position = CDIO.ReadPos[];
ir: CD.Rect;
objectName: ROPE;
importeeName: ROPE;
ob: CD.Object;
IF CDIO.VersionKey[] >= 8 THEN ir ← CDIO.ReadRect[]
ELSE ir ← CDBasics.RectAt[[0, 0], sz];
objectName ← TokenIO.ReadRope[];
importeeName ← TokenIO.ReadRope[];
ob ← InternalCreateImport[
into: CDIO.DesignInReadOperation[],
ir: ir, size: sz,
objectName: objectName, importeeName: importeeName,
autoCreateOb: TRUE,
autoImport: TRUE,
autoLoad: FALSE,
allowConflicts: interactive,
include: FALSE
];
RETURN [ob]
};
GetImportList: PUBLIC PROC [design: CD.Design] RETURNS [imp: REF ImportList] = {
WITH CDValue.Fetch[design, importListKey, design] SELECT FROM
imp: REF ImportList => RETURN[imp];
ENDCASE => {
imp ← NEW[ImportList ← [list: NIL]];
[] ← CDValue.StoreConditional[boundTo: design, key: importListKey, value: imp];
RETURN [GetImportList[design]]
};
};
GetImportEntry: PUBLIC PROC [into: CD.Design, importeeName: ROPENIL, createIfNotFound: BoolOrInteractive ← true] RETURNS [REF ImportDesign←NIL] = {
--get the entry in design into telling about importing importeeName
ToBool: PROC[b: BoolOrInteractive, r, r2: ROPENIL] RETURNS [BOOL] = {
SELECT b FROM
true => RETURN [TRUE];
false => RETURN [FALSE];
ENDCASE => {
TerminalIO.WriteRopes[r, r2];
RETURN [TerminalIO.Confirm[r]]
}
};
mdata: REF ImportDesign ← NIL;
impl: REF ImportList = GetImportList[into];
IF Rope.IsEmpty[importeeName] THEN
ERROR CD.Error[ec: other, explanation: "design has empty name, but shouldn't"];
IF impl#NIL THEN
FOR l: ImpList ← impl.list, l.rest WHILE l#NIL DO
IF l.first#NIL AND Rope.Equal[l.first.importeeName, importeeName] THEN RETURN [l.first]
ENDLOOP;
IF ToBool[createIfNotFound, "create an import", importeeName] THEN {
pData: ImpOfDesign ← NewPerImpDesign[];
mdata ← NEW[ImportDesign ← [importeeName: importeeName, loaded: FALSE, reservedForCDImports: pData]];
IF Rope.Equal[into.name, importeeName] THEN
ERROR CD.Error[ec: other, explanation: "circular import"];
impl.list ← CONS[mdata, impl.list]; --should be atomic--
};
RETURN [mdata]
};
BindImportee: PROC [importer, importee: CD.Design, allowSizeConflicts, overload: BoolOrInteractive ← true] = {
done1: BOOLTRUE;
BindOneOb: PROC [ob: CD.Object] = {
done1 ← done1 AND BindObject[importer, ob, importee, allowSizeConflicts].ok
};
impPriv: ImpOfDesign; mdata: REF ImportDesign;
IF importer=importee OR Rope.Equal[importer.name, importee.name] THEN ERROR;
mdata ← GetImportEntry[importer, importee.name, true];
IF mdata=NIL THEN ERROR;
impPriv ← NARROW[mdata.reservedForCDImports];
IF mdata.loaded THEN {
IF overload=false THEN RETURN
ELSE IF overload=interactive THEN
IF NOT TerminalIO.Confirm[label: "design already loaded", choice: "overload"] THEN {
TerminalIO.WriteRope["dont overload; not done\n"];
RETURN
}
};
impPriv.d ← importee;
mdata.loaded ← TRUE;
EachImpOb[impPriv, BindOneOb];
IF NOT done1 THEN TerminalIO.WriteRope["some import not bound\n"];
CDOps.DelayedRedraw[importer];
};
BindObject: PROC [design: CD.Design, ob: CD.Object, importee: CD.Design, allowSizeConflicts: BoolOrInteractive ← true] RETURNS [ok: BOOLFALSE] = {
iPtr: ImportPtr = NARROW[ob.specificRef, ImportPtr];
oldRect, newRect: CD.Rect;
referedOb: CD.Object ← CDDirectory.Fetch[importee, iPtr.objectName].object;
IF referedOb=NIL THEN {
TerminalIO.WriteF["object %g in %g not found\n", [rope[iPtr.objectName]], [rope[importee.name]]]; RETURN
};
oldRect ← InterestRect[ob];
newRect ← CD.InterestRect[referedOb];
IF newRect#oldRect THEN {
TerminalIO.WriteRopes["size miss match for object ", iPtr.objectName];
IF allowSizeConflicts=false THEN {
TerminalIO.WriteRope["not resolved\n"]; RETURN
};
IF allowSizeConflicts=interactive THEN {
IF ~TerminalIO.Confirm[choice: "import anyway", label: "size conflict"] THEN {
TerminalIO.WriteRope["no\n"]; RETURN
};
TerminalIO.WriteRope["yes\n"];
};
};
iPtr.boundInstance ← CDInstances.NewInst[ob: referedOb];
BEGIN
oldSize: CD.Position = ob.size;
oldBase: CD.Position = CDBasics.BaseOfRect[oldRect];
newSize: CD.Position = referedOb.size;
newBase: CD.Position = CDBasics.BaseOfRect[newRect];
IF oldSize#newSize OR oldRect#newRect THEN {
ob.size ← newSize;
iPtr.ir ← newRect;
CDDirectory.RepositionObject[design: design, ob: ob, oldSize: oldSize, baseOff: CDBasics.SubPoints[oldBase, newBase]];
};
END;
CDDirectory.PropagateChange[ob, design];
ok ← TRUE;
};
RemSpaces: PROC [r: ROPE] RETURNS [ROPENIL] = {
leng: INT ← Rope.Length[r];
start: INT ← 0;
WHILE start<leng AND Rope.Fetch[r, start]=' DO start ← start+1 ENDLOOP;
WHILE leng>start AND Rope.Fetch[r, leng-1]=' DO leng ← leng-1 ENDLOOP;
IF leng>start THEN RETURN [Rope.Substr[r, start, leng-start]];
};
GetHintList: PROC [for: CD.Design] RETURNS [LIST OF ROPENIL] = {
IF for#NIL THEN
WITH CDProperties.GetDesignProp[for, $ImportHints] SELECT FROM
rL: LIST OF ROPE => RETURN [rL];
ENDCASE => NULL;
};
UseFile: PROC [into: CD.Design, importeeName: ROPE] RETURNS [f: ROPENIL] = {
rl: LIST OF ROPE ← GetHintList[into];
key, rest: ROPENIL;
FOR list: LIST OF ROPE ← rl, list.rest WHILE list#NIL DO
[key, rest] ← CDEnvironment.SplitLine[list.first];
IF Rope.Equal[importeeName, key] THEN RETURN [RemSpaces[rest]];
ENDLOOP;
f ← UserProfile.Token[Rope.Cat["ChipNDale.ImportFor.", importeeName], NIL];
};
GetOrLoadImportee: PROC [into: CD.Design, importeeName: ROPE] RETURNS [d: CD.Design←NIL] = {
ENABLE CDRemote.ioFailed => GOTO thatsit;
d ← CDRemote.FetchDesign[into, importeeName];
IF d=NIL THEN {
[] ← CDRemote.GetTableUsingFile[for: into, remoteDesign: importeeName, remoteFile: UseFile[into, importeeName]];
d ← CDRemote.FetchDesign[into, importeeName];
}
EXITS thatsit => NULL;
};
Load: PUBLIC PROC [into: CD.Design, importeeName: ROPE, overload, allowConflicts: BoolOrInteractive←true] RETURNS [done: BOOLFALSE] = {
indirectImport: REF ImportList;
importee: CD.Design ← GetOrLoadImportee[into, importeeName];
IF importee=NIL THEN {
TerminalIO.WriteRope["load not done\n"];
RETURN
};
indirectImport ← GetImportList[importee];
IF indirectImport^.list#NIL THEN TerminalIO.WriteRope["There are indirect imports\n"];
-- check for forbidden circular import
FOR list: ImpList ← indirectImport^, list.rest WHILE list#NIL DO
IF Rope.Equal[list.first.importeeName, into.name] THEN {
TerminalIO.WriteRope["**creates circular imports\n"];
RETURN
}
ENDLOOP;
-- now we certainly have no circular import
--
-- do the actual import
BindImportee[importer: into, importee: importee, allowSizeConflicts: allowConflicts, overload: overload];
--check all already imported designs for importing the new design
FOR list: ImpList ← GetImportList[into]^, list.rest WHILE list#NIL DO
ip: ImpOfDesign = NARROW[list.first.reservedForCDImports];
IF ip.d#NIL AND ip.d#importee THEN
BindImportee[importer: ip.d, importee: importee, allowSizeConflicts: false, overload: true];
ENDLOOP;
--check the new design for importing of already imported and loaded designs
FOR list: ImpList ← indirectImport^, list.rest WHILE list#NIL DO
ip: ImpOfDesign = NARROW[list.first.reservedForCDImports];
IF ip.d=NIL THEN {--new design did not load..
imp: REF ImportDesign ← GetImportEntry[into, list.first.importeeName, false];
IF imp#NIL THEN {
oldip: ImpOfDesign = NARROW[imp.reservedForCDImports];
IF oldip.d#NIL AND oldip.d#importee THEN
BindImportee[importer: importee, importee: oldip.d, allowSizeConflicts: false, overload: true];
};
}
ENDLOOP;
done ← TRUE;
};
DesignHasBeenRenamed: CDEvents.EventProc = {
-- prevent renaming if it would cause circularity
imp: REF ImportDesign = GetImportEntry[into: design, importeeName: design.name, createIfNotFound: false];
IF imp#NIL THEN {
dont ← TRUE;
TerminalIO.WriteRope["rename causes circularities; not done\n"]
};
};
OneLevelIncludedCopy: PUBLIC PROC [impObject: CD.Object, design: CD.Design] RETURNS [CD.Object] = {
--imp is an imported and bound object which will be made local to design
ReplaceChildrenByImports: PROC[me: CD.Object, design: CD.Design, importeeName: ROPE] = {
replaceList: CDDirectory.ReplaceList←NIL;
PerChild: CDDirectory.EnumerateObjectsProc = {
--PROC [me: CD.Object, x: REF]
IF me.class.inDirectory THEN {
impChild: CD.Object;
FOR list: CDDirectory.ReplaceList ← replaceList, list.rest WHILE list#NIL DO
IF list.first.old=me THEN RETURN -- eliminate duplicates
ENDLOOP;
impChild ← InternalCreateImport[
into: design, objectName: CDDirectory.Name[me], importeeName: importeeName,
size: me.size,
autoImport: TRUE, autoLoad: FALSE,
autoCreateOb: TRUE, allowConflicts: true,
include: TRUE
];
replaceList ← CONS[
NEW[CDDirectory.ReplaceRec←[
old: me,
oldSize: me.size,
new: impChild,
newSize: impChild.size,
off: [0, 0]
]],
replaceList
];
}
};
--build list of direct children
CDDirectory.EnumerateChildObjects[me: me, p: PerChild, x: NIL];
--replace each direct child by an import
IF replaceList#NIL THEN
[] ← CDDirectory.ReplaceDirectChild[me: me, design: design, replace: replaceList];
}; --ReplaceChildrenByImports
--OneLevelIncludedCopy
WITH impObject.specificRef SELECT FROM
impPtr: ImportPtr => {
newOb: CD.Object; tm, cm: CDDirectory.DMode;
import: REF ImportDesign = GetImportEntry[design, impPtr.designName, false];
ip: ImpOfDesign;
IF impPtr.boundInstance=NIL OR import=NIL OR ~import.loaded THEN
ERROR CD.Error[callingError, "OneLevelIncludedCopy impObject not bound "];
ip ← NARROW[import.reservedForCDImports];
[newOb, tm, cm] ← CDDirectory.Another[me: impPtr.boundInstance.ob, fromOrNil: ip.d, into: design];
IF newOb=NIL OR tm=immutable THEN ERROR;
IF tm=ready THEN [] ← CDDirectory.Include[design, newOb];
IF cm=immutable THEN
ReplaceChildrenByImports[me: newOb, design: design, importeeName: import.importeeName];
RETURN [newOb]
};
ENDCASE => ERROR CD.Error[callingError, "bad object class"]
};
Another: PROC [me: CD.Object, fromOrNil: CD.Design, into: CD.Design, friendly: BOOL] RETURNS [new: CD.Object, topMode: CDDirectory.InclOrReady ← included, childMode: CDDirectory.ImmOrIncl ← included] = {
impPtr: ImportPtr = NARROW[me.specificRef]; own: REF;
IF into=NIL THEN ERROR;
new ← InternalCreateImport[into: into, objectName: impPtr.objectName, importeeName: impPtr.designName, autoCreateOb: TRUE, autoImport: TRUE, allowConflicts: true, include: TRUE, size: me.size, autoLoad: FALSE];
IF new#me THEN {
IF new=NIL THEN ERROR;
own ← CDProperties.GetObjectProp[new, $OwnerDesign];
CDProperties.AppendProps[looser: me.properties, winner: new.properties, putOnto: new];
CDProperties.PutObjectProp[new, $OwnerDesign, own];
};
};
Expand: PROC [me: CD.Object, fromOrNil: CD.Design, into: CD.Design, friendly: BOOL] RETURNS [new: CD.Object, topMode: CDDirectory.DMode ← immutable, childMode: CDDirectory.ImmOrIncl ← immutable] = {
impPtr: ImportPtr = NARROW[me.specificRef];
IF impPtr.boundInstance=NIL THEN RETURN [NIL]; --can not expand unloaded object
IF into#NIL --AND friendly-- THEN {
tm, cm: CDDirectory.DMode;
[me, tm, cm] ← CDDirectory.Another[me: me, fromOrNil: fromOrNil, into: into];
IF me#NIL AND tm=included THEN {
new ← OneLevelIncludedCopy[impObject: me, design: into];
IF new#NIL THEN RETURN [new, included, included];
}
};
RETURN [impPtr.boundInstance.ob, immutable, immutable];
};
MergeInImports: PUBLIC PROC [into: CD.Design, importeeName: ROPE] = {
--Includes all the imported and bound objects from importeeName (including
--their transitive closure; but not indirect imports) into design.
imp: REF ImportDesign ← GetImportEntry[into, importeeName, false];
IF imp=NIL THEN {
TerminalIO.WriteRopes["MergeInImports not done; ", importeeName, " is not imported\n"];
RETURN
};
IF ~imp.loaded THEN {
TerminalIO.WriteRopes["MerginImport not done; ", importeeName, " is not loaded\n"];
RETURN
};
BEGIN
EachOb: PROC [ob: CD.Object] = {
pr: ImportPtr = NARROW[ob.specificRef];
IF pr.boundInstance#NIL THEN {
newOb: CD.Object ← CDGenerate.FetchNCall[table: generatorTable, design: into, key: pr.objectName, cache: TRUE];
IF newOb#NIL THEN {
remList ← CONS[pr.objectName, remList];
CDDirectory.ReplaceObject[design: into, old: ob, new: newOb];
IF CDDirectoryOps.RemoveIfUnused[design: into, ob: ob].done THEN {
[] ← CDDirectory.Rename[into, newOb, pr.objectName];
};
}
}
};
remList: LIST OF ROPENIL;
impPrivate: ImpOfDesign = NARROW[imp.reservedForCDImports];
generatorTable: CDGenerate.Table;
importee: CD.Design ← impPrivate.d;
CDRemote.CacheDesign[for: into, remote: importee];
generatorTable ← CDRemote.GetTable[imp.importeeName];
EachImpOb[impPrivate, EachOb];
FOR l: LIST OF ROPE ← remList, l.rest WHILE l#NIL DO
[] ← SymTab.Delete[impPrivate.obTab, l.first];
ENDLOOP
END
};
HasUnloadedImports: PUBLIC PROC [design: CD.Design] RETURNS [yes: BOOLFALSE] = {
CheckObjectLoaded: PROC [ob: CD.Object] = {
ip: ImportPtr = NARROW[ob.specificRef];
IF ip.boundInstance=NIL THEN ERROR unLoaded;
};
unLoaded: ERROR = CODE;
impList: REF CDImports.ImportList = GetImportList[design];
IF impList#NIL THEN
FOR list: LIST OF REF CDImports.ImportDesign ← impList^, list.rest WHILE list#NIL DO
IF ~list.first.loaded THEN {
--a directly imported design is not loaded
RETURN [yes ← TRUE]
}
ELSE {
p: ImpOfDesign ← NARROW[list.first.reservedForCDImports];
--check all objects of this design
EachImpOb[p, CheckObjectLoaded ! unLoaded => GOTO HasUnLoaded];
--check for indirect objects; there are no loops
yes ← p.d#NIL AND HasUnloadedImports[p.d];
}
ENDLOOP;
EXITS HasUnLoaded => RETURN [TRUE]
};
dirProcs: REF CDDirectory.DirectoryProcs ~ CDDirectory.InstallDirectoryProcs[importsClass, [
enumerateChildObjects: EnumerateItsObjects,
replaceDirectChilds: ReplaceDirectChild,
another: Another,
expand: Expand
]];
CDValue.RegisterKey[importListKey];
CDEvents.RegisterEventProc[$RenameDesign, DesignHasBeenRenamed];
END.