OneToOneImpl.Mesa
Last tweaked by Mike Spreitzer on April 2, 1987 3:11:03 pm PST
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: BOOLFALSE] --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: BOOLTRUE] 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: BOOLTRUE] 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: BOOLTRUE] 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: BOOLTRUE] 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];
};
}.