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