DIRECTORY OneToOne, RefTab; OneToOneImpl: CEDAR PROGRAM IMPORTS OneToOne, RefTab EXPORTS OneToOne = {OPEN OneToOne; Contradiction: PUBLIC ERROR [oto: OneToOne, a, b: REF ANY] = CODE; CreateVanillaOneToOne: PUBLIC PROC [hashA, hashB: RefTab.HashProc _ NIL, compareA, compareB: RefTab.EqualProc _ NIL] RETURNS [oto: OneToOne] = { oto _ NEW [OneToOnePrivate _ [HashedEnumerate, HashedAssociate, HashedMap, NEW [HashOneToOnePrivate _ [RefTab.Create[equal: compareA, hash: hashA], RefTab.Create[equal: compareB, hash: hashB]]]]]; }; HashOneToOne: TYPE = REF HashOneToOnePrivate; HashOneToOnePrivate: TYPE = RECORD [ forward, backward: RefTab.Ref ]; HashedEnumerate: PROC [oto: OneToOne, Consume: PROC [a, b: REF ANY]] = { hoto: HashOneToOne = NARROW[oto.data]; PerPair: PROC [key, val: REF ANY] RETURNS [quit: BOOL _ FALSE] --RefTab.EachPairAction-- = { Consume[key, val]; }; [] _ hoto.forward.Pairs[PerPair]; }; HashedAssociate: PROC [oto: OneToOne, a, b: REF ANY] = { hoto: HashOneToOne = NARROW[oto.data]; IF a=NIL OR b=NIL OR NOT (hoto.forward.Insert[a, b] AND hoto.backward.Insert[b, a]) THEN ERROR Contradiction[oto, a, b]; }; HashedMap: PROC [oto: OneToOne, from: REF ANY, forward: BOOL _ TRUE] RETURNS [to: REF ANY] = { hoto: HashOneToOne = NARROW[oto.data]; to _ (IF forward THEN hoto.forward ELSE hoto.backward).Fetch[from].val; }; id: PUBLIC OneToOne = NEW [OneToOnePrivate _ [NIL, NIL, MapId]]; MapId: PROC [oto: OneToOne, from: REF ANY, forward: BOOL _ TRUE] RETURNS [REF ANY] = {RETURN [from]}; Reverse: PUBLIC PROC [fwd: OneToOne] RETURNS [rev: OneToOne] = { rev _ NEW [OneToOnePrivate _ [ReversedEnumerate, ReversedAssociate, ReversedMap, fwd]]; }; ReversedEnumerate: PROC [oto: OneToOne, Consume: PROC [a, b: REF ANY]] = { fwd: OneToOne = NARROW[oto.data]; Reverse: PROC [a, b: REF ANY] = {Consume[b, a]}; fwd.Enumerate[Reverse]; }; ReversedAssociate: PROC [oto: OneToOne, a, b: REF ANY] = { fwd: OneToOne = NARROW[oto.data]; fwd.Associate[b, a]}; ReversedMap: PROC [oto: OneToOne, from: REF ANY, forward: BOOL _ TRUE] RETURNS [to: REF ANY] = { fwd: OneToOne = NARROW[oto.data]; to _ fwd.Map[from, NOT forward]; }; Triplate: PUBLIC PROC [inward, inner, outward: OneToOne] RETURNS [outer: OneToOne] = { t: Triplator = NEW [TriplatorPrivate _ [inward, inner, outward]]; outer _ NEW [OneToOnePrivate _ [TriplatedEnumerate, TriplatedAssociate, TriplatedMap, t]]; }; Triplator: TYPE = REF TriplatorPrivate; TriplatorPrivate: TYPE = RECORD [inward, inner, outward: OneToOne]; TriplatedEnumerate: PROC [oto: OneToOne, Consume: PROC [a, b: REF ANY]] = { t: Triplator = NARROW[oto.data]; Triplate: PROC [a, b: REF ANY] = { Consume[t.inward.Map[a, FALSE], t.outward.Map[b, TRUE]]; }; t.inner.Enumerate[Triplate]; }; TriplatedAssociate: PROC [oto: OneToOne, a, b: REF ANY] = { t: Triplator = NARROW[oto.data]; t.inner.Associate[t.inward.Map[a, TRUE], t.outward.Map[b, FALSE]]; }; TriplatedMap: PROC [oto: OneToOne, from: REF ANY, forward: BOOL _ TRUE] RETURNS [to: REF ANY] = { t: Triplator = NARROW[oto.data]; to _ IF forward THEN t.outward.Map[t.inner.Map[t.inward.Map[from, TRUE], TRUE], TRUE] ELSE t.inward.Map[t.inner.Map[t.outward.Map[from, FALSE], FALSE], FALSE]; }; }. XOneToOneImpl.Mesa Last tweaked by Mike Spreitzer on April 2, 1987 3:11:03 pm PST Κv– "cedar" style˜code™K™>—K˜KšΟk œ˜K˜šΡbnx œœ˜Kšœ˜Kšœ ˜K˜Kšœœ ˜K˜Kš Οn œœœœœœ˜BK˜š Ÿœœœ"œ)œœ˜KšœœBœv˜ΔK˜—K˜Kšœœœ˜-šœœœ˜$K˜K˜—K˜š ŸœœŸœœœœ˜HKšœœ ˜&šŸœœ œœœœœΟcœ˜\K˜K˜—K˜!K˜—K˜šŸœœœœ˜8Kšœœ ˜&Kšœœœœœœœœœ˜xK˜—K˜šŸ œœœœ œœœœœ˜^Kšœœ ˜&Kšœœ œœ ˜GK˜—K˜Kš œœ œœœ ˜@K˜KšŸœœœœ œœœœœœ ˜eK˜šŸœœœœ˜@KšœœN˜WK˜—K˜š ŸœœŸœœœœ˜JKšœœ ˜!KšŸœœœœ˜0K˜K˜—K˜šŸœœœœ˜:Kšœœ ˜!K˜—K˜šŸ œœœœ œœœœœ˜`Kšœœ ˜!Kšœœ ˜ K˜—K˜šŸœœœ$œ˜VKšœœ/˜AKšœœO˜ZK˜—K˜Kšœ œœ˜'Kšœœœ$˜CK˜š ŸœœŸœœœœ˜KKšœœ ˜ šŸœœœœ˜"Kšœœœ˜8K˜—Kšœ˜K˜—K˜šŸœœœœ˜;Kšœœ ˜ Kšœ"œœ˜BK˜—K˜šŸ œœœœ œœœœœ˜aKšœœ ˜ šœœ˜Kšœ.œœœ˜EKšœ.œœœ˜I—K˜—K˜K˜——…— €N