LichenOpsImpl:
CEDAR PROGRAM
IMPORTS LichenOps, IO, RedBlackTree, Rope, ViewerIO
EXPORTS LichenDataStructure, LichenOps =
BEGIN OPEN LichenDataStructure, LichenOps;
MirrorName: PUBLIC ROPE ← " world ";
log: IO.STREAM ← ViewerIO.CreateViewerStreams["Compare Log"].out;
Warn:
PUBLIC PROC [source: Source, format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] = {
IF source.stream #
NIL THEN {
log.PutRope["Before "];
IF source.name # NIL THEN log.PutRope[source.name];
log.PutF["[%g]: ", IO.int[source.stream.GetIndex[]]];
}
ELSE IF source.name # NIL THEN log.PutF["In %g: ", IO.rope[source.name]];
log.PutF[format, v1, v2, v3, v4, v5];
log.PutChar['\n];
};
Err:
PUBLIC PROC [source: Source, format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] = {
IF source.stream #
NIL THEN {
log.PutRope["Before "];
IF source.name # NIL THEN log.PutRope[source.name];
log.PutF["[%g]: ", IO.int[source.stream.GetIndex[]]];
}
ELSE IF source.name # NIL THEN log.PutF["In %g: ", IO.rope[source.name]];
log.PutF[format, v1, v2, v3, v4, v5];
log.PutChar['\n];
log.Flush[];
ERROR;
};
Log:
PUBLIC PROC [format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] =
{log.PutF[format, v1, v2, v3, v4, v5]};
Fail:
PUBLIC PROC [af: AssertionFamily, ao: FailableAssertionOp, format:
ROPE, v1, v2, v3, v4, v5:
IO.Value ← [null[]]] = {
SELECT ao
FROM
report => {log.PutF[format, v1, v2, v3, v4, v5]; log.PutRope["\n"]};
check => (SELECT af FROM normal => NotNormal, comparable => NotComparable, ENDCASE => ERROR)[IO.PutFR[format, v1, v2, v3, v4, v5]];
ENDCASE => ERROR
};
FlushLog: PUBLIC PROC = {log.Flush[]};
IsMirror:
PUBLIC PROC [v: Vertex]
RETURNS [isMirror:
BOOL] =
{isMirror ← v = v.parent.mirror};
EnumerateNames:
PUBLIC PROC [names: Names, consume:
PROC [name:
ROPE, class:
ATOM--UNION[$designed, $unknown, $progged]--]] = {
Doit:
PROC [rl: RopeList, class:
ATOM] = {
FOR rl ← rl, rl.rest WHILE rl # NIL DO consume[rl.first, class] ENDLOOP;
};
Doit[names.designed, $designed];
Doit[names.unknown, $unknown];
Doit[names.progged, $progged];
};
NamesInclude:
PUBLIC PROC [names: Names, name:
ROPE]
RETURNS [incl:
BOOL] = {
incl
←
RopeListIncludes[names.designed, name] OR
RopeListIncludes[names.unknown, name] OR
RopeListIncludes[names.progged, name];
};
AddVertex:
PUBLIC PROC [v: Vertex] =
BEGIN
Insert[v.parent.parts, v.names, v];
SELECT v.class
FROM
net => v.parent.netCount ← v.parent.netCount + 1;
cell => v.parent.cellCount ← v.parent.cellCount + 1;
ENDCASE => ERROR;
END;
FindPort:
PUBLIC PROC [ports: PortS, name:
ROPE]
RETURNS [portIndex:
NAT] = {
FOR i:
NAT IN [0 .. ports.length)
DO
IF NamesInclude[ports[i].names, name] THEN RETURN [i];
ENDLOOP;
portIndex ← notFound;
};
RopeListIncludes:
PUBLIC PROC [rl: RopeList, r:
ROPE]
RETURNS [found:
BOOL] = {
FOR rl ← rl, rl.rest
WHILE rl #
NIL DO
IF rl.first.Equal[r] THEN RETURN [TRUE];
ENDLOOP;
found ← FALSE};
AddNames:
PUBLIC PROC [ra:
REF ANY--UNION[Vertex, CellType]--, names: Names] = {
Work:
PROC [old: Names, byName: SymbolTable]
RETURNS [new: Names] = {
ReallyWork:
PROC [old, add: RopeList]
RETURNS [new: RopeList] = {
new ← old;
FOR add ← add, add.rest
WHILE add #
NIL DO
a: Alias ← NEW [AliasRep ← [name: add.first, thing: ra]];
byName.Insert[a, a.name];
new ← CONS[add.first, new];
ENDLOOP;
};
new.designed ← ReallyWork[old.designed, names.designed];
new.unknown ← ReallyWork[old.unknown, names.unknown];
new.progged ← ReallyWork[old.progged, names.progged];
};
WITH ra
SELECT FROM
ct: CellType => ct.names ← Work[ct.names, ct.design.cellTypesByName];
v: Vertex => v.names ← Work[v.names, v.parent.parts];
ENDCASE => ERROR;
};
Insert:
PUBLIC PROC [st: SymbolTable, names: Names, val:
REF ANY] = {
Work:
PROC [rl: RopeList] = {
FOR rl ← rl, rl.rest
WHILE rl #
NIL DO
a: Alias ← NEW [AliasRep ← [name: rl.first, thing: val]];
st.Insert[a, a.name];
ENDLOOP;
};
Work[names.designed];
Work[names.unknown];
Work[names.progged];
};
Delete:
PUBLIC PROC [st: SymbolTable, names: Names, val:
REF ANY] = {
Work:
PROC [rl: RopeList] = {
FOR rl ← rl, rl.rest
WHILE rl #
NIL DO
deld: REF ANY ← AntiAlias[st.Delete[rl.first].data];
IF deld # val THEN ERROR;
ENDLOOP;
};
Work[names.designed];
Work[names.unknown];
Work[names.progged];
};
GetIDKey:
PUBLIC PROC [data:
REF ANY]
RETURNS [key:
REF ANY]
--RedBlackTree.GetKey-- =
{key ← data};
CompareRopes:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
c ← NARROW[k, ROPE].Compare[NARROW[data]];
END;
GetAliasKey:
PUBLIC PROC [data:
REF ANY]
RETURNS [key:
ROPE]
--RedBlackTree.GetKey-- =
{a: Alias ← NARROW[data]; key ← a.name};
CompareAliases:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
k1: ROPE ← NARROW[k];
k2: ROPE ← GetAliasKey[data];
c ← k1.Compare[k2];
END;
CompareByAddress:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
i1: INT ← LOOPHOLE[k];
i2: INT ← LOOPHOLE[data];
c ←
SELECT i1 - i2
FROM
<0 => less,
=0 => equal,
>0 => greater,
ENDCASE => ERROR;
END;
GetECParentNet:
PUBLIC PROC [data:
REF ANY]
RETURNS [key: Vertex]
--RedBlackTree.GetKey-- =
{ec: ExtraConnection ← NARROW[data]; key ← ec.parentNet};
CompareECParentNet:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
k1: Vertex ← NARROW[k];
k2: Vertex ← GetECParentNet[data];
c ← CompareByAddress[k1, k2];
END;
GetECSubCell:
PUBLIC PROC [data:
REF ANY]
RETURNS [key: Vertex]
--RedBlackTree.GetKey-- =
{ec: ExtraConnection ← NARROW[data]; key ← ec.subCell};
CompareECSubCell:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
k1: Vertex ← NARROW[k];
k2: Vertex ← GetECSubCell[data];
c ← CompareByAddress[k1, k2];
END;
GetECChildNet:
PUBLIC PROC [data:
REF ANY]
RETURNS [key: Vertex]
--RedBlackTree.GetKey-- =
{ec: ExtraConnection ← NARROW[data]; key ← ec.childNet};
CompareECChildNet:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
k1: Vertex ← NARROW[k];
k2: Vertex ← GetECChildNet[data];
c ← CompareByAddress[k1, k2];
END;
CompareECSubCellThenChildNet:
PUBLIC PROC [k, data:
REF ANY]
RETURNS [c: Basics.Comparison]
--RedBlackTree.Compare-- =
BEGIN
k1: ExtraConnection ← NARROW[k];
k2: ExtraConnection ← NARROW[data];
IF (c ← CompareByAddress[k1.subCell, k2.subCell]) # equal THEN RETURN;
c ← CompareByAddress[k1.childNet, k2.childNet]
END;
Lookup:
PUBLIC PROC [st: SymbolTable, key:
ROPE]
RETURNS [val:
REF ANY] =
{val ← AntiAlias[st.Lookup[key]]};
AntiAlias:
PUBLIC PROC [ra:
REF ANY]
RETURNS [val:
REF ANY] = {
FOR val ← ra, NARROW[val, Alias].thing WHILE (val # NIL) AND ISTYPE[val, Alias] DO NULL ENDLOOP;
};
GlobalCellTypeName:
PUBLIC PROC [ct: CellType]
RETURNS [r:
ROPE] = {
r ← ct.design.name.Cat[".", PickAName[ct.names]]};
GlobalPortName:
PUBLIC PROC [ct: CellType, portIndex: PortIndex]
RETURNS [r:
ROPE] = {
r ← GlobalCellTypeName[ct].Cat[".", PickAName[ct.ports[portIndex].names]]};
GlobalVertexName:
PUBLIC PROC [v: Vertex]
RETURNS [r:
ROPE] = {
r ← GlobalCellTypeName[v.parent].Cat[".", PickAName[v.names]]};
GlobalName:
PUBLIC PROC [ra:
REF ANY, soFar: Naming ← [
NIL,
NIL]]
RETURNS [name:
ROPE] = {
nn: Names ← NamingNames[soFar];
name ← PickAName[nn];
WITH ra
SELECT FROM
design: Design => NULL;
ct: CellType => name ← ct.design.name.Cat[".", name];
v: Vertex => name ← GlobalCellTypeName[v.type].Cat[".", name];
s: Socket => name ← GlobalCellTypeName[s.ct].Cat[".", name];
ENDCASE => ERROR;
};
KeepAll:
PUBLIC PROC [ra:
REF ANY]
RETURNS [keepAll:
BOOL] = {
keepAll ←
WITH ra
SELECT FROM
d: Design => d.allKept,
ct: CellType => ct.design.allKept,
v: Vertex => v.type.design.allKept,
s: Socket => s.ct.design.allKept,
ENDCASE => ERROR};
PickAName:
PUBLIC PROC [names: Names]
RETURNS [name:
ROPE] = {
Try:
PROC [rl: RopeList]
RETURNS [done:
BOOL] =
{IF done ← (rl # NIL) THEN name ← rl.first};
IF Try[names.designed] THEN RETURN;
IF Try[names.unknown] THEN RETURN;
IF Try[names.progged] THEN RETURN;
ERROR;
};
END.