DIRECTORY AbSets, Basics, BiRels, Convert, LichenArrayStuff, LichenDataOps, LichenDataStructure, List, LRUCache, Rope, SetBasics; LichenNewArrayImpl1: CEDAR PROGRAM IMPORTS AbSets, BiRels, Convert, LichenDataOps, LichenDataStructure, List, LRUCache, Rope, SetBasics EXPORTS LichenArrayStuff, LichenDataStructure = BEGIN OPEN LichenDataOps, LichenDataStructure, LichenArrayStuff, Sets:AbSets; Array: TYPE ~ LichenDataStructure.Array; CreateArrayRep: PUBLIC PROC [eltType: CellType, size2, basePeriod: Size2] RETURNS [Array] ~ { statrep: StatRep ~ CreateStatRep[]; a: Array = NEW [ArrayPrivate _ [ eltType: eltType, prevArray: NIL, nextArray: NIL, size2: size2, size: size2[Foo]*size2[Bar], basePeriod: basePeriod, dumrep: NIL, statrep: statrep ]]; RETURN [a]}; CreateStatRep: PUBLIC PROC RETURNS [sr: StatRep] ~ { sr _ NEW [StatRepPrivate _ [ edges: Sets.CreateHashSet[statEdges], portEdge: [ FALSE: BiRels.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]], TRUE: BiRels.CreateHashReln[functional: [FALSE, TRUE], mappable: [TRUE, FALSE]]], apToPAI: BiRels.CreateHashFn[spaces: [SetBasics.refs, portsAtIndices], invable: FALSE] ]]; RETURN}; flushSelves: BOOL _ TRUE; MakeArrayNewConnection: PUBLIC PROC [act: CellType, rangeA: Range2, delta: Int2, epA, epB: Port] ~ { a: Array ~ act.asArray; fullRangeA: Range2 ~ Range2Intersection[SizeRange[a.size2], Range2Off[SizeRange[a.size2], Int2Neg[delta]]]; rangeB: Range2 ~ Range2Off[rangeA, delta]; IF a.buildPhase#buildingStatrep THEN ERROR; IF ABS[delta[Foo]]>1 OR ABS[delta[Bar]]>1 THEN ERROR; IF epA=epB AND delta=[0, 0] THEN --this self-connection is always implicitly present, let's not make it explicit-- IF flushSelves THEN RETURN; IF rangeA # fullRangeA THEN ERROR; FOR ff: NAT IN [0 .. a.basePeriod[Foo]) DO FOR fb: NAT IN [0 .. a.basePeriod[Bar]) DO fA: Nat2 ~ [ff, fb]; fB: Nat2 ~ Nat2AddMod[fA, delta, a.basePeriod]; svA: StatVertex ~ NEW [StatVertexPrivate _ [epA, fA]]; svB: StatVertex ~ NEW [StatVertexPrivate _ [epB, fB]]; IF FindStatEdge[a.statrep, [vs: [svA, svB], d: delta]]=NIL THEN [] _ AddStatEdge[a.statrep, [vs: [FALSE: svA, TRUE: svB], d: delta]]; act _ act; ENDLOOP ENDLOOP; RETURN}; MakeStatEdge: PUBLIC PROC [sep: StatEdgePrivate] RETURNS [StatEdge] ~ { rev: BOOL ~ SELECT sep.d[Foo] FROM <0 => TRUE, =0 => sep.d[Bar]<0, >0 => FALSE, ENDCASE => ERROR; IF rev THEN sep _ [ vs: [FALSE: sep.vs[TRUE], TRUE: sep.vs[FALSE]], d: Int2Neg[sep.d] ]; RETURN [NEW [StatEdgePrivate _ sep]]}; AddStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [se: StatEdge] ~ { se _ MakeStatEdge[sep]; IF sr.edges.HasMemA[se] THEN ERROR; sr.portEdge[FALSE].AddNewAA[se.vs[FALSE].port, se]; sr.portEdge[TRUE].AddNewAA[se.vs[TRUE].port, se]; IF NOT sr.edges.AddA[se] THEN ERROR; RETURN}; RemStatEdge: PUBLIC PROC [sr: StatRep, se: StatEdge] ~ { IF NOT sr.edges.RemA[se] THEN ERROR; IF sr.portEdge[FALSE].RemAA[se.vs[FALSE].port, se].had[rightToLeft]#same THEN ERROR; IF sr.portEdge[TRUE].RemAA[se.vs[TRUE].port, se].had[rightToLeft]#same THEN ERROR; RETURN}; StatEdgeRedundant: PROC [a: Array, sep: StatEdgePrivate, avoid: StatEdge _ NIL] RETURNS [redundant: BOOL] ~ { seen: Set--of PortAtIndex-- ~ Sets.CreateHashSet[portsAtIndices]; frontier: Set--of PortAtIndex-- ~ Sets.CreateHashSet[portsAtIndices]; c1: Int2 ~ WidenNat2[sep.vs[FALSE].phase]; c2: Int2 ~ Int2Add[c1, sep.d]; bounds: Range2 ~ Int2sRange[c1, c2]; IF sep.vs[TRUE].phase # Nat2AddMod[sep.vs[FALSE].phase, sep.d, a.basePeriod] THEN ERROR; IF NOT frontier.AddA[NEW [PortAtIndexPrivate _ [sep.vs[FALSE].port, c1]]] THEN ERROR; WHILE NOT frontier.Empty[] DO pai: PortAtIndex ~ NARROW[frontier.Pop.MA]; IF NOT seen.AddA[pai] THEN LOOP; IF pai.port = sep.vs[TRUE].port AND pai.ai = c2 THEN RETURN [TRUE]; {sv: StatVertex ~ NEW [StatVertexPrivate _ [pai.port, Int2Mod[pai.ai, a.basePeriod]]]; TestEdge: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL] ~ { d: Int2 ~ IF ob THEN se.d ELSE Int2Neg[se.d]; oai: ArrayIndex ~ Int2Add[pai.ai, d]; IF se#avoid AND Int2InRange[oai, bounds] THEN [] _ frontier.AddA[NEW [PortAtIndexPrivate _ [se.vs[ob].port, oai]]]; RETURN [FALSE]}; [] _ ScanStatEdgesFrom[a.statrep, sv, TestEdge]; }ENDLOOP; RETURN [FALSE]}; FindStatEdge: PUBLIC PROC [sr: StatRep, sep: StatEdgePrivate] RETURNS [fse: StatEdge] ~ { TestEdge: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL] ~ { RETURN [statVerts.SEqual[AV[se.vs[ob]], AV[sep.vs[TRUE]]] AND sep.d = (IF ob THEN se.d ELSE Int2Neg[se.d])]}; fse _ ScanStatEdgesFrom[sr, sep.vs[FALSE], TestEdge].se; RETURN}; FinishedMakingArrayConnections: PUBLIC PROC [act: CellType] ~ { a: Array ~ act.asArray; dumrep: DumRep ~ NEW [DumRepPrivate _ [ topWires: Sets.CreateHashSet[], epToTopWire: BiRels.CreateHashFn[invable: FALSE], apToWire: BiRels.CreateHashFn[invable: TRUE] ]]; PerStatEdge: PROC [ra: REF ANY] ~ { DumbifyStatEdge[a, NARROW[ra]]; RETURN}; PerPort: PROC [rap, rpai: REF ANY] ~ { ap: Port ~ NARROW[rap]; pai: PortAtIndex ~ NARROW[rpai]; dw: DumbWire ~ GetDumbWireForPort[a, pai.port, pai.ai, TRUE]; IF dw=NIL THEN ERROR; dumrep.apToWire.AddNewAA[ap, dw]; RETURN}; IF a.buildPhase#buildingStatrep THEN ERROR; a.buildPhase _ statrepFixed; a.dumrep _ dumrep; a.statrep.edges.EnumA[PerStatEdge]; a.statrep.apToPAI.EnumAA[PerPort]; RETURN}; SetStatRep: PUBLIC PROC [act: CellType, statrep: StatRep, reset: BOOL] ~ { a: Array ~ act.asArray; IF a.buildPhase # (IF reset THEN statrepFixed ELSE buildingStatrep) THEN ERROR; a.buildPhase _ buildingStatrep; a.statrep _ statrep; FinishedMakingArrayConnections[act]; RETURN}; DumbifyStatEdge: PROC [a: Array, se: StatEdge] ~ { epA: Port ~ se.vs[FALSE].port; epB: Port ~ se.vs[TRUE].port; fullRangeA: Range2 ~ Range2Intersection[SizeRange[a.size2], Range2Off[SizeRange[a.size2], Int2Neg[se.d]]]; iRangeA: Range2 ~ Range2Div[fullRangeA, a.basePeriod, se.vs[FALSE].phase]; dwsA: RefSeq--cai _ TopDumbWire-- ~ GetDumbWires[a, epA, TRUE]; dwsB: RefSeq--cai _ TopDumbWire-- ~ GetDumbWires[a, epB, TRUE]; FOR if: INT IN [iRangeA[Foo].min .. iRangeA[Foo].maxPlusOne) DO FOR ib: INT IN [iRangeA[Bar].min .. iRangeA[Bar].maxPlusOne) DO aiA: Int2 ~ [ if*a.basePeriod[Foo]+se.vs[FALSE].phase[Foo], ib*a.basePeriod[Bar]+se.vs[FALSE].phase[Bar]]; aiB: ArrayIndex ~ Int2Add[se.d, aiA]; caiA: CompositeArrayIndex ~ ComposeAI[a, aiA]; caiB: CompositeArrayIndex ~ ComposeAI[a, aiB]; dwA: TopDumbWire ~ NARROW[dwsA[caiA]]; dwB: TopDumbWire ~ NARROW[dwsB[caiB]]; IF dwA=dwB THEN {IF dwA=NIL THEN { dw: TopDumbWire ~ CreateDumbTop[a]; AddDumbElt[a, dw, epA, aiA]; AddDumbElt[a, dw, epB, aiB]}} ELSE IF dwA=NIL THEN AddDumbElt[a, dwB, epA, aiA] ELSE IF dwB=NIL THEN AddDumbElt[a, dwA, epB, aiB] ELSE JoinDumbWires[a, dwA, dwB]; a _ a; ENDLOOP ENDLOOP; RETURN}; CreateDumbTop: PROC [a: Array] RETURNS [tdw: TopDumbWire] ~ { tdw _ NEW [DumbWirePrivate[top] _ [ children: BiRels.CreateHashFn[invable: FALSE], variant: top[eps: BiRels.CreateHashFn[invable: FALSE]] ]]; IF NOT a.dumrep.topWires.AddA[tdw] THEN ERROR; RETURN}; AddDumbElt: PROC [a: Array, dw: TopDumbWire, ep: Port, ai: ArrayIndex] ~ { cai: CompositeArrayIndex ~ ComposeAI[a, ai]; dws: RefSeq--CompositeArrayIndex _ TopDumbWire-- ~ GetDumbWires[a, ep, TRUE]; mems: BoolSeq--CompositeArrayIndex _ member-- _ NARROW[dw.eps.ApplyA[ep].MDA]; IF mems=NIL THEN dw.eps.AddNewAA[ep, mems _ CreateBoolSeq[a.size, FALSE]]; dws[cai] _ dw; mems[cai] _ TRUE; RETURN}; JoinDumbWires: PROC [a: Array, dwA, dwB: TopDumbWire] ~ { MoveElt: PROC [pair: BiRels.Pair] ~ { ep: Port ~ NARROW[pair[left].VA]; dws: RefSeq--CompositeArrayIndex _ DumbWire-- ~ NARROW[a.dumrep.epToTopWire.ApplyA[ep].MA]; memsB: BoolSeq ~ NARROW[pair[right].VA]; memsA: BoolSeq ~ NARROW[dwA.eps.ApplyA[ep].MDA]; IF memsA=NIL THEN { dwA.eps.AddNewAA[ep, memsB]; FOR cai: CompositeArrayIndex IN [0 .. a.size) DO IF memsB[cai] THEN dws[cai] _ dwA; ENDLOOP; } ELSE { FOR cai: CompositeArrayIndex IN [0 .. a.size) DO IF memsB[cai] THEN { memsA[cai] _ TRUE; dws[cai] _ dwA}; ENDLOOP; }; RETURN}; MoveExport: PROC [ra: Sets.Value] ~ { ap: Port ~ NARROW[ra.VA]; [] _ a.dumrep.apToWire.AddAA[ap, dwA]; RETURN}; IF NOT a.dumrep.topWires.RemA[dwB] THEN ERROR; dwB.eps.Enumerate[MoveElt]; a.dumrep.apToWire.MappingA[dwB, rightToLeft].Enumerate[MoveExport]; RETURN}; GetDumbWires: PROC [a: Array, ep: Port, mayAdd: BOOL] RETURNS [dws: RefSeq--cai _ TopDumbWire--] ~ { dws _ NARROW[a.dumrep.epToTopWire.ApplyA[ep].MDA]; IF dws=NIL AND mayAdd THEN a.dumrep.epToTopWire.AddNewAA[ep, dws _ CreateRefSeq[a.size]]; RETURN}; GetDumbWire: PUBLIC PROC [a: Array, ep: Port, ai: ArrayIndex] RETURNS [dw: DumbWire] ~ { cai: CompositeArrayIndex ~ ComposeAI[a, ai]; Work: PROC [ep: Port] RETURNS [dw: DumbWire] ~ { dws: RefSeq--cai _ TopDumbWire-- ~ GetDumbWires[a, ep, FALSE]; IF dws#NIL THEN dw _ NARROW[dws[cai]]; IF dw#NIL THEN RETURN; IF ep.parent # a.eltType.port THEN { pdw: DumbWire ~ Work[NARROW[ep.parent]]; IF pdw#NIL THEN RETURN [GetDumbChild[pdw, ep]]; }; RETURN}; IF a.buildPhase#statrepFixed THEN ERROR; RETURN Work[ep]}; GetDumbChild: PROC [pdw: DumbWire, port: Port] RETURNS [cdw: ChildDumbWire] ~ { cdw _ NARROW[pdw.children.ApplyA[port].MDA]; IF cdw#NIL THEN RETURN; pdw.children.AddNewAA[port, cdw _ NEW [DumbWirePrivate[child] _ [ children: BiRels.CreateHashFn[invable: FALSE], variant: child[pdw, port] ]] ]; RETURN}; GetDumbWireForPort: PROC [a: Array, ep: Port, ai: ArrayIndex, mayAdd: BOOL] RETURNS [dw: DumbWire] ~ { dw _ GetDumbWire[a, ep, ai]; IF dw#NIL OR NOT mayAdd THEN RETURN; AddDumbSubtree[a, ai, ep]; dw _ GetDumbWire[a, ep, ai]; RETURN}; AddDumbSubtree: PROC [a: Array, index: ArrayIndex, ep: Port] ~ { Check: PROC [ep, done: Port] RETURNS [ok: BOOL _ TRUE] ~ { ok _ GetDumbWire[a, ep, index] = NIL; FOR cep: Port _ ep.FirstChildPort, cep.NextChildPort WHILE ok AND cep#NIL DO ok _ cep=done OR Check[cep, NIL]; ENDLOOP; RETURN}; IF NOT Check[ep, NIL] THEN RETURN; {WorkUp: PROC [ep: Port] ~ { WITH ep.parent SELECT FROM parent: Port => IF parent#a.eltType.port THEN { pdw: DumbWire ~ GetDumbWire[a, parent, index]; IF pdw#NIL THEN {WorkDown[pdw, parent]; RETURN}; IF Check[parent, ep] THEN {WorkUp[parent]; RETURN}; }; ENDCASE => NULL; {tdw: TopDumbWire ~ CreateDumbTop[a]; AddDumbElt[a, tdw, ep, index]; WorkDown[tdw, ep]; RETURN}}; WorkDown: PROC [dw: DumbWire, ep: Port] ~ { FOR cep: Port _ ep.FirstChildPort, cep.NextChildPort WHILE cep#NIL DO WorkDown[GetDumbChild[dw, cep], cep]; ENDLOOP; RETURN}; WorkUp[ep]; RETURN}}; ArrayEltPortsConnected: PUBLIC PROC [a: Array, ai1, ai2: ArrayIndex, ep1, ep2: Port] RETURNS [BOOL] ~ { dw1: DumbWire ~ GetDumbWire[a, ep1, ai1]; dw2: DumbWire ~ GetDumbWire[a, ep2, ai2]; IF a.buildPhase#statrepFixed THEN ERROR; RETURN [dw1=dw2 AND dw1#NIL]}; EnumerateConnectedEltPorts: PUBLIC PROC [a: Array, ep: Port, Consume: PROC [Port], mayDuplicate: BOOL] ~ { seenPorts: Set--of elt Port--; PerWire: PROC [dw: DumbWire] ~ { [] _ ScanPortsInDumbWire[a, dw, PassPort]; RETURN}; PassPort: PROC [ep: Port] RETURNS [BOOL] ~ { IF (mayDuplicate OR seenPorts.AddA[ep]) THEN Consume[ep]; RETURN [FALSE]}; IF NOT mayDuplicate THEN seenPorts _ Sets.CreateHashSet[]; IF a.buildPhase#statrepFixed THEN ERROR; EnumerateDumbWiresForPort[a, ep, PerWire]; RETURN}; EnumerateDumbWiresForPort: PUBLIC PROC [a: Array, ep: Port, Consume: PROC [DumbWire]] ~ { seenWires: Set--of TopDumbWire-- ~ Sets.CreateHashSet[]; Work: PROC [port: Port, Consume: PROC [DumbWire]] ~ { dws: RefSeq--CompositeArrayIndex _ TopDumbWire-- ~ NARROW[a.dumrep.epToTopWire.ApplyA[port].MDA]; IF dws#NIL THEN { FOR cai: CompositeArrayIndex IN [0 .. a.size) DO dw: TopDumbWire ~ NARROW[dws[cai]]; IF seenWires.AddA[dw] THEN Consume[dw]; ENDLOOP; }; WITH port.parent SELECT FROM parent: Port => { Pass: PROC [parent: DumbWire] ~ { child: ChildDumbWire ~ GetDumbChild[parent, port]; Consume[child]; RETURN}; Work[parent, Pass]; }; x: CellType => NULL; ENDCASE => ERROR; RETURN}; IF a.buildPhase#statrepFixed THEN ERROR; Work[ep, Consume]; RETURN}; ScanPortsInDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, Test: PROC [Port] RETURNS [BOOL]] RETURNS [found: BOOL, ep: Port] ~ { ScanWire: PROC [dw: DumbWire, Test: PROC [Port] RETURNS [BOOL]] RETURNS [found: BOOL, ep: Port] ~ { WITH dw SELECT FROM tdw: TopDumbWire => { TestPort: PROC [pair: BiRels.Pair] RETURNS [pass: BOOL _ FALSE] ~ { port: Port ~ NARROW[pair[left].VA]; IF (pass _ Test[port]) THEN ep _ port; RETURN}; found _ tdw.eps.Scan[TestPort].found; RETURN}; cdw: ChildDumbWire => { index: NATURAL ~ cdw.port.PortIndex; TestPort: PROC [parent: Port] RETURNS [pass: BOOL _ FALSE] ~ { child: Port ~ parent.SubPort[index]; IF (pass _ Test[child]) THEN ep _ child; RETURN}; found _ ScanWire[cdw.parent, TestPort].found; RETURN}; ENDCASE => ERROR; }; RETURN ScanWire[dw, Test]}; GetInstForPortInDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, ep: Port] RETURNS [ArrayIndex] ~ { WITH dw SELECT FROM tdw: TopDumbWire => { mems: BoolSeq--CompositeArrayIndex _ member-- ~ NARROW[tdw.eps.ApplyA[ep].MA]; FOR cai: NATURAL IN [0 .. a.size) DO IF mems[cai] THEN RETURN DecomposeAI[a, cai]; ENDLOOP; RETURN [ALL[-1]]}; cdw: ChildDumbWire => RETURN GetInstForPortInDumbWire[a, cdw.parent, NARROW[ep.parent]]; ENDCASE => ERROR; }; ScanPortsAtIndicesForDumbWire: PUBLIC PROC [a: Array, dw: DumbWire, Test: PROC [port: Port, ai: ArrayIndex] RETURNS [BOOL]] RETURNS [found: BOOL, pai: PortAtIndexPrivate] ~ { WITH dw SELECT FROM tdw: TopDumbWire => { PerPort: PROC [pair: BiRels.Pair] RETURNS [pass: BOOL] ~ { ep: Port ~ NARROW[pair[left].VA]; mems: BoolSeq--CompositeArrayIndex _ member-- ~ NARROW[pair[right].VA]; FOR f: INT IN [0 .. a.size2[Foo]) DO FOR b: INT IN [0 .. a.size2[Bar]) DO cai: CompositeArrayIndex ~ ComposeAI[a, [f, b]]; IF mems[cai] THEN IF (pass _ Test[ep, [f, b]]) THEN {pai _ [ep, [f, b]]; RETURN}; ENDLOOP ENDLOOP; RETURN [FALSE]}; found _ tdw.eps.Scan[PerPort].found; RETURN}; cdw: ChildDumbWire => { index: NATURAL ~ cdw.port.PortIndex; Pass: PROC [port: Port, ai: ArrayIndex] RETURNS [pass: BOOL] ~ { child: Port ~ port.SubPort[index]; IF (pass _ Test[child, ai]) THEN pai _ [child, ai]; RETURN}; found _ ScanPortsAtIndicesForDumbWire[a, cdw.parent, Pass].found; RETURN}; ENDCASE => ERROR; }; ScanStatVertices: PUBLIC PROC [a: Array, Test: PROC [StatVertex] RETURNS [BOOL]] RETURNS [found: BOOL _ FALSE, sv: StatVertex _ NIL] ~ { seen: Set--of StatVertex-- ~ Sets.CreateHashSet[statVerts]; PerEdge: PROC [ra: Sets.Value] ~ { se: StatEdge ~ NARROW[ra.VA]; IF seen.AddA[se.vs[FALSE]] AND Test[se.vs[FALSE]] THEN {found _ TRUE; sv _ se.vs[FALSE]; RETURN}; IF seen.AddA[se.vs[TRUE]] AND Test[se.vs[TRUE]] THEN {found _ TRUE; sv _ se.vs[TRUE]}; RETURN}; a.statrep.edges.Enumerate[PerEdge]; RETURN}; ScanStatEdgesFrom: PUBLIC PROC [sr: StatRep, from: StatVertex, Test: PROC [se: StatEdge, ob: BOOL] RETURNS [BOOL]] RETURNS [found: BOOL _ FALSE, se: StatEdge _ NIL, ob: BOOL _ FALSE] ~ { FOR ob IN BOOL DO sb: BOOL ~ NOT ob; TestEdge: PROC [ra: Sets.Value] RETURNS [pass: BOOL] ~ { se: StatEdge ~ NARROW[ra.VA]; pass _ se.vs[sb].phase = from.phase AND Test[se, ob]; RETURN}; mp: BiRels.MaybePair ~ sr.portEdge[sb].ScanMapping[AV[from.port], TestEdge]; IF mp.found THEN RETURN [TRUE, NARROW[mp.it[right].VA], ob]; ENDLOOP; RETURN}; GetArrayPortForPort: PUBLIC PROC [act: CellType, index: ArrayIndex, ep: Port, mayAdd: BOOL] RETURNS [arrayPort: Port] ~ { a: Array ~ act.asArray; IF a.buildPhase#statrepFixed THEN ERROR; {dw: DumbWire ~ GetDumbWireForPort[a, ep, index, mayAdd]; IF dw=NIL THEN {IF mayAdd THEN ERROR--trying to export a composite wire that doesn't really exist-- ELSE RETURN [NIL]}; {aPort: Port ~ NARROW[a.dumrep.apToWire.ScanHalfRestriction[set: Sets.CreateSingleton[AV[dw], SetBasics.refs], Test: BiRels.AcceptAny, side: right].KeepHalf[left].MDA]; IF aPort#NIL THEN RETURN [aPort]; IF NOT mayAdd THEN RETURN [NIL]; arrayPort _ FullyAddPort[[parent: act.port, names: CreateSteppyNames[IF act.inheritNames THEN LIST[List.Append[NameIndex[a, index], SteppyDescribe[ep, a.eltType.port]]] ELSE NIL]]].port; a.statrep.apToPAI.AddNewAA[arrayPort, NEW[PortAtIndexPrivate _ [ep, index]]]; a.dumrep.apToWire.AddNewAA[arrayPort, dw]; RETURN}}}; NoteNewEltPort: PUBLIC PROC [a: Array, ep: Port] ~ { RETURN}; IsIncompleteArray: PUBLIC PROC [act: CellType] RETURNS [BOOL] ~ {RETURN [FALSE]}; ComposeAI: PROC [a: Array, ai: ArrayIndex] RETURNS [CompositeArrayIndex] ~ INLINE {RETURN [a.size2[Bar]*ai[Foo]+ai[Bar]]}; DecomposeAI: PROC [a: Array, cai: CompositeArrayIndex] RETURNS [ArrayIndex] ~ { f: NATURAL ~ cai/a.size2[Bar]; RETURN [[f, cai - f*a.size2[Bar]]]}; NameIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [SteppyName] = { SELECT TRUE FROM a.size2[Foo]=1 => RETURN [LIST[NewInt[index[Bar]]]]; a.size2[Bar]=1 => RETURN [LIST[NewInt[index[Foo]]]]; ENDCASE => RETURN [LIST[NewInt[index[Foo]], NewInt[index[Bar]]]]; }; FmtIndex: PUBLIC PROC [a: Array, index: ArrayIndex] RETURNS [asRope: ROPE] = { asRope _ SELECT TRUE FROM a.size2[Foo]=1 => Subscript[NIL, index[Bar]], a.size2[Bar]=1 => Subscript[NIL, index[Foo]], ENDCASE => Subscript2[NIL, index]; }; sublen: NATURAL ~ 64; subs: ARRAY [0 .. sublen) OF ROPE _ ALL[NIL]; Subscript: PUBLIC PROC [base: ROPE, index: INT] RETURNS [sub: ROPE] ~ { sub _ IF index < sublen THEN sub _ subs[index] ELSE sub _ Convert.RopeFromInt[index].Concat["/"]; IF base.Length#0 THEN sub _ base.Cat["/", sub]; RETURN}; sub2len: NATURAL _ 2050; sub2Ps: LRUCache.Handle _ LRUCache.Create[sub2len, HashAI, EqualAI]; sub2Rs: RefSeq _ CreateRefSeq[sub2len]; s2probes, s2misses: CARD _ 0; HashAI: PROC [ra: REF ANY] RETURNS [CARDINAL] --LRUCache.HashProc-- ~ { rai: REF ArrayIndex ~ NARROW[ra]; lnF: Basics.LongNumber ~ [li[rai[Foo]]]; lnB: Basics.LongNumber ~ [li[rai[Bar]]]; ln: Basics.LongNumber ~ [lc[lnF.lo + lnF.hi*3 + lnB.lo*5 + lnB.hi*7]]; RETURN [ln.lo+ln.hi]; }; EqualAI: PROC [r1, r2: REF ANY] RETURNS [BOOL] --LRUCache.EqualProc-- ~ { rai1: REF ArrayIndex ~ NARROW[r1]; rai2: REF ArrayIndex ~ NARROW[r2]; RETURN [rai1^ = rai2^]}; Subscript2: PUBLIC PROC [base: ROPE, index: ArrayIndex] RETURNS [sub: ROPE] ~ { rai: REF ArrayIndex ~ NEW [ArrayIndex _ index]; p: NATURAL; news: BOOL; [p, news, ] _ sub2Ps.Include[rai]; s2probes _ s2probes+1; IF news THEN { sub2Rs[p] _ Rope.Cat[Convert.RopeFromInt[index[Foo]], "/", Convert.RopeFromInt[index[Bar]], "/"]; s2misses _ s2misses+1; }; sub _ NARROW[sub2Rs[p]]; IF base.Length#0 THEN sub _ base.Cat["/", sub]; RETURN}; statEdges: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate _ [ Contains: StatEdgesContains, Equal: StatEdgesEqual, Hash: HashStatEdge, Compare: CompareStatEdges, name: "stat edges" ]]; StatEdgesContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ { RETURN [WITH v.ra SELECT FROM x: StatEdge => TRUE, ENDCASE => FALSE]}; StatEdgesEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ { RETURN [CompareStatEdges[data, v1, v2]=equal]}; HashStatEdge: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ { se: StatEdge ~ NARROW[v.ra]; RETURN [statVerts.SHash[AV[se.vs[FALSE]]]*17 + statVerts.SHash[AV[se.vs[TRUE]]] + SetBasics.HashIntI[se.d[Foo]]*137 + SetBasics.HashIntI[se.d[Bar]]*33]}; CompareStatEdges: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ { se1: StatEdge ~ NARROW[v1.ra]; se2: StatEdge ~ NARROW[v2.ra]; IF (c _ statVerts.SCompare[AV[se1.vs[FALSE]], AV[se2.vs[FALSE]]]) = equal THEN IF (c _ statVerts.SCompare[AV[se1.vs[TRUE]], AV[se2.vs[TRUE]]]) = equal THEN IF (c _ SetBasics.CompareIntI[se1.d[Foo], se2.d[Foo]]) = equal THEN c _ SetBasics.CompareIntI[se1.d[Bar], se2.d[Bar]]; RETURN}; statVerts: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate _ [ Contains: StatVertsContains, Equal: StatVertsEqual, Hash: HashStatVert, Compare: CompareStatVerts, name: "stat verts" ]]; StatVertsContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ { RETURN [WITH v.ra SELECT FROM x: StatVertex => TRUE, ENDCASE => FALSE]}; StatVertsEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ { RETURN [CompareStatVerts[data, v1, v2]=equal]}; HashStatVert: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ { sv: StatVertex ~ NARROW[v.VA]; RETURN [SetBasics.HashRefI[sv.port] + SetBasics.HashIntI[sv.phase[Foo]]*137 + SetBasics.HashIntI[sv.phase[Bar]]]}; CompareStatVerts: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ { sv1: StatVertex ~ NARROW[v1.VA]; sv2: StatVertex ~ NARROW[v2.VA]; IF (c _ SetBasics.CompareRefI[sv1.port, sv2.port]) = equal THEN IF (c _ SetBasics.CompareIntI[sv1.phase[Foo], sv2.phase[Foo]]) = equal THEN c _ SetBasics.CompareIntI[sv1.phase[Bar], sv2.phase[Bar]]; RETURN}; portsAtIndices: PUBLIC SetBasics.Space ~ NEW [SetBasics.SpacePrivate _ [ Contains: PortsAtIndicesContains, Equal: PortsAtIndicesEqual, Hash: PortsAtIndicesHash, Compare: PortsAtIndicesCompare, name: "ports at indices" ]]; PortsAtIndicesContains: PROC [data: REF ANY, v: Sets.Value] RETURNS [BOOL] ~ { RETURN [WITH v.ra SELECT FROM x: PortAtIndex => TRUE, ENDCASE => FALSE]}; PortsAtIndicesEqual: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [BOOL] ~ { RETURN [PortsAtIndicesCompare[data, v1, v2]=equal]}; PortsAtIndicesHash: PROC [data: REF ANY, v: Sets.Value] RETURNS [CARDINAL] ~ { pai: PortAtIndex ~ NARROW[v.VA]; RETURN [SetBasics.HashRefI[pai.port] + SetBasics.HashIntI[pai.ai[Foo]]*137 + SetBasics.HashIntI[pai.ai[Bar]]]}; PortsAtIndicesCompare: PROC [data: REF ANY, v1, v2: Sets.Value] RETURNS [c: Basics.Comparison] ~ { pai1: PortAtIndex ~ NARROW[v1.VA]; pai2: PortAtIndex ~ NARROW[v2.VA]; IF (c _ SetBasics.CompareRefI[pai1.port, pai2.port]) = equal THEN IF (c _ SetBasics.CompareIntI[pai1.ai[Foo], pai2.ai[Foo]]) = equal THEN c _ SetBasics.CompareIntI[pai1.ai[Bar], pai2.ai[Bar]]; RETURN}; Range2Div: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = { rr _ [ Foo: [ min: CeilDiv[r[Foo].min-f[Foo], t[Foo]], maxPlusOne: FloorDiv[r[Foo].maxPlusOne-1-f[Foo], t[Foo]] + 1], Bar: [ min: CeilDiv[r[Bar].min-f[Bar], t[Bar]], maxPlusOne: FloorDiv[r[Bar].maxPlusOne-1-f[Bar], t[Bar]] + 1]]; }; Range1Div: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = { rr _ [ min: CeilDiv[r.min-f, t], maxPlusOne: FloorDiv[r.maxPlusOne-1-f, t] + 1]; }; Range2MulA: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = { rr _ [ Foo: [ min: r[Foo].min*t[Foo] + f[Foo], maxPlusOne: (r[Foo].maxPlusOne-1)*t[Foo] + 1 + f[Foo]], Bar: [ min: r[Bar].min*t[Bar] + f[Bar], maxPlusOne: (r[Bar].maxPlusOne-1)*t[Bar] + 1 + f[Bar]]]; }; Range2MulB: PUBLIC PROC [r: Range2, t, f: Nat2] RETURNS [rr: Range2] = { rr _ [ Foo: [ min: r[Foo].min*t[Foo] + f[Foo], maxPlusOne: r[Foo].maxPlusOne*t[Foo] + f[Foo]], Bar: [ min: r[Bar].min*t[Bar] + f[Bar], maxPlusOne: r[Bar].maxPlusOne*t[Bar] + f[Bar]]]; }; Range1MulB: PUBLIC PROC [r: Range, t, f: NAT] RETURNS [rr: Range] = { rr _ [ min: r.min*t + f, maxPlusOne: r.maxPlusOne*t + f]; }; Start: PROC ~ { FOR index: NATURAL IN [0 .. sublen) DO subs[index] _ Convert.RopeFromInt[index].Concat["/"]; ENDLOOP; RETURN}; Start[]; END. bLichenNewArrayImpl1.Mesa Last tweaked by Mike Spreitzer on February 1, 1988 10:52:04 am PST ส๙– "cedar" style˜code™K™B—K˜Kšฯk œx˜K˜šฯnœœ˜"Kšœ]˜dKšœ&˜-K˜—K˜Kšœœ7žœ˜MK˜Kšœœ˜(K˜šžœœœ/œ ˜]Kšœ#˜#šœ œ˜ K˜Kšœ œ˜Kšœ œ˜K˜ K˜Kšœ˜Kšœœ˜ Kšœ˜K˜—Kšœ˜ —K˜šž œœœœ˜4šœœ˜K˜%šœ ˜ Kš œ%œœœœ˜QKš œ%œœœœ˜Q—KšœPœ˜VK˜—Kšœ˜—K˜Kšœ œœ˜K˜šžœœœA˜dK˜Kšœk˜kK˜*Kšœœœ˜+Kš œœœœœœ˜5Kšœ œœฯcQœœ œœ˜ŽKšœœœ˜"šœฯgฯdœœœœœ กœœœ˜UKš œ  กœ กœ˜Kš œ œ˜/Kšœœ œ˜6Kšœœ œ˜6Kšœ* œ œœ#œœ œ ˜…K˜ Kšœœ˜—Kšœ˜—K˜šž œœœœ˜Gšœœœ œ˜"Kšœœ˜ Kšœ  œ˜Kšœœ˜ Kšœœ˜—šœœ˜Kš œœ œœ œ˜/Kš œ œ˜K˜—Kšœœ˜&—K˜šž œœœ%œ˜WKšœ˜Kšœœœ˜#Kšœ œœ ˜3Kšœ œœ ˜1Kšœœœœ˜$Kšœ˜—K˜šž œœœ ˜8Kšœœœœ˜$Kš œ œœ"œœ˜TKš œ œœ"œœ˜RKšœ˜—K˜š žœœ4œœ œ˜mKšœ Ÿœ&˜AKšœ Ÿœ&˜EKšœœ ˜*Kšœ œ˜Kšœ$˜$Kš œœœ  œœœ˜XKš œœœœœœ˜Ušœœ˜Kšœœœ˜+Kšœœœœ˜ Kš œœœ œœœ˜CKšœœA˜Vš žœœœœœ˜:Kš  œ œœ œœ  œ˜-Kšœ" œ˜%Kšœ œœœ/˜sKšœœ˜—Kšœ0˜0Kšœœ˜ —Kšœœ˜—K˜šž œœœ%œ˜Yš žœœœœœ˜:Kšœœ œœœ œœœ œœ  œ˜m—Kšœ#œ˜8Kšœ˜—K˜šžœœœ˜?K˜šœœ˜'Kšœ˜Kšœ*œ˜1Kšœ'œ˜,K˜—šž œœœœ˜#Kšœœ˜Kšœ˜—šžœœ œœ˜&Kšœ œ˜Kšœœ˜ Kšœ7œ˜=Kšœœœœ˜Kšœ!˜!Kšœ˜—Kšœœœ˜+Kšœ˜K˜Kšœ#˜#Kšœ"˜"Kšœ˜—K˜šž œœœ*œ˜JK˜Kš œœœœœœ˜OKšœ˜K˜Kšœ$˜$Kšœ˜—K˜šžœœ˜2Kšœœ˜Kšœœ˜Kšœe œ˜jKšœ<œ ˜JKšœ ŸะcmŸœœ˜?Kšœ ŸขŸœœ˜?šœกœœœ/œœกœœœ/˜˜ Kšœกœœ ˜-Kšœกœœ˜.—Kšœ œ˜%Kšœ.˜.Kšœ.˜.Kšœœ ˜&Kšœœ ˜&š œ œœœœ˜"Kšœ#˜#K˜Kšœ˜—Kšœœœœ˜1Kšœœœœ˜1Kšœ˜ Kšœ˜Kšœœ˜—Kšœ˜—K˜šž œœ œ˜=šœœ˜#Kšœ'œ˜.Kšœ/œ˜6K˜—Kšœœœœ˜.Kšœ˜—K˜šž œœ:˜JKšœ,˜,Kšœ ŸขŸœœ˜MKš œ ŸขŸ œœœ˜NKšœœœ:˜JKšœ˜Kšœ œ˜Kšœ˜—K˜šž œœ&˜9šžœœ˜%Kšœ œ œ˜!Kšœ ŸขŸ œœ%˜[Kšœœ œ˜(Kšœœœ˜0šœœœ˜Kšœ˜šœœ˜0Kšœ œ˜"Kšœ˜—K˜—šœ˜šœœ˜0šœ œ˜Kšœ œ˜Kšœ˜—Kšœ˜—K˜—Kšœ˜—šž œœ˜%Kšœ œœ˜K˜&Kšœ˜—Kšœœœœ˜.K˜KšœC˜CKšœ˜—K˜š ž œœœœ ŸขŸœ˜dKšœœ!œ˜2Kšœœœœ?˜YKšœ˜—K˜šž œœœ&œ˜XKšœ,˜,šžœœ œ˜0Kšœ ŸขŸœœ˜>Kšœœœœ ˜&Kšœœœœ˜šœœ˜$Kšœœ ˜(Kšœœœœ˜/Kšœ˜—Kšœ˜—Kšœœœ˜(Kšœ ˜—K˜šž œœœ˜OKšœœœ˜,Kšœœœœ˜šœ"œ˜AKšœ'œ˜.Kšœ˜—Kšœ˜—K˜šžœœ.œœ˜fK˜Kš œœœœœœ˜$Kšœ˜K˜Kšœ˜—K˜šžœœ,˜@š žœœœœœ˜:Kšœ!œ˜%š œ2œœœ˜LKšœœ œ˜!Kšœ˜—Kšœ˜—Kš œœ œœœ˜"šœžœœ˜šœ œ˜šœœœ˜/Kšœ.˜.Kšœœœœ˜0Kšœœœ˜3K˜—Kšœœ˜—Kšœ%˜%Kšœ˜K˜Kšœ˜ —šžœœ˜+šœ2œœ˜EKšœ%˜%Kšœ˜—Kšœ˜—K˜ Kšœ˜ —K˜š žœœœ2œœ˜gKšœ)˜)Kšœ)˜)Kšœœœ˜(Kšœ œœ˜—K˜š žœœœžœœœ˜jKšœŸœ˜šžœœ˜ Kšœ*˜*Kšœ˜—šžœœ œœ˜,Kšœœœ ˜9Kšœœ˜—Kšœœœ"˜:Kšœœœ˜(Kšœ*˜*Kšœ˜—K˜š žœœœžœœ˜YKšœŸœ˜8šžœœžœœ˜5Kš œ ŸขŸœœ#œ˜ašœœœ˜šœœ˜0Kšœœ ˜#Kšœœ ˜'Kšœ˜—K˜—šœ œ˜šœ˜šžœœ˜!Kšœ2˜2K˜Kšœ˜—K˜K˜—Kšœœ˜Kšœœ˜—Kšœ˜—Kšœœœ˜(Kšœ˜Kšœ˜—K˜šžœœœžœœœœœ œ˜šžœœžœœœœœ œ˜cšœœ˜šœ˜š žœœœœœ˜CKšœ œ œ˜#Kšœœ ˜&Kšœ˜—Kšœ%˜%Kšœ˜—šœ˜Kšœœ˜$š žœœœœœ˜>Kšœ$˜$Kšœœ ˜(Kšœ˜—Kšœ-˜-Kšœ˜—Kšœœ˜—K˜—Kšœ˜—K˜šžœœœ$œ˜ašœœ˜šœ˜Kš œ ŸขŸ œœœ˜Nšœœœ˜$Kšœ œœ˜-Kšœ˜—Kšœœ˜—Kšœœ)œ ˜XKšœœ˜—Kšœ˜—K˜šžœœœžœœœœœ œ˜ฎšœœ˜šœ˜šžœœœœ˜:Kšœ œ œ˜!Kš œ ŸขŸ œœ œ˜Gšœœœœœœœ˜IKšœ0˜0šœ œœ˜.Kšœœ˜"—Kšœœ˜—Kšœœ˜—Kšœ$˜$Kšœ˜—šœ˜Kšœœ˜$šžœœœœ˜@K˜"Kšœœ˜3Kšœ˜—KšœA˜AKšœ˜—Kšœœ˜—Kšœ˜—K˜šžœœœ žœœœœœ œœœ˜ˆKšœ Ÿœ!˜;šžœœ˜"Kšœœœ˜Kšœœœ œœ œ œœ˜aKšœœœ œœ œ œ˜VKšœ˜—Kšœ#˜#Kšœ˜—K˜šžœœœ!žœœœœœœ œœœœœ˜บšœœœ˜Kšœœœ˜šžœœœœ˜8Kšœœœ˜Kšœ$œ˜5Kšœ˜—KšœL˜LKš œ œœœœœ˜—˜Kšœ œ œ˜(Kšœ) œ œ ˜?——K˜—K˜šž œœœ  œ œœœ˜D˜Kšœ œ œ˜Kšœ$ œ œ˜/—K˜—K˜š ž œœœ  œ œœ˜H˜˜Kšœ œ œ˜ Kšœ" œ  œ˜7—˜Kšœ œ œ˜ Kšœ" œ  œ˜8——K˜—K˜š ž œœœ  œ œœ˜H˜˜Kšœ œ œ˜ Kšœ œ œ˜/—˜Kšœ œ œ˜ Kšœ œ œ˜0——K˜—K˜šž œœœ  œ œœœ˜E˜Kšœ  œ œ˜Kšœ œ œ˜ —K˜—K˜šžœœ˜šœœœ˜&Kšœ5˜5Kšœ˜—Kšœ˜—K˜K˜K˜Kšœ˜—…—Yšx๕