Attenuation now has alternative template possibilities

This commit is contained in:
Tony Garnock-Jones 2021-02-25 11:41:26 +01:00
parent ec7a816aeb
commit c3100f158e
1 changed files with 14 additions and 12 deletions

View File

@ -29,7 +29,8 @@ export interface Ref {
readonly attenuation?: Attenuation;
}
export type Attenuation = Array<Rewrite>;
export type Attenuation = Array<RewriteStage>; // array of stages, each a list of alternatives
export type RewriteStage = Array<Rewrite>;
export type Rewrite = { pattern: Pattern, template: Template };
export type PatternPointer =
@ -37,7 +38,6 @@ export type PatternPointer =
| { type: 'discard' }
| { type: 'bind', name: string, pattern: Pattern }
| { type: 'and', patterns: Array<Pattern> }
| { type: 'or', patterns: Array<Pattern> }
| { type: 'not', pattern: Pattern };
export type Pattern = Value<PatternPointer>;
@ -56,7 +56,6 @@ export const pdiscard: Pattern = { type: 'discard' };
export const pbind = (name: string, pattern: Pattern = pdiscard): Pattern =>
({ type: 'bind', name, pattern });
export const pand = (... patterns: Pattern[]): Pattern => ({ type: 'and', patterns });
export const por = (... patterns: Pattern[]): Pattern => ({ type: 'or', patterns });
export const pnot = (pattern: Pattern): Pattern => ({ type: 'not', pattern });
export const tref = (name: string): Template => ({ type: 'ref', name });
@ -230,11 +229,6 @@ export function match(p: Pattern, v: Assertion): Bindings | null {
if (!walk(p, v)) return false;
}
return true;
case 'or':
for (const p of t.patterns) {
if (walk(p, v)) return true;
}
return false;
}
} else {
if (!isRef(v)) return false;
@ -257,10 +251,18 @@ export function rewrite(r: Rewrite, v: Assertion): Assertion | null {
return instantiate(r.template, bindings);
}
export function examineAlternatives(alternatives: RewriteStage, v: Assertion): Assertion | null {
for (const r of alternatives) {
const w = rewrite(r, v);
if (w !== null) return w;
}
return null;
}
export function runRewrites(a: Attenuation | undefined, v: Assertion): Assertion | null {
if (a !== void 0) {
for (const r of a) {
const w = rewrite(r, v);
for (const stage of a) {
const w = examineAlternatives(stage, v);
if (w === null) return null;
v = w;
}
@ -268,8 +270,8 @@ export function runRewrites(a: Attenuation | undefined, v: Assertion): Assertion
return v;
}
export function rfilter(... patterns: Pattern[]): Rewrite {
return { pattern: pbind('a', por(... patterns)), template: tref('a') };
export function rfilter(... patterns: Pattern[]): RewriteStage {
return patterns.map(p => ({ pattern: pbind('a', p), template: tref('a') }));
}
export function attenuate(ref: Ref, ... a: Attenuation): Ref {