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];
};
}.