PWPinsImpl:
CEDAR
PROGRAM
IMPORTS CD, CDBasics, CDCells, CDDirectory, CDInstances, CDProperties, CDSymbolicObjects, Convert, Rope
EXPORTS PWPins
SHARES CDCells, CDSymbolicObjects =
BEGIN
OPEN PWPins;
EnumerationProc: TYPE = PROC [ob: CD.Object, transf: CD.Transformation, properties: CD.PropList ← NIL, eachPin: InstanceEnumerator, stopEnumerateDeepPins: BOOL, filter: FilterProc] RETURNS [quit: BOOL ← FALSE];
FilterProc:
TYPE =
PROC [subRect:
CD.Rect]
RETURNS [isSubInteresting:
BOOL ←
TRUE];
GetSide:
PUBLIC
PROC [ob:
CD.Object, pin:
CD.Instance]
RETURNS [side: Side] = {
LargerSide:
PROC [hSide, vSide: Side]
RETURNS [side: Side] = {
delta: INT ← pinRect.x2-pinRect.x1- (pinRect.y2-pinRect.y1);
side ← IF delta=0 THEN ERROR ELSE IF delta>0 THEN hSide ELSE vSide;
};
rect: CD.Rect ← CD.InterestRect[ob]; -- the border
pinRect: CD.Rect ← CDSymbolicObjects.Denotes[pin]; -- bbox of the pin (CDInstances.InstRectO)
side ←
SELECT
TRUE
FROM
pinRect.x1 = pinRect.x2 AND pinRect.y1 = pinRect.y2 => none,
pinRect.x1 = pinRect.x2
AND pinRect.y1 = pinRect.y2 =>
SELECT pinRect.x1
FROM
rect.x1 => left,
rect.y1 => bottom,
rect.x2 => right,
rect.y2 => top,
ENDCASE => none,
pinRect.x1 = pinRect.x2 =>
SELECT pinRect.x1
FROM
rect.x1 => left,
rect.x2 => right,
ENDCASE => none,
pinRect.y1 = pinRect.y2 =>
SELECT pinRect.y1
FROM
rect.y1 => bottom,
rect.y2 => top,
ENDCASE => none,
rect.y1 = pinRect.y1 AND rect.y2 = pinRect.y2 => ERROR, -- pin on 2 opposite sides
rect.x1 = pinRect.x1 AND rect.x2 = pinRect.x2 => ERROR, -- pin on 2 opposite sides
rect.y2 = pinRect.y2 AND rect.x1 = pinRect.x1 => LargerSide[top, left],
rect.y2 = pinRect.y2 AND rect.x2 = pinRect.x2 => LargerSide[top, right],
rect.y1 = pinRect.y1 AND rect.x1 = pinRect.x1 => LargerSide[bottom, left],
rect.y1 = pinRect.y1 AND rect.x2 = pinRect.x2 => LargerSide[bottom, right],
rect.y2 = pinRect.y2 => top,
rect.y1 = pinRect.y1 => bottom,
rect.x1 = pinRect.x1 => left,
rect.x2 = pinRect.x2 => right,
ENDCASE => none;
};
Because we must finally get instances, this one has in its parameters all necessary information for reconstructing the application.
EnumerateDeepPinsInContext:
PUBLIC EnumerationProc = {
value: REF;
IF ~filter[CDBasics.MapRect[itemInCell:
CD.InterestRect[ob], cellInWorld: transf]]
THEN RETURN;
value ← CDProperties.GetObjectProp[ob, enumerationProcProp];
IF value#NIL THEN RETURN [NARROW [value, REF EnumerationProc]^[ob, transf, properties, eachPin, stopEnumerateDeepPins, filter]];
value ← CDProperties.GetProp[ob.class, enumerationProcProp];
IF value#NIL THEN RETURN [NARROW [value, REF EnumerationProc]^[ob, transf, properties, eachPin, stopEnumerateDeepPins, filter]];
ob ← CDDirectory.Expand[ob, NIL, NIL].new;
quit ← ob#NIL AND EnumerateDeepPinsInContext[ob, transf, NIL, eachPin, stopEnumerateDeepPins, filter];
};
PinEnumerateDeepPinsInContext: EnumerationProc = {
quit ← eachPin[NEW [CD.InstanceRep ← [ob: ob, trans: transf, properties: CDProperties.DCopyProps[properties]]]];
};
CellEnumerateDeepPinsInContext: EnumerationProc = {
cellPtr: CD.CellSpecific ← NARROW [ob.specific];
InstEnumerate: CDCells.InstEnumerator = {
IF ~stopEnumerateDeepPins OR CDProperties.GetInstanceProp[inst, $StopEnumerateDeepPins]=
NIL
THEN
quit ← EnumerateDeepPinsInContext[
inst.ob,
CDBasics.ComposeTransform[inst.trans, transf],
inst.properties,
eachPin, stopEnumerateDeepPins, filter];
};
quit ← CDCells.EnumerateInstances[ob, InstEnumerate];
};
EnumerateDeepPins:
PUBLIC
PROC [ob:
CD.Object, eachPin: InstanceEnumerator, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [quit:
BOOL] = {
DefaultFilter: FilterProc = {};
quit ← EnumerateDeepPinsInContext[ob: ob, transf: [], eachPin: eachPin, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: DefaultFilter];
};
EnumerateEdgePins:
PUBLIC
PROC [ob:
CD.Object, eachPin: InstanceEnumerator, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [quit:
BOOL] = {
iRectShrank: CD.Rect ← CDBasics.Extend[CD.InterestRect[ob], -1];
EdgeFilter: FilterProc = {isSubInteresting ← ~CDBasics.Inside[subRect, iRectShrank]};
EachPinFilter: InstanceEnumerator
-- [inst: CD.Instance] RETURNS [quit: BOOL ← FALSE] -- = {
IF GetSide[ob, inst]#none THEN quit ← eachPin[inst];
};
quit ← EnumerateDeepPinsInContext[ob: ob, transf: [], eachPin: EachPinFilter, stopEnumerateDeepPins: stopEnumerateDeepPins, filter: EdgeFilter];
};
ChangePins:
PUBLIC
PROC [ob:
CD.Object, changePinProc: ChangePinProc ← DefaultChangePinProc, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [cell:
CD.Object] =
BEGIN
cellPtr: CD.CellSpecific;
KeepPinOnEdge: InstanceEnumerator
-- [inst: CD.Instance] RETURNS [quit: BOOL ← FALSE] -- = {
newInst: CD.Instance ← changePinProc[inst];
IF newInst#NIL THEN cellPtr.contents ← CONS [newInst, cellPtr.contents];
};
inst: CD.Instance ← NEW [CD.InstanceRep ← [ob: ob]];
IF stopEnumerateDeepPins THEN CDProperties.PutInstanceProp[inst, $StopEnumerateDeepPins, $StopEnumerateDeepPins];
cell ← CDCells.CreateEmptyCell[]; cellPtr ← NARROW [cell.specific];
[] ← EnumerateEdgePins[ob, KeepPinOnEdge];
cellPtr.contents ← CONS[inst, cellPtr.contents];
CDCells.SetInterestRect[NIL, cell, CD.InterestRect[ob], dontNotify];
END;
DefaultChangePinProc: PUBLIC ChangePinProc = {newPin ← oldPin};
RenamePins:
PUBLIC
PROC [ob:
CD.Object, renameProc: RenameProc ← DefaultRenameProc, stopEnumerateDeepPins:
BOOL ←
TRUE]
RETURNS [cell:
CD.Object] = {
ChangePin: ChangePinProc = {
newRope: ROPE ← renameProc[CDSymbolicObjects.GetName[oldPin]];
IF Rope.IsEmpty[newRope] THEN RETURN;
newPin ← CDInstances.Copy[oldPin];
CDSymbolicObjects.SetName[newPin, newRope];
};
cell ← ChangePins[ob, ChangePin, stopEnumerateDeepPins];
};
DefaultRenameProc: PUBLIC RenameProc = {newRope ← oldRope};
Useful in many RenameProcs for indexing names. e.g. Index["foo", 4]="foo[4]"
Index:
PUBLIC
PROC [rope:
ROPE, index:
INT]
RETURNS [indexedRope:
ROPE] = {
indexedRope ← Rope.Cat[rope, "[", Convert.RopeFromInt[index], "]"];
};
KeepAll:
PUBLIC SelectNamesProc = {keepIt ←
TRUE};
Position:
PROC [inst:
CD.Instance, newObj, template:
CD.Object, side: Side, orientation:
CD.Orientation]
RETURNS [position:
CD.Position] = {
position ← CDBasics.SubPoints[
CDBasics.BaseOfRect[
CDBasics.MapRect[CD.InterestRect[inst.ob], inst.trans]],
CDBasics.BaseOfRect[CD.InterestRect[template]]];
SELECT side
FROM
top, bottom => position.y ← 0;
left, right => position.x ← 0;
ENDCASE => ERROR;
position ← CDBasics.SubPoints[position, CDBasics.BaseOfRect[CDBasics.MapRect[CD.InterestRect[newObj], [[0, 0], orientation]]]];
};
TransferCell:
PUBLIC
PROC [template:
CD.Object, objSide: Side, width:
INT, objProc: ForEachPinProc, selectNameProc: SelectNamesProc ← KeepAll]
RETURNS [cell:
CD.Object] = {
instances: CD.InstanceList ← NIL;
KeepPinOnEdge: PWPins.InstanceEnumerator = {
newObj: CD.Object;
side: Side ← GetSide[template, inst].side;
IF side=objSide
AND selectNameProc[CDSymbolicObjects.GetName[inst]]
THEN {
orient: CD.Orientation ←
SELECT objSide
FROM
bottom => rotate270, right => original, top => rotate90, left => rotate180,
ENDCASE => ERROR;
newObj ← objProc[inst]; IF newObj=NIL THEN RETURN;
instances ← CONS [CDInstances.NewInst[ob: newObj, trans: [Position[inst, newObj, template, objSide, orient], orient]], instances];
};
};
iRect: CD.Rect = CD.InterestRect[template];
-- Start with an empty cell of appropriate interestRect (origin in 0,0)
IF objSide=none THEN ERROR;
[] ← EnumerateEdgePins[template, KeepPinOnEdge];
cell ← CDCells.CreateCell[il: instances, ir:
SELECT objSide
FROM
top, bottom => [0, 0, iRect.x2-iRect.x1, width],
left, right => [0, 0, width, iRect.y2-iRect.y1],
ENDCASE => ERROR];
};
enumerationProcProp: PUBLIC ATOM ← $EnumerationProcPWPins;
[] ← CDProperties.RegisterProperty[enumerationProcProp, $PWPins];
CDProperties.InstallProcs[enumerationProcProp, [makeCopy: CDProperties.CopyVal]];
[] ← CDProperties.RegisterProperty[$StopEnumerateDeepPins, $PWPins];
CDProperties.InstallProcs[$StopEnumerateDeepPins, [makeCopy: CDProperties.CopyVal]];
CDProperties.PutProp[CDSymbolicObjects.pinClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDSymbolicObjects.segmentClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDSymbolicObjects.markClass, enumerationProcProp, NEW [EnumerationProc ← PinEnumerateDeepPinsInContext]];
CDProperties.PutProp[CDCells.pCellClass, enumerationProcProp, NEW [EnumerationProc ← CellEnumerateDeepPinsInContext]];
END.