Better record typing
This commit is contained in:
parent
080c5bd278
commit
c7f5f487e7
53
actor.ts
53
actor.ts
|
@ -33,65 +33,66 @@ export type Rewrite = { pattern: Pattern, template: Template };
|
|||
export const _CRec = Symbol.for('rec');
|
||||
export const CRec = Record.makeConstructor<{label: Assertion, arity: number}, Ref>()(
|
||||
_CRec, ['label', 'arity']);
|
||||
export type CRec = ReturnType<typeof CRec>;
|
||||
|
||||
export const _CArr = Symbol.for('arr');
|
||||
export const CArr = Record.makeConstructor<{arity: number}, Ref>()(
|
||||
_CArr, ['arity']);
|
||||
export type CArr = ReturnType<typeof CArr>;
|
||||
|
||||
export const _CDict = Symbol.for('dict');
|
||||
export const CDict = Record.makeConstructor<{}, Ref>()(
|
||||
_CDict, []);
|
||||
export type CDict = ReturnType<typeof CDict>;
|
||||
|
||||
export type ConstructorSpec = CRec | CArr | CDict;
|
||||
export type ConstructorSpec =
|
||||
| Record<typeof _CRec, [string, number], Ref>
|
||||
| Record<typeof _CArr, [number], Ref>
|
||||
| Record<typeof _CDict, [], Ref>;
|
||||
|
||||
export const _PDiscard = Symbol.for('_');
|
||||
export const PDiscard = Record.makeConstructor<{}, Ref>()(
|
||||
_PDiscard, []);
|
||||
export type PDiscard = ReturnType<typeof PDiscard>;
|
||||
|
||||
export const _PBind = Symbol.for('bind');
|
||||
export const PBind = Record.makeConstructor<{name: string, pattern: Assertion}, Ref>()(
|
||||
export const PBind = Record.makeConstructor<{name: string, pattern: Pattern}, Ref>()(
|
||||
_PBind, ['name', 'pattern']);
|
||||
export type PBind = ReturnType<typeof PBind>;
|
||||
|
||||
export const _PAnd = Symbol.for('and');
|
||||
export const PAnd = Record.makeConstructor<{patterns: Array<Assertion>}, Ref>()(
|
||||
export const PAnd = Record.makeConstructor<{patterns: Array<Pattern>}, Ref>()(
|
||||
_PAnd, ['patterns']);
|
||||
export type PAnd = ReturnType<typeof PAnd>;
|
||||
|
||||
export const _PNot = Symbol.for('not');
|
||||
export const PNot = Record.makeConstructor<{pattern: Assertion}, Ref>()(
|
||||
export const PNot = Record.makeConstructor<{pattern: Pattern}, Ref>()(
|
||||
_PNot, ['pattern']);
|
||||
export type PNot = ReturnType<typeof PNot>;
|
||||
|
||||
export const _Lit = Symbol.for('lit');
|
||||
export const Lit = Record.makeConstructor<{value: Assertion}, Ref>()(
|
||||
_Lit, ['value']);
|
||||
export type Lit = ReturnType<typeof Lit>;
|
||||
|
||||
export const _PCompound = Symbol.for('compound');
|
||||
export const PCompound =
|
||||
Record.makeConstructor<{ctor: ConstructorSpec, members: Dictionary<Assertion>}, Ref>()(
|
||||
Record.makeConstructor<{ctor: ConstructorSpec, members: Dictionary<Pattern>}, Ref>()(
|
||||
_PCompound, ['ctor', 'members']);
|
||||
export type PCompound = ReturnType<typeof PCompound>;
|
||||
|
||||
export type Pattern = PDiscard | PBind | PAnd | PNot | Lit | PCompound;
|
||||
export type Pattern =
|
||||
| Record<typeof _PDiscard, [], Ref>
|
||||
| Record<typeof _PBind, [string, Pattern], Ref>
|
||||
| Record<typeof _PAnd, [Pattern[]], Ref>
|
||||
| Record<typeof _PNot, [Pattern], Ref>
|
||||
| Record<typeof _Lit, [Assertion], Ref>
|
||||
| Record<typeof _PCompound, [ConstructorSpec, Dictionary<Pattern>], Ref>;
|
||||
|
||||
export const _TRef = Symbol.for('ref');
|
||||
export const TRef = Record.makeConstructor<{name: string}, Ref>()(
|
||||
_TRef, ['name']);
|
||||
export type TRef = ReturnType<typeof TRef>;
|
||||
|
||||
export const _TCompound = Symbol.for('compound');
|
||||
export const TCompound =
|
||||
Record.makeConstructor<{ctor: ConstructorSpec, members: Dictionary<Assertion>}, Ref>()(
|
||||
Record.makeConstructor<{ctor: ConstructorSpec, members: Dictionary<Template>}, Ref>()(
|
||||
_TCompound, ['ctor', 'members']);
|
||||
export type TCompound = ReturnType<typeof TCompound>;
|
||||
|
||||
export type Template = TRef | Lit | TCompound;
|
||||
export type Template =
|
||||
| Record<typeof _TRef, [string], Ref>
|
||||
| Record<typeof _Lit, [Assertion], Ref>
|
||||
| Record<typeof _TCompound, [ConstructorSpec, Dictionary<Template>], Ref>;
|
||||
|
||||
export type Bindings = { [name: string]: Assertion };
|
||||
|
||||
|
@ -224,20 +225,20 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
|
|||
case _PDiscard:
|
||||
return true;
|
||||
case _PBind:
|
||||
if (walk(PBind._.pattern(p) as Pattern, v)) {
|
||||
if (walk(PBind._.pattern(p), v)) {
|
||||
bindings[PBind._.name(p)] = v;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case _PAnd:
|
||||
for (const pp of PAnd._.patterns(p) as Pattern[]) {
|
||||
for (const pp of PAnd._.patterns(p)) {
|
||||
if (!walk(pp, v)) return false;
|
||||
}
|
||||
return true;
|
||||
case _PNot: {
|
||||
const savedBindings = bindings;
|
||||
bindings = {};
|
||||
const result = !walk(PNot._.pattern(p) as Pattern, v)
|
||||
const result = !walk(PNot._.pattern(p), v)
|
||||
bindings = savedBindings;
|
||||
return result;
|
||||
}
|
||||
|
@ -245,10 +246,10 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
|
|||
return is(Lit._.value(p), v);
|
||||
case _PCompound: {
|
||||
const ctor = PCompound._.ctor(p);
|
||||
const members = PCompound._.members(p) as Dictionary<Pattern, Ref>;
|
||||
const members = PCompound._.members(p);
|
||||
switch (ctor.label) {
|
||||
case _CRec:
|
||||
if (!Record.isRecord<Assertion, Ref>(v)) return false;
|
||||
if (!Record.isRecord<Assertion, any, Ref>(v)) return false;
|
||||
if (!is(CRec._.label(ctor), v.label)) return false;
|
||||
if (CRec._.arity(ctor) !== v.length) return false;
|
||||
for (const [key, pp] of members) {
|
||||
|
@ -293,10 +294,10 @@ export function instantiate(t: Template, b: Bindings): Assertion {
|
|||
return Lit._.value(t);
|
||||
case _TCompound: {
|
||||
const ctor = TCompound._.ctor(t);
|
||||
const members = TCompound._.members(t) as Dictionary<Template, Ref>;
|
||||
const members = TCompound._.members(t);
|
||||
switch (ctor.label) {
|
||||
case _CRec: {
|
||||
const v = Record<Assertion, Ref>(CRec._.label(ctor), []);
|
||||
const v = Record<Assertion, any, Ref>(CRec._.label(ctor), []);
|
||||
v.length = CRec._.arity(ctor);
|
||||
for (const [key, tt] of members) {
|
||||
v[key as number] = walk(tt);
|
||||
|
|
|
@ -31,12 +31,12 @@ export const Observe = Record.makeConstructor<{label: Assertion, observer: Ref},
|
|||
Symbol.for('Observe'), ['label', 'observer']);
|
||||
|
||||
export class Dataspace implements Partial<Entity> {
|
||||
readonly handleMap: IdentityMap<Handle, Record<Assertion, Ref>> = new IdentityMap();
|
||||
readonly handleMap: IdentityMap<Handle, Record<Assertion, any, Ref>> = new IdentityMap();
|
||||
readonly assertions = new Bag<Ref>();
|
||||
readonly subscriptions: Dictionary<Map<Ref, Dictionary<Handle>>> = new Dictionary();
|
||||
|
||||
assert(turn: Turn, rec: Assertion, handle: Handle): void {
|
||||
if (!Record.isRecord<Assertion, Ref>(rec)) return;
|
||||
if (!Record.isRecord<Assertion, any, Ref>(rec)) return;
|
||||
this.handleMap.set(handle, rec);
|
||||
if (this.assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
|
||||
if (Observe.isClassOf(rec)) {
|
||||
|
@ -46,7 +46,7 @@ export class Dataspace implements Partial<Entity> {
|
|||
if (!this.subscriptions.has(label)) this.subscriptions.set(label, new Map());
|
||||
this.subscriptions.get(label)!.set(observer, seen);
|
||||
this.assertions.forEach((_count, prev) =>
|
||||
is((prev as Record<Assertion, Ref>).label, label)
|
||||
is((prev as Record<Assertion, any, Ref>).label, label)
|
||||
&& seen.set(prev, turn.assert(observer, prev)));
|
||||
}
|
||||
this.subscriptions.get(rec.label)?.forEach((seen, peer) =>
|
||||
|
@ -73,7 +73,7 @@ export class Dataspace implements Partial<Entity> {
|
|||
}
|
||||
|
||||
message(turn: Turn, rec: Assertion): void {
|
||||
if (!Record.isRecord<Assertion, Ref>(rec)) return;
|
||||
if (!Record.isRecord<Assertion, any, Ref>(rec)) return;
|
||||
this.subscriptions.get(rec.label)?.forEach((_seen, peer) => turn.message(peer, rec));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue