diff --git a/schemas/sturdy.prs b/schemas/sturdy.prs index 5a64456..2c69c11 100644 --- a/schemas/sturdy.prs +++ b/schemas/sturdy.prs @@ -26,8 +26,10 @@ CDict = . Lit = . -Pattern = PDiscard / PBind / PAnd / PNot / Lit / PCompound . +Pattern = PDiscard / PAtom / PPointer / PBind / PAnd / PNot / Lit / PCompound . PDiscard = <_>. +PAtom = =Boolean / =Float / =Double / =SignedInteger / =String / =ByteString / =Symbol . +PPointer = =Pointer . PBind = . PAnd = . PNot = . diff --git a/src/gen/sturdy.ts b/src/gen/sturdy.ts index 35a696f..9148abd 100644 --- a/src/gen/sturdy.ts +++ b/src/gen/sturdy.ts @@ -1,6 +1,14 @@ import * as _ from "@preserves/core"; import * as _i_Actor from "../actor"; +export const $Boolean = Symbol.for("Boolean"); +export const $ByteString = Symbol.for("ByteString"); +export const $Double = Symbol.for("Double"); +export const $Float = Symbol.for("Float"); +export const $Pointer = Symbol.for("Pointer"); +export const $SignedInteger = Symbol.for("SignedInteger"); +export const $String = Symbol.for("String"); +export const $Symbol = Symbol.for("Symbol"); export const $_ = Symbol.for("_"); export const $and = Symbol.for("and"); export const $arr = Symbol.for("arr"); @@ -50,6 +58,8 @@ export type Lit = {"value": _val}; export type Pattern = ( {"_variant": "PDiscard", "value": PDiscard} | + {"_variant": "PAtom", "value": PAtom} | + {"_variant": "PPointer", "value": PPointer} | {"_variant": "PBind", "value": PBind} | {"_variant": "PAnd", "value": PAnd} | {"_variant": "PNot", "value": PNot} | @@ -59,6 +69,18 @@ export type Pattern = ( export type PDiscard = null; +export type PAtom = ( + {"_variant": "Boolean"} | + {"_variant": "Float"} | + {"_variant": "Double"} | + {"_variant": "SignedInteger"} | + {"_variant": "String"} | + {"_variant": "ByteString"} | + {"_variant": "Symbol"} +); + +export type PPointer = null; + export type PBind = {"name": symbol, "pattern": Pattern}; export type PAnd = {"patterns": Array}; @@ -117,6 +139,8 @@ export function Lit(value: _val): Lit {return {"value": value};} export namespace Pattern { export function PDiscard(value: PDiscard): Pattern {return {"_variant": "PDiscard", "value": value};}; + export function PAtom(value: PAtom): Pattern {return {"_variant": "PAtom", "value": value};}; + export function PPointer(value: PPointer): Pattern {return {"_variant": "PPointer", "value": value};}; export function PBind(value: PBind): Pattern {return {"_variant": "PBind", "value": value};}; export function PAnd(value: PAnd): Pattern {return {"_variant": "PAnd", "value": value};}; export function PNot(value: PNot): Pattern {return {"_variant": "PNot", "value": value};}; @@ -126,6 +150,18 @@ export namespace Pattern { export function PDiscard(): PDiscard {return null;} +export namespace PAtom { + export function Boolean(): PAtom {return {"_variant": "Boolean"};}; + export function Float(): PAtom {return {"_variant": "Float"};}; + export function Double(): PAtom {return {"_variant": "Double"};}; + export function SignedInteger(): PAtom {return {"_variant": "SignedInteger"};}; + export function String(): PAtom {return {"_variant": "String"};}; + export function ByteString(): PAtom {return {"_variant": "ByteString"};}; + export function Symbol(): PAtom {return {"_variant": "Symbol"};}; +} + +export function PPointer(): PPointer {return null;} + export function PBind({name, pattern}: {name: symbol, pattern: Pattern}): PBind {return {"name": name, "pattern": pattern};} export function PAnd(patterns: Array): PAnd {return {"patterns": patterns};} @@ -465,25 +501,35 @@ export function toPattern(v: _val): undefined | Pattern { _tmp0 = toPDiscard(v); if (_tmp0 !== void 0) {result = {"_variant": "PDiscard", "value": _tmp0};}; if (result === void 0) { - let _tmp1: (PBind) | undefined; - _tmp1 = toPBind(v); - if (_tmp1 !== void 0) {result = {"_variant": "PBind", "value": _tmp1};}; + let _tmp1: (PAtom) | undefined; + _tmp1 = toPAtom(v); + if (_tmp1 !== void 0) {result = {"_variant": "PAtom", "value": _tmp1};}; if (result === void 0) { - let _tmp2: (PAnd) | undefined; - _tmp2 = toPAnd(v); - if (_tmp2 !== void 0) {result = {"_variant": "PAnd", "value": _tmp2};}; + let _tmp2: (PPointer) | undefined; + _tmp2 = toPPointer(v); + if (_tmp2 !== void 0) {result = {"_variant": "PPointer", "value": _tmp2};}; if (result === void 0) { - let _tmp3: (PNot) | undefined; - _tmp3 = toPNot(v); - if (_tmp3 !== void 0) {result = {"_variant": "PNot", "value": _tmp3};}; + let _tmp3: (PBind) | undefined; + _tmp3 = toPBind(v); + if (_tmp3 !== void 0) {result = {"_variant": "PBind", "value": _tmp3};}; if (result === void 0) { - let _tmp4: (Lit) | undefined; - _tmp4 = toLit(v); - if (_tmp4 !== void 0) {result = {"_variant": "Lit", "value": _tmp4};}; + let _tmp4: (PAnd) | undefined; + _tmp4 = toPAnd(v); + if (_tmp4 !== void 0) {result = {"_variant": "PAnd", "value": _tmp4};}; if (result === void 0) { - let _tmp5: (PCompound) | undefined; - _tmp5 = toPCompound(v); - if (_tmp5 !== void 0) {result = {"_variant": "PCompound", "value": _tmp5};}; + let _tmp5: (PNot) | undefined; + _tmp5 = toPNot(v); + if (_tmp5 !== void 0) {result = {"_variant": "PNot", "value": _tmp5};}; + if (result === void 0) { + let _tmp6: (Lit) | undefined; + _tmp6 = toLit(v); + if (_tmp6 !== void 0) {result = {"_variant": "Lit", "value": _tmp6};}; + if (result === void 0) { + let _tmp7: (PCompound) | undefined; + _tmp7 = toPCompound(v); + if (_tmp7 !== void 0) {result = {"_variant": "PCompound", "value": _tmp7};}; + }; + }; }; }; }; @@ -495,6 +541,8 @@ export function toPattern(v: _val): undefined | Pattern { export function fromPattern(_v: Pattern): _val { switch (_v._variant) { case "PDiscard": {return fromPDiscard(_v.value);}; + case "PAtom": {return fromPAtom(_v.value);}; + case "PPointer": {return fromPPointer(_v.value);}; case "PBind": {return fromPBind(_v.value);}; case "PAnd": {return fromPAnd(_v.value);}; case "PNot": {return fromPNot(_v.value);}; @@ -521,6 +569,78 @@ export function toPDiscard(v: _val): undefined | PDiscard { export function fromPDiscard(_v: PDiscard): _val {return _.Record($_, []);} +export function asPAtom(v: _val): PAtom { + let result = toPAtom(v); + if (result === void 0) throw new TypeError(`Invalid PAtom: ${_.stringify(v)}`); + return result; +} + +export function toPAtom(v: _val): undefined | PAtom { + let _tmp0: (null) | undefined; + let result: undefined | PAtom; + _tmp0 = _.is(v, $Boolean) ? null : void 0; + if (_tmp0 !== void 0) {result = {"_variant": "Boolean"};}; + if (result === void 0) { + let _tmp1: (null) | undefined; + _tmp1 = _.is(v, $Float) ? null : void 0; + if (_tmp1 !== void 0) {result = {"_variant": "Float"};}; + if (result === void 0) { + let _tmp2: (null) | undefined; + _tmp2 = _.is(v, $Double) ? null : void 0; + if (_tmp2 !== void 0) {result = {"_variant": "Double"};}; + if (result === void 0) { + let _tmp3: (null) | undefined; + _tmp3 = _.is(v, $SignedInteger) ? null : void 0; + if (_tmp3 !== void 0) {result = {"_variant": "SignedInteger"};}; + if (result === void 0) { + let _tmp4: (null) | undefined; + _tmp4 = _.is(v, $String) ? null : void 0; + if (_tmp4 !== void 0) {result = {"_variant": "String"};}; + if (result === void 0) { + let _tmp5: (null) | undefined; + _tmp5 = _.is(v, $ByteString) ? null : void 0; + if (_tmp5 !== void 0) {result = {"_variant": "ByteString"};}; + if (result === void 0) { + let _tmp6: (null) | undefined; + _tmp6 = _.is(v, $Symbol) ? null : void 0; + if (_tmp6 !== void 0) {result = {"_variant": "Symbol"};}; + }; + }; + }; + }; + }; + }; + return result; +} + +export function fromPAtom(_v: PAtom): _val { + switch (_v._variant) { + case "Boolean": {return $Boolean;}; + case "Float": {return $Float;}; + case "Double": {return $Double;}; + case "SignedInteger": {return $SignedInteger;}; + case "String": {return $String;}; + case "ByteString": {return $ByteString;}; + case "Symbol": {return $Symbol;}; + }; +} + +export function asPPointer(v: _val): PPointer { + let result = toPPointer(v); + if (result === void 0) throw new TypeError(`Invalid PPointer: ${_.stringify(v)}`); + return result; +} + +export function toPPointer(v: _val): undefined | PPointer { + let _tmp0: (null) | undefined; + let result: undefined | PPointer; + _tmp0 = _.is(v, $Pointer) ? null : void 0; + if (_tmp0 !== void 0) {result = _tmp0;}; + return result; +} + +export function fromPPointer(_v: PPointer): _val {return $Pointer;} + export function asPBind(v: _val): PBind { let result = toPBind(v); if (result === void 0) throw new TypeError(`Invalid PBind: ${_.stringify(v)}`); diff --git a/src/rewrite.ts b/src/rewrite.ts index 51be772..9e4133d 100644 --- a/src/rewrite.ts +++ b/src/rewrite.ts @@ -1,7 +1,7 @@ import type { Assertion, Handle, Ref, Turn } from "./actor.js"; -import { Dictionary, IdentityMap, is, Record, Tuple } from "@preserves/core"; +import { Bytes, Dictionary, DoubleFloat, IdentityMap, is, isPointer, Record, SingleFloat, Tuple } from "@preserves/core"; -import { Alts, Attenuation, Caveat, PBind, Pattern, Rewrite, TRef, Template } from './gen/sturdy.js'; +import { Alts, Attenuation, Caveat, PBind, Pattern, Rewrite, TRef, Template, _val, PCompound, ConstructorSpec, CRec, PCompoundMembers, Lit, PPointer, PAtom, CArr, CDict, PNot, PAnd } from './gen/sturdy.js'; export * from './gen/sturdy.js'; export type Bindings = { [name: string]: Assertion }; @@ -13,6 +13,18 @@ export function match(p: Pattern, v: Assertion): Bindings | null { switch (p._variant) { case 'PDiscard': return true; + case 'PAtom': + switch (p.value._variant) { + case 'Boolean': return typeof v === 'boolean'; + case 'ByteString': return Bytes.isBytes(v); + case 'Double': return DoubleFloat.isDouble(v); + case 'Float': return SingleFloat.isSingle(v); + case 'SignedInteger': return typeof v === 'number'; + case 'String': return typeof v === 'string'; + case 'Symbol': return typeof v === 'symbol'; + } + case 'PPointer': + return isPointer(v); case 'PBind': if (walk(p.value.pattern, v)) { bindings[p.value.name.asPreservesText()] = v; @@ -65,6 +77,9 @@ export function match(p: Pattern, v: Assertion): Bindings | null { return true; } } + default: + ((_p : never) => {})(p); + return false; } } @@ -158,6 +173,7 @@ export function rfilter(... patterns: Pattern[]): Caveat { } export function attenuate(ref: Ref, ... a: Attenuation): Ref { + if (a.length === 0) return ref; return { ... ref, attenuation: [... a, ... (ref.attenuation ?? [])] }; } @@ -191,3 +207,71 @@ export function forwarder(t: Turn, ref: Ref): { proxy: Ref, revoker: Ref } { }); return { proxy, revoker }; } + +export function pRec(label: _val, ... members: Array): Pattern { + return Pattern.PCompound(PCompound({ + ctor: ConstructorSpec.CRec(CRec({ label: label, arity: members.length })), + members: PCompoundMembers(new Dictionary( + members.map((p, i) => [i, p] as const).filter(e => e[1]._variant !== 'PDiscard')))})); +} + +export function pArr(... members: Array): Pattern { + return Pattern.PCompound(PCompound({ + ctor: ConstructorSpec.CArr(CArr(members.length)), + members: PCompoundMembers(new Dictionary( + members.map((p, i) => [i, p] as const).filter(e => e[1]._variant !== 'PDiscard')))})); +} + +export function pDict(... entries: [_val, Pattern][]): Pattern { + return Pattern.PCompound(PCompound({ + ctor: ConstructorSpec.CDict(CDict()), + members: PCompoundMembers(new Dictionary(entries))})); +} + +export function pLit(value: _val): Pattern { + return Pattern.Lit(Lit(value)); +} + +export function pNot(p: Pattern): Pattern { + return Pattern.PNot(PNot(p)); +} + +export function pAnd(... ps: Pattern[]): Pattern { + return Pattern.PAnd(PAnd(ps)); +} + +export function pBind(name: symbol, pattern: Pattern): Pattern { + return Pattern.PBind(PBind({ name, pattern })); +} + +export function pPointer(): Pattern { + return Pattern.PPointer(PPointer()); +} + +export function pSymbol(): Pattern { + return Pattern.PAtom(PAtom.Symbol()); +} + +export function pByteString(): Pattern { + return Pattern.PAtom(PAtom.ByteString()); +} + +export function pString(): Pattern { + return Pattern.PAtom(PAtom.String()); +} + +export function pSignedInteger(): Pattern { + return Pattern.PAtom(PAtom.SignedInteger()); +} + +export function pDouble(): Pattern { + return Pattern.PAtom(PAtom.Double()); +} + +export function pFloat(): Pattern { + return Pattern.PAtom(PAtom.Float()); +} + +export function pBoolean(): Pattern { + return Pattern.PAtom(PAtom.Boolean()); +} diff --git a/src/secure-chat-moderator.ts b/src/secure-chat-moderator.ts index 2fb7be4..2376064 100644 --- a/src/secure-chat-moderator.ts +++ b/src/secure-chat-moderator.ts @@ -1,6 +1,20 @@ -import { $claimNick, $joinedUser, asNickClaim, fromJoin, fromNickConflict, fromUserInfo, Join, NickConflict, UserId, UserInfo } from "./gen/secure-chat-protocol.js"; +import { + $claimNick, + $joinedUser, + $says, + $user, + Join, + NickConflict, + UserId, + UserInfo, + asNickClaim, + fromJoin, + fromNickConflict, + fromUserInfo, +} from "./gen/secure-chat-protocol.js"; import { Assertion, Handle, Ref, Turn } from "./actor.js"; import { observe, during, $Observe, asObserve } from "./dataspace.js"; +import { attenuate, rfilter, pRec, pPointer, pString, pLit } from "./rewrite.js"; export default function (t: Turn, ds: Ref) { let nextUserId: UserId = 0; @@ -13,7 +27,14 @@ export default function (t: Turn, ds: Ref) { const uid: UserId = nextUserId++; const f = t.facet(t => { - t.assert(o.observer, fromJoin(Join({ uid, handle: ds }))); + t.assert(o.observer, fromJoin(Join({ + uid, + handle: attenuate(ds, rfilter( + pRec($Observe, pLit($user), pPointer()), + pRec($Observe, pLit($says), pPointer()), + pRec($claimNick, pLit(uid), pString(), pPointer()), + pRec($says, pLit(uid), pString()))), + }))); let infoHandle: Handle | undefined; let nick: string | undefined; observe(t, ds, $claimNick, {