Tighten and simplify

This commit is contained in:
Tony Garnock-Jones 2021-02-22 22:06:02 +01:00
parent 5d49794d88
commit 6a5cac5328
1 changed files with 34 additions and 50 deletions

84
main.ts
View File

@ -15,71 +15,55 @@ import { Bag, ChangeDescription } from './bag';
const Observe = Record.makeConstructor<Ref<Entity>>('Observe', ['label', 'observer']); const Observe = Record.makeConstructor<Ref<Entity>>('Observe', ['label', 'observer']);
function makeDataspace(): Entity { function makeDataspace(): Entity {
const handleMap: IdentityMap<Handle, Assertion> = new IdentityMap(); const handleMap: IdentityMap<Handle, Record<Ref<Entity>>> = new IdentityMap();
const assertions = new Bag<Ref<Entity>>(); const assertions = new Bag<Ref<Entity>>();
const subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary(); const subscriptions: Dictionary<Map<Ref<Entity>, Dictionary<Handle>>> = new Dictionary();
function forEachSubscription(assertion: Assertion, f: (handleMap: Dictionary<Handle>, peer: Ref<Entity>) => void): void { function forEachSubscription(assertion: Record<Ref<Entity>>, f: (seen: Dictionary<Handle>, peer: Ref<Entity>) => void): void {
if (!Record.isRecord(assertion)) return;
subscriptions.get(assertion.label)?.forEach(f); subscriptions.get(assertion.label)?.forEach(f);
} }
return { return {
[assert](turn: Turn, assertion: Assertion, handle: Handle): void { [assert](turn: Turn, rec: Assertion, handle: Handle): void {
// console.log(`DS: assert ${assertion.asPreservesText()} :: ${handle}`); if (!Record.isRecord<Ref<Entity>>(rec)) return;
handleMap.set(handle, assertion); handleMap.set(handle, rec);
if (assertions.change(assertion, +1) === ChangeDescription.ABSENT_TO_PRESENT) { if (assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
if (Observe.isClassOf(assertion)) { if (Observe.isClassOf(rec)) {
const observedLabel = Observe._.label(assertion)!; const label = Observe._.label(rec)!;
const observer = Observe._.observer(assertion) as Ref<Entity>; const observer = Observe._.observer(rec) as Ref<Entity>;
let peerMap = subscriptions.get(observedLabel); const seen = new Dictionary<Handle>();
if (peerMap === void 0) { if (!subscriptions.has(label)) subscriptions.set(label, new Map());
peerMap = new Map(); subscriptions.get(label)!.set(observer, seen);
subscriptions.set(observedLabel, peerMap); assertions.forEach((_count, prev) =>
} is((prev as Record<Ref<Entity>>).label, label)
const handleMap: Dictionary<Handle> = new Dictionary(); && seen.set(prev, turn.assert(observer, prev)));
peerMap.set(observer, handleMap);
assertions.forEach((_count, assertion) => {
if (Record.isRecord(assertion)) {
if (is(assertion.label, observedLabel)) {
handleMap.set(assertion, turn.assert(observer, assertion));
}
}
});
}
forEachSubscription(assertion, (handleMap, peer) => {
if (!handleMap.has(assertion)) {
handleMap.set(assertion, turn.assert(peer, assertion));
}
});
} }
forEachSubscription(rec, (seen, peer) =>
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
}, },
[retract](turn: Turn, upstreamHandle: Handle): void { [retract](turn: Turn, upstreamHandle: Handle): void {
const assertion = handleMap.get(upstreamHandle); const rec = handleMap.get(upstreamHandle);
// console.log(`DS: retract ${(assertion ?? Symbol.for('missing')).asPreservesText()} :: ${upstreamHandle}`); if (rec === void 0) return;
if (assertion !== void 0) { handleMap.delete(upstreamHandle);
handleMap.delete(upstreamHandle); if (assertions.change(rec, -1) !== ChangeDescription.PRESENT_TO_ABSENT) return;
if (assertions.change(assertion, -1) === ChangeDescription.PRESENT_TO_ABSENT) { forEachSubscription(rec, (seen, _peer) => {
forEachSubscription(assertion, (handleMap, _peer) => { const downstreamHandle = seen.get(rec);
const downstreamHandle = handleMap.get(assertion); if (downstreamHandle !== void 0) {
if (downstreamHandle !== void 0) { turn.retract(downstreamHandle);
turn.retract(downstreamHandle); seen.delete(rec);
handleMap.delete(assertion);
}
});
if (Observe.isClassOf(assertion)) {
let peerMap = subscriptions.get(Observe._.label(assertion)!)!;
peerMap.delete(Observe._.observer(assertion)! as Ref<Entity>);
if (peerMap.size === 0) subscriptions.delete(Observe._.label(assertion)!);
}
} }
});
if (Observe.isClassOf(rec)) {
let peerMap = subscriptions.get(Observe._.label(rec)!)!;
peerMap.delete(Observe._.observer(rec) as Ref<Entity>);
if (peerMap.size === 0) subscriptions.delete(Observe._.label(rec)!);
} }
}, },
[message](turn: Turn, message: Assertion): void { [message](turn: Turn, rec: Assertion): void {
// console.log(`DS: message ${message.asPreservesText()}`); if (!Record.isRecord<Ref<Entity>>(rec)) return;
forEachSubscription(message, (_handleMap, peer) => turn.message(peer, message)); forEachSubscription(rec, (_seen, peer) => turn.message(peer, rec));
} }
}; };
} }