Switch to directly-represented embedded values

This commit is contained in:
Tony Garnock-Jones 2024-03-12 21:38:49 +01:00
parent f5ed511c4e
commit 9521fc3dcc
7 changed files with 43 additions and 48 deletions

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { IdentitySet, Value, embeddedId, is, fromJS, stringify, Dictionary, KeyedSet, Tuple } from '@preserves/core';
import { IdentitySet, Value, embeddedId, is, fromJS, stringify, Dictionary, KeyedSet, Tuple, Embeddable } from '@preserves/core';
import { Cell, Field, Graph } from './dataflow.js';
import { Caveat, runRewrites } from './rewrite.js';
import { ActorSpace } from './space.js';
@ -23,7 +23,11 @@ export type ExitReason = null | { ok: true } | { ok: false, err: unknown };
export type LocalAction = () => void;
export type DetailedAction<T = AnyValue> = LocalAction & { detail: T };
export type Assertable = Assertion | { __as_preserve__: <T>() => Value<T> } | { __as_preserve__: () => Assertion };
export type Assertable =
| Assertion
| { __as_preserve__: <T extends Embeddable>() => Value<T> }
| { __as_preserve__: () => Assertion }
;
export interface Entity {
assert(assertion: Assertion, handle: Handle): void;
@ -35,13 +39,7 @@ export interface Entity {
export type Cap = Ref;
export interface Ref {
readonly relay: Facet;
readonly target: Partial<Entity>;
readonly attenuation?: Caveat[];
}
export class RefImpl implements Ref {
export class Ref {
readonly relay: Facet;
readonly target: Partial<Entity>;
readonly attenuation?: Caveat[];
@ -64,6 +62,10 @@ export class RefImpl implements Ref {
if ('sync' in this.target) sig = sig + 'S';
return `${this.relay.idChain()}<${sig}>${entityRepr}`;
}
static __from_preserve__(v: AnyValue): undefined | Ref {
return typeof v === 'object' && 'relay' in v ? v : void 0;
}
}
//---------------------------------------------------------------------------
@ -351,7 +353,7 @@ export class Turn {
}
ref<T extends Partial<Entity>>(e: T): Ref {
return new RefImpl(this.activeFacet, e);
return new Ref(this.activeFacet, e);
}
facet(bootProc: LocalAction): Facet {

View File

@ -3,7 +3,7 @@
// Bags and Deltas (which are Bags where item-counts can be negative).
import { Value, KeyedDictionary, KeyedSet } from '@preserves/core';
import { Value, KeyedDictionary, KeyedSet, Embeddable } from '@preserves/core';
export enum ChangeDescription {
PRESENT_TO_ABSENT = -1,
@ -12,7 +12,7 @@ export enum ChangeDescription {
PRESENT_TO_PRESENT = 2,
}
export class Bag<T, V extends Value<T> = Value<T>> {
export class Bag<T extends Embeddable, V extends Value<T> = Value<T>> {
_items: KeyedDictionary<V, number, T>;
constructor(s?: KeyedSet<V, T>) {

View File

@ -2,7 +2,7 @@
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Turn } from "./actor.js";
import { Bytes, Dictionary, DoubleFloat, embed, IdentityMap, is, isEmbedded, Record, Tuple, stringify } from "@preserves/core";
import { Bytes, Dictionary, DoubleFloat, IdentityMap, is, isEmbedded, Record, Tuple, stringify } from "@preserves/core";
import type { Assertion, Handle, Ref } from "./actor.js";
import type { SturdyValue } from "../transport/sturdy.js";
@ -113,8 +113,7 @@ export function instantiate(t: Template, b: Bindings): Assertion {
if (!isEmbedded(v)) {
throw new Error(`Attempt to attenuate non-capability: ${stringify(v)}`);
}
const r = v.embeddedValue;
return embed(attenuate(r, ... t.value.attenuation));
return attenuate(v, ... t.value.attenuation);
}
case 'TRef': {
const n = t.value.binding;

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Set, Dictionary, KeyedDictionary, IdentitySet, stringify, Value } from '@preserves/core';
import { Set, Dictionary, KeyedDictionary, IdentitySet, stringify, Value, Embeddable } from '@preserves/core';
import { AnyValue, Assertion, Ref } from './actor.js';
import { Bag, ChangeDescription } from './bag.js';
import * as Stack from './stack.js';
@ -142,13 +142,13 @@ export class Index<T> {
}
}
function dumpBag<T, V extends Value<T>>(b: Bag<T, V>, indent: string) {
function dumpBag<T extends Embeddable, V extends Value<T>>(b: Bag<T, V>, indent: string) {
for (const [v, count] of b.entries()) {
console.log(indent + stringify(v) + ' = ' + count);
}
}
function dumpSet<V>(s: Set<V>, indent: string) {
function dumpSet<V extends Embeddable>(s: Set<V>, indent: string) {
s.forEach(v => console.log(indent + stringify(v)));
}

View File

@ -2,7 +2,7 @@
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { Actor, Assertion, Entity, Facet, Handle, Ref, Turn } from '../runtime/actor.js';
import { BytesLike, Decoder, Dictionary, embed, encode, IdentityMap, mapEmbeddeds, stringify, underlying, Value } from '@preserves/core';
import { BytesLike, Decoder, Dictionary, encode, IdentityMap, mapEmbeddeds, stringify, underlying, Value } from '@preserves/core';
import * as IO from '../gen/protocol.js';
import { wireRefEmbeddedType } from './protocol.js';
import { attenuate } from '../runtime/rewrite.js';
@ -193,7 +193,7 @@ export class Relay {
register(targetRemoteOid: IO.Oid | null, assertion: Assertion, handle: Handle | null): Value<WireRef> {
const transient = (handle === null);
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(assertion, r => embed(this.rewriteRefOut(r, transient, pins)));
const rewritten = mapEmbeddeds(assertion, r => this.rewriteRefOut(r, transient, pins));
if (handle !== null) {
if (targetRemoteOid !== null /* belt and suspenders */) {
this.grabImportedOid(targetRemoteOid, pins);
@ -316,7 +316,7 @@ export class Relay {
rewriteIn(a: Value<WireRef>): [Assertion, Array<WireSymbol>]
{
const pins: Array<WireSymbol> = [];
const rewritten = mapEmbeddeds(a, r => embed(this.rewriteRefIn(r, pins)));
const rewritten = mapEmbeddeds(a, r => this.rewriteRefIn(r, pins));
return [rewritten, pins];
}

View File

@ -1,7 +1,7 @@
/// SPDX-License-Identifier: GPL-3.0-or-later
/// SPDX-FileCopyrightText: Copyright © 2016-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { randomId, Observe, FlexMap, embed, Embedded, Ref, Turn, AnyValue, Dataspace } from "@syndicate-lang/core";
import { randomId, Observe, FlexMap, Ref, Turn, AnyValue, Dataspace } from "@syndicate-lang/core";
import { QuasiValue as Q } from "@syndicate-lang/core";
import * as P from "./protocol";
@ -46,7 +46,7 @@ export function spawnGlobalEventFactory(ds: Ref) {
function handler(event: Event) {
facet.turn(() => {
send message P.GlobalEvent(selector, eventType, embed(create ({ data: event })));
send message P.GlobalEvent(selector, eventType, create ({ data: event }));
});
return dealWithPreventDefault(eventType, event);
}
@ -78,7 +78,7 @@ export function spawnWindowEventFactory(ds: Ref) {
let handler = (event: Event) => {
facet.turn(() => {
send message P.WindowEvent(eventType, embed(create ({ data: event })));
send message P.WindowEvent(eventType, create ({ data: event }));
});
return dealWithPreventDefault(eventType, event);
};
@ -149,7 +149,7 @@ function spawnUIFragmentFactory(ds: Ref) {
removeNodes();
selector = newSelector;
html = (newHtml as Embedded<Ref>).embeddedValue.target.data as ChildNode[];
html = (newHtml as Ref).target.data as ChildNode[];
orderBy = newOrderBy;
anchorNodes = (selector !== null) ? selectorMatch(document.body, selector) : [];
@ -191,7 +191,7 @@ function spawnUIFragmentFactory(ds: Ref) {
const facet = Turn.activeFacet;
function handler(event: Event) {
facet.turn(() => {
send message P.UIEvent(fragmentId, selector, eventType, embed(create ({ data: event })));
send message P.UIEvent(fragmentId, selector, eventType, create ({ data: event }));
});
return dealWithPreventDefault(eventType, event);
}
@ -507,7 +507,7 @@ export class Anchor {
if (!Array.isArray(html)) {
html = html.nodes();
}
return P.UIFragment(this.fragmentId, selector, embed(create ({ data: html })), orderBy);
return P.UIFragment(this.fragmentId, selector, create ({ data: html }), orderBy);
}
}

View File

@ -6,7 +6,6 @@ import {
Assertion,
Bytes,
Dataspace,
Embedded,
IdentitySet,
Observe,
QuasiValue as Q,
@ -23,6 +22,7 @@ import {
isEmbedded,
stringify,
underlying,
Embeddable,
} from "@syndicate-lang/core";
import G = Schemas.gatekeeper;
import S = Schemas.sturdy;
@ -140,14 +140,10 @@ export function boot(ds = Dataspace.global, debug: boolean = false, WebSocketCon
console.log('tracking', addr.url);
during G.TransportConnection({
"addr": addr,
"control": $control_e: Embedded,
"resolved": G.Resolved.accepted($peer_e: Embedded),
"control": $control: Ref,
"resolved": G.Resolved.accepted($peer: Ref),
}) => {
const entry = {
addr,
control: control_e.embeddedValue,
peer: peer_e.embeddedValue,
};
const entry = { addr, control, peer };
candidates.value.add(entry);
candidates.changed();
on stop {
@ -237,11 +233,10 @@ export function boot(ds = Dataspace.global, debug: boolean = false, WebSocketCon
}) }) => {
const origin0 = Q.drop_lit(originPatValue);
if (!origin0 || !isEmbedded(origin0)) return;
const origin = origin0.embeddedValue;
const origin = origin0;
const detail0 = Q.drop_lit(detailPatValue, N.toNoisePathStepDetail);
if (!detail0) return;
const spec: N.NoiseSpec<Ref> = detail0;
const spec = Q.drop_lit(detailPatValue, N.toNoisePathStepDetail);
if (!spec) return;
const algorithms = SaltyCrypto.Noise_25519_ChaChaPoly_BLAKE2s;
const protocol =
@ -378,11 +373,10 @@ export function boot(ds = Dataspace.global, debug: boolean = false, WebSocketCon
}) }) => {
const origin0 = Q.drop_lit(originPatValue);
if (!origin0 || !isEmbedded(origin0)) return;
const origin = origin0.embeddedValue;
const origin = origin0;
const detail0 = Q.drop_lit(detailPatValue, S.toSturdyPathStepDetail);
if (!detail0) return;
const parameters: S.Parameters = detail0;
const parameters = Q.drop_lit(detailPatValue, S.toSturdyPathStepDetail);
if (!parameters) return;
at origin {
assert G.Resolve({
@ -411,7 +405,7 @@ export function boot(ds = Dataspace.global, debug: boolean = false, WebSocketCon
}
}
export function unpackStandardRoute<R>(route: E.StandardRoute<R>): G.Route<R> {
export function unpackStandardRoute<R extends Embeddable>(route: E.StandardRoute<R>): G.Route<R> {
if (route._variant === 'general') return route.value;
const { transports, key, service, sig, oid } = route;
@ -465,15 +459,15 @@ export function contactRemote(
) => void,
ds = Dataspace.global,
) {
const routeValue = Record.isRecord(route) ? route : G.fromRoute(G.Route(route));
const routeValue = 'pathSteps' in route ? G.fromRoute(G.Route(route)) : route;
at ds {
during G.ResolvePath({
"route": routeValue,
"addr": $addr,
"control": $control_e: Embedded,
"resolved": G.Resolved.accepted($resolved_e: Embedded),
"control": $control: Ref,
"resolved": G.Resolved.accepted($resolved: Ref),
}) => {
connectedFacet(resolved_e.embeddedValue, control_e.embeddedValue, addr);
connectedFacet(resolved, control, addr);
}
}
}