<> <> DIRECTORY HashTable, OneToOne; OneToOneImpl: CEDAR PROGRAM IMPORTS HashTable, OneToOne EXPORTS OneToOne = {OPEN OneToOne; Contradiction: PUBLIC ERROR [oto: OneToOne, a, b: REF ANY] = CODE; CreateVanillaOneToOne: PUBLIC PROC RETURNS [oto: OneToOne] = { oto _ NEW [OneToOnePrivate _ [HashedEnumerate, HashedAssociate, HashedMap, NEW [HashOneToOnePrivate _ [HashTable.Create[], HashTable.Create[]]]]]; }; HashOneToOne: TYPE = REF HashOneToOnePrivate; HashOneToOnePrivate: TYPE = RECORD [ forward, backward: HashTable.Table ]; HashedEnumerate: PROC [oto: OneToOne, Consume: PROC [a, b: REF ANY]] = { hoto: HashOneToOne = NARROW[oto.data]; PerPair: PROC [key, value: REF ANY] RETURNS [quit: BOOL _ FALSE] --HashTable.EachPairAction-- = { Consume[key, value]; }; [] _ 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].value; }; 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]; }; Translate: PUBLIC PROC [inner, translator: OneToOne, translateForward: BOOL _ TRUE] RETURNS [outer: OneToOne] = { t: Translator = NEW [TranslatorPrivate _ [inner, translator, translateForward]]; outer _ NEW [OneToOnePrivate _ [TranslatedEnumerate, TranslatedAssociate, TranlatedMap, t]]; }; Translator: TYPE = REF TranslatorPrivate; TranslatorPrivate: TYPE = RECORD [ inner, translate: OneToOne, translateForward: BOOL ]; TranslatedEnumerate: PROC [oto: OneToOne, Consume: PROC [a, b: REF ANY]] = { t: Translator = NARROW[oto.data]; Translate: PROC [a, b: REF ANY] = { Consume[t.translate.Map[a, t.translateForward], t.translate.Map[b, t.translateForward]]; }; t.inner.Enumerate[Translate]; }; TranslatedAssociate: PROC [oto: OneToOne, a, b: REF ANY] = { t: Translator = NARROW[oto.data]; t.inner.Associate[t.translate.Map[a, NOT t.translateForward], t.translate.Map[b, NOT t.translateForward]]; }; TranlatedMap: PROC [oto: OneToOne, from: REF ANY, forward: BOOL _ TRUE] RETURNS [to: REF ANY] = { t: Translator = NARROW[oto.data]; to _ t.translate.Map[t.inner.Map[t.translate.Map[from, NOT t.translateForward], forward], t.translateForward]; }; }.