Update to new schema compiler backend

This commit is contained in:
Tony Garnock-Jones 2021-03-23 12:18:57 +01:00
parent 346218f26a
commit 1bd65cd283
24 changed files with 1110 additions and 1349 deletions

View File

@ -1,9 +1,9 @@
version 1 . version 1 .
pointer Actor.Ref . pointer Actor.Ref .
BoxState = <BoxState int>. BoxState = <BoxState @value int>.
SetBox = <SetBox int>. SetBox = <SetBox @value int>.
; BoxCap = BoxState / <Observe =SetBox ref>. ; BoxCap = BoxState / <Observe =SetBox @observer ref>.
; ClientCap = SetBox / <Observe =BoxState ref>. ; ClientCap = SetBox / <Observe =BoxState @observer ref>.
. .

View File

@ -5,5 +5,5 @@ pointer Actor.Ref .
Observe = <Observe @label symbol @observer ref>. Observe = <Observe @label symbol @observer ref>.
; ;As will be implemented soon ; ;As will be implemented soon
; Observe = <Observe Pattern ref>. ; Observe = <Observe @pattern Pattern @observer ref>.
. .

View File

@ -5,7 +5,8 @@ Assertion = any .
Handle = int . Handle = int .
Event = Assert / Retract / Message / Sync . Event = Assert / Retract / Message / Sync .
Oid = int . Oid = int .
Turn = [[Oid Event] ...]. Turn = [TurnEvent ...].
TurnEvent = [@oid Oid @event Event].
Assert = <assert @assertion Assertion @handle Handle>. Assert = <assert @assertion Assertion @handle Handle>.
Retract = <retract @handle Handle>. Retract = <retract @handle Handle>.

View File

@ -3,7 +3,7 @@ pointer Actor.Ref .
; Each Attenuation is a stage. The sequence of Attenuations is run RIGHT-TO-LEFT. ; Each Attenuation is a stage. The sequence of Attenuations is run RIGHT-TO-LEFT.
; That is, the newest Attenuations are at the right. ; 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. ; An individual Attenuation is run RIGHT-TO-LEFT.
; That is, the newest Caveats are at the right. ; That is, the newest Caveats are at the right.
@ -13,7 +13,7 @@ Attenuation = [Caveat ...].
; can add 3rd-party caveats and richer predicates later ; can add 3rd-party caveats and richer predicates later
Caveat = Rewrite / Alts . Caveat = Rewrite / Alts .
Rewrite = <rewrite @pattern Pattern @template Template>. Rewrite = <rewrite @pattern Pattern @template Template>.
Alts = <or @alternatives [Rewrite ...]>. Alts = <or [@alternatives Rewrite ...]>.
Resolve = <resolve @sturdyref SturdyRef @observer ref>. Resolve = <resolve @sturdyref SturdyRef @observer ref>.
@ -29,10 +29,13 @@ Lit = <lit @value any>.
Pattern = PDiscard / PBind / PAnd / PNot / Lit / PCompound . Pattern = PDiscard / PBind / PAnd / PNot / Lit / PCompound .
PDiscard = <_>. PDiscard = <_>.
PBind = <bind @name symbol @pattern Pattern>. PBind = <bind @name symbol @pattern Pattern>.
PAnd = <and @patterns [Pattern ...]>. PAnd = <and [@patterns Pattern ...]>.
PNot = <not @pattern 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 . Template = TRef / Lit / TCompound .
TRef = <ref @name symbol>. TRef = <ref @name symbol>.
TCompound = <compound @ctor ConstructorSpec @members { any: Template ...:... }>. TCompound = <compound @ctor ConstructorSpec @members TCompoundMembers>.
TCompoundMembers = { any: Template ...:... }.

View File

@ -1,3 +1,3 @@
version 1 . version 1 .
Instance = <Instance string any>. Instance = <Instance @name string @argument any>.

View File

@ -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 { Attenuation, runRewrites } from './rewrite.js';
import { queueTask } from './task.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; return 'relay' in v && v.relay instanceof Actor && 'target' in v;
} }
export function decodeRef(_d: TypedDecoder<Ref>): Ref | undefined { export function toRef(_v: any): Ref | undefined {
throw new DecodeError("Cannot decode Ref"); return isRef(_v) ? _v : void 0;
} }
let nextActorId = 0; let nextActorId = 0;

View File

@ -10,7 +10,7 @@ export enum ChangeDescription {
} }
export class Bag<T extends object = DefaultPointer> { export class Bag<T extends object = DefaultPointer> {
_items: Dictionary<number, T>; _items: Dictionary<T, number>;
constructor(s?: Set<T>) { constructor(s?: Set<T>) {
this._items = new Dictionary(); this._items = new Dictionary();
@ -65,7 +65,7 @@ export class Bag<T extends object = DefaultPointer> {
this._items.forEach(f); this._items.forEach(f);
} }
snapshot(): Dictionary<number, T> { snapshot(): Dictionary<T, number> {
return this._items.clone(); return this._items.clone();
} }

View File

@ -1,5 +1,5 @@
import { BoxState, SetBox } from "./gen/box-protocol.js"; import { BoxState, $SetBox, fromBoxState } from "./gen/box-protocol.js";
import { Observe } from "./gen/dataspace.js"; import { fromObserve, Observe } from "./gen/dataspace.js";
import { Assertion, Handle, Ref, Turn } from "./actor.js"; import { Assertion, Handle, Ref, Turn } from "./actor.js";
let startTime = Date.now(); let startTime = Date.now();
@ -12,10 +12,10 @@ export default function (t: Turn, arg: Assertion) {
console.log('Spawning Box', LIMIT, REPORT_EVERY); console.log('Spawning Box', LIMIT, REPORT_EVERY);
let valueHandle: Handle | undefined; let valueHandle: Handle | undefined;
function setValue(t: Turn, value: number) { function setValue(t: Turn, value: number) {
valueHandle = t.replace(ds, valueHandle, BoxState(value)); valueHandle = t.replace(ds, valueHandle, fromBoxState(BoxState(value)));
} }
setValue(t, 0); 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 { message(t: Turn, [newValue]: [number]): void {
// console.log(`Box ${t.actor.id}: got ${newValue}`); // console.log(`Box ${t.actor.id}: got ${newValue}`);
if (newValue % REPORT_EVERY === 0) { if (newValue % REPORT_EVERY === 0) {
@ -29,5 +29,5 @@ export default function (t: Turn, arg: Assertion) {
if (newValue === LIMIT) t.quit(); if (newValue === LIMIT) t.quit();
setValue(t, newValue); setValue(t, newValue);
} }
}))); }))));
} }

View File

@ -1,17 +1,17 @@
import { BoxState, SetBox } from "./gen/box-protocol.js"; import { $BoxState, fromSetBox, SetBox } from "./gen/box-protocol.js";
import { Observe } from "./gen/dataspace.js"; import { fromObserve, Observe } from "./gen/dataspace.js";
import { Assertion, Ref, Turn } from "./actor.js"; import { Assertion, Ref, Turn } from "./actor.js";
export default function (t: Turn, ds: Ref) { export default function (t: Turn, ds: Ref) {
console.log('Spawning Client'); console.log('Spawning Client');
let count = 0; 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 { assert(t: Turn, [currentValue]: [number]): void {
// console.log(`Client ${t.actor.id}: got ${currentValue}`); // 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 { assert(_t: Turn, _assertion: Assertion): void {
count++; count++;
// console.log('inc to', count, _assertion); // console.log('inc to', count, _assertion);
@ -23,5 +23,5 @@ export default function (t: Turn, ds: Ref) {
} }
// console.log('dec to', count); // console.log('dec to', count);
}, },
}))); }))));
} }

View File

@ -2,7 +2,7 @@ import { Assertion, Entity, Handle, Ref, Turn } from 'actor';
import { Dictionary, IdentityMap, is, Record, Tuple } from '@preserves/core'; import { Dictionary, IdentityMap, is, Record, Tuple } from '@preserves/core';
import { Bag, ChangeDescription } from './bag'; import { Bag, ChangeDescription } from './bag';
import { Observe } from './gen/dataspace'; import { toObserve } from './gen/dataspace';
export * from './gen/dataspace'; export * from './gen/dataspace';
// Q. Why keep "Observe"? Why not do the clever trick of asserting the // 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> { export class Dataspace implements Partial<Entity> {
readonly handleMap: IdentityMap<Handle, Record<Assertion, any, Ref>> = new IdentityMap(); readonly handleMap: IdentityMap<Handle, Record<Assertion, any, Ref>> = new IdentityMap();
readonly assertions = new Bag<Ref>(); 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 { assert(turn: Turn, rec: Assertion, handle: Handle): void {
// console.log(preserves`ds ${turn.actor.id} assert ${rec} ${handle}`); // console.log(preserves`ds ${turn.actor.id} assert ${rec} ${handle}`);
if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(rec)) return; if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(rec)) return;
this.handleMap.set(handle, rec); this.handleMap.set(handle, rec);
if (this.assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return; if (this.assertions.change(rec, +1) !== ChangeDescription.ABSENT_TO_PRESENT) return;
if (Observe.isClassOf(rec)) { {
const label = Observe._.label(rec)!; const o = toObserve(rec);
const observer = Observe._.observer(rec); if (o !== void 0) {
const seen = new Dictionary<Handle, Ref>(); const seen = new Dictionary<Ref, Handle>();
if (!this.subscriptions.has(label)) this.subscriptions.set(label, new Map()); if (!this.subscriptions.has(o.label)) this.subscriptions.set(o.label, new Map());
this.subscriptions.get(label)!.set(observer, seen); this.subscriptions.get(o.label)!.set(o.observer, seen);
this.assertions.forEach((_count, prev) => this.assertions.forEach((_count, prev) =>
is((prev as Record<Assertion, any, Ref>).label, label) is((prev as Record<Assertion, any, Ref>).label, o.label)
&& seen.set(prev, turn.assert(observer, prev))); && seen.set(prev, turn.assert(o.observer, prev)));
}
} }
this.subscriptions.get(rec.label)?.forEach((seen, peer) => this.subscriptions.get(rec.label)?.forEach((seen, peer) =>
seen.has(rec) || seen.set(rec, turn.assert(peer, rec))); 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)); turn.retract(seen.get(rec));
seen.delete(rec); seen.delete(rec);
}); });
if (Observe.isClassOf(rec)) { {
let peerMap = this.subscriptions.get(Observe._.label(rec)!)!; const o = toObserve(rec);
peerMap.delete(Observe._.observer(rec) as Ref); if (o !== void 0) {
if (peerMap.size === 0) this.subscriptions.delete(Observe._.label(rec)!); let peerMap = this.subscriptions.get(o.label)!;
peerMap.delete(o.observer);
if (peerMap.size === 0) this.subscriptions.delete(o.label);
}
} }
} }

View File

@ -4,72 +4,62 @@ import * as _i_Actor from "../actor";
export const $BoxState = Symbol.for("BoxState"); export const $BoxState = Symbol.for("BoxState");
export const $SetBox = Symbol.for("SetBox"); 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 _ptr = _i_Actor.Ref;
export type _val = _.Value<_ptr>; export type _val = _.Value<_ptr>;
export type BoxState = {"value": number};
export function isBoxState(v: any): v is BoxState { export type SetBox = {"value": number};
return (
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
_.is(v.label, $BoxState) && export const _toPtr = (v: _val) => {let result: undefined | _ptr; result = _i_Actor.toRef(v); return result;};
((v.length === 1) && typeof v[0] === 'number')
); 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 { export function toBoxState(v: _val): undefined | BoxState {
if (!isBoxState(v)) {throw new TypeError(`Invalid BoxState: ${_.stringify(v)}`);} else {return v;}; let result: undefined | BoxState;
} if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp0: (null) | undefined;
export function decodeBoxState(d: _.TypedDecoder<_ptr>): BoxState | undefined { _tmp0 = _.is(v.label, $BoxState) ? null : void 0;
let result;
if (d.openRecord()) {
let _tmp0: any;
_tmp0 = _.asLiteral(d.nextSymbol(), $BoxState);
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
let _tmp1, _tmp2: any; let _tmp1: (number) | undefined;
_tmp2 = d.nextSignedInteger(); _tmp1 = typeof v[0] === 'number' ? v[0] : void 0;
if (_tmp2 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2];}; if (_tmp1 !== void 0) {result = {"value": _tmp1};};
if (_tmp1 !== void 0) result = _.Record<(typeof $BoxState), [number]>(_tmp0 as any, _tmp1 as any);
}; };
}; };
return result; return result;
} }
export function isSetBox(v: any): v is SetBox { export function fromBoxState(_v: BoxState): _val {return _.Record($BoxState, [_v["value"]]);}
return (
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && export function asSetBox(v: _val): SetBox {
_.is(v.label, $SetBox) && let result = toSetBox(v);
((v.length === 1) && typeof v[0] === 'number') if (result === void 0) throw new TypeError(`Invalid SetBox: ${_.stringify(v)}`);
); return result;
} }
export function asSetBox(v: any): SetBox { export function toSetBox(v: _val): undefined | SetBox {
if (!isSetBox(v)) {throw new TypeError(`Invalid SetBox: ${_.stringify(v)}`);} else {return v;}; let result: undefined | SetBox;
} if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp0: (null) | undefined;
export function decodeSetBox(d: _.TypedDecoder<_ptr>): SetBox | undefined { _tmp0 = _.is(v.label, $SetBox) ? null : void 0;
let result; if (_tmp0 !== void 0) {
if (d.openRecord()) { let _tmp1: (number) | undefined;
let _tmp3: any; _tmp1 = typeof v[0] === 'number' ? v[0] : void 0;
_tmp3 = _.asLiteral(d.nextSymbol(), $SetBox); if (_tmp1 !== void 0) {result = {"value": _tmp1};};
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);
}; };
}; };
return result; 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"]]);}

View File

@ -3,44 +3,40 @@ import * as _i_Actor from "../actor";
export const $Observe = Symbol.for("Observe"); 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 _ptr = _i_Actor.Ref;
export type _val = _.Value<_ptr>; export type _val = _.Value<_ptr>;
export type Observe = {"label": symbol, "observer": _ptr};
export function isObserve(v: any): v is Observe {
return ( export const _toPtr = (v: _val) => {let result: undefined | _ptr; result = _i_Actor.toRef(v); return result;};
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
_.is(v.label, $Observe) && export function Observe(label: symbol, observer: _ptr): Observe {return {label, observer};}
((v.length === 2) && typeof v[0] === 'symbol' && _.isPointer(v[1]))
); 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 { export function toObserve(v: _val): undefined | Observe {
if (!isObserve(v)) {throw new TypeError(`Invalid Observe: ${_.stringify(v)}`);} else {return v;}; let result: undefined | Observe;
} if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp0: (null) | undefined;
export function decodeObserve(d: _.TypedDecoder<_ptr>): Observe | undefined { _tmp0 = _.is(v.label, $Observe) ? null : void 0;
let result;
if (d.openRecord()) {
let _tmp0: any;
_tmp0 = _.asLiteral(d.nextSymbol(), $Observe);
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
let _tmp1, _tmp2, _tmp3: any; let _tmp1: (symbol) | undefined;
_tmp2 = d.nextSymbol(); _tmp1 = typeof v[0] === 'symbol' ? v[0] : void 0;
if (_tmp2 !== void 0) { if (_tmp1 !== void 0) {
_tmp3 = _decodePtr(d); let _tmp2: (_ptr) | undefined;
if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2, _tmp3];}; _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; 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"]]);}

View File

@ -6,280 +6,291 @@ export const $message = Symbol.for("message");
export const $retract = Symbol.for("retract"); export const $retract = Symbol.for("retract");
export const $sync = Symbol.for("sync"); 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 _ptr = _i_Protocol.WireRef;
export type _val = _.Value<_ptr>; 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 { export type Event = (
if (!isAssertion(v)) {throw new TypeError(`Invalid Assertion: ${_.stringify(v)}`);} else {return v;}; {"_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 { export function TurnEvent(oid: Oid, event: Event): TurnEvent {return {oid, event};}
if (!isHandle(v)) {throw new TypeError(`Invalid Handle: ${_.stringify(v)}`);} else {return v;};
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 toAssertion(v: _val): undefined | Assertion {
let _tmp0: (_val) | undefined;
export function isEvent(v: any): v is Event { let result: undefined | Assertion;
return _.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && ( _tmp0 = v;
( if (_tmp0 !== void 0) {result = _tmp0;};
( return result;
_.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 asEvent(v: any): Event { export function fromAssertion(_v: Assertion): _val {return _v;}
if (!isEvent(v)) {throw new TypeError(`Invalid Event: ${_.stringify(v)}`);} else {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 { export function toHandle(v: _val): undefined | Handle {
let result; let _tmp0: (number) | undefined;
if (d.openRecord()) { let result: undefined | Handle;
let _tmp0, _tmp1: any; _tmp0 = typeof v === 'number' ? v : void 0;
_tmp0 = d.next(); if (_tmp0 !== void 0) {result = _tmp0;};
_tmp1 = d.mark(); return result;
if (_.is(_tmp0, $assert)) { }
let _tmp2, _tmp3, _tmp4: any;
_tmp3 = decodeAssertion(d); export function fromHandle(_v: Handle): _val {return _v;}
if (_tmp3 !== void 0) {
_tmp4 = decodeHandle(d); export function asEvent(v: _val): Event {
if (_tmp4 !== void 0) {if (d.closeCompound()) _tmp2 = [_tmp3, _tmp4];}; let result = toEvent(v);
}; if (result === void 0) throw new TypeError(`Invalid Event: ${_.stringify(v)}`);
if (_tmp2 !== void 0) result = _.Record<(typeof $assert), [Assertion, Handle]>(_tmp0 as any, _tmp2 as any); 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) { if (result === void 0) {
d.restoreMark(_tmp1); let _tmp2: (Message) | undefined;
if (_.is(_tmp0, $retract)) { _tmp2 = toMessage(v);
let _tmp5, _tmp6: any; if (_tmp2 !== void 0) {result = {"_variant": "Message", "value": _tmp2};};
_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);
};
if (result === void 0) { if (result === void 0) {
d.restoreMark(_tmp1); let _tmp3: (Sync) | undefined;
if (_.is(_tmp0, $message)) { _tmp3 = toSync(v);
let _tmp7, _tmp8: any; if (_tmp3 !== void 0) {result = {"_variant": "Sync", "value": _tmp3};};
_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);
};
};
}; };
}; };
}; };
return result; return result;
} }
export function isOid(v: any): v is Oid {return typeof v === 'number';} export function fromEvent(_v: Event): _val {
switch (_v._variant) {
export function asOid(v: any): Oid { case "Assert": {return fromAssert(_v.value);};
if (!isOid(v)) {throw new TypeError(`Invalid Oid: ${_.stringify(v)}`);} else {return v;}; 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 asOid(v: _val): Oid {
let result = toOid(v);
export function isTurn(v: any): v is Turn { if (result === void 0) throw new TypeError(`Invalid Oid: ${_.stringify(v)}`);
return ( return result;
_.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 asTurn(v: any): Turn { export function toOid(v: _val): undefined | Oid {
if (!isTurn(v)) {throw new TypeError(`Invalid Turn: ${_.stringify(v)}`);} else {return v;}; 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 { export function fromOid(_v: Oid): _val {return _v;}
let result;
if (d.openSequence()) { export function asTurn(v: _val): Turn {
let _tmp11: any; let result = toTurn(v);
{ if (result === void 0) throw new TypeError(`Invalid Turn: ${_.stringify(v)}`);
let vN: Array<[Oid, Event]> | undefined = []; return result;
while (!d.closeCompound()) { }
let _tmp12, _tmp13: any;
_tmp11 = void 0; export function toTurn(v: _val): undefined | Turn {
if (d.openSequence()) { let result: undefined | Turn;
_tmp12 = decodeOid(d); if (_.Array.isArray(v)) {
if (_tmp12 !== void 0) { let _tmp0: (Array<TurnEvent>) | undefined;
_tmp13 = decodeEvent(d); _tmp0 = [];
if (_tmp13 !== void 0) {if (d.closeCompound()) _tmp11 = [_tmp12, _tmp13];}; for (const _tmp1 of v) {
}; let _tmp2: (TurnEvent) | undefined;
}; _tmp2 = toTurnEvent(_tmp1);
if (_tmp11 === void 0) {vN = void 0; break;}; if (_tmp2 !== void 0) {_tmp0.push(_tmp2); continue;};
vN.push(_tmp11); _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; return result;
} }
export function isAssert(v: any): v is Assert { export function fromAssert(_v: Assert): _val {
return ( return _.Record($assert, [fromAssertion(_v["assertion"]), fromHandle(_v["handle"])]);
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
_.is(v.label, $assert) &&
((v.length === 2) && isAssertion(v[0]) && isHandle(v[1]))
);
} }
export function asAssert(v: any): Assert { export function asRetract(v: _val): Retract {
if (!isAssert(v)) {throw new TypeError(`Invalid Assert: ${_.stringify(v)}`);} else {return v;}; 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 { export function toRetract(v: _val): undefined | Retract {
let result; let result: undefined | Retract;
if (d.openRecord()) { if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp14: any; let _tmp0: (null) | undefined;
_tmp14 = _.asLiteral(d.nextSymbol(), $assert); _tmp0 = _.is(v.label, $retract) ? null : void 0;
if (_tmp14 !== void 0) { if (_tmp0 !== void 0) {
let _tmp15, _tmp16, _tmp17: any; let _tmp1: (Handle) | undefined;
_tmp16 = decodeAssertion(d); _tmp1 = toHandle(v[0]);
if (_tmp16 !== void 0) { if (_tmp1 !== void 0) {result = {"handle": _tmp1};};
_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);
}; };
}; };
return result; return result;
} }
export function isRetract(v: any): v is Retract { export function fromRetract(_v: Retract): _val {return _.Record($retract, [fromHandle(_v["handle"])]);}
return (
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && export function asMessage(v: _val): Message {
_.is(v.label, $retract) && let result = toMessage(v);
((v.length === 1) && isHandle(v[0])) if (result === void 0) throw new TypeError(`Invalid Message: ${_.stringify(v)}`);
); return result;
} }
export function asRetract(v: any): Retract { export function toMessage(v: _val): undefined | Message {
if (!isRetract(v)) {throw new TypeError(`Invalid Retract: ${_.stringify(v)}`);} else {return v;}; let result: undefined | Message;
} if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp0: (null) | undefined;
export function decodeRetract(d: _.TypedDecoder<_ptr>): Retract | undefined { _tmp0 = _.is(v.label, $message) ? null : void 0;
let result; if (_tmp0 !== void 0) {
if (d.openRecord()) { let _tmp1: (Assertion) | undefined;
let _tmp18: any; _tmp1 = toAssertion(v[0]);
_tmp18 = _.asLiteral(d.nextSymbol(), $retract); if (_tmp1 !== void 0) {result = {"body": _tmp1};};
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);
}; };
}; };
return result; return result;
} }
export function isMessage(v: any): v is Message { export function fromMessage(_v: Message): _val {return _.Record($message, [fromAssertion(_v["body"])]);}
return (
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) && export function asSync(v: _val): Sync {
_.is(v.label, $message) && let result = toSync(v);
((v.length === 1) && isAssertion(v[0])) if (result === void 0) throw new TypeError(`Invalid Sync: ${_.stringify(v)}`);
); return result;
} }
export function asMessage(v: any): Message { export function toSync(v: _val): undefined | Sync {
if (!isMessage(v)) {throw new TypeError(`Invalid Message: ${_.stringify(v)}`);} else {return v;}; let result: undefined | Sync;
} if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp0: (null) | undefined;
export function decodeMessage(d: _.TypedDecoder<_ptr>): Message | undefined { _tmp0 = _.is(v.label, $sync) ? null : void 0;
let result; if (_tmp0 !== void 0) {
if (d.openRecord()) { let _tmp1: (_ptr) | undefined;
let _tmp21: any; _tmp1 = _toPtr(v[0]);
_tmp21 = _.asLiteral(d.nextSymbol(), $message); if (_tmp1 !== void 0) {result = {"peer": _tmp1};};
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);
}; };
}; };
return result; return result;
} }
export function isSync(v: any): v is Sync { export function fromSync(_v: Sync): _val {return _.Record($sync, [_v["peer"]]);}
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;};

File diff suppressed because it is too large Load Diff

View File

@ -2,44 +2,40 @@ import * as _ from "@preserves/core";
export const $Instance = Symbol.for("Instance"); 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 _ptr = never;
export type _val = _.Value<_ptr>; export type _val = _.Value<_ptr>;
export type Instance = {"name": string, "argument": _val};
export function isInstance(v: any): v is Instance {
return ( export const _toPtr = () => { throw new _.DecodeError("Pointers forbidden"); };
_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v) &&
_.is(v.label, $Instance) && export function Instance(name: string, argument: _val): Instance {return {name, argument};}
((v.length === 2) && typeof v[0] === 'string' && true)
); 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 { export function toInstance(v: _val): undefined | Instance {
if (!isInstance(v)) {throw new TypeError(`Invalid Instance: ${_.stringify(v)}`);} else {return v;}; let result: undefined | Instance;
} if (_.Record.isRecord<_val, _.Tuple<_val>, _ptr>(v)) {
let _tmp0: (null) | undefined;
export function decodeInstance(d: _.TypedDecoder<_ptr>): Instance | undefined { _tmp0 = _.is(v.label, $Instance) ? null : void 0;
let result;
if (d.openRecord()) {
let _tmp0: any;
_tmp0 = _.asLiteral(d.nextSymbol(), $Instance);
if (_tmp0 !== void 0) { if (_tmp0 !== void 0) {
let _tmp1, _tmp2, _tmp3: any; let _tmp1: (string) | undefined;
_tmp2 = d.nextString(); _tmp1 = typeof v[0] === 'string' ? v[0] : void 0;
if (_tmp2 !== void 0) { if (_tmp1 !== void 0) {
_tmp3 = d.next(); let _tmp2: (_val) | undefined;
if (_tmp3 !== void 0) {if (d.closeCompound()) _tmp1 = [_tmp2, _tmp3];}; _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; return result;
} }
export const _decodePtr = () => { throw new _.DecodeError("Pointers forbidden"); }; export function fromInstance(_v: Instance): _val {return _.Record($Instance, [_v["name"], _v["argument"]]);}

View File

@ -1,12 +1,13 @@
import { Actor, Assertion, Ref, Turn } from './actor.js'; import { Actor, Assertion, Ref, Turn } from './actor.js';
import { Dictionary, Record } from '@preserves/core'; import { Dictionary, Record } from '@preserves/core';
import { Dataspace, Observe } from './dataspace.js'; import { Dataspace } from './dataspace.js';
import { Worker } from 'worker_threads'; import { Worker } from 'worker_threads';
import { Relay, spawnRelay } from './relay.js'; import { Relay, spawnRelay } from './relay.js';
import { attenuate, CRec, Lit, Pattern, PCompound, rfilter } from './rewrite.js';
import path from 'path'; 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}>()( const Instance = Record.makeConstructor<{moduleName: string, arg: Assertion}>()(
Symbol.for('Instance'), ['moduleName', 'arg']); Symbol.for('Instance'), ['moduleName', 'arg']);
@ -56,30 +57,25 @@ Turn.for(new Actor(), async (t: Turn) => {
const ds_for_box = attenuate( const ds_for_box = attenuate(
ds, ds,
rfilter(PCompound(CRec(BoxState.constructorInfo.label, rfilter(
BoxState.constructorInfo.arity), Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($BoxState, 1)), new Dictionary())),
new Dictionary()), Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($Observe, 2)),
PCompound(CRec(Observe.constructorInfo.label, new Dictionary<Ref, Pattern>([
Observe.constructorInfo.arity), [0, Pattern.Lit(Lit($SetBox))]])))));
new Dictionary<Pattern, Ref>([
[0, Lit(SetBox.constructorInfo.label)]]))));
const ds_for_client = attenuate( const ds_for_client = attenuate(
ds_unproxied, ds_unproxied,
rfilter(PCompound(CRec(SetBox.constructorInfo.label, rfilter(
SetBox.constructorInfo.arity), Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($SetBox, 1)), new Dictionary())),
new Dictionary()), Pattern.PCompound(PCompound(ConstructorSpec.CRec(CRec($Observe, 2)),
PCompound(CRec(Observe.constructorInfo.label, new Dictionary<Ref, Pattern>([
Observe.constructorInfo.arity), [0, Pattern.Lit(Lit($BoxState))]])))));
new Dictionary<Pattern, Ref>([
[0, Lit(BoxState.constructorInfo.label)]]))));
const boxpath = path.join(__dirname, 'box.js'); const boxpath = path.join(__dirname, 'box.js');
const clientpath = path.join(__dirname, 'client.js'); const clientpath = path.join(__dirname, 'client.js');
// spawnModule(t, boxpath, [ds_for_box, 500000, 25000]); spawnModule(t, boxpath, [ds_for_box, 500000, 25000]);
spawnWorker(t, boxpath, [ds_for_box, 50000, 2500]); // spawnWorker(t, boxpath, [ds_for_box, 50000, 2500]);
spawnModule(t, clientpath, ds_for_client); spawnModule(t, clientpath, ds_for_client);
// spawnWorker(t, clientpath, ds_for_client); // spawnWorker(t, clientpath, ds_for_client);

View File

@ -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 * as IO from './gen/protocol.js';
import { decodeRef, Ref } from './actor.js'; import { Assertion, Ref } from './actor.js';
import { TypedDecoder } from '@preserves/core'; import { mapPointers } from '@preserves/core';
import { pointerNotAllowed } from './sturdy.js';
export type WireSymbol = { oid: IO.Oid, ref: Ref, count: number }; 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 }; return { loc: 'your', oid, attenuation };
} }
export function decodeWireRef(d: TypedDecoder<WireRef>): WireRef | undefined { export function toWireRef(v: IO._val): WireRef | undefined {
if (d.openSequence()) { if (Array.isArray(v) && v.length >= 2) {
switch (d.nextSignedInteger()) { switch (v[0]) {
case 0: { case 0: {
const oid = d.nextSignedInteger(); const oid = v[1];
if (oid !== void 0) { if (typeof oid === 'number') return myRef(oid);
if (d.closeCompound()) {
return myRef(oid);
}
}
break; break;
} }
case 1: { case 1: {
const oid = d.nextSignedInteger(); const oid = v[1];
if (oid !== void 0) { if (typeof oid === 'number') {
const attenuation = d.withPointerDecoder(decodeRef, d => decodeAttenuation(d)); const attenuation = toAttenuation(mapPointers(v.slice(2), pointerNotAllowed) as Array<Assertion>);
if (attenuation !== void 0) { if (attenuation !== void 0) return yourRef(oid, attenuation);
if (d.closeCompound()) {
return yourRef(oid, attenuation);
}
}
} }
break; break;
} }

View File

@ -1,10 +1,10 @@
import { Actor, Assertion, Entity, Handle, Ref, Turn } from './actor.js'; import { Actor, Assertion, Entity, Handle, Ref, Turn } from './actor.js';
import { BytesLike, canonicalString, Decoder, encode, FlexMap, IdentityMap, mapPointers, underlying, Value } from '@preserves/core'; import { BytesLike, canonicalString, Decoder, encode, FlexMap, IdentityMap, mapPointers, underlying, Value } from '@preserves/core';
import * as IO from './gen/protocol.js'; 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 { queueTask } from './task.js';
import { attenuate } from './rewrite.js'; import { attenuate } from './rewrite.js';
import { Attenuation } from './gen/sturdy.js'; import { Attenuation, fromAttenuation } from './gen/sturdy.js';
import { pointerNotAllowed } from './sturdy.js'; import { pointerNotAllowed } from './sturdy.js';
export class SyncPeerEntity implements Entity { export class SyncPeerEntity implements Entity {
@ -52,16 +52,16 @@ export class RelayEntity implements Entity {
} }
assert(_turn: Turn, assertion: Assertion, handle: Handle): void { 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 { retract(_turn: Turn, handle: Handle): void {
this.relay.deregister(handle); this.relay.deregister(handle);
this.send(IO.Retract(handle)); this.send(IO.Event.Retract(IO.Retract(handle)));
} }
message(_turn: Turn, body: Assertion): void { 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 { sync(turn: Turn, peer: Ref): void {
@ -69,7 +69,7 @@ export class RelayEntity implements Entity {
const exported: Array<WireSymbol> = []; const exported: Array<WireSymbol> = [];
const ior = this.relay.rewriteRefOut(turn.ref(peerEntity), false, exported); const ior = this.relay.rewriteRefOut(turn.ref(peerEntity), false, exported);
peerEntity.e = exported[0]; 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; trustPeer: boolean;
readonly decoder = new Decoder(void 0, { includeAnnotations: false }) readonly decoder = new Decoder(void 0, { includeAnnotations: false })
.replacePointerDecoder(decodeWireRef); .replacePointerDecoder<WireRef>(d => toWireRef(d.next()));
constructor(t: Turn, options: RelayOptions) { constructor(t: Turn, options: RelayOptions) {
this.actor = t.actor; this.actor = t.actor;
@ -227,20 +227,20 @@ export class Relay {
if (this.pendingTurn.length === 0) { if (this.pendingTurn.length === 0) {
queueTask(() => { queueTask(() => {
if (this.debug) console.log('OUT', this.pendingTurn.asPreservesText()); 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, canonical: true,
encodePointer: (e, n) => { encodePointer: (e, n) => {
switch (n.loc) { switch (n.loc) {
case 'mine': return e.push([0, n.oid]); case 'mine': return e.push([0, n.oid]);
case 'your': return e.push([1, n.oid, ... mapPointers<Ref, IO._ptr>( 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 = [];
}); });
} }
this.pendingTurn.push([remoteOid, m]); this.pendingTurn.push(IO.TurnEvent(remoteOid, m));
} }
lookupLocal(localOid: IO.Oid): Ref { lookupLocal(localOid: IO.Oid): Ref {
@ -251,14 +251,13 @@ export class Relay {
Turn.for(this.actor, t => { Turn.for(this.actor, t => {
this.decoder.write(bs); this.decoder.write(bs);
while (true) { while (true) {
const wireTurn = this.decoder.shortGuard( const rawTurn = this.decoder.try_next();
() => IO.decodeTurn(this.decoder) ?? false, if (rawTurn === void 0) break;
() => void 0); const wireTurn = IO.toTurn(rawTurn);
if (wireTurn === void 0) break; if (wireTurn === void 0) throw new Error("Bad IO.Turn");
if (wireTurn === false) throw new Error("Bad IO.Turn");
if (this.debug) console.log('IN', wireTurn.asPreservesText()); if (this.debug) console.log('IN', wireTurn.asPreservesText());
wireTurn.forEach(v => { wireTurn.forEach(v => {
const [localOid, m] = v; const { oid: localOid, event: m } = v;
this.handle(t, this.lookupLocal(localOid), m); this.handle(t, this.lookupLocal(localOid), m);
}); });
} }
@ -266,17 +265,17 @@ export class Relay {
} }
handle(t: Turn, r: Ref, m: IO.Event) { handle(t: Turn, r: Ref, m: IO.Event) {
switch (m.label) { switch (m._variant) {
case IO.$assert: { case 'Assert': {
const [a, imported] = this.rewriteIn(t, IO.Assert._.assertion(m)); const [a, imported] = this.rewriteIn(t, m.value.assertion);
this.inboundAssertions.set(IO.Assert._.handle(m), { this.inboundAssertions.set(m.value.handle, {
localHandle: t.assert(r, a), localHandle: t.assert(r, a),
imported, imported,
}); });
break; break;
} }
case IO.$retract: { case 'Retract': {
const remoteHandle = IO.Retract._.handle(m); const remoteHandle = m.value.handle;
const h = this.inboundAssertions.get(remoteHandle); const h = this.inboundAssertions.get(remoteHandle);
if (h === void 0) throw new Error(`Peer retracted invalid handle ${remoteHandle}`); if (h === void 0) throw new Error(`Peer retracted invalid handle ${remoteHandle}`);
this.inboundAssertions.delete(remoteHandle); this.inboundAssertions.delete(remoteHandle);
@ -284,15 +283,15 @@ export class Relay {
t.retract(h.localHandle); t.retract(h.localHandle);
break; break;
} }
case IO.$message: { case 'Message': {
const [a, imported] = this.rewriteIn(t, IO.Message._.body(m)); const [a, imported] = this.rewriteIn(t, m.value.body);
if (imported.length > 0) throw new Error("Cannot receive transient reference"); if (imported.length > 0) throw new Error("Cannot receive transient reference");
t.message(r, a); t.message(r, a);
break; break;
} }
case IO.$sync: { case 'Sync': {
const imported: Array<WireSymbol> = []; 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.sync(r).then(t => {
t.message(k, true); t.message(k, true);
imported.forEach(e => this.imported.drop(e)); imported.forEach(e => this.imported.drop(e));

View File

@ -1,34 +1,7 @@
import type { Assertion, Handle, Ref, Turn } from "./actor.js"; import type { Assertion, Handle, Ref, Turn } from "./actor.js";
import { Dictionary, IdentityMap, is, Record, Tuple } from "@preserves/core"; import { Dictionary, IdentityMap, is, Record, Tuple } from "@preserves/core";
import { import { Alts, Attenuation, Caveat, PBind, Pattern, Rewrite, TRef, Template } from './gen/sturdy.js';
$__,
$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';
export * from './gen/sturdy.js'; export * from './gen/sturdy.js';
export type Bindings = { [name: string]: Assertion }; export type Bindings = { [name: string]: Assertion };
@ -37,52 +10,52 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
let bindings: Bindings = {}; let bindings: Bindings = {};
function walk(p: Pattern, v: Assertion): boolean { function walk(p: Pattern, v: Assertion): boolean {
switch (p.label) { switch (p._variant) {
case $__: case 'PDiscard':
return true; return true;
case $bind: case 'PBind':
if (walk(PBind._.pattern(p), v)) { if (walk(p.value.pattern, v)) {
bindings[PBind._.name(p).asPreservesText()] = v; bindings[p.value.name.asPreservesText()] = v;
return true; return true;
} }
return false; return false;
case $and: case 'PAnd':
for (const pp of PAnd._.patterns(p)) { for (const pp of p.value.patterns) {
if (!walk(pp, v)) return false; if (!walk(pp, v)) return false;
} }
return true; return true;
case $not: { case 'PNot': {
const savedBindings = bindings; const savedBindings = bindings;
bindings = {}; bindings = {};
const result = !walk(PNot._.pattern(p), v) const result = !walk(p.value.pattern, v)
bindings = savedBindings; bindings = savedBindings;
return result; return result;
} }
case $lit: case 'Lit':
return is(Lit._.value(p), v); return is(p.value.value, v);
case $compound: { case 'PCompound': {
const ctor = PCompound._.ctor(p); const ctor = p.value.ctor;
const members = PCompound._.members(p); const members = p.value.members;
switch (ctor.label) { switch (ctor._variant) {
case $rec: case 'CRec':
if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(v)) return false; if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(v)) return false;
if (!is(CRec._.label(ctor), v.label)) return false; if (!is(ctor.value.label, v.label)) return false;
if (CRec._.arity(ctor) !== v.length) return false; if (ctor.value.arity !== v.length) return false;
for (const [key, pp] of members) { for (const [key, pp] of members) {
if (typeof key !== 'number') return false; if (typeof key !== 'number') return false;
if (!walk(pp, v[key])) return false; if (!walk(pp, v[key])) return false;
} }
return true; return true;
case $arr: case 'CArr':
if (!Array.isArray(v)) return false; if (!Array.isArray(v)) return false;
if ('label' in 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) { for (const [key, pp] of members) {
if (typeof key !== 'number') return false; if (typeof key !== 'number') return false;
if (!walk(pp, v[key])) return false; if (!walk(pp, v[key])) return false;
} }
return true; return true;
case $dict: case 'CDict':
if (!Dictionary.isDictionary<Assertion, Ref>(v)) return false; if (!Dictionary.isDictionary<Assertion, Ref>(v)) return false;
for (const [key, pp] of members) { for (const [key, pp] of members) {
const vv = v.get(key as Assertion); 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 { export function instantiate(t: Template, b: Bindings): Assertion {
function walk(t: Template): Assertion { function walk(t: Template): Assertion {
switch (t.label) { switch (t._variant) {
case $ref: { case 'TRef': {
const n = TRef._.name(t).asPreservesText() const n = t.value.name.asPreservesText()
const v = b[n]; const v = b[n];
if (v === void 0) throw new Error(`Unbound reference: ${n}`); if (v === void 0) throw new Error(`Unbound reference: ${n}`);
return v; return v;
} }
case $lit: case 'Lit':
return Lit._.value(t) as Assertion; return t.value.value as Assertion;
case $compound: { case 'TCompound': {
const ctor = TCompound._.ctor(t); const ctor = t.value.ctor;
const members = TCompound._.members(t); const members = t.value.members;
switch (ctor.label) { switch (ctor._variant) {
case $rec: { case 'CRec': {
const v = Record( const v = [] as unknown as Record<Assertion, Assertion[], Ref>;
CRec._.label(ctor) as Assertion, v.length = ctor.value.arity;
[] as Assertion[], v.label = ctor.value.label;
);
v.length = CRec._.arity(ctor);
for (const [key, tt] of members) { for (const [key, tt] of members) {
v[key as number] = walk(tt); v[key as number] = walk(tt);
} }
return v; return v;
} }
case $arr: { case 'CArr': {
const v = []; const v = [];
v.length = CArr._.arity(ctor); v.length = ctor.value.arity;
for (const [key, tt] of members) { for (const [key, tt] of members) {
v[key as number] = walk(tt); v[key as number] = walk(tt);
} }
return v; return v;
} }
case $dict: { case 'CDict': {
const v = new Dictionary<Assertion, Ref>(); const v = new Dictionary<Ref, Assertion>();
for (const [key, tt] of members) { for (const [key, tt] of members) {
v.set(key as Assertion, walk(tt)); 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 { 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; 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 { export function examineAlternatives(cav: Caveat, v: Assertion): Assertion | null {
if (cav.label === $or) { if (cav._variant === 'Alts') {
for (const r of Alts._.alternatives(cav)) { for (const r of cav.value.alternatives) {
const w = rewrite(r, v); const w = rewrite(r, v);
if (w !== null) return w; if (w !== null) return w;
} }
return null; return null;
} else { } 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'); const _a = Symbol.for('a');
export function rfilter(... patterns: Pattern[]): Caveat { export function rfilter(... patterns: Pattern[]): Caveat {
const ps = patterns.map(p => Rewrite(PBind(_a, p), TRef(_a))); const ps = patterns.map(p => Rewrite(Pattern.PBind(PBind(_a, p)), Template.TRef(TRef(_a))));
return ps.length === 1 ? ps[0] : Alts(ps); return ps.length === 1 ? Caveat.Rewrite(ps[0]) : Caveat.Alts(Alts(ps));
} }
export function attenuate(ref: Ref, ... a: Attenuation): Ref { export function attenuate(ref: Ref, ... a: Attenuation): Ref {

View File

@ -1,7 +1,7 @@
import { Actor, Ref, Turn } from "./actor"; import { Actor, Ref, Turn } from "./actor";
import { Relay, spawnRelay } from "./relay"; import { Relay, spawnRelay } from "./relay";
import { sturdyDecode } from "./sturdy"; import { sturdyDecode } from "./sturdy";
import { Resolve, asSturdyRef } from "./gen/sturdy"; import { Resolve, asSturdyRef, fromResolve } from "./gen/sturdy";
import * as net from 'net'; import * as net from 'net';
import { Bytes } from "@preserves/core"; import { Bytes } from "@preserves/core";
@ -29,11 +29,11 @@ const socket = net.createConnection({ port: 5999, host: 'localhost' }, () => {
// debug: true, // debug: true,
}).then(gatekeeper => import(moduleName).then(m => t.freshen(t => { }).then(gatekeeper => import(moduleName).then(m => t.freshen(t => {
t.assert(shutdownRef, true); t.assert(shutdownRef, true);
t.assert(gatekeeper, Resolve(asSturdyRef(cap), t.ref({ t.assert(gatekeeper, fromResolve(Resolve(asSturdyRef(cap), t.ref({
assert(t, ds) { assert(t, ds) {
m.default(t, ds); m.default(t, ds);
} }
}))); }))));
}))); })));
}); });
}); });

View File

@ -3,16 +3,16 @@ import { Dataspace } from './dataspace.js';
import { Relay, spawnRelay } from './relay.js'; import { Relay, spawnRelay } from './relay.js';
import * as net from 'net'; 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 { KEY_LENGTH } from './cryptography.js';
import { attenuate } from './rewrite.js'; import { attenuate } from './rewrite.js';
import { Bytes, IdentityMap } from '@preserves/core'; 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); const secretKey = new Bytes(KEY_LENGTH);
mint('syndicate', secretKey).then(v => { mint('syndicate', secretKey).then(v => {
console.log(v.asPreservesText()); console.log(v.asPreservesText());
console.log(sturdyEncode(v).toHex()); console.log(sturdyEncode(fromSturdyRef(v)).toHex());
}); });
Turn.for(new Actor(), t => { Turn.for(new Actor(), t => {
@ -32,19 +32,20 @@ Turn.for(new Actor(), t => {
}, },
initialRef: t.ref({ initialRef: t.ref({
handleMap: new IdentityMap<Handle, Handle>(), handleMap: new IdentityMap<Handle, Handle>(),
async assert(t, a, h) { async assert(t, a0, h) {
if (!isResolve(a)) return; const a = toResolve(a0);
const r = Resolve._.sturdyref(a); if (a === void 0) return;
const r = a.sturdyref;
if (!await validate(r, secretKey)) { if (!await validate(r, secretKey)) {
console.warn(`Invalid SturdyRef: ${r.asPreservesText()}`); console.warn(`Invalid SturdyRef: ${r.asPreservesText()}`);
return; return;
} }
const cavs: Attenuation = []; const cavs: Attenuation = [];
SturdyRef._.caveatChain(r).forEach(cs => cavs.push(... cs)); r.caveatChain.forEach(cs => cavs.push(... cs));
const attenuated_ds = attenuate(ds, ... cavs); const attenuated_ds = attenuate(ds, ... cavs);
t.freshen(t => this.handleMap.set( t.freshen(t => this.handleMap.set(
h, h,
t.assert(Resolve._.observer(a), attenuated_ds))); t.assert(a.observer, attenuated_ds)));
}, },
retract(t, h) { retract(t, h) {
t.retract(this.handleMap.get(h)); t.retract(this.handleMap.get(h));

View File

@ -1,32 +1,34 @@
import { newKey } from './cryptography.js'; 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 * as RW from './rewrite.js';
import { Bytes, Dictionary } from '@preserves/core'; import { Bytes, Dictionary } from '@preserves/core';
import { Ref } from 'actor.js'; import { Ref } from 'actor.js';
async function main() { async function main() {
const m1 = await mint('hello world', new Bytes(KEY_LENGTH)); const m1 = await mint('hello world', new Bytes(KEY_LENGTH));
console.log(m1.asPreservesText()); console.log(m1);
const m2 = await attenuate(m1, Rewrite( const m2 = await attenuate(m1, Caveat.Rewrite(Rewrite(
RW.PBind(Symbol.for('a'), RW.Pattern.PBind(RW.PBind(
RW.PCompound(RW.CRec(Symbol.for('says'), 2), Symbol.for('a'),
new Dictionary<RW.Pattern, Ref>([ RW.Pattern.PCompound(RW.PCompound(
[0, RW.Lit('Tony')]]))), RW.ConstructorSpec.CRec(RW.CRec(Symbol.for('says'), 2)),
RW.TRef(Symbol.for('a')))); new Dictionary<Ref, RW.Pattern>([
console.log(m2.asPreservesText()); [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(m1, new Bytes(KEY_LENGTH)));
console.log('should be true:', await validate(m2, 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))); 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'; m2.oid = 'hello world2';
console.log(m2.asPreservesText()); console.log(m2);
console.log('should be false:', await validate(m2, new Bytes(KEY_LENGTH))); console.log('should be false:', await validate(m2, new Bytes(KEY_LENGTH)));
m2[0] = 'hello world'; m2.oid = 'hello world';
console.log(m2.asPreservesText()); console.log(m2);
console.log('should be true:', await validate(m2, new Bytes(KEY_LENGTH))); console.log('should be true:', await validate(m2, new Bytes(KEY_LENGTH)));
console.log('should be false:', await validate(m2, await newKey())); console.log('should be false:', await validate(m2, await newKey()));
console.log((await newKey()).asPreservesText()); console.log((await newKey()).asPreservesText());
console.log((await newKey()).asPreservesText()); console.log((await newKey()).asPreservesText());
console.log(sturdyEncode(m2).asPreservesText()); console.log(sturdyEncode(RW.fromSturdyRef(m2)).asPreservesText());
} }
main(); main();

View File

@ -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> { export async function attenuate(r: S.SturdyRef, ... a: S.Attenuation): Promise<S.SturdyRef> {
return S.SturdyRef( return S.SturdyRef(
S.SturdyRef._.oid(r), r.oid,
[... S.SturdyRef._.caveatChain(r), a], [... r.caveatChain, a],
await mac(S.SturdyRef._.sig(r), sturdyEncode(a)) await mac(r.sig, sturdyEncode(S.fromAttenuation(a)))
); );
} }
export async function validate(r: S.SturdyRef, secretKey: Bytes): Promise<boolean> { export async function validate(r: S.SturdyRef, secretKey: Bytes): Promise<boolean> {
const sig = await S.SturdyRef._.caveatChain(r).reduce( const sig = await r.caveatChain.reduce(
async (sig, a) => mac(await sig, sturdyEncode(a)), async (sig, a) => mac(await sig, sturdyEncode(S.fromAttenuation(a))),
mac(secretKey, sturdyEncode(S.SturdyRef._.oid(r)))); mac(secretKey, sturdyEncode(r.oid)));
return is(sig, S.SturdyRef._.sig(r)); return is(sig, r.sig);
} }

View File

@ -1,10 +1,13 @@
import { Bytes, Reader } from '@preserves/core'; 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 [ base, pat ] = process.argv.slice(2);
const baseCap = sturdyDecode(Bytes.fromHex(base ?? '')) as SturdyRef; const baseCap = toSturdyRef(sturdyDecode(Bytes.fromHex(base ?? '')));
const cs = new Reader(pat).next() as Array<Caveat>; 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 => { attenuate(baseCap, ... cs).then(derived => {
console.log(derived.asPreservesText()); console.log(derived.asPreservesText());
console.log(sturdyEncode(derived).toHex()); console.log(sturdyEncode(fromSturdyRef(derived)).toHex());
}); });