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: BOOLTRUE, literal: BOOLFALSE] 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 ANYNIL] ~ {
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: BOOLTRUE, literal: BOOLFALSE] 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 ANYNIL] ~ {
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 ANYNIL] ~ {
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: BOOLTRUE, literal: BOOLFALSE] 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 ANYNIL] ~ {
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: BOOLFALSE] ~ {
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 ANYNIL] ~ {
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 ANYNIL] ~ {
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.