Update to new schema compiler backend
This commit is contained in:
parent
346218f26a
commit
1bd65cd283
|
@ -1,9 +1,9 @@
|
|||
version 1 .
|
||||
pointer Actor.Ref .
|
||||
|
||||
BoxState = <BoxState int>.
|
||||
SetBox = <SetBox int>.
|
||||
BoxState = <BoxState @value int>.
|
||||
SetBox = <SetBox @value int>.
|
||||
|
||||
; BoxCap = BoxState / <Observe =SetBox ref>.
|
||||
; ClientCap = SetBox / <Observe =BoxState ref>.
|
||||
; BoxCap = BoxState / <Observe =SetBox @observer ref>.
|
||||
; ClientCap = SetBox / <Observe =BoxState @observer ref>.
|
||||
.
|
||||
|
|
|
@ -5,5 +5,5 @@ pointer Actor.Ref .
|
|||
Observe = <Observe @label symbol @observer ref>.
|
||||
|
||||
; ;As will be implemented soon
|
||||
; Observe = <Observe Pattern ref>.
|
||||
; Observe = <Observe @pattern Pattern @observer ref>.
|
||||
.
|
||||
|
|
|
@ -5,7 +5,8 @@ Assertion = any .
|
|||
Handle = int .
|
||||
Event = Assert / Retract / Message / Sync .
|
||||
Oid = int .
|
||||
Turn = [[Oid Event] ...].
|
||||
Turn = [TurnEvent ...].
|
||||
TurnEvent = [@oid Oid @event Event].
|
||||
|
||||
Assert = <assert @assertion Assertion @handle Handle>.
|
||||
Retract = <retract @handle Handle>.
|
||||
|
|
|
@ -3,7 +3,7 @@ pointer Actor.Ref .
|
|||
|
||||
; Each Attenuation is a stage. The sequence of Attenuations is run RIGHT-TO-LEFT.
|
||||
; That is, the newest Attenuations are at the right.
|
||||
SturdyRef = <ref @oid any @caveatChain [Attenuation ...] @sig bytes>.
|
||||
SturdyRef = <ref @oid any [@caveatChain Attenuation ...] @sig bytes>.
|
||||
|
||||
; An individual Attenuation is run RIGHT-TO-LEFT.
|
||||
; That is, the newest Caveats are at the right.
|
||||
|
@ -13,7 +13,7 @@ Attenuation = [Caveat ...].
|
|||
; can add 3rd-party caveats and richer predicates later
|
||||
Caveat = Rewrite / Alts .
|
||||
Rewrite = <rewrite @pattern Pattern @template Template>.
|
||||
Alts = <or @alternatives [Rewrite ...]>.
|
||||
Alts = <or [@alternatives Rewrite ...]>.
|
||||
|
||||
Resolve = <resolve @sturdyref SturdyRef @observer ref>.
|
||||
|
||||
|
@ -29,10 +29,13 @@ Lit = <lit @value any>.
|
|||
Pattern = PDiscard / PBind / PAnd / PNot / Lit / PCompound .
|
||||
PDiscard = <_>.
|
||||
PBind = <bind @name symbol @pattern Pattern>.
|
||||
PAnd = <and @patterns [Pattern ...]>.
|
||||
PAnd = <and [@patterns Pattern ...]>.
|
||||
PNot = <not @pattern Pattern>.
|
||||
PCompound = <compound @ctor ConstructorSpec @members { any: Pattern ...:... }>.
|
||||
PCompound = <compound @ctor ConstructorSpec @members PCompoundMembers>.
|
||||
PCompoundMembers = { any: Pattern ...:... }.
|
||||
|
||||
Template = TRef / Lit / TCompound .
|
||||
TRef = <ref @name symbol>.
|
||||
TCompound = <compound @ctor ConstructorSpec @members { any: Template ...:... }>.
|
||||
TCompound = <compound @ctor ConstructorSpec @members TCompoundMembers>.
|
||||
TCompoundMembers = { any: Template ...:... }.
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version 1 .
|
||||
|
||||
Instance = <Instance string any>.
|
||||
Instance = <Instance @name string @argument any>.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { DecodeError, IdentitySet, TypedDecoder, Value } from '@preserves/core';
|
||||
import { DecodeError, IdentitySet, Value } from '@preserves/core';
|
||||
import { Attenuation, runRewrites } from './rewrite.js';
|
||||
import { queueTask } from './task.js';
|
||||
|
||||
|
@ -32,8 +32,8 @@ export function isRef(v: any): v is Ref {
|
|||
return 'relay' in v && v.relay instanceof Actor && 'target' in v;
|
||||
}
|
||||
|
||||
export function decodeRef(_d: TypedDecoder<Ref>): Ref | undefined {
|
||||
throw new DecodeError("Cannot decode Ref");
|
||||
export function toRef(_v: any): Ref | undefined {
|
||||
return isRef(_v) ? _v : void 0;
|
||||
}
|
||||
|
||||
let nextActorId = 0;
|
||||
|
|
|
@ -10,7 +10,7 @@ export enum ChangeDescription {
|
|||
}
|
||||
|
||||
export class Bag<T extends object = DefaultPointer> {
|
||||
_items: Dictionary<number, T>;
|
||||
_items: Dictionary<T, number>;
|
||||
|
||||
constructor(s?: Set<T>) {
|
||||
this._items = new Dictionary();
|
||||
|
@ -65,7 +65,7 @@ export class Bag<T extends object = DefaultPointer> {
|
|||
this._items.forEach(f);
|
||||
}
|
||||
|
||||
snapshot(): Dictionary<number, T> {
|
||||
snapshot(): Dictionary<T, number> {
|
||||
return this._items.clone();
|
||||
}
|
||||
|
||||
|
|
10
src/box.ts
10
src/box.ts
|
@ -1,5 +1,5 @@
|
|||
import { BoxState, SetBox } from "./gen/box-protocol.js";
|
||||
import { Observe } from "./gen/dataspace.js";
|
||||
import { BoxState, $SetBox, fromBoxState } from "./gen/box-protocol.js";
|
||||
import { fromObserve, Observe } from "./gen/dataspace.js";
|
||||
import { Assertion, Handle, Ref, Turn } from "./actor.js";
|
||||
|
||||
let startTime = Date.now();
|
||||
|
@ -12,10 +12,10 @@ export default function (t: Turn, arg: Assertion) {
|
|||
console.log('Spawning Box', LIMIT, REPORT_EVERY);
|
||||
let valueHandle: Handle | undefined;
|
||||
function setValue(t: Turn, value: number) {
|
||||
valueHandle = t.replace(ds, valueHandle, BoxState(value));
|
||||
valueHandle = t.replace(ds, valueHandle, fromBoxState(BoxState(value)));
|
||||
}
|
||||
setValue(t, 0);
|
||||
t.assert(ds, Observe(SetBox.constructorInfo.label, t.ref({
|
||||
t.assert(ds, fromObserve(Observe($SetBox, t.ref({
|
||||
message(t: Turn, [newValue]: [number]): void {
|
||||
// console.log(`Box ${t.actor.id}: got ${newValue}`);
|
||||
if (newValue % REPORT_EVERY === 0) {
|
||||
|
@ -29,5 +29,5 @@ export default function (t: Turn, arg: Assertion) {
|
|||
if (newValue === LIMIT) t.quit();
|
||||
setValue(t, newValue);
|
||||
}
|
||||
})));
|
||||
}))));
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { BoxState, SetBox } from "./gen/box-protocol.js";
|
||||
import { Observe } from "./gen/dataspace.js";
|
||||
import { $BoxState, fromSetBox, SetBox } from "./gen/box-protocol.js";
|
||||
import { fromObserve, Observe } from "./gen/dataspace.js";
|
||||
import { Assertion, Ref, Turn } from "./actor.js";
|
||||
|
||||
export default function (t: Turn, ds: Ref) {
|
||||
console.log('Spawning Client');
|
||||
let count = 0;
|
||||
t.assert(ds, Observe(BoxState.constructorInfo.label, t.ref({
|
||||
t.assert(ds, fromObserve(Observe($BoxState, t.ref({
|
||||
assert(t: Turn, [currentValue]: [number]): void {
|
||||
// console.log(`Client ${t.actor.id}: got ${currentValue}`);
|
||||
t.message(ds, SetBox(currentValue + 1));
|
||||
t.message(ds, fromSetBox(SetBox(currentValue + 1)));
|
||||
}
|
||||
})));
|
||||
t.assert(ds, Observe(BoxState.constructorInfo.label, t.ref({
|
||||
}))));
|
||||
t.assert(ds, fromObserve(Observe($BoxState, t.ref({
|
||||
assert(_t: Turn, _assertion: Assertion): void {
|
||||
count++;
|
||||
// console.log('inc to', count, _assertion);
|
||||
|
@ -23,5 +23,5 @@ export default function (t: Turn, ds: Ref) {
|
|||
}
|
||||
// console.log('dec to', count);
|
||||
},
|
||||
})));
|
||||
}))));
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Assertion, Entity, Handle, Ref, Turn } from 'actor';
|
|||
import { Dictionary, IdentityMap, is, Record, Tuple } from '@preserves/core';
|
||||
import { Bag, ChangeDescription } from './bag';
|
||||
|
||||
import { Observe } from './gen/dataspace';
|
||||
import { toObserve } from './gen/dataspace';
|
||||
export * from './gen/dataspace';
|
||||
|
||||
// Q. Why keep "Observe"? Why not do the clever trick of asserting the
|
||||
|
@ -38,22 +38,23 @@ export * from './gen/dataspace';
|
|||
export class Dataspace implements Partial<Entity> {
|
||||
readonly handleMap: IdentityMap<Handle, Record<Assertion, any, Ref>> = new IdentityMap();
|
||||
readonly assertions = new Bag<Ref>();
|
||||
readonly subscriptions = new Dictionary<Map<Ref, Dictionary<Handle, Ref>>, Ref>();
|
||||
readonly subscriptions = new Dictionary<Ref, Map<Ref, Dictionary<Ref, Handle>>>();
|
||||
|
||||
assert(turn: Turn, rec: Assertion, handle: Handle): void {
|
||||
// console.log(preserves`ds ${turn.actor.id} assert ${rec} ${handle}`);
|
||||
if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(rec)) return;
|
||||
this.handleMap.set(handle, rec);
|
||||
if (this.assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
|
||||
if (Observe.isClassOf(rec)) {
|
||||
const label = Observe._.label(rec)!;
|
||||
const observer = Observe._.observer(rec);
|
||||
const seen = new Dictionary<Handle, Ref>();
|
||||
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, any, Ref>).label, label)
|
||||
&& seen.set(prev, turn.assert(observer, prev)));
|
||||
{
|
||||
const o = toObserve(rec);
|
||||
if (o !== void 0) {
|
||||
const seen = new Dictionary<Ref, Handle>();
|
||||
if (!this.subscriptions.has(o.label)) this.subscriptions.set(o.label, new Map());
|
||||
this.subscriptions.get(o.label)!.set(o.observer, seen);
|
||||
this.assertions.forEach((_count, prev) =>
|
||||
is((prev as Record<Assertion, any, Ref>).label, o.label)
|
||||
&& seen.set(prev, turn.assert(o.observer, prev)));
|
||||
}
|
||||
}
|
||||
this.subscriptions.get(rec.label)?.forEach((seen, peer) =>
|
||||
seen.has(rec) || seen.set(rec, turn.assert(peer, rec)));
|
||||
|
@ -69,10 +70,13 @@ export class Dataspace implements Partial<Entity> {
|
|||
turn.retract(seen.get(rec));
|
||||
seen.delete(rec);
|
||||
});
|
||||
if (Observe.isClassOf(rec)) {
|
||||
let peerMap = this.subscriptions.get(Observe._.label(rec)!)!;
|
||||
peerMap.delete(Observe._.observer(rec) as Ref);
|
||||
if (peerMap.size === 0) this.subscriptions.delete(Observe._.label(rec)!);
|
||||
{
|
||||
const o = toObserve(rec);
|
||||
if (o !== void 0) {
|
||||
let peerMap = this.subscriptions.get(o.label)!;
|
||||
peerMap.delete(o.observer);
|
||||
if (peerMap.size === 0) this.subscriptions.delete(o.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,72 +4,62 @@ import * as _i_Actor from "../actor";
|
|||
export const $BoxState = Symbol.for("BoxState");
|
||||
export const $SetBox = Symbol.for("SetBox");
|
||||
|
||||
export const BoxState = _.Record.makeConstructor<{"_field0": number}, _ptr>()($BoxState, ["_field0"]);
|
||||
|
||||
export type BoxState = _.Record<(typeof $BoxState), [number], _ptr>;
|
||||
|
||||
export const SetBox = _.Record.makeConstructor<{"_field0": number}, _ptr>()($SetBox, ["_field0"]);
|
||||
|
||||
export type SetBox = _.Record<(typeof $SetBox), [number], _ptr>;
|
||||
|
||||
export type _ptr = _i_Actor.Ref;
|
||||
|
||||
export type _val = _.Value<_ptr>;
|
||||
|
||||
export type BoxState = {"value": number};
|
||||
|
||||
export function isBoxState(v: any): v is BoxState {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $BoxState) &&
|
||||
((v.length === 1) && typeof v[0] === 'number')
|
||||
);
|
||||
export type SetBox = {"value": number};
|
||||
|
||||
|
||||
export const _toPtr = (v: _val) => {let result: undefined | _ptr; result = _i_Actor.toRef(v); return result;};
|
||||
|
||||
export function BoxState(value: number): BoxState {return {value};}
|
||||
|
||||
export function SetBox(value: number): SetBox {return {value};}
|
||||
|
||||
export function asBoxState(v: _val): BoxState {
|
||||
let result = toBoxState(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid BoxState: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asBoxState(v: any): BoxState {
|
||||
if (!isBoxState(v)) {throw new TypeError(`Invalid BoxState: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeBoxState(d: _.TypedDecoder<_ptr>): BoxState | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp0: any;
|
||||
_tmp0 = _.asLiteral(d.nextSymbol(), $BoxState);
|
||||
export function toBoxState(v: _val): undefined | BoxState {
|
||||
let result: undefined | BoxState;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $BoxState) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1, _tmp2: any;
|
||||
_tmp2 = d.nextSignedInteger();
|
||||
if (_tmp2 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2];};
|
||||
if (_tmp1 !== void 0) result = _.Record<(typeof $BoxState), [number]>(_tmp0 as any, _tmp1 as any);
|
||||
let _tmp1: (number) | undefined;
|
||||
_tmp1 = typeof v[0] === 'number' ? v[0] : void 0;
|
||||
if (_tmp1 !== void 0) {result = {"value": _tmp1};};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isSetBox(v: any): v is SetBox {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $SetBox) &&
|
||||
((v.length === 1) && typeof v[0] === 'number')
|
||||
);
|
||||
export function fromBoxState(_v: BoxState): _val {return _.Record($BoxState, [_v["value"]]);}
|
||||
|
||||
export function asSetBox(v: _val): SetBox {
|
||||
let result = toSetBox(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid SetBox: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asSetBox(v: any): SetBox {
|
||||
if (!isSetBox(v)) {throw new TypeError(`Invalid SetBox: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeSetBox(d: _.TypedDecoder<_ptr>): SetBox | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp3: any;
|
||||
_tmp3 = _.asLiteral(d.nextSymbol(), $SetBox);
|
||||
if (_tmp3 !== void 0) {
|
||||
let _tmp4, _tmp5: any;
|
||||
_tmp5 = d.nextSignedInteger();
|
||||
if (_tmp5 !== void 0) {if (d.closeCompound()) _tmp4 = [_tmp5];};
|
||||
if (_tmp4 !== void 0) result = _.Record<(typeof $SetBox), [number]>(_tmp3 as any, _tmp4 as any);
|
||||
export function toSetBox(v: _val): undefined | SetBox {
|
||||
let result: undefined | SetBox;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $SetBox) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1: (number) | undefined;
|
||||
_tmp1 = typeof v[0] === 'number' ? v[0] : void 0;
|
||||
if (_tmp1 !== void 0) {result = {"value": _tmp1};};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export const _decodePtr = (d: _.TypedDecoder<_ptr>) => {let result; result = _i_Actor.decodeRef(d); return result;};
|
||||
export function fromSetBox(_v: SetBox): _val {return _.Record($SetBox, [_v["value"]]);}
|
||||
|
||||
|
|
|
@ -3,44 +3,40 @@ import * as _i_Actor from "../actor";
|
|||
|
||||
export const $Observe = Symbol.for("Observe");
|
||||
|
||||
export const Observe = _.Record.makeConstructor<{"label": symbol, "observer": _ptr}, _ptr>()($Observe, ["label","observer"]);
|
||||
|
||||
export type Observe = _.Record<(typeof $Observe), [symbol, _ptr], _ptr>;
|
||||
|
||||
export type _ptr = _i_Actor.Ref;
|
||||
|
||||
export type _val = _.Value<_ptr>;
|
||||
|
||||
export type Observe = {"label": symbol, "observer": _ptr};
|
||||
|
||||
export function isObserve(v: any): v is Observe {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $Observe) &&
|
||||
((v.length === 2) && typeof v[0] === 'symbol' && _.isPointer(v[1]))
|
||||
);
|
||||
|
||||
export const _toPtr = (v: _val) => {let result: undefined | _ptr; result = _i_Actor.toRef(v); return result;};
|
||||
|
||||
export function Observe(label: symbol, observer: _ptr): Observe {return {label, observer};}
|
||||
|
||||
export function asObserve(v: _val): Observe {
|
||||
let result = toObserve(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Observe: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asObserve(v: any): Observe {
|
||||
if (!isObserve(v)) {throw new TypeError(`Invalid Observe: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeObserve(d: _.TypedDecoder<_ptr>): Observe | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp0: any;
|
||||
_tmp0 = _.asLiteral(d.nextSymbol(), $Observe);
|
||||
export function toObserve(v: _val): undefined | Observe {
|
||||
let result: undefined | Observe;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $Observe) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1, _tmp2, _tmp3: any;
|
||||
_tmp2 = d.nextSymbol();
|
||||
if (_tmp2 !== void 0) {
|
||||
_tmp3 = _decodePtr(d);
|
||||
if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2, _tmp3];};
|
||||
let _tmp1: (symbol) | undefined;
|
||||
_tmp1 = typeof v[0] === 'symbol' ? v[0] : void 0;
|
||||
if (_tmp1 !== void 0) {
|
||||
let _tmp2: (_ptr) | undefined;
|
||||
_tmp2 = _toPtr(v[1]);
|
||||
if (_tmp2 !== void 0) {result = {"label": _tmp1, "observer": _tmp2};};
|
||||
};
|
||||
if (_tmp1 !== void 0) result = _.Record<(typeof $Observe), [symbol, _ptr]>(_tmp0 as any, _tmp1 as any);
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export const _decodePtr = (d: _.TypedDecoder<_ptr>) => {let result; result = _i_Actor.decodeRef(d); return result;};
|
||||
export function fromObserve(_v: Observe): _val {return _.Record($Observe, [_v["label"], _v["observer"]]);}
|
||||
|
||||
|
|
|
@ -6,280 +6,291 @@ export const $message = Symbol.for("message");
|
|||
export const $retract = Symbol.for("retract");
|
||||
export const $sync = Symbol.for("sync");
|
||||
|
||||
export type Assertion = _val;
|
||||
|
||||
export type Handle = number;
|
||||
|
||||
export type Event = (Assert | Retract | Message | Sync);
|
||||
|
||||
export type Oid = number;
|
||||
|
||||
export type Turn = Array<[Oid, Event]>;
|
||||
|
||||
export const Assert = _.Record.makeConstructor<{"assertion": Assertion, "handle": Handle}, _ptr>()($assert, ["assertion","handle"]);
|
||||
|
||||
export type Assert = _.Record<(typeof $assert), [Assertion, Handle], _ptr>;
|
||||
|
||||
export const Retract = _.Record.makeConstructor<{"handle": Handle}, _ptr>()($retract, ["handle"]);
|
||||
|
||||
export type Retract = _.Record<(typeof $retract), [Handle], _ptr>;
|
||||
|
||||
export const Message = _.Record.makeConstructor<{"body": Assertion}, _ptr>()($message, ["body"]);
|
||||
|
||||
export type Message = _.Record<(typeof $message), [Assertion], _ptr>;
|
||||
|
||||
export const Sync = _.Record.makeConstructor<{"peer": _ptr}, _ptr>()($sync, ["peer"]);
|
||||
|
||||
export type Sync = _.Record<(typeof $sync), [_ptr], _ptr>;
|
||||
|
||||
export type _ptr = _i_Protocol.WireRef;
|
||||
|
||||
export type _val = _.Value<_ptr>;
|
||||
|
||||
export type Assertion = _val;
|
||||
|
||||
export function isAssertion(v: any): v is Assertion {return true;}
|
||||
export type Handle = number;
|
||||
|
||||
export function asAssertion(v: any): Assertion {
|
||||
if (!isAssertion(v)) {throw new TypeError(`Invalid Assertion: ${_.stringify(v)}`);} else {return v;};
|
||||
export type Event = (
|
||||
{"_variant": "Assert", "value": Assert} |
|
||||
{"_variant": "Retract", "value": Retract} |
|
||||
{"_variant": "Message", "value": Message} |
|
||||
{"_variant": "Sync", "value": Sync}
|
||||
);
|
||||
|
||||
export type Oid = number;
|
||||
|
||||
export type Turn = Array<TurnEvent>;
|
||||
|
||||
export type TurnEvent = {"oid": Oid, "event": Event};
|
||||
|
||||
export type Assert = {"assertion": Assertion, "handle": Handle};
|
||||
|
||||
export type Retract = {"handle": Handle};
|
||||
|
||||
export type Message = {"body": Assertion};
|
||||
|
||||
export type Sync = {"peer": _ptr};
|
||||
|
||||
|
||||
export const _toPtr = (v: _val) => {
|
||||
let result: undefined | _ptr;
|
||||
result = _i_Protocol.toWireRef(v);
|
||||
return result;
|
||||
};
|
||||
|
||||
export function Assertion(value: _val): Assertion {return value;}
|
||||
|
||||
export function Handle(value: number): Handle {return value;}
|
||||
|
||||
export namespace Event {
|
||||
export function Assert(value: Assert): Event {return {"_variant": "Assert", value};};
|
||||
export function Retract(value: Retract): Event {return {"_variant": "Retract", value};};
|
||||
export function Message(value: Message): Event {return {"_variant": "Message", value};};
|
||||
export function Sync(value: Sync): Event {return {"_variant": "Sync", value};};
|
||||
}
|
||||
|
||||
export function decodeAssertion(d: _.TypedDecoder<_ptr>): Assertion | undefined {let result; result = d.next(); return result;}
|
||||
export function Oid(value: number): Oid {return value;}
|
||||
|
||||
export function isHandle(v: any): v is Handle {return typeof v === 'number';}
|
||||
export function Turn(value: Array<TurnEvent>): Turn {return value;}
|
||||
|
||||
export function asHandle(v: any): Handle {
|
||||
if (!isHandle(v)) {throw new TypeError(`Invalid Handle: ${_.stringify(v)}`);} else {return v;};
|
||||
export function TurnEvent(oid: Oid, event: Event): TurnEvent {return {oid, event};}
|
||||
|
||||
export function Assert(assertion: Assertion, handle: Handle): Assert {return {assertion, handle};}
|
||||
|
||||
export function Retract(handle: Handle): Retract {return {handle};}
|
||||
|
||||
export function Message(body: Assertion): Message {return {body};}
|
||||
|
||||
export function Sync(peer: _ptr): Sync {return {peer};}
|
||||
|
||||
export function asAssertion(v: _val): Assertion {
|
||||
let result = toAssertion(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Assertion: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function decodeHandle(d: _.TypedDecoder<_ptr>): Handle | undefined {let result; result = d.nextSignedInteger(); return result;}
|
||||
|
||||
export function isEvent(v: any): v is Event {
|
||||
return _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && (
|
||||
(
|
||||
(
|
||||
_.is(v.label, $assert) && ((v.length === 2) && isAssertion(v[0]) && isHandle(v[1]))
|
||||
) ||
|
||||
(_.is(v.label, $retract) && ((v.length === 1) && isHandle(v[0]))) ||
|
||||
(_.is(v.label, $message) && ((v.length === 1) && isAssertion(v[0]))) ||
|
||||
(_.is(v.label, $sync) && ((v.length === 1) && _.isPointer(v[0])))
|
||||
)
|
||||
);
|
||||
export function toAssertion(v: _val): undefined | Assertion {
|
||||
let _tmp0: (_val) | undefined;
|
||||
let result: undefined | Assertion;
|
||||
_tmp0 = v;
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asEvent(v: any): Event {
|
||||
if (!isEvent(v)) {throw new TypeError(`Invalid Event: ${_.stringify(v)}`);} else {return v;};
|
||||
export function fromAssertion(_v: Assertion): _val {return _v;}
|
||||
|
||||
export function asHandle(v: _val): Handle {
|
||||
let result = toHandle(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Handle: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function decodeEvent(d: _.TypedDecoder<_ptr>): Event | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp0, _tmp1: any;
|
||||
_tmp0 = d.next();
|
||||
_tmp1 = d.mark();
|
||||
if (_.is(_tmp0, $assert)) {
|
||||
let _tmp2, _tmp3, _tmp4: any;
|
||||
_tmp3 = decodeAssertion(d);
|
||||
if (_tmp3 !== void 0) {
|
||||
_tmp4 = decodeHandle(d);
|
||||
if (_tmp4 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3, _tmp4];};
|
||||
};
|
||||
if (_tmp2 !== void 0) result = _.Record<(typeof $assert), [Assertion, Handle]>(_tmp0 as any, _tmp2 as any);
|
||||
};
|
||||
export function toHandle(v: _val): undefined | Handle {
|
||||
let _tmp0: (number) | undefined;
|
||||
let result: undefined | Handle;
|
||||
_tmp0 = typeof v === 'number' ? v : void 0;
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function fromHandle(_v: Handle): _val {return _v;}
|
||||
|
||||
export function asEvent(v: _val): Event {
|
||||
let result = toEvent(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Event: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toEvent(v: _val): undefined | Event {
|
||||
let _tmp0: (Assert) | undefined;
|
||||
let result: undefined | Event;
|
||||
_tmp0 = toAssert(v);
|
||||
if (_tmp0 !== void 0) {result = {"_variant": "Assert", "value": _tmp0};};
|
||||
if (result === void 0) {
|
||||
let _tmp1: (Retract) | undefined;
|
||||
_tmp1 = toRetract(v);
|
||||
if (_tmp1 !== void 0) {result = {"_variant": "Retract", "value": _tmp1};};
|
||||
if (result === void 0) {
|
||||
d.restoreMark(_tmp1);
|
||||
if (_.is(_tmp0, $retract)) {
|
||||
let _tmp5, _tmp6: any;
|
||||
_tmp6 = decodeHandle(d);
|
||||
if (_tmp6 !== void 0) {if (d.closeCompound()) _tmp5 = [_tmp6];};
|
||||
if (_tmp5 !== void 0) result = _.Record<(typeof $retract), [Handle]>(_tmp0 as any, _tmp5 as any);
|
||||
};
|
||||
let _tmp2: (Message) | undefined;
|
||||
_tmp2 = toMessage(v);
|
||||
if (_tmp2 !== void 0) {result = {"_variant": "Message", "value": _tmp2};};
|
||||
if (result === void 0) {
|
||||
d.restoreMark(_tmp1);
|
||||
if (_.is(_tmp0, $message)) {
|
||||
let _tmp7, _tmp8: any;
|
||||
_tmp8 = decodeAssertion(d);
|
||||
if (_tmp8 !== void 0) {if (d.closeCompound()) _tmp7 = [_tmp8];};
|
||||
if (_tmp7 !== void 0) result = _.Record<(typeof $message), [Assertion]>(_tmp0 as any, _tmp7 as any);
|
||||
};
|
||||
if (result === void 0) {
|
||||
d.restoreMark(_tmp1);
|
||||
if (_.is(_tmp0, $sync)) {
|
||||
let _tmp9, _tmp10: any;
|
||||
_tmp10 = _decodePtr(d);
|
||||
if (_tmp10 !== void 0) {if (d.closeCompound()) _tmp9 = [_tmp10];};
|
||||
if (_tmp9 !== void 0) result = _.Record<(typeof $sync), [_ptr]>(_tmp0 as any, _tmp9 as any);
|
||||
};
|
||||
};
|
||||
let _tmp3: (Sync) | undefined;
|
||||
_tmp3 = toSync(v);
|
||||
if (_tmp3 !== void 0) {result = {"_variant": "Sync", "value": _tmp3};};
|
||||
};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isOid(v: any): v is Oid {return typeof v === 'number';}
|
||||
|
||||
export function asOid(v: any): Oid {
|
||||
if (!isOid(v)) {throw new TypeError(`Invalid Oid: ${_.stringify(v)}`);} else {return v;};
|
||||
export function fromEvent(_v: Event): _val {
|
||||
switch (_v._variant) {
|
||||
case "Assert": {return fromAssert(_v.value);};
|
||||
case "Retract": {return fromRetract(_v.value);};
|
||||
case "Message": {return fromMessage(_v.value);};
|
||||
case "Sync": {return fromSync(_v.value);};
|
||||
};
|
||||
}
|
||||
|
||||
export function decodeOid(d: _.TypedDecoder<_ptr>): Oid | undefined {let result; result = d.nextSignedInteger(); return result;}
|
||||
|
||||
export function isTurn(v: any): v is Turn {
|
||||
return (
|
||||
_.Array.isArray(v) &&
|
||||
!_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
(v.length >= 0) &&
|
||||
v.every(v => (
|
||||
(
|
||||
_.Array.isArray(v) &&
|
||||
!_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
(v.length === 2) &&
|
||||
isOid(v[0]) &&
|
||||
isEvent(v[1])
|
||||
)
|
||||
))
|
||||
);
|
||||
export function asOid(v: _val): Oid {
|
||||
let result = toOid(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Oid: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asTurn(v: any): Turn {
|
||||
if (!isTurn(v)) {throw new TypeError(`Invalid Turn: ${_.stringify(v)}`);} else {return v;};
|
||||
export function toOid(v: _val): undefined | Oid {
|
||||
let _tmp0: (number) | undefined;
|
||||
let result: undefined | Oid;
|
||||
_tmp0 = typeof v === 'number' ? v : void 0;
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function decodeTurn(d: _.TypedDecoder<_ptr>): Turn | undefined {
|
||||
let result;
|
||||
if (d.openSequence()) {
|
||||
let _tmp11: any;
|
||||
{
|
||||
let vN: Array<[Oid, Event]> | undefined = [];
|
||||
while (!d.closeCompound()) {
|
||||
let _tmp12, _tmp13: any;
|
||||
_tmp11 = void 0;
|
||||
if (d.openSequence()) {
|
||||
_tmp12 = decodeOid(d);
|
||||
if (_tmp12 !== void 0) {
|
||||
_tmp13 = decodeEvent(d);
|
||||
if (_tmp13 !== void 0) {if (d.closeCompound()) _tmp11 = [_tmp12, _tmp13];};
|
||||
};
|
||||
};
|
||||
if (_tmp11 === void 0) {vN = void 0; break;};
|
||||
vN.push(_tmp11);
|
||||
export function fromOid(_v: Oid): _val {return _v;}
|
||||
|
||||
export function asTurn(v: _val): Turn {
|
||||
let result = toTurn(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Turn: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toTurn(v: _val): undefined | Turn {
|
||||
let result: undefined | Turn;
|
||||
if (_.Array.isArray(v)) {
|
||||
let _tmp0: (Array<TurnEvent>) | undefined;
|
||||
_tmp0 = [];
|
||||
for (const _tmp1 of v) {
|
||||
let _tmp2: (TurnEvent) | undefined;
|
||||
_tmp2 = toTurnEvent(_tmp1);
|
||||
if (_tmp2 !== void 0) {_tmp0.push(_tmp2); continue;};
|
||||
_tmp0 = void 0;
|
||||
break;
|
||||
};
|
||||
if (_tmp0 !== void 0) {result = _tmp0;};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function fromTurn(_v: Turn): _val {return _v.map(v => fromTurnEvent(v));}
|
||||
|
||||
export function asTurnEvent(v: _val): TurnEvent {
|
||||
let result = toTurnEvent(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid TurnEvent: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toTurnEvent(v: _val): undefined | TurnEvent {
|
||||
let result: undefined | TurnEvent;
|
||||
if (_.Array.isArray(v) && v.length === 2) {
|
||||
let _tmp0: (Oid) | undefined;
|
||||
_tmp0 = toOid(v[0]);
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1: (Event) | undefined;
|
||||
_tmp1 = toEvent(v[1]);
|
||||
if (_tmp1 !== void 0) {result = {"oid": _tmp0, "event": _tmp1};};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function fromTurnEvent(_v: TurnEvent): _val {return [fromOid(_v["oid"]), fromEvent(_v["event"])];}
|
||||
|
||||
export function asAssert(v: _val): Assert {
|
||||
let result = toAssert(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Assert: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function toAssert(v: _val): undefined | Assert {
|
||||
let result: undefined | Assert;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $assert) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1: (Assertion) | undefined;
|
||||
_tmp1 = toAssertion(v[0]);
|
||||
if (_tmp1 !== void 0) {
|
||||
let _tmp2: (Handle) | undefined;
|
||||
_tmp2 = toHandle(v[1]);
|
||||
if (_tmp2 !== void 0) {result = {"assertion": _tmp1, "handle": _tmp2};};
|
||||
};
|
||||
result = vN;
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isAssert(v: any): v is Assert {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $assert) &&
|
||||
((v.length === 2) && isAssertion(v[0]) && isHandle(v[1]))
|
||||
);
|
||||
export function fromAssert(_v: Assert): _val {
|
||||
return _.Record($assert, [fromAssertion(_v["assertion"]), fromHandle(_v["handle"])]);
|
||||
}
|
||||
|
||||
export function asAssert(v: any): Assert {
|
||||
if (!isAssert(v)) {throw new TypeError(`Invalid Assert: ${_.stringify(v)}`);} else {return v;};
|
||||
export function asRetract(v: _val): Retract {
|
||||
let result = toRetract(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Retract: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function decodeAssert(d: _.TypedDecoder<_ptr>): Assert | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp14: any;
|
||||
_tmp14 = _.asLiteral(d.nextSymbol(), $assert);
|
||||
if (_tmp14 !== void 0) {
|
||||
let _tmp15, _tmp16, _tmp17: any;
|
||||
_tmp16 = decodeAssertion(d);
|
||||
if (_tmp16 !== void 0) {
|
||||
_tmp17 = decodeHandle(d);
|
||||
if (_tmp17 !== void 0) {if (d.closeCompound()) _tmp15 = [_tmp16, _tmp17];};
|
||||
};
|
||||
if (_tmp15 !== void 0) result = _.Record<(typeof $assert), [Assertion, Handle]>(_tmp14 as any, _tmp15 as any);
|
||||
export function toRetract(v: _val): undefined | Retract {
|
||||
let result: undefined | Retract;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $retract) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1: (Handle) | undefined;
|
||||
_tmp1 = toHandle(v[0]);
|
||||
if (_tmp1 !== void 0) {result = {"handle": _tmp1};};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isRetract(v: any): v is Retract {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $retract) &&
|
||||
((v.length === 1) && isHandle(v[0]))
|
||||
);
|
||||
export function fromRetract(_v: Retract): _val {return _.Record($retract, [fromHandle(_v["handle"])]);}
|
||||
|
||||
export function asMessage(v: _val): Message {
|
||||
let result = toMessage(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Message: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asRetract(v: any): Retract {
|
||||
if (!isRetract(v)) {throw new TypeError(`Invalid Retract: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeRetract(d: _.TypedDecoder<_ptr>): Retract | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp18: any;
|
||||
_tmp18 = _.asLiteral(d.nextSymbol(), $retract);
|
||||
if (_tmp18 !== void 0) {
|
||||
let _tmp19, _tmp20: any;
|
||||
_tmp20 = decodeHandle(d);
|
||||
if (_tmp20 !== void 0) {if (d.closeCompound()) _tmp19 = [_tmp20];};
|
||||
if (_tmp19 !== void 0) result = _.Record<(typeof $retract), [Handle]>(_tmp18 as any, _tmp19 as any);
|
||||
export function toMessage(v: _val): undefined | Message {
|
||||
let result: undefined | Message;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $message) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1: (Assertion) | undefined;
|
||||
_tmp1 = toAssertion(v[0]);
|
||||
if (_tmp1 !== void 0) {result = {"body": _tmp1};};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isMessage(v: any): v is Message {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $message) &&
|
||||
((v.length === 1) && isAssertion(v[0]))
|
||||
);
|
||||
export function fromMessage(_v: Message): _val {return _.Record($message, [fromAssertion(_v["body"])]);}
|
||||
|
||||
export function asSync(v: _val): Sync {
|
||||
let result = toSync(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Sync: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asMessage(v: any): Message {
|
||||
if (!isMessage(v)) {throw new TypeError(`Invalid Message: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeMessage(d: _.TypedDecoder<_ptr>): Message | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp21: any;
|
||||
_tmp21 = _.asLiteral(d.nextSymbol(), $message);
|
||||
if (_tmp21 !== void 0) {
|
||||
let _tmp22, _tmp23: any;
|
||||
_tmp23 = decodeAssertion(d);
|
||||
if (_tmp23 !== void 0) {if (d.closeCompound()) _tmp22 = [_tmp23];};
|
||||
if (_tmp22 !== void 0) result = _.Record<(typeof $message), [Assertion]>(_tmp21 as any, _tmp22 as any);
|
||||
export function toSync(v: _val): undefined | Sync {
|
||||
let result: undefined | Sync;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $sync) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1: (_ptr) | undefined;
|
||||
_tmp1 = _toPtr(v[0]);
|
||||
if (_tmp1 !== void 0) {result = {"peer": _tmp1};};
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isSync(v: any): v is Sync {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $sync) &&
|
||||
((v.length === 1) && _.isPointer(v[0]))
|
||||
);
|
||||
}
|
||||
|
||||
export function asSync(v: any): Sync {
|
||||
if (!isSync(v)) {throw new TypeError(`Invalid Sync: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeSync(d: _.TypedDecoder<_ptr>): Sync | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp24: any;
|
||||
_tmp24 = _.asLiteral(d.nextSymbol(), $sync);
|
||||
if (_tmp24 !== void 0) {
|
||||
let _tmp25, _tmp26: any;
|
||||
_tmp26 = _decodePtr(d);
|
||||
if (_tmp26 !== void 0) {if (d.closeCompound()) _tmp25 = [_tmp26];};
|
||||
if (_tmp25 !== void 0) result = _.Record<(typeof $sync), [_ptr]>(_tmp24 as any, _tmp25 as any);
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export const _decodePtr = (d: _.TypedDecoder<_ptr>) => {let result; result = _i_Protocol.decodeWireRef(d); return result;};
|
||||
export function fromSync(_v: Sync): _val {return _.Record($sync, [_v["peer"]]);}
|
||||
|
||||
|
|
1417
src/gen/sturdy.ts
1417
src/gen/sturdy.ts
File diff suppressed because it is too large
Load Diff
|
@ -2,44 +2,40 @@ import * as _ from "@preserves/core";
|
|||
|
||||
export const $Instance = Symbol.for("Instance");
|
||||
|
||||
export const Instance = _.Record.makeConstructor<{"_field0": string, "_field1": _val}, _ptr>()($Instance, ["_field0","_field1"]);
|
||||
|
||||
export type Instance = _.Record<(typeof $Instance), [string, _val], _ptr>;
|
||||
|
||||
export type _ptr = never;
|
||||
|
||||
export type _val = _.Value<_ptr>;
|
||||
|
||||
export type Instance = {"name": string, "argument": _val};
|
||||
|
||||
export function isInstance(v: any): v is Instance {
|
||||
return (
|
||||
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
|
||||
_.is(v.label, $Instance) &&
|
||||
((v.length === 2) && typeof v[0] === 'string' && true)
|
||||
);
|
||||
|
||||
export const _toPtr = () => { throw new _.DecodeError("Pointers forbidden"); };
|
||||
|
||||
export function Instance(name: string, argument: _val): Instance {return {name, argument};}
|
||||
|
||||
export function asInstance(v: _val): Instance {
|
||||
let result = toInstance(v);
|
||||
if (result === void 0) throw new TypeError(`Invalid Instance: ${_.stringify(v)}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function asInstance(v: any): Instance {
|
||||
if (!isInstance(v)) {throw new TypeError(`Invalid Instance: ${_.stringify(v)}`);} else {return v;};
|
||||
}
|
||||
|
||||
export function decodeInstance(d: _.TypedDecoder<_ptr>): Instance | undefined {
|
||||
let result;
|
||||
if (d.openRecord()) {
|
||||
let _tmp0: any;
|
||||
_tmp0 = _.asLiteral(d.nextSymbol(), $Instance);
|
||||
export function toInstance(v: _val): undefined | Instance {
|
||||
let result: undefined | Instance;
|
||||
if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
|
||||
let _tmp0: (null) | undefined;
|
||||
_tmp0 = _.is(v.label, $Instance) ? null : void 0;
|
||||
if (_tmp0 !== void 0) {
|
||||
let _tmp1, _tmp2, _tmp3: any;
|
||||
_tmp2 = d.nextString();
|
||||
if (_tmp2 !== void 0) {
|
||||
_tmp3 = d.next();
|
||||
if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2, _tmp3];};
|
||||
let _tmp1: (string) | undefined;
|
||||
_tmp1 = typeof v[0] === 'string' ? v[0] : void 0;
|
||||
if (_tmp1 !== void 0) {
|
||||
let _tmp2: (_val) | undefined;
|
||||
_tmp2 = v[1];
|
||||
if (_tmp2 !== void 0) {result = {"name": _tmp1, "argument": _tmp2};};
|
||||
};
|
||||
if (_tmp1 !== void 0) result = _.Record<(typeof $Instance), [string, _val]>(_tmp0 as any, _tmp1 as any);
|
||||
};
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
export const _decodePtr = () => { throw new _.DecodeError("Pointers forbidden"); };
|
||||
export function fromInstance(_v: Instance): _val {return _.Record($Instance, [_v["name"], _v["argument"]]);}
|
||||
|
||||
|
|
36
src/main.ts
36
src/main.ts
|
@ -1,12 +1,13 @@
|
|||
import { Actor, Assertion, Ref, Turn } from './actor.js';
|
||||
import { Dictionary, Record } from '@preserves/core';
|
||||
import { Dataspace, Observe } from './dataspace.js';
|
||||
import { Dataspace } from './dataspace.js';
|
||||
import { Worker } from 'worker_threads';
|
||||
import { Relay, spawnRelay } from './relay.js';
|
||||
import { attenuate, CRec, Lit, Pattern, PCompound, rfilter } from './rewrite.js';
|
||||
import path from 'path';
|
||||
|
||||
import { BoxState, SetBox } from './gen/box-protocol.js';
|
||||
import { attenuate, CRec, Lit, Pattern, PCompound, rfilter, ConstructorSpec } from './rewrite.js';
|
||||
import { $BoxState, $SetBox } from './gen/box-protocol.js';
|
||||
import { $Observe } from './gen/dataspace.js';
|
||||
|
||||
const Instance = Record.makeConstructor<{moduleName: string, arg: Assertion}>()(
|
||||
Symbol.for('Instance'), ['moduleName', 'arg']);
|
||||
|
@ -56,30 +57,25 @@ Turn.for(new Actor(), async (t: Turn) => {
|
|||
|
||||
const ds_for_box = attenuate(
|
||||
ds,
|
||||
rfilter(PCompound(CRec(BoxState.constructorInfo.label,
|
||||
BoxState.constructorInfo.arity),
|
||||
new Dictionary()),
|
||||
PCompound(CRec(Observe.constructorInfo.label,
|
||||
Observe.constructorInfo.arity),
|
||||
new Dictionary<Pattern, Ref>([
|
||||
[0, Lit(SetBox.constructorInfo.label)]]))));
|
||||
rfilter(
|
||||
Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($BoxState, 1)), new Dictionary())),
|
||||
Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($Observe, 2)),
|
||||
new Dictionary<Ref, Pattern>([
|
||||
[0, Pattern.Lit(Lit($SetBox))]])))));
|
||||
|
||||
const ds_for_client = attenuate(
|
||||
ds_unproxied,
|
||||
rfilter(PCompound(CRec(SetBox.constructorInfo.label,
|
||||
SetBox.constructorInfo.arity),
|
||||
new Dictionary()),
|
||||
PCompound(CRec(Observe.constructorInfo.label,
|
||||
Observe.constructorInfo.arity),
|
||||
new Dictionary<Pattern, Ref>([
|
||||
[0, Lit(BoxState.constructorInfo.label)]]))));
|
||||
|
||||
rfilter(
|
||||
Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($SetBox, 1)), new Dictionary())),
|
||||
Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($Observe, 2)),
|
||||
new Dictionary<Ref, Pattern>([
|
||||
[0, Pattern.Lit(Lit($BoxState))]])))));
|
||||
|
||||
const boxpath = path.join(__dirname, 'box.js');
|
||||
const clientpath = path.join(__dirname, 'client.js');
|
||||
|
||||
// spawnModule(t, boxpath, [ds_for_box, 500000, 25000]);
|
||||
spawnWorker(t, boxpath, [ds_for_box, 50000, 2500]);
|
||||
spawnModule(t, boxpath, [ds_for_box, 500000, 25000]);
|
||||
// spawnWorker(t, boxpath, [ds_for_box, 50000, 2500]);
|
||||
|
||||
spawnModule(t, clientpath, ds_for_client);
|
||||
// spawnWorker(t, clientpath, ds_for_client);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { Attenuation, decodeAttenuation } from './gen/sturdy.js';
|
||||
import { Attenuation, toAttenuation } from './gen/sturdy.js';
|
||||
import * as IO from './gen/protocol.js';
|
||||
import { decodeRef, Ref } from './actor.js';
|
||||
import { TypedDecoder } from '@preserves/core';
|
||||
import { Assertion, Ref } from './actor.js';
|
||||
import { mapPointers } from '@preserves/core';
|
||||
import { pointerNotAllowed } from './sturdy.js';
|
||||
|
||||
export type WireSymbol = { oid: IO.Oid, ref: Ref, count: number };
|
||||
|
||||
|
@ -17,27 +18,19 @@ export function yourRef(oid: IO.Oid, attenuation: Attenuation): WireRef & { loc:
|
|||
return { loc: 'your', oid, attenuation };
|
||||
}
|
||||
|
||||
export function decodeWireRef(d: TypedDecoder<WireRef>): WireRef | undefined {
|
||||
if (d.openSequence()) {
|
||||
switch (d.nextSignedInteger()) {
|
||||
export function toWireRef(v: IO._val): WireRef | undefined {
|
||||
if (Array.isArray(v) && v.length >= 2) {
|
||||
switch (v[0]) {
|
||||
case 0: {
|
||||
const oid = d.nextSignedInteger();
|
||||
if (oid !== void 0) {
|
||||
if (d.closeCompound()) {
|
||||
return myRef(oid);
|
||||
}
|
||||
}
|
||||
const oid = v[1];
|
||||
if (typeof oid === 'number') return myRef(oid);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
const oid = d.nextSignedInteger();
|
||||
if (oid !== void 0) {
|
||||
const attenuation = d.withPointerDecoder(decodeRef, d => decodeAttenuation(d));
|
||||
if (attenuation !== void 0) {
|
||||
if (d.closeCompound()) {
|
||||
return yourRef(oid, attenuation);
|
||||
}
|
||||
}
|
||||
const oid = v[1];
|
||||
if (typeof oid === 'number') {
|
||||
const attenuation = toAttenuation(mapPointers(v.slice(2), pointerNotAllowed) as Array<Assertion>);
|
||||
if (attenuation !== void 0) return yourRef(oid, attenuation);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
51
src/relay.ts
51
src/relay.ts
|
@ -1,10 +1,10 @@
|
|||
import { Actor, Assertion, Entity, Handle, Ref, Turn } from './actor.js';
|
||||
import { BytesLike, canonicalString, Decoder, encode, FlexMap, IdentityMap, mapPointers, underlying, Value } from '@preserves/core';
|
||||
import * as IO from './gen/protocol.js';
|
||||
import { decodeWireRef, myRef, WireRef, WireSymbol, yourRef } from './protocol.js';
|
||||
import { myRef, toWireRef, WireRef, WireSymbol, yourRef } from './protocol.js';
|
||||
import { queueTask } from './task.js';
|
||||
import { attenuate } from './rewrite.js';
|
||||
import { Attenuation } from './gen/sturdy.js';
|
||||
import { Attenuation, fromAttenuation } from './gen/sturdy.js';
|
||||
import { pointerNotAllowed } from './sturdy.js';
|
||||
|
||||
export class SyncPeerEntity implements Entity {
|
||||
|
@ -52,16 +52,16 @@ export class RelayEntity implements Entity {
|
|||
}
|
||||
|
||||
assert(_turn: Turn, assertion: Assertion, handle: Handle): void {
|
||||
this.send(IO.Assert(this.relay.register(assertion, handle), handle));
|
||||
this.send(IO.Event.Assert(IO.Assert(this.relay.register(assertion, handle), handle)))
|
||||
}
|
||||
|
||||
retract(_turn: Turn, handle: Handle): void {
|
||||
this.relay.deregister(handle);
|
||||
this.send(IO.Retract(handle));
|
||||
this.send(IO.Event.Retract(IO.Retract(handle)));
|
||||
}
|
||||
|
||||
message(_turn: Turn, body: Assertion): void {
|
||||
this.send(IO.Message(this.relay.register(body, null)));
|
||||
this.send(IO.Event.Message(IO.Message(this.relay.register(body, null))));
|
||||
}
|
||||
|
||||
sync(turn: Turn, peer: Ref): void {
|
||||
|
@ -69,7 +69,7 @@ export class RelayEntity implements Entity {
|
|||
const exported: Array<WireSymbol> = [];
|
||||
const ior = this.relay.rewriteRefOut(turn.ref(peerEntity), false, exported);
|
||||
peerEntity.e = exported[0];
|
||||
this.send(IO.Sync(ior));
|
||||
this.send(IO.Event.Sync(IO.Sync(ior)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ export class Relay {
|
|||
trustPeer: boolean;
|
||||
|
||||
readonly decoder = new Decoder(void 0, { includeAnnotations: false })
|
||||
.replacePointerDecoder(decodeWireRef);
|
||||
.replacePointerDecoder<WireRef>(d => toWireRef(d.next()));
|
||||
|
||||
constructor(t: Turn, options: RelayOptions) {
|
||||
this.actor = t.actor;
|
||||
|
@ -227,20 +227,20 @@ export class Relay {
|
|||
if (this.pendingTurn.length === 0) {
|
||||
queueTask(() => {
|
||||
if (this.debug) console.log('OUT', this.pendingTurn.asPreservesText());
|
||||
this.w(underlying(encode<WireRef>(this.pendingTurn, {
|
||||
this.w(underlying(encode<WireRef>(IO.fromTurn(this.pendingTurn), {
|
||||
canonical: true,
|
||||
encodePointer: (e, n) => {
|
||||
switch (n.loc) {
|
||||
case 'mine': return e.push([0, n.oid]);
|
||||
case 'your': return e.push([1, n.oid, ... mapPointers<Ref, IO._ptr>(
|
||||
n.attenuation, pointerNotAllowed) as Array<IO._val>]);
|
||||
fromAttenuation(n.attenuation), pointerNotAllowed) as Array<IO._val>]);
|
||||
}
|
||||
},
|
||||
})));
|
||||
this.pendingTurn = [];
|
||||
});
|
||||
}
|
||||
this.pendingTurn.push([remoteOid, m]);
|
||||
this.pendingTurn.push(IO.TurnEvent(remoteOid, m));
|
||||
}
|
||||
|
||||
lookupLocal(localOid: IO.Oid): Ref {
|
||||
|
@ -251,14 +251,13 @@ export class Relay {
|
|||
Turn.for(this.actor, t => {
|
||||
this.decoder.write(bs);
|
||||
while (true) {
|
||||
const wireTurn = this.decoder.shortGuard(
|
||||
() => IO.decodeTurn(this.decoder) ?? false,
|
||||
() => void 0);
|
||||
if (wireTurn === void 0) break;
|
||||
if (wireTurn === false) throw new Error("Bad IO.Turn");
|
||||
const rawTurn = this.decoder.try_next();
|
||||
if (rawTurn === void 0) break;
|
||||
const wireTurn = IO.toTurn(rawTurn);
|
||||
if (wireTurn === void 0) throw new Error("Bad IO.Turn");
|
||||
if (this.debug) console.log('IN', wireTurn.asPreservesText());
|
||||
wireTurn.forEach(v => {
|
||||
const [localOid, m] = v;
|
||||
const { oid: localOid, event: m } = v;
|
||||
this.handle(t, this.lookupLocal(localOid), m);
|
||||
});
|
||||
}
|
||||
|
@ -266,17 +265,17 @@ export class Relay {
|
|||
}
|
||||
|
||||
handle(t: Turn, r: Ref, m: IO.Event) {
|
||||
switch (m.label) {
|
||||
case IO.$assert: {
|
||||
const [a, imported] = this.rewriteIn(t, IO.Assert._.assertion(m));
|
||||
this.inboundAssertions.set(IO.Assert._.handle(m), {
|
||||
switch (m._variant) {
|
||||
case 'Assert': {
|
||||
const [a, imported] = this.rewriteIn(t, m.value.assertion);
|
||||
this.inboundAssertions.set(m.value.handle, {
|
||||
localHandle: t.assert(r, a),
|
||||
imported,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case IO.$retract: {
|
||||
const remoteHandle = IO.Retract._.handle(m);
|
||||
case 'Retract': {
|
||||
const remoteHandle = m.value.handle;
|
||||
const h = this.inboundAssertions.get(remoteHandle);
|
||||
if (h === void 0) throw new Error(`Peer retracted invalid handle ${remoteHandle}`);
|
||||
this.inboundAssertions.delete(remoteHandle);
|
||||
|
@ -284,15 +283,15 @@ export class Relay {
|
|||
t.retract(h.localHandle);
|
||||
break;
|
||||
}
|
||||
case IO.$message: {
|
||||
const [a, imported] = this.rewriteIn(t, IO.Message._.body(m));
|
||||
case 'Message': {
|
||||
const [a, imported] = this.rewriteIn(t, m.value.body);
|
||||
if (imported.length > 0) throw new Error("Cannot receive transient reference");
|
||||
t.message(r, a);
|
||||
break;
|
||||
}
|
||||
case IO.$sync: {
|
||||
case 'Sync': {
|
||||
const imported: Array<WireSymbol> = [];
|
||||
const k = this.rewriteRefIn(t, IO.Sync._.peer(m), imported);
|
||||
const k = this.rewriteRefIn(t, m.value.peer, imported);
|
||||
t.sync(r).then(t => {
|
||||
t.message(k, true);
|
||||
imported.forEach(e => this.imported.drop(e));
|
||||
|
|
121
src/rewrite.ts
121
src/rewrite.ts
|
@ -1,34 +1,7 @@
|
|||
import type { Assertion, Handle, Ref, Turn } from "./actor.js";
|
||||
import { Dictionary, IdentityMap, is, Record, Tuple } from "@preserves/core";
|
||||
|
||||
import {
|
||||
$__,
|
||||
$and,
|
||||
$arr,
|
||||
$bind,
|
||||
$compound,
|
||||
$dict,
|
||||
$lit,
|
||||
$not,
|
||||
$or,
|
||||
$rec,
|
||||
$ref,
|
||||
Alts,
|
||||
Attenuation,
|
||||
CArr,
|
||||
CRec,
|
||||
Caveat,
|
||||
Lit,
|
||||
PAnd,
|
||||
PBind,
|
||||
PCompound,
|
||||
PNot,
|
||||
Pattern,
|
||||
Rewrite,
|
||||
TCompound,
|
||||
TRef,
|
||||
Template,
|
||||
} from './gen/sturdy.js';
|
||||
import { Alts, Attenuation, Caveat, PBind, Pattern, Rewrite, TRef, Template } from './gen/sturdy.js';
|
||||
export * from './gen/sturdy.js';
|
||||
|
||||
export type Bindings = { [name: string]: Assertion };
|
||||
|
@ -37,52 +10,52 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
|
|||
let bindings: Bindings = {};
|
||||
|
||||
function walk(p: Pattern, v: Assertion): boolean {
|
||||
switch (p.label) {
|
||||
case $__:
|
||||
switch (p._variant) {
|
||||
case 'PDiscard':
|
||||
return true;
|
||||
case $bind:
|
||||
if (walk(PBind._.pattern(p), v)) {
|
||||
bindings[PBind._.name(p).asPreservesText()] = v;
|
||||
case 'PBind':
|
||||
if (walk(p.value.pattern, v)) {
|
||||
bindings[p.value.name.asPreservesText()] = v;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case $and:
|
||||
for (const pp of PAnd._.patterns(p)) {
|
||||
case 'PAnd':
|
||||
for (const pp of p.value.patterns) {
|
||||
if (!walk(pp, v)) return false;
|
||||
}
|
||||
return true;
|
||||
case $not: {
|
||||
case 'PNot': {
|
||||
const savedBindings = bindings;
|
||||
bindings = {};
|
||||
const result = !walk(PNot._.pattern(p), v)
|
||||
const result = !walk(p.value.pattern, v)
|
||||
bindings = savedBindings;
|
||||
return result;
|
||||
}
|
||||
case $lit:
|
||||
return is(Lit._.value(p), v);
|
||||
case $compound: {
|
||||
const ctor = PCompound._.ctor(p);
|
||||
const members = PCompound._.members(p);
|
||||
switch (ctor.label) {
|
||||
case $rec:
|
||||
case 'Lit':
|
||||
return is(p.value.value, v);
|
||||
case 'PCompound': {
|
||||
const ctor = p.value.ctor;
|
||||
const members = p.value.members;
|
||||
switch (ctor._variant) {
|
||||
case 'CRec':
|
||||
if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(v)) return false;
|
||||
if (!is(CRec._.label(ctor), v.label)) return false;
|
||||
if (CRec._.arity(ctor) !== v.length) return false;
|
||||
if (!is(ctor.value.label, v.label)) return false;
|
||||
if (ctor.value.arity !== v.length) return false;
|
||||
for (const [key, pp] of members) {
|
||||
if (typeof key !== 'number') return false;
|
||||
if (!walk(pp, v[key])) return false;
|
||||
}
|
||||
return true;
|
||||
case $arr:
|
||||
case 'CArr':
|
||||
if (!Array.isArray(v)) return false;
|
||||
if ('label' in v) return false;
|
||||
if (CArr._.arity(ctor) !== v.length) return false;
|
||||
if (ctor.value.arity !== v.length) return false;
|
||||
for (const [key, pp] of members) {
|
||||
if (typeof key !== 'number') return false;
|
||||
if (!walk(pp, v[key])) return false;
|
||||
}
|
||||
return true;
|
||||
case $dict:
|
||||
case 'CDict':
|
||||
if (!Dictionary.isDictionary<Assertion, Ref>(v)) return false;
|
||||
for (const [key, pp] of members) {
|
||||
const vv = v.get(key as Assertion);
|
||||
|
@ -100,40 +73,38 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
|
|||
|
||||
export function instantiate(t: Template, b: Bindings): Assertion {
|
||||
function walk(t: Template): Assertion {
|
||||
switch (t.label) {
|
||||
case $ref: {
|
||||
const n = TRef._.name(t).asPreservesText()
|
||||
switch (t._variant) {
|
||||
case 'TRef': {
|
||||
const n = t.value.name.asPreservesText()
|
||||
const v = b[n];
|
||||
if (v === void 0) throw new Error(`Unbound reference: ${n}`);
|
||||
return v;
|
||||
}
|
||||
case $lit:
|
||||
return Lit._.value(t) as Assertion;
|
||||
case $compound: {
|
||||
const ctor = TCompound._.ctor(t);
|
||||
const members = TCompound._.members(t);
|
||||
switch (ctor.label) {
|
||||
case $rec: {
|
||||
const v = Record(
|
||||
CRec._.label(ctor) as Assertion,
|
||||
[] as Assertion[],
|
||||
);
|
||||
v.length = CRec._.arity(ctor);
|
||||
case 'Lit':
|
||||
return t.value.value as Assertion;
|
||||
case 'TCompound': {
|
||||
const ctor = t.value.ctor;
|
||||
const members = t.value.members;
|
||||
switch (ctor._variant) {
|
||||
case 'CRec': {
|
||||
const v = [] as unknown as Record<Assertion, Assertion[], Ref>;
|
||||
v.length = ctor.value.arity;
|
||||
v.label = ctor.value.label;
|
||||
for (const [key, tt] of members) {
|
||||
v[key as number] = walk(tt);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
case $arr: {
|
||||
case 'CArr': {
|
||||
const v = [];
|
||||
v.length = CArr._.arity(ctor);
|
||||
v.length = ctor.value.arity;
|
||||
for (const [key, tt] of members) {
|
||||
v[key as number] = walk(tt);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
case $dict: {
|
||||
const v = new Dictionary<Assertion, Ref>();
|
||||
case 'CDict': {
|
||||
const v = new Dictionary<Ref, Assertion>();
|
||||
for (const [key, tt] of members) {
|
||||
v.set(key as Assertion, walk(tt));
|
||||
}
|
||||
|
@ -148,20 +119,20 @@ export function instantiate(t: Template, b: Bindings): Assertion {
|
|||
}
|
||||
|
||||
export function rewrite(r: Rewrite, v: Assertion): Assertion | null {
|
||||
const bindings = match(Rewrite._.pattern(r), v);
|
||||
const bindings = match(r.pattern, v);
|
||||
if (bindings === null) return null;
|
||||
return instantiate(Rewrite._.template(r), bindings);
|
||||
return instantiate(r.template, bindings);
|
||||
}
|
||||
|
||||
export function examineAlternatives(cav: Caveat, v: Assertion): Assertion | null {
|
||||
if (cav.label === $or) {
|
||||
for (const r of Alts._.alternatives(cav)) {
|
||||
if (cav._variant === 'Alts') {
|
||||
for (const r of cav.value.alternatives) {
|
||||
const w = rewrite(r, v);
|
||||
if (w !== null) return w;
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return rewrite(cav, v);
|
||||
return rewrite(cav.value, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,8 +150,8 @@ export function runRewrites(a: Attenuation | undefined, v: Assertion): Assertion
|
|||
const _a = Symbol.for('a');
|
||||
|
||||
export function rfilter(... patterns: Pattern[]): Caveat {
|
||||
const ps = patterns.map(p => Rewrite(PBind(_a, p), TRef(_a)));
|
||||
return ps.length === 1 ? ps[0] : Alts(ps);
|
||||
const ps = patterns.map(p => Rewrite(Pattern.PBind(PBind(_a, p)), Template.TRef(TRef(_a))));
|
||||
return ps.length === 1 ? Caveat.Rewrite(ps[0]) : Caveat.Alts(Alts(ps));
|
||||
}
|
||||
|
||||
export function attenuate(ref: Ref, ... a: Attenuation): Ref {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Actor, Ref, Turn } from "./actor";
|
||||
import { Relay, spawnRelay } from "./relay";
|
||||
import { sturdyDecode } from "./sturdy";
|
||||
import { Resolve, asSturdyRef } from "./gen/sturdy";
|
||||
import { Resolve, asSturdyRef, fromResolve } from "./gen/sturdy";
|
||||
|
||||
import * as net from 'net';
|
||||
import { Bytes } from "@preserves/core";
|
||||
|
@ -29,11 +29,11 @@ const socket = net.createConnection({ port: 5999, host: 'localhost' }, () => {
|
|||
// debug: true,
|
||||
}).then(gatekeeper => import(moduleName).then(m => t.freshen(t => {
|
||||
t.assert(shutdownRef, true);
|
||||
t.assert(gatekeeper, Resolve(asSturdyRef(cap), t.ref({
|
||||
t.assert(gatekeeper, fromResolve(Resolve(asSturdyRef(cap), t.ref({
|
||||
assert(t, ds) {
|
||||
m.default(t, ds);
|
||||
}
|
||||
})));
|
||||
}))));
|
||||
})));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,16 +3,16 @@ import { Dataspace } from './dataspace.js';
|
|||
import { Relay, spawnRelay } from './relay.js';
|
||||
import * as net from 'net';
|
||||
|
||||
import { mint, sturdyEncode, SturdyRef, validate, Resolve } from './sturdy.js';
|
||||
import { mint, sturdyEncode, validate } from './sturdy.js';
|
||||
import { KEY_LENGTH } from './cryptography.js';
|
||||
import { attenuate } from './rewrite.js';
|
||||
import { Bytes, IdentityMap } from '@preserves/core';
|
||||
import { Attenuation, isResolve } from './gen/sturdy.js';
|
||||
import { Attenuation, fromSturdyRef, toResolve } from './gen/sturdy.js';
|
||||
|
||||
const secretKey = new Bytes(KEY_LENGTH);
|
||||
mint('syndicate', secretKey).then(v => {
|
||||
console.log(v.asPreservesText());
|
||||
console.log(sturdyEncode(v).toHex());
|
||||
console.log(sturdyEncode(fromSturdyRef(v)).toHex());
|
||||
});
|
||||
|
||||
Turn.for(new Actor(), t => {
|
||||
|
@ -32,19 +32,20 @@ Turn.for(new Actor(), t => {
|
|||
},
|
||||
initialRef: t.ref({
|
||||
handleMap: new IdentityMap<Handle, Handle>(),
|
||||
async assert(t, a, h) {
|
||||
if (!isResolve(a)) return;
|
||||
const r = Resolve._.sturdyref(a);
|
||||
async assert(t, a0, h) {
|
||||
const a = toResolve(a0);
|
||||
if (a === void 0) return;
|
||||
const r = a.sturdyref;
|
||||
if (!await validate(r, secretKey)) {
|
||||
console.warn(`Invalid SturdyRef: ${r.asPreservesText()}`);
|
||||
return;
|
||||
}
|
||||
const cavs: Attenuation = [];
|
||||
SturdyRef._.caveatChain(r).forEach(cs => cavs.push(... cs));
|
||||
r.caveatChain.forEach(cs => cavs.push(... cs));
|
||||
const attenuated_ds = attenuate(ds, ... cavs);
|
||||
t.freshen(t => this.handleMap.set(
|
||||
h,
|
||||
t.assert(Resolve._.observer(a), attenuated_ds)));
|
||||
t.assert(a.observer, attenuated_ds)));
|
||||
},
|
||||
retract(t, h) {
|
||||
t.retract(this.handleMap.get(h));
|
||||
|
|
|
@ -1,32 +1,34 @@
|
|||
import { newKey } from './cryptography.js';
|
||||
import { attenuate, KEY_LENGTH, mint, Rewrite, sturdyEncode, validate } from './sturdy.js';
|
||||
import { attenuate, KEY_LENGTH, mint, Caveat, Rewrite, sturdyEncode, validate } from './sturdy.js';
|
||||
import * as RW from './rewrite.js';
|
||||
import { Bytes, Dictionary } from '@preserves/core';
|
||||
import { Ref } from 'actor.js';
|
||||
|
||||
async function main() {
|
||||
const m1 = await mint('hello world', new Bytes(KEY_LENGTH));
|
||||
console.log(m1.asPreservesText());
|
||||
const m2 = await attenuate(m1, Rewrite(
|
||||
RW.PBind(Symbol.for('a'),
|
||||
RW.PCompound(RW.CRec(Symbol.for('says'), 2),
|
||||
new Dictionary<RW.Pattern, Ref>([
|
||||
[0, RW.Lit('Tony')]]))),
|
||||
RW.TRef(Symbol.for('a'))));
|
||||
console.log(m2.asPreservesText());
|
||||
console.log(m1);
|
||||
const m2 = await attenuate(m1, Caveat.Rewrite(Rewrite(
|
||||
RW.Pattern.PBind(RW.PBind(
|
||||
Symbol.for('a'),
|
||||
RW.Pattern.PCompound(RW.PCompound(
|
||||
RW.ConstructorSpec.CRec(RW.CRec(Symbol.for('says'), 2)),
|
||||
new Dictionary<Ref, RW.Pattern>([
|
||||
[0, RW.Pattern.Lit(RW.Lit('Tony'))]]))))),
|
||||
RW.Template.TRef(RW.TRef(Symbol.for('a'))))));
|
||||
console.log(m2);
|
||||
console.log('should be true:', await validate(m1, new Bytes(KEY_LENGTH)));
|
||||
console.log('should be true:', await validate(m2, new Bytes(KEY_LENGTH)));
|
||||
console.log('should be false:', await validate(m2, Bytes.of(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)));
|
||||
m2[0] = 'hello world2';
|
||||
console.log(m2.asPreservesText());
|
||||
m2.oid = 'hello world2';
|
||||
console.log(m2);
|
||||
console.log('should be false:', await validate(m2, new Bytes(KEY_LENGTH)));
|
||||
m2[0] = 'hello world';
|
||||
console.log(m2.asPreservesText());
|
||||
m2.oid = 'hello world';
|
||||
console.log(m2);
|
||||
console.log('should be true:', await validate(m2, new Bytes(KEY_LENGTH)));
|
||||
console.log('should be false:', await validate(m2, await newKey()));
|
||||
console.log((await newKey()).asPreservesText());
|
||||
console.log((await newKey()).asPreservesText());
|
||||
console.log(sturdyEncode(m2).asPreservesText());
|
||||
console.log(sturdyEncode(RW.fromSturdyRef(m2)).asPreservesText());
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
@ -40,15 +40,15 @@ export async function mint(oid: SturdyValue, secretKey: Bytes): Promise<S.Sturdy
|
|||
|
||||
export async function attenuate(r: S.SturdyRef, ... a: S.Attenuation): Promise<S.SturdyRef> {
|
||||
return S.SturdyRef(
|
||||
S.SturdyRef._.oid(r),
|
||||
[... S.SturdyRef._.caveatChain(r), a],
|
||||
await mac(S.SturdyRef._.sig(r), sturdyEncode(a))
|
||||
r.oid,
|
||||
[... r.caveatChain, a],
|
||||
await mac(r.sig, sturdyEncode(S.fromAttenuation(a)))
|
||||
);
|
||||
}
|
||||
|
||||
export async function validate(r: S.SturdyRef, secretKey: Bytes): Promise<boolean> {
|
||||
const sig = await S.SturdyRef._.caveatChain(r).reduce(
|
||||
async (sig, a) => mac(await sig, sturdyEncode(a)),
|
||||
mac(secretKey, sturdyEncode(S.SturdyRef._.oid(r))));
|
||||
return is(sig, S.SturdyRef._.sig(r));
|
||||
const sig = await r.caveatChain.reduce(
|
||||
async (sig, a) => mac(await sig, sturdyEncode(S.fromAttenuation(a))),
|
||||
mac(secretKey, sturdyEncode(r.oid)));
|
||||
return is(sig, r.sig);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { Bytes, Reader } from '@preserves/core';
|
||||
import { attenuate, Caveat, sturdyDecode, sturdyEncode, SturdyRef } from '../sturdy.js';
|
||||
import { fromSturdyRef, toSturdyRef, toCaveat, attenuate, sturdyDecode, sturdyEncode } from '../sturdy.js';
|
||||
|
||||
const [ base, pat ] = process.argv.slice(2);
|
||||
const baseCap = sturdyDecode(Bytes.fromHex(base ?? '')) as SturdyRef;
|
||||
const cs = new Reader(pat).next() as Array<Caveat>;
|
||||
const baseCap = toSturdyRef(sturdyDecode(Bytes.fromHex(base ?? '')));
|
||||
if (baseCap === void 0) throw new Error("Cannot decode sturdyref");
|
||||
const cs0 = new Reader(pat).next();
|
||||
if (!Array.isArray(cs0)) throw new Error("Expected array of caveats");
|
||||
const cs = cs0.map(c => toCaveat(c) ?? (()=>{ throw new Error("Cannot decode caveat"); })());
|
||||
attenuate(baseCap, ... cs).then(derived => {
|
||||
console.log(derived.asPreservesText());
|
||||
console.log(sturdyEncode(derived).toHex());
|
||||
console.log(sturdyEncode(fromSturdyRef(derived)).toHex());
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue