LichenNavigationImpl.mesa
Last tweaked by Mike Spreitzer on August 28, 1987 11:17:28 am PDT
DIRECTORY Asserting, LichenCollections, LichenDataOps, LichenDataStructure, LichenIntFunctions, LichenNavigation, LichenPairCollections, RegularExpression, Rope;
LichenNavigationImpl:
CEDAR
PROGRAM
IMPORTS Asserting, LichenCollections, LichenDataOps, LichenDataStructure, LichenIntFunctions, LichenPairCollections, RegularExpression, Rope
EXPORTS LichenNavigation
=
BEGIN OPEN LichenDataOps, LichenDataStructure, LichenNavigation, Colls:LichenCollections, PairColls:LichenPairCollections, IntFns:LichenIntFunctions;
CTByName:
PUBLIC
PROC [d: Design, name:
ROPE]
RETURNS [ans: CellType ←
NIL] ~ {
ans ← NARROW[CTsByName[d, name, TRUE, TRUE].TheElt[]];
RETURN};
CTsByName:
PUBLIC
PROC [d: Design, pattern:
ROPE, case:
BOOL ←
TRUE, literal:
BOOL ←
FALSE]
RETURNS [Set
--of CellType--] ~ {
f: RegularExpression.Finder ~ RegularExpression.CreateFromRope[
addBounds: TRUE,
literal: literal,
ignoreCase: NOT case,
pattern: pattern];
dat: CTsByNameData ~ NEW[CTsByNameDataPrivate ← [d, f]];
RETURN Colls.CreateEnumerator[e: [EnumCTsByName, Colls.refs, dat], mayDuplicate: FALSE, enumerateePersists: TRUE];
};
CTsByNameData: TYPE ~ REF CTsByNameDataPrivate;
CTsByNameDataPrivate: TYPE ~ RECORD [d: Design, f: RegularExpression.Finder];
EnumCTsByName:
PROC [
Consume:
PROC [val: Colls.Value], data:
REF
ANY ←
NIL] ~ {
d: CTsByNameData ~ NARROW[data];
TestCT:
PROC [ra:
REF
ANY] ~ {
ct: CellType ~ NARROW[ra];
IF HasMatchingNameAssn[ct.otherPublic, d.f] THEN Consume[ct];
RETURN};
d.d.cellTypes.Enumerate[TestCT];
RETURN};
ChildByName:
PUBLIC
PROC [ct: CellType, name:
ROPE]
RETURNS [ans: Vertex ←
NIL] ~ {
ans ← NARROW[ChildrenByName[ct, name, TRUE, TRUE].TheElt[]];
RETURN};
ChildrenByName:
PUBLIC
PROC [ct: CellType, pattern:
ROPE, case:
BOOL ←
TRUE, literal:
BOOL ←
FALSE]
RETURNS [Set
--of CellType--] ~ {
f: RegularExpression.Finder ~ RegularExpression.CreateFromRope[
addBounds: TRUE,
literal: literal,
ignoreCase: NOT case,
pattern: pattern];
dat: ChildrenByNameData ~ NEW[ChildrenByNameDataPrivate ← [ct, f]];
RETURN Colls.CreateEnumerator[e: [EnumChildrenByName, Colls.refs, dat], mayDuplicate: FALSE, enumerateePersists: TRUE];
};
ChildrenByNameData: TYPE ~ REF ChildrenByNameDataPrivate;
ChildrenByNameDataPrivate: TYPE ~ RECORD [ct: CellType, f: RegularExpression.Finder];
EnumChildrenByName:
PROC [
Consume:
PROC [val: Colls.Value], data:
REF
ANY ←
NIL] ~ {
d: ChildrenByNameData ~ NARROW[data];
TestV:
PROC [v: Vertex] ~ {
IF HasMatchingSteppyName[v.names, d.f] THEN Consume[v];
RETURN};
d.ct.EnumerateParts[TestV, FALSE];
RETURN};
ChildByType:
PUBLIC
PROC [parent, type: CellType]
RETURNS [ans: CellInstance ←
NIL] ~ {
ans ← NARROW[ChildrenByType[parent, type].First[].DVal];
RETURN};
ChildrenByType:
PUBLIC
PROC [parent, type: CellType]
RETURNS [ans: Set
--of CellInstance--] ~ {
dat: ChildrenByTypeData ~ NEW[ChildrenByTypeDataPrivate ← [parent, type]];
RETURN Colls.CreateEnumerator[e: [EnumChildrenByType, Colls.refs, dat], mayDuplicate: FALSE, enumerateePersists: TRUE];
};
ChildrenByTypeData: TYPE ~ REF ChildrenByTypeDataPrivate;
ChildrenByTypeDataPrivate: TYPE ~ RECORD [parent, type: CellType];
EnumChildrenByType:
PROC [
Consume:
PROC [val: Colls.Value], data:
REF
ANY ←
NIL] ~ {
d: ChildrenByTypeData ~ NARROW[data];
TestV:
PROC [ra:
REF
ANY] ~ {
ci: CellInstance ~ NARROW[ra];
IF ci.type=d.type THEN Consume[ci];
RETURN};
d.parent.asUnorganized.containedInstances.Enumerate[TestV];
RETURN};
PortByName:
PUBLIC
PROC [root: Port, name:
ROPE]
RETURNS [ans: Port] ~ {
ans ← NARROW[PortsByName[root, name, TRUE, TRUE].First[].DVal];
RETURN};
PortsByName:
PUBLIC
PROC [root: Port, pattern:
ROPE, case:
BOOL ←
TRUE, literal:
BOOL ←
FALSE]
RETURNS [ans: Set
--of Port--] ~ {
f: RegularExpression.Finder ~ RegularExpression.CreateFromRope[
addBounds: TRUE,
literal: literal,
ignoreCase: NOT case,
pattern: pattern];
dat: PortsByNameData ~ NEW[PortsByNameDataPrivate ← [root, f]];
RETURN Colls.CreateEnumerator[e: [EnumPortsByName, Colls.refs, dat], mayDuplicate: FALSE, enumerateePersists: TRUE];
};
PortsByNameData: TYPE ~ REF PortsByNameDataPrivate;
PortsByNameDataPrivate: TYPE ~ RECORD [root: Port, f: RegularExpression.Finder];
EnumPortsByName:
PROC [
Consume:
PROC [val: Colls.Value], data:
REF
ANY ←
NIL] ~ {
d: PortsByNameData ~ NARROW[data];
stack: PortList ← LIST[d.root];
WHILE stack#
NIL
DO
p: Port ~ stack.first;
IF HasMatchingSteppyName[p.names, d.f] THEN Consume[p];
stack ← stack.rest;
IF p.firstChild#NIL THEN stack ← CONS[p.firstChild, stack];
IF p.next#NIL THEN stack ← CONS[p.next, stack];
ENDLOOP;
RETURN};
Quit: ERROR ~ CODE;
HasMatchingNameAssn:
PROC [assns: Assertions, f: RegularExpression.Finder]
RETURNS [
BOOL] ~ {
TestName:
PROC [assertion: Assertion] ~ {
thisN: ROPE ~ NARROW[Asserting.TermOf[assertion]];
before, after: INT;
found: BOOL;
[found: found, before: before, after: after] ← f.SearchRope[thisN];
IF found AND before=0 AND after=thisN.Length THEN Quit;
};
Asserting.EnumerateAssertionsAbout[nameReln, assns, TestName !Quit => GOTO Has];
RETURN [FALSE];
EXITS Has => RETURN [TRUE];
};
HasMatchingSteppyName:
PROC [listData: ListData, f: RegularExpression.Finder]
RETURNS [has:
BOOL] ~ {
names: Set ~ [listClass, listData];
TestName:
PROC [val:
REF
ANY]
RETURNS [pass:
BOOL ←
FALSE] ~ {
steppy: SteppyName ~ NARROW[val];
ropy: ROPE ~ UnparseSteppyName[steppy];
before, after: INT;
found: BOOL;
[found: found, before: before, after: after] ← f.SearchRope[ropy];
IF found AND before=0 AND after=ropy.Length THEN pass ← TRUE;
RETURN};
has ← names.Scan[TestName].found;
RETURN};
FilterSet:
PUBLIC
PROC [big: Set,
Test:
PROC [ra:
REF
ANY]
RETURNS [passes:
BOOL]]
RETURNS [filtered: Set] ~ {
MaybePass:
PROC [ra:
REF
ANY] ~ {
IF Test[ra] AND NOT filtered.AddElt[ra] THEN ERROR;
};
filtered ← Colls.CreateHashSet[];
big.Enumerate[MaybePass];
big ← big;
};
instanceType: PUBLIC Function ~ PairColls.FnFromProc[Apply: InstanceToType, ScanInverse: ScanInstancesOfType];
InstanceToType:
PROC [data:
REF
ANY, v:
REF
ANY]
RETURNS [Colls.MaybeValue] ~ {
WITH v
SELECT
FROM
ci: CellInstance => RETURN [[TRUE, ci.type]];
ENDCASE => RETURN [Colls.noMaybe];
};
ScanInstancesOfType:
PROC [data:
REF
ANY, v: Colls.Value,
Test: PairColls.Tester]
RETURNS [PairColls.MaybePair] ~ {
WITH v
SELECT
FROM
ct: CellType => {
FOR ci: CellInstance ← ct.firstInstance, ci.nextInstance
WHILE ci #
NIL
DO
IF Test[[ci, ct]] THEN RETURN [[TRUE, [ci, ct]]];
ENDLOOP;
};
ENDCASE => NULL;
RETURN [PairColls.noMaybePair]};
wireToChildren: PUBLIC OneToOne ~ PairColls.FnFromProc[Apply: WireToChildren, ScanInverse: ScanParentOfChildWires, spaces: [Colls.refs, PairColls.refPairColls], oneToOne: TRUE];
WireToChildren:
PROC [data:
REF
ANY, v: Colls.Value]
RETURNS [mv: Colls.MaybeValue] ~ {
WITH v
SELECT
FROM
x: Wire => RETURN [[TRUE, IntFns.CreateFromCollection[Colls.CreateEnumerator[e: [EnumerateChildrenOfWire, Colls.refs, x], mayDuplicate: FALSE, enumerateePersists: TRUE, orderStyle: client]].Refify]];
ENDCASE => RETURN [Colls.noMaybe];
};
ScanParentOfChildWires:
PROC [data:
REF
ANY, v: Colls.Value,
Test: PairColls.Tester]
RETURNS [PairColls.MaybePair] ~ {
children: Seq ~ IntFns.DeRef[v];
child: Wire ~ NARROW[children.Apply[0].val];
IF child.containingWire=NIL THEN RETURN [PairColls.noMaybePair];
IF NOT children.Equal[IntFns.DeRef[WireToChildren[data: NIL, v: child.containingWire].val]] THEN RETURN [PairColls.noMaybePair];
IF Test[[child.containingWire, v]] THEN RETURN [[TRUE, [child.containingWire, v]]];
RETURN [PairColls.noMaybePair];
};
EnumerateChildrenOfWire:
PROC [
Consume:
PROC [val: Colls.Value], data:
REF
ANY ←
NIL] ~ {
w: Wire ~ NARROW[data];
FOR child: Wire ← w.FirstChildWire[], child.NextChildWire[] UNTIL child=NIL DO Consume[child] ENDLOOP;
RETURN};
portToChildren: PUBLIC OneToOne ~ PairColls.FnFromProc[Apply: PortToChildren, ScanInverse: ScanParentOfChildPorts, spaces: [Colls.refs, PairColls.refPairColls], oneToOne: TRUE];
PortToChildren:
PROC [data:
REF
ANY, v: Colls.Value]
RETURNS [mv: Colls.MaybeValue] ~ {
WITH v
SELECT
FROM
x: Port => RETURN [[TRUE, IntFns.CreateFromCollection[Colls.CreateEnumerator[e: [EnumerateChildrenOfPort, Colls.refs, x], mayDuplicate: FALSE, enumerateePersists: TRUE, orderStyle: client]].Refify]];
ENDCASE => RETURN [Colls.noMaybe];
};
ScanParentOfChildPorts:
PROC [data:
REF
ANY, v: Colls.Value,
Test: PairColls.Tester]
RETURNS [PairColls.MaybePair] ~ {
children: Seq ~ IntFns.DeRef[v];
child: Port ~ NARROW[children.Apply[0].val];
parent: Port ~
WITH child.parent
SELECT
FROM
x: Port => x,
ct: CellType => NIL,
ENDCASE => ERROR;
IF parent=NIL THEN RETURN [PairColls.noMaybePair];
IF NOT children.Equal[IntFns.DeRef[PortToChildren[data: NIL, v: parent].val]] THEN RETURN [PairColls.noMaybePair];
IF Test[[parent, v]] THEN RETURN [[TRUE, [parent, v]]];
RETURN [PairColls.noMaybePair];
};
EnumerateChildrenOfPort:
PROC [
Consume:
PROC [val: Colls.Value], data:
REF
ANY ←
NIL] ~ {
w: Port ~ NARROW[data];
FOR child: Port ← w.FirstChildPort[], child.NextChildPort[] UNTIL child=NIL DO Consume[child] ENDLOOP;
RETURN};
bestVertexShortName: PUBLIC Function ~ PairColls.FnFromProc[Apply: VertexToBestShortName, spaces: [Colls.refs, Colls.ropes[TRUE]]];
VertexToBestShortName:
PROC [data:
REF
ANY, v: Colls.Value]
RETURNS [mv: Colls.MaybeValue] ~ {
x: Vertex ~ NARROW[v];
mv ← x.VertexNames.First[];
RETURN};
bestPortShortName: PUBLIC Function ~ PairColls.FnFromProc[Apply: PortToBestShortName, spaces: [Colls.refs, Colls.ropes[TRUE]]];
PortToBestShortName:
PROC [data:
REF
ANY, v: Colls.Value]
RETURNS [mv: Colls.MaybeValue] ~ {
x: Port ~ NARROW[v];
mv ← x.PortNames.First[];
RETURN};
vertexNames: PUBLIC Function ~ PairColls.FnFromProc[Apply: VertexToNames, spaces: [Colls.refs, Colls.refColls]];
VertexToNames:
PROC [data:
REF
ANY, v: Colls.Value]
RETURNS [mv: Colls.MaybeValue] ~ {
x: Vertex ~ NARROW[v];
mv ← [TRUE, x.VertexNames.Refify];
RETURN};
portNames: PUBLIC Function ~ PairColls.FnFromProc[Apply: PortToNames, spaces: [Colls.refs, Colls.refColls]];
PortToNames:
PROC [data:
REF
ANY, v: Colls.Value]
RETURNS [mv: Colls.MaybeValue] ~ {
x: Port ~ NARROW[v];
mv ← [TRUE, x.PortNames.Refify];
RETURN};
END.