IPToolBoxImpl:
CEDAR
PROGRAM
IMPORTS CD, CDSymbolicObjects, IO, Rope, FileNames, CDOrient, Misc, IPBasicOps
EXPORTS IPToolBox = BEGIN OPEN BO: IPBasicOps, IPToolBox;
IPPinsFromCDPins:
PUBLIC
PROC [cdObj:
CD.Object]
RETURNS [iPins: LIST OF REF IP.PinRep ← NIL] ={
EachPin: CDSymbolicObjects.InstEnumerator ~ {
pLoc: CD.Position ← inst.location;
pSize: CD.Position ← CD.InterestSize[inst.ob];
coord: IntVector ← [pLoc.x + pSize.x/2, pLoc.y + pSize.y/2]; --use the center
phyPins: PhysicalPins ← LIST[NEW[IP.PhysicalPinRep ← [coord]]];
pin: REF IP.PinRep ← NEW[IP.PinRep ← [CDSymbolicObjects.GetName[inst], phyPins]];
iPins ← CONS[pin, iPins];
};
[] ← CDSymbolicObjects.EnumerateSymbolicObs[cdObj, EachPin];
}; --IPPinsFromCDPins
-- IPPinFromCDPin:
PROC [cdPin:
CD.Instance]
RETURNS [
REF
IP.PinRep] = {
-- physicalPins:
PROC
RETURNS [phyPins: PhysicalPins ←
NIL] = {
-- FOR pPins:
LIST
OF
REF CDPins.PhysicalPin ← cdPin.physicalPin, pPins.rest
UNTIL pPins =
NIL
DO
-- pRect: CD.Rect ← pPins.first.rect;
-- coord: IntVector ← [(pRect.x1 + pRect.x2)/2, (pRect.y1 + pRect.y2)/2];
-- phyPins ← CONS[NEW[IP.PhysicalPinRep ← [coord]], phyPins];
-- ENDLOOP;
-- };
--physicalPins
-- RETURN [NEW[IP.PinRep ← [cdPin.pinName, physicalPins[]]]]
-- };
--IPPinFromCDPin
MakeIPPins:
PUBLIC
PROC[ipPins:
LIST
OF
REF
IP.PinRep, origin: IntVector ← [0, 0], coShape:
REF
IP.ShapeRep ←
NIL, cutOff:
NAT ← 0]
RETURNS [newPins:
LIST
OF
REF
IP.PinRep ←
NIL] ={
makePhyPin:
PROC [phyPin:
REF
IP.PhysicalPinRep]
RETURNS [
REF
IP.PhysicalPinRep] = {
coord: IntVector ← [phyPin.coord.x - origin.x, phyPin.coord.y - origin.y];
side: IP.PinSideType ← NearestSide[coShape, coord, cutOff].side;
RETURN [NEW[IP.PhysicalPinRep ← [coord, side, phyPin.active]]];
}; --makePhyPin
makeIPPins:
PROC[ipPin:
REF
IP.PinRep]
RETURNS [
REF
IP.PinRep] ={
phyPins: PhysicalPins ← NIL;
FOR l: PhysicalPins ← ipPin.physicalPins, l.rest
UNTIL l =
NIL
DO
phyPins ← CONS[makePhyPin[l.first], phyPins];
ENDLOOP;
RETURN [NEW[IP.PinRep ← [ipPin.name, phyPins, ipPin.auxInfo]]]
}; --makeIPPins
WHILE ipPins #
NIL
DO
newPins ← CONS[makeIPPins[ipPins.first], newPins];
ipPins ← ipPins.rest;
ENDLOOP;
}; --MakeIPPins
NearestSide:
PUBLIC
PROC [shape:
REF
IP.ShapeRep, point:
IntVector, cutOff:
NAT ← 0]
RETURNS [inShape:
BOOL, side:
IP.PinSideType] ={
minDist: INT ← LAST[INT];
--(1) Check if point is in shape
inShape ← Misc.RectContainPt[GetBRect[shape], point.x, point.y];
FOR corner:
IP.CornerTypes
IN [sw..nw]
DO
IF Misc.RectContainPt[GetCornerRect[shape, corner], point.x, point.y]
THEN inShape ← FALSE;
ENDLOOP;
--(2) Now find nearest side (this is not very efficient but is ok?)
FOR pSide:
IP.PinSideType
IN [south..nwVer]
DO
newDist: INT ← DistFromSide[shape, point, pSide];
IF newDist < minDist THEN {minDist ← newDist; side ← pSide};
ENDLOOP;
IF minDist > cutOff THEN side ← interior;
}; --NearestSide
DistFromSide:
PUBLIC
PROC[shape:
REF
IP.ShapeRep, point:
IntVector, side:
IP.PinSideType]
RETURNS [
INT] ={
ptCoord, ptProj, sdCoord: INT;
sdIntl: Misc.Interval;
rect: Misc.Rect;
--Algorithm: IF ptProj IN sdIntl
--THEN distance = ABS[ptCoord - sdCoord]
--ELSE (also for any other patho cases) distance = LAST[INT]
--(0) For patho cases simply return infinity
IF shape = NIL THEN RETURN [LAST[INT]];
--(1) Compute ptCoord, ptProj
SELECT side
FROM
south, north, swHor, seHor, neHor, nwHor => {ptProj ← point.x; ptCoord ← point.y};
east, west, swVer, seVer, neVer, nwVer => {ptProj ← point.y; ptCoord ← point.x};
interior, unknown => RETURN [LAST [INT]]; -- no need to do anything
ENDCASE => ERROR;
--(3) Compute sdCoord and sdIntl
IF side
IN [south..west]
THEN {
rect ← GetBRect[shape];
SELECT side
FROM
south => {sdCoord ← Misc.yMin[rect];
sdIntl ← Misc.x[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, sw]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, se]]];};
east => {sdCoord ← Misc.xMax[rect];
sdIntl ← Misc.y[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, se]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, ne]]];};
north => {sdCoord ← Misc.yMax[rect];
sdIntl ← Misc.x[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, ne]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.x[GetCornerRect[shape, nw]]];};
west => {sdCoord ← Misc.xMin[rect];
sdIntl ← Misc.y[rect];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, nw]]];
sdIntl ← Misc.IntlSubtract[sdIntl, Misc.y[GetCornerRect[shape, sw]]];};
ENDCASE => ERROR;
}
ELSE {
SELECT side
FROM
swHor => {rect ← GetCornerRect[shape, sw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMax[rect];
sdIntl ← Misc.x[rect];};
seHor => {rect ← GetCornerRect[shape, se, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMax[rect];
sdIntl ← Misc.x[rect];};
neHor => {rect ← GetCornerRect[shape, ne, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMin[rect];
sdIntl ← Misc.x[rect];};
nwHor => {rect ← GetCornerRect[shape, nw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.yMin[rect];
sdIntl ← Misc.x[rect];};
swVer => {rect ← GetCornerRect[shape, sw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMax[rect];
sdIntl ← Misc.y[rect];};
seVer => {rect ← GetCornerRect[shape, se, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMax[rect];
sdIntl ← Misc.y[rect];};
neVer => {rect ← GetCornerRect[shape, ne, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMin[rect];
sdIntl ← Misc.y[rect];};
nwVer => {rect ← GetCornerRect[shape, nw, , 0];
IF rect = NIL THEN RETURN [LAST[INT]];
sdCoord ← Misc.xMin[rect];
sdIntl ← Misc.y[rect];};
ENDCASE => ERROR;
};
IF Misc.IntlContainPt[sdIntl, ptProj]
THEN RETURN [ABS[ptCoord - sdCoord]]
ELSE RETURN [LAST[INT]];
}; --DistFromSide
GetCorner:
PUBLIC
PROC [shape:
IP.ShapeRep, corner:
IP.CornerTypes]
RETURNS [
REF
IP.NatVector] ={
-- REMARK: Here is okay to use 'IP.ShapeRep' as argument instead of `REF IP.ShapeRep'
-- because callers do not intend to modify shape. Remember that parameters are pass by
-- value in Cedar
SELECT corner
FROM
sw => RETURN [shape.cornerSpaces.sw];
se => RETURN [shape.cornerSpaces.se];
ne => RETURN [shape.cornerSpaces.ne];
nw => RETURN [shape.cornerSpaces.nw];
ENDCASE => ERROR;
};--GetCorner
GetBRect:
PUBLIC
PROC[shape:
REF
IP.ShapeRep, origin:
IntVector ← [0, 0]]
RETURNS [Misc.Rect] ={
IF shape = NIL THEN RETURN [NIL];
RETURN[Misc.RectCreate[origin.x, origin.y, origin.x + shape.dim.x, origin.y + shape.dim.y ]]
}; --GetBRect
GetCornerRect:
PUBLIC
PROC[shape:
REF
IP.ShapeRep, corner:
IP.CornerTypes, origin:
IntVector ← [0, 0], crop:
INT ← 1]
RETURNS [Misc.Rect] ={
cSpace: REF IP.NatVector ← GetCorner[shape^, corner];
IF cSpace = NIL THEN RETURN [NIL];
BEGIN
OPEN s: shape.cornerSpaces;
SELECT corner
FROM
sw => RETURN [Misc.RectCreate[origin.x, origin.y, origin.x + s.sw.x - crop, origin.y + s.sw.y - crop]];
se => RETURN [Misc.RectCreate[origin.x + shape.dim.x - s.se.x + crop, origin.y, origin.x + shape.dim.x, origin.y + s.se.y - crop]] ;
ne => RETURN [Misc.RectCreate[origin.x+ shape.dim.x - s.ne.x + crop, origin.y+shape.dim.y - s.ne.y + crop, origin.x+ shape.dim.x, origin.y+shape.dim.y]];
nw => RETURN [Misc.RectCreate[origin.x, origin.y + shape.dim.y - s.nw.y + crop, origin.x + s.nw.x - crop, origin.y + shape.dim.y]];
ENDCASE => ERROR;
END;
};--GetCornerRect
GetCornerRects:
PUBLIC
PROC[shape:
REF
IP.ShapeRep, origin:
IntVector ← [0, 0], crop:
INT ← 1]
RETURNS [sw, se, ne, nw: Misc.Rect ←
NIL] ={
IF shape = NIL THEN RETURN;
BEGIN
OPEN s: shape.cornerSpaces;
IF s.sw # NIL THEN sw ← Misc.RectCreate[origin.x, origin.y, origin.x + s.sw.x - crop, origin.y + s.sw.y - crop];
IF s.se # NIL THEN se ← Misc.RectCreate[origin.x + shape.dim.x - s.se.x + crop, origin.y, origin.x + shape.dim.x, origin.y + s.se.y - crop];
IF s.ne # NIL THEN ne ← Misc.RectCreate[origin.x+ shape.dim.x - s.ne.x + crop, origin.y+shape.dim.y - s.ne.y + crop, origin.x+ shape.dim.x, origin.y+shape.dim.y];
IF s.nw # NIL THEN nw ← Misc.RectCreate[origin.x, origin.y + shape.dim.y - s.nw.y + crop, origin.x + s.nw.x - crop, origin.y + shape.dim.y];
END;
};--GetCornerRects
CopyShape:
PUBLIC
PROC[oShape:
REF
IP.ShapeRep, orient:
CD.Orientation]
RETURNS [nShape:
REF
IP.ShapeRep] ={
nShape ← BO.Copy1Shape[oShape];
OrientShape[nShape, orient];
}; --CopyShape
OrientShape:
PUBLIC PROC[shape:
REF
IP.ShapeRep, orient:
IP.Orientation] ={
--Decompose orient into its basis and calls MirrorXShape and Rotate90Shape
IF CDOrient.IncludesMirrorX[orient] THEN MirrorXShape[shape];
Rotate90Shape[shape, orient/2];
}; --OrientShape
MirrorXShape:
PUBLIC PROC[shape:
REF
IP.ShapeRep] ={
--modifies shape: (shape.dim <=> shape.dim; shape.sw <=> shape.se; shape.ne <=> shape.nw)
OPEN sC: shape.cornerSpaces;
sw, se, ne, nw: REF IP.NatVector;
[sw, se, ne, nw] ← shape.cornerSpaces;
--(1) Swap bottom
sC.sw ← se;
sC.se ← sw;
--(2) Swap top
sC.nw ← ne;
sC.ne ← nw;
};--MirrorXShape
Rotate90Shape:
PUBLIC PROC [shape:
REF
IP.ShapeRep, numberOfRot:
INT ← 1] ={
modifies shape: if numberOfRot = 1 then
--(shape.dim <=> shape.dim; se ← sw, ne ← se, nw ← ne, sw← nw)
--numberOfRot can be any positive or negative
OPEN sC: shape.cornerSpaces;
sw, se, ne, nw: REF IP.NatVector;
[sw, se, ne, nw] ← shape.cornerSpaces;
SELECT numberOfRot
MOD 4
FROM
0 => NULL;
1, -3 => {sC.sw ← nw; sC.se ← sw; sC.ne ← se; sC.nw ← ne};
2, -2 => {sC.sw ← ne; sC.se ← nw; sC.ne ← sw; sC.nw ← se};
3, -1 => {sC.nw ← sw; sC.sw ← se; sC.se ← ne; sC.ne ← nw};
ENDCASE => ERROR;
}; --Rotate90Shape
--Simple parsing routines
ParseError: PUBLIC ERROR [reason: ATOM, at: REF] = CODE;
GetIdRope:
PUBLIC
PROC[stream:
IO.
STREAM]
RETURNS [Rope.
ROPE]={
id: Rope.ROPE ← stream.GetID[];
char: CHAR;
--Need to search further because "Input[0]" could be a valid name
WHILE (char ← stream.GetChar) # ':
DO
id ← Rope.Cat[id, Rope.FromChar[char]]
ENDLOOP;
RETURN [id];
}; --GetIdRope--
GetIdAtom:
PUBLIC
PROC[stream:
IO.
STREAM]
RETURNS [
ATOM]={
id: ATOM ← stream.GetAtom[];
char: CHAR;
IF (char ← stream.GetChar) = ':
THEN RETURN [id]
ELSE ERROR ParseError[$syntaxError, NEW[CHAR ← char]];
}; --GetIdRope--
EnterBlock:
PUBLIC
PROC [stream:
IO.
STREAM] = {
char: CHAR;
[] ← stream.SkipWhitespace[];
IF (char ← stream.GetChar) # '{
THEN ERROR ParseError[$noBegin, NEW[CHAR ← char]];
}; --EnterBlock
ExitBlock:
PUBLIC
PROC [stream:
IO.
STREAM]
RETURNS [
BOOL ←
TRUE]= {
[] ← stream.SkipWhitespace[];
IF stream.PeekChar = '}
THEN [] ← stream.GetChar
ELSE RETURN [FALSE]
}; --ExitBlock
RemoveBlock:
PUBLIC
PROC [stream:
IO.
STREAM] = {
EnterBlock[stream];
UNTIL ExitBlock[stream]
DO
IF stream.GetChar = '{ THEN RemoveBlock[stream];
ENDLOOP;
}; --RemoveBlock
GetNatVector:
PUBLIC
PROC[stream:
IO.
STREAM]
RETURNS [
REF
IP.NatVector] = {
refPair: LIST OF REF ANY ← NARROW[stream.GetRefAny];
x, y: NAT;
IF refPair = NIL THEN RETURN [NIL];
x ← NARROW[refPair.first, REF INT]^;
y ← NARROW[refPair.rest.first, REF INT]^;
RETURN [BO.NuNatVector[x, y]]
}; --GetNatVector--
GetIntVector:
PUBLIC
PROC[stream:
IO.
STREAM]
RETURNS [
REF
IntVector] = {
refPair: LIST OF REF ANY ← NARROW[stream.GetRefAny];
x, y: INT;
IF refPair = NIL THEN RETURN [NIL];
x ← NARROW[refPair.first, REF INT]^;
y ← NARROW[refPair.rest.first, REF INT]^;
RETURN [BO.NuIntVector[x, y]]
}; --GetIntVector--
GetShape:
PUBLIC
PROC [stream:
IO.
STREAM]
RETURNS [shape:
REF
IP.ShapeRep] = {
OPEN sC: shape.cornerSpaces;
EnterBlock[stream];
shape ← NEW[IP.ShapeRep ← [dim: GetNatVector[stream]]];
UNTIL ExitBlock[stream]
DO
token: ATOM ← GetIdAtom[stream];
SELECT token
FROM
$sw => sC.sw ← GetNatVector[stream]; --$sw
$se => sC.se ← GetNatVector[stream]; --$se
$ne => sC.ne ← GetNatVector[stream]; --$ne
$nw => sC.nw ← GetNatVector[stream]; --$nw
ENDCASE => ERROR ParseError[$badToken, token];
ENDLOOP;
}; --GetShape
GetPhysicalPins:
PUBLIC
PROC[stream:
IO.
STREAM]
RETURNS [phyPins: PhysicalPins ←
NIL] ={
getPhyPin:
PROC
RETURNS [
REF
IP.PhysicalPinRep] ={
coord: IntVector ← GetIntVector[stream]^;
side: IP.PinSideType ← GetPinSide[stream];
active: BOOL ← stream.GetBool;
RETURN [NEW [IP.PhysicalPinRep ← [coord, side, active]]]
}; --getPhyPin
EnterBlock[stream];
UNTIL ExitBlock[stream]
DO
phyPins ← CONS [getPhyPin[], phyPins];
ENDLOOP;
}; --GetPhysicalPins
PutShape:
PUBLIC
PROC[stream:
IO.
STREAM, shape:
REF
IP.ShapeRep] ={
stream.PutF["{"];
IF shape #
NIL
THEN {
OPEN sC: shape.cornerSpaces;
stream.PutF["(%g %g) ", IO.int[shape.dim.x], IO.int[shape.dim.y]];
IF sC.sw # NIL THEN stream.PutF["sw: (%g %g) ", IO.int[sC.sw.x], IO.int[sC.sw.y]];
IF sC.se # NIL THEN stream.PutF["se: (%g %g) ", IO.int[sC.se.x], IO.int[sC.se.y]];
IF sC.ne # NIL THEN stream.PutF["ne: (%g %g) ", IO.int[sC.ne.x], IO.int[sC.ne.y]];
IF sC.nw # NIL THEN stream.PutF["nw: (%g %g) ", IO.int[sC.nw.x], IO.int[sC.nw.y]];
}; --endIF
stream.PutF["}"];
};--PutShape
PutPhysicalPins:
PUBLIC
PROC[stream:
IO.
STREAM, physicalPins: PhysicalPins] ={
stream.PutF["{"];
WHILE physicalPins #
NIL
DO
phyPin: REF IP.PhysicalPinRep ← physicalPins.first;
stream.PutF[" (%g %g) %g %g",
IO.int[phyPin.coord.x],
IO.int[phyPin.coord.y],
IO.atom[IPPinSideToAtom[phyPin.side]],
IO.bool[phyPin.active],
];
physicalPins ← physicalPins.rest;
ENDLOOP;
stream.PutF["}"];
}; --PutShape
OrientPhysicalPins:
PUBLIC
PROC [phyPins: PhysicalPins, cellDim:
IP.NatVector, cellOrient:
IP.Orientation, cellOrigin:
IntVector ← [0, 0]] ={
WHILE phyPins #
NIL
DO
pPin: REF IP.PhysicalPinRep ← phyPins.first;
pPin.coord ← CDOrient.MapPoint[pPin.coord, [cellDim.x, cellDim.y], cellOrient, cellOrigin];
pPin.side ← OrientPinSide[pPin.side, cellOrient];
phyPins ← phyPins.rest;
ENDLOOP;
}; --OrientPhysicalPins
MirrorXPhysicalPins:
PUBLIC
PROC [phyPins: PhysicalPins, cellDim:
IP.NatVector, cellOrigin:
IntVector ← [0, 0]] ={
WHILE phyPins #
NIL
DO
pPin: REF IP.PhysicalPinRep ← phyPins.first;
pPin.coord ← CDOrient.MapPoint[pPin.coord, [cellDim.x, cellDim.y], CDOrient.mirrorX, cellOrigin];
pPin.side ← MirrorXPinSide[pPin.side];
phyPins ← phyPins.rest;
ENDLOOP;
};--MirrorXPhysicalPins
Rotate90PhysicalPins:
PUBLIC
PROC [phyPins: PhysicalPins, cellDim:
IP.NatVector, numberOfRot:
INT ← 1, cellOrigin:
IntVector ← [0, 0]] ={
CDRotn: CDOrient.Orientation;
SELECT numberOfRot
MOD 4
FROM
0 => CDRotn ← 0;
1, -3 => CDRotn ← 2;
2, -2 => CDRotn ← 4;
3, -1 => CDRotn ← 6;
ENDCASE => ERROR;
WHILE phyPins #
NIL
DO
pPin: REF IP.PhysicalPinRep ← phyPins.first;
pPin.coord ← CDOrient.MapPoint[pPin.coord, [cellDim.x, cellDim.y], CDRotn, cellOrigin];
pPin.side ← Rotate90PinSide[pPin.side, numberOfRot];
phyPins ← phyPins.rest;
ENDLOOP;
};--Rotate90PhysicalPins
OrientPinSide:
PUBLIC
PROC[side:
IP.PinSideType, orient:
IP.Orientation]
RETURNS [
IP.PinSideType] ={
IF CDOrient.IncludesMirrorX[orient] THEN side ← MirrorXPinSide[side];
RETURN [Rotate90PinSide[side, orient/2]];
}; --OrientPinSide
MirrorXPinSide:
PUBLIC
PROC[side:
IP.PinSideType]
RETURNS [
IP.PinSideType] ={
RETURN [
SELECT side
FROM
south, north, interior, unknown => side,
east => west,
west => east,
swHor => seHor,
seHor => swHor,
neHor => nwHor,
nwHor => neHor,
swVer => seVer,
seVer => swVer,
neVer => nwVer,
nwVer => neVer,
ENDCASE => ERROR
];
};--MirrorXPinSide
Rotate90PinSide:
PUBLIC
PROC [side:
IP.PinSideType, numberOfRot:
INT ← 1]
RETURNS [
IP.PinSideType]={
rot1:
PROC [s:
IP.PinSideType]
RETURNS [
IP.PinSideType] = {
RETURN [
SELECT s
FROM
south => east,
east => north,
north => west,
west => south,
swHor => seVer,
seVer => neHor,
neHor => nwVer,
nwVer => swHor,
swVer => seHor,
seHor => neVer,
neVer => nwHor,
nwHor => swVer,
interior, unknown => side,
ENDCASE => ERROR];
}; --rot1
rot2:
PROC [s:
IP.PinSideType]
RETURNS [
IP.PinSideType] = {
RETURN [
SELECT s
FROM
south => north,
north => south,
east => west,
west => east,
swHor => neHor,
swVer => neVer,
seHor => nwHor,
seVer => nwVer,
neHor => swHor,
neVer => swVer,
nwHor => seHor,
nwVer => seVer,
interior, unknown => side,
ENDCASE => ERROR];
}; --rot2
rot3:
PROC [s:
IP.PinSideType]
RETURNS [
IP.PinSideType] = {
RETURN [
SELECT s
FROM
south => west,
west => north,
north => east,
east => south,
swHor => nwVer,
nwVer => neHor,
neHor => seVer,
seVer => swHor,
swVer => nwHor,
nwHor => neVer,
neVer => seHor,
seHor => swVer,
interior, unknown => side,
ENDCASE => ERROR];
}; --rot3
RETURN [
SELECT numberOfRot
MOD 4
FROM
0 => side,
1, -3 => rot1[side],
2, -2 => rot2[side],
3, -1 => rot3[side],
ENDCASE => ERROR];
}; --Rotate90PinSide
CoChannels:
PUBLIC
PROC[co:
REF
IP.ComponentRep, action:
PROC[
REF
IP.ChannelRep]
RETURNS [quit:
BOOL]] ={
OPEN coP: co.prinChannels, coC: co.cornerChannels;
IF action[coP.south] THEN RETURN;
IF action[coP.east] THEN RETURN;
IF action[coP.north] THEN RETURN;
IF action[coP.west] THEN RETURN;
IF coC.sw #
NIL
THEN {
IF action[coC.sw.hor] THEN RETURN;
IF action[coC.sw.ver] THEN RETURN;
};
IF coC.se #
NIL
THEN {
IF action[coC.se.hor] THEN RETURN;
IF action[coC.se.ver] THEN RETURN;
};
IF coC.ne #
NIL
THEN {
IF action[coC.ne.hor] THEN RETURN;
IF action[coC.ne.ver] THEN RETURN;
};
IF coC.nw #
NIL
THEN {
IF action[coC.nw.hor] THEN RETURN;
IF action[coC.nw.ver] THEN RETURN;
};
}; --CoChannels
--###Low level Private routines###--
IPPinSideToAtom:
PROC[side:
IP.PinSideType]
RETURNS [
ATOM] ={
RETURN[
SELECT side
FROM
south => $south,
east => $east,
north => $north,
west => $west,
swHor => $swHor,
seHor => $seHor,
neHor => $neHor,
nwHor => $nwHor,
swVer => $swVer,
seVer => $seVer,
neVer => $neVer,
nwVer => $nwVer,
interior => $interior,
unknown => $unknown,
ENDCASE => ERROR];
}; --IPPinSideToAtom
GetPinSide:
PROC[stream:
IO.
STREAM]
RETURNS [
IP.PinSideType] ={
token: ATOM ← stream.GetAtom;
RETURN [
SELECT token
FROM
$south => south,
$east => east,
$north => north,
$west => west,
$swHor => swHor,
$seHor => seHor,
$neHor => neHor,
$nwHor => nwHor,
$swVer => swVer,
$seVer => seVer,
$neVer => neVer,
$nwVer => nwVer,
$interior => interior,
$unknown => unknown,
ENDCASE => ERROR ParseError[$badToken, token]];
}; --GetPinSide
ConstructFileName:
PUBLIC
PROC[defaultDir, inputFile, defaultExt: Rope.
ROPE]
RETURNS[fullName: Rope.ROPE] = {
dirPart: Rope.ROPE ← FileNames.Directory[inputFile];
IF Rope.IsEmpty[inputFile] THEN RETURN[NIL];
IF Rope.IsEmpty[dirPart] THEN dirPart ← defaultDir;
fullName ← Rope.Cat[dirPart, FileNames.GetShortName[inputFile]];
IF Rope.Find[inputFile, "."] < 0
AND Rope.Find[inputFile, "!"] < 0
THEN
fullName ← Rope.Cat[fullName, ".", defaultExt];
}; -- ConstructFileName
END.