Back up to speed by avoiding S.* prefix and importing individual values directly

This commit is contained in:
Tony Garnock-Jones 2021-03-11 22:57:18 +01:00
parent 5086e3b209
commit 30bb5393c6
2 changed files with 78 additions and 51 deletions

View File

@ -26,8 +26,6 @@ export interface Ref {
readonly attenuation?: Attenuation;
}
export type Bindings = { [name: string]: Assertion };
//---------------------------------------------------------------------------
export function isRef(v: any): v is Ref {

View File

@ -1,59 +1,88 @@
import type { Assertion, Bindings, 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 * as S from './gen/sturdy.js';
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';
export * from './gen/sturdy.js';
export function match(p: S.Pattern, v: Assertion): Bindings | null {
export type Bindings = { [name: string]: Assertion };
export function match(p: Pattern, v: Assertion): Bindings | null {
let bindings: Bindings = {};
function walk(p: S.Pattern, v: Assertion): boolean {
function walk(p: Pattern, v: Assertion): boolean {
switch (p.label) {
case S.$__:
case $__:
return true;
case S.$bind:
if (walk(S.PBind._.pattern(p), v)) {
bindings[S.PBind._.name(p).asPreservesText()] = v;
case $bind:
if (walk(PBind._.pattern(p), v)) {
bindings[PBind._.name(p).asPreservesText()] = v;
return true;
}
return false;
case S.$and:
for (const pp of S.PAnd._.patterns(p)) {
case $and:
for (const pp of PAnd._.patterns(p)) {
if (!walk(pp, v)) return false;
}
return true;
case S.$not: {
case $not: {
const savedBindings = bindings;
bindings = {};
const result = !walk(S.PNot._.pattern(p), v)
const result = !walk(PNot._.pattern(p), v)
bindings = savedBindings;
return result;
}
case S.$lit:
return is(S.Lit._.value(p), v);
case S.$compound: {
const ctor = S.PCompound._.ctor(p);
const members = S.PCompound._.members(p);
case $lit:
return is(Lit._.value(p), v);
case $compound: {
const ctor = PCompound._.ctor(p);
const members = PCompound._.members(p);
switch (ctor.label) {
case S.$rec:
case $rec:
if (!Record.isRecord<Assertion, Tuple<Assertion>, Ref>(v)) return false;
if (!is(S.CRec._.label(ctor), v.label)) return false;
if (S.CRec._.arity(ctor) !== v.length) return false;
if (!is(CRec._.label(ctor), v.label)) return false;
if (CRec._.arity(ctor) !== v.length) return false;
for (const [key, pp] of members) {
if (typeof key !== 'number') return false;
if (!walk(pp, v[key])) return false;
}
return true;
case S.$arr:
case $arr:
if (!Array.isArray(v)) return false;
if ('label' in v) return false;
if (S.CArr._.arity(ctor) !== v.length) return false;
if (CArr._.arity(ctor) !== 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 S.$dict:
case $dict:
if (!Dictionary.isDictionary<Assertion, Ref>(v)) return false;
for (const [key, pp] of members) {
const vv = v.get(key as Assertion);
@ -69,41 +98,41 @@ export function match(p: S.Pattern, v: Assertion): Bindings | null {
return walk(p, v) ? bindings : null;
}
export function instantiate(t: S.Template, b: Bindings): Assertion {
function walk(t: S.Template): Assertion {
export function instantiate(t: Template, b: Bindings): Assertion {
function walk(t: Template): Assertion {
switch (t.label) {
case S.$ref: {
const n = S.TRef._.name(t).asPreservesText()
case $ref: {
const n = TRef._.name(t).asPreservesText()
const v = b[n];
if (v === void 0) throw new Error(`Unbound reference: ${n}`);
return v;
}
case S.$lit:
return S.Lit._.value(t) as Assertion;
case S.$compound: {
const ctor = S.TCompound._.ctor(t);
const members = S.TCompound._.members(t);
case $lit:
return Lit._.value(t) as Assertion;
case $compound: {
const ctor = TCompound._.ctor(t);
const members = TCompound._.members(t);
switch (ctor.label) {
case S.$rec: {
case $rec: {
const v = Record(
S.CRec._.label(ctor) as Assertion,
CRec._.label(ctor) as Assertion,
[] as Assertion[],
);
v.length = S.CRec._.arity(ctor);
v.length = CRec._.arity(ctor);
for (const [key, tt] of members) {
v[key as number] = walk(tt);
}
return v;
}
case S.$arr: {
case $arr: {
const v = [];
v.length = S.CArr._.arity(ctor);
v.length = CArr._.arity(ctor);
for (const [key, tt] of members) {
v[key as number] = walk(tt);
}
return v;
}
case S.$dict: {
case $dict: {
const v = new Dictionary<Assertion, Ref>();
for (const [key, tt] of members) {
v.set(key as Assertion, walk(tt));
@ -118,15 +147,15 @@ export function instantiate(t: S.Template, b: Bindings): Assertion {
return walk(t);
}
export function rewrite(r: S.Rewrite, v: Assertion): Assertion | null {
const bindings = match(S.Rewrite._.pattern(r), v);
export function rewrite(r: Rewrite, v: Assertion): Assertion | null {
const bindings = match(Rewrite._.pattern(r), v);
if (bindings === null) return null;
return instantiate(S.Rewrite._.template(r), bindings);
return instantiate(Rewrite._.template(r), bindings);
}
export function examineAlternatives(cav: S.Caveat, v: Assertion): Assertion | null {
if (cav.label === S.$or) {
for (const r of S.Alts._.alternatives(cav)) {
export function examineAlternatives(cav: Caveat, v: Assertion): Assertion | null {
if (cav.label === $or) {
for (const r of Alts._.alternatives(cav)) {
const w = rewrite(r, v);
if (w !== null) return w;
}
@ -136,7 +165,7 @@ export function examineAlternatives(cav: S.Caveat, v: Assertion): Assertion | nu
}
}
export function runRewrites(a: S.Attenuation | undefined, v: Assertion): Assertion | null {
export function runRewrites(a: Attenuation | undefined, v: Assertion): Assertion | null {
if (a !== void 0) {
for (const stage of a) {
const w = examineAlternatives(stage, v);
@ -149,12 +178,12 @@ export function runRewrites(a: S.Attenuation | undefined, v: Assertion): Asserti
const _a = Symbol.for('a');
export function rfilter(... patterns: S.Pattern[]): S.Caveat {
const ps = patterns.map(p => S.Rewrite(S.PBind(_a, p), S.TRef(_a)));
return ps.length === 1 ? ps[0] : S.Alts(ps);
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);
}
export function attenuate(ref: Ref, ... a: S.Attenuation): Ref {
export function attenuate(ref: Ref, ... a: Attenuation): Ref {
return { ... ref, attenuation: [... a, ... (ref.attenuation ?? [])] };
}