CDMerginImpl.mesa (part of ChipNDale)
Copyright © 1983, 1985 by Xerox Corporation. All rights reserved.
by Christian Jacobi, September 8, 1983 9:45 am
last edited by Christian Jacobi, June 29, 1985 5:35:16 pm PDT
DIRECTORY
Atom,
CedarProcess,
CD,
CDInstances,
CDCells,
CDSimpleOps,
CDDirectory,
CDExtras,
CDBasics,
CDMarks,
CDOps,
CDPrivate,
CDProperties,
IO,
Process,
Rope,
SymTab,
TerminalIO;
CDExtrasImpl: CEDAR MONITOR
IMPORTS Atom, CedarProcess, CD, CDInstances, CDCells, CDSimpleOps, CDDirectory, CDBasics, CDMarks, CDOps, CDProperties, IO, Process, Rope, SymTab, TerminalIO
EXPORTS CDExtras
SHARES CD =
BEGIN
MergeIn: PROC [design: CD.Design, from: CD.Design, name: Rope.ROPENIL, fullDirectory: BOOLTRUE] RETURNS [ob: CD.Object, pos: CD.Position];
--"from" is transfered to an object, and is included (transitive) to "design"'s directory
--"from" then may be resetted (preserving the rule: any object is in at most one directory)
--the caller is assumed to have the locks of both designs
--if "from" is pushed in, it's merged copy will be popped out, either by flushing,
--replacing or creating new cells
--"name" replaces "from"'s design name for the new created object, but it is a hint only
--"pos": if "ob" is included at position "pos" in an empty design we would get "from" again
--"fullDirectory": whether all objects of "from"'s directory are merged to design,
--or only those used by "from"'s top level
--the "from"'s object's may change name to avoid conflicts with "design"'s directory
--ob gets nil if "from" is empty
--technologies must be compatible
MergeInObjects: PROC [design: CD.Design, from: CD.Design, objects: LIST OF CD.Object];
--"objects" which are in "from"'s directory are transferrerd (transitive) to "design"'s directory
--"from" then may be resetted (preserving the rule: any object is in at most one directory)
--the caller is assumed to have the locks of both designs
--the object's may change name to avoid conflicts with "design"'s directory
--technologies must be compatible
Cellize: PUBLIC PROC [design: CD.Design, name: Rope.ROPENIL] RETURNS [cell: CD.Object←NIL, pos: CD.Position] =
--makes a single "cell" of of the "design", removes all instances;
--pos: if "cell" is included at position "pos" in an empty design we would get "design" again
--if "design" is pushed in, it will be popped out, either by flushing,
--replacing cells or creating new cells
BEGIN
done: BOOL;
il: CD.InstanceList;
PopToTopLayer[design];
CDSimpleOps.SelectAll[design];
IF (il�Ops.InstList[design])#NIL THEN {
IF il.rest=NIL AND ISTYPE[il.first.ob.specificRef, CD.CellPtr] AND il.first.orientation=CD.original THEN {
cell ← il.first.ob;
IF name#NIL THEN [] ← CDDirectory.Rename[design, cell, name];
done ← TRUE
}
ELSE {
IF name=NIL THEN name ← design.name;
IF name=NIL THEN name ← "no named design";
[done, cell] ← CDCells.CreateCellSelected[design, name];
};
IF done THEN {
pos ← CDOps.InstList[design].first.location;
}
ELSE cell ← NIL
};
CDOps.SetInstList[design, NIL]
END;
SkipAt: PROC [n: Rope.ROPE] RETURNS [Rope.ROPE] =
--skip everything after and inclusive first "@"
BEGIN
RETURN [Rope.Substr[base: n, len: Rope.SkipTo[s: n, skip: "@"]]]
END;
MergeIn: PUBLIC PROC [design: CD.Design, from: CD.Design, name: Rope.ROPENIL, fullDirectory: BOOLTRUE] RETURNS [ob: CD.Object←NIL, pos: CD.Position] =
--"from" is transfered to an object, and is included (transitive) to "design"'s directory
--"from" then may be resetted (preserving the rule: any object is in at most one directory)
--the caller is assumed to have the locks of both designs
--if "from" is pushed in, it's merged copy will be popped out, either by flushing,
--replacing or creating new cells
--"name" replaces "from"'s design name for the new created object, but it is a hint only
--"pos": if "ob" is included at position "pos" in an empty design we would get "from" again
--"fullDirectory": whether all objects of "from"'s directory are merged to design,
--or only those used by "from"'s top layer
--the "from"'s object's may change name to avoid conflicts with "design"'s directory
--ob gets nil if "from" is empty
--technologies must be compatible
BEGIN
m: CDMarks.MarkRange;
IncludeOneEntry: CDDirectory.EachEntryAction = {
--[name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL�LSE]--
IF fullDirectory OR ob.marked=m THEN {
IF NOT CDDirectory.Remove[design: from, name: name, expectObject: ob] THEN ERROR;
[] ← CDDirectory.Include[design: design, object: ob, alternateName: SkipAt[name]]
}
};
IF design=from THEN RETURN;
IF design.technology#from.technology THEN
RETURN WITH ERROR CD.Error[callingError, "MergIn design has different technology"];
[ob, pos] ← Cellize[from, name];
IF ob#NIL THEN {
IF ~fullDirectory THEN {
m ← CDMarks.GetNewMark[from];
CDMarks.MarkUnMarkedInclusiveChildren[from, ob, m];
};
[] ← CDDirectory.Enumerate[design: from, action: IncludeOneEntry];
IF ~fullDirectory THEN CDMarks.ReleaseMark[from, m];
CDOps.ResetDesign[from];
}
ELSE ob ← NIL
END;
MergeInObjects: PUBLIC PROC [design: CD.Design, from: CD.Design, objects: LIST OF CD.Object] =
--"objects" which are in "from"'s directory are transferrerd (transitive) to "design"'s directory
--"from" then may be resetted (preserving the rule: any object is in at most one directory)
--the caller is assumed to have the locks of both designs
--the object's may change name to avoid conflicts with "design"'s directory
--technologies must be compatible
BEGIN
m: CDMarks.MarkRange = CDMarks.GetNewMark[from];
IncludeOneEntry: CDDirectory.EachEntryAction = {
--[name: Rope.ROPE, ob: CD.Object] RETURNS [quit: BOOL�LSE]--
IF ob.marked=m THEN {
IF NOT CDDirectory.Remove[design: from, name: name, expectObject: ob] THEN ERROR;
[] ← CDDirectory.Include[design: design, object: ob, alternateName: SkipAt[name]]
}
};
IF design=from THEN RETURN;
IF design.technology#from.technology THEN
RETURN WITH ERROR CD.Error[callingError, "MergInObjects design has different technology"];
FOR l: LIST OF CD.Object ← objects, l.rest WHILE l#NIL DO
CDMarks.MarkUnMarkedInclusiveChildren[from, l.first, m];
ENDLOOP;
[] ← CDDirectory.Enumerate[design: from, action: IncludeOneEntry];
CDOps.ResetDesign[from];
END;
END.