Refactor match and instantiate

This commit is contained in:
Emery Hemingway 2022-03-07 17:14:57 -06:00
parent d1e196f6f0
commit 0bf6b684fe
1 changed files with 83 additions and 87 deletions

View File

@ -171,97 +171,93 @@ proc enqueue(turn: var Turn; target: Facet; action: TurnAction) =
type Bindings = Table[Preserve[Ref], Preserve[Ref]]
proc match(p: Pattern; v: Assertion): Option[Bindings] =
proc walk(bindings: var Bindings; p: Pattern; v: Assertion): bool =
case p.orKind
of PatternKind.Pdiscard: result = true
of PatternKind.Patom:
result = case p.patom
of PAtom.Boolean: v.isBoolean
of PAtom.Float: v.isFloat
of PAtom.Double: v.isDouble
of PAtom.Signedinteger: v.isInteger
of PAtom.String: v.isString
of PAtom.Bytestring: v.isByteString
of PAtom.Symbol: v.isSymbol
of PatternKind.Pembedded:
result = v.isEmbedded
of PatternKind.Pbind:
if walk(bindings, p.pbind.pattern, v):
bindings[toPreserve(p.pbind.pattern, Ref)] = v
proc match(bindings: var Bindings; p: Pattern; v: Assertion): bool =
case p.orKind
of PatternKind.Pdiscard: result = true
of PatternKind.Patom:
result = case p.patom
of PAtom.Boolean: v.isBoolean
of PAtom.Float: v.isFloat
of PAtom.Double: v.isDouble
of PAtom.Signedinteger: v.isInteger
of PAtom.String: v.isString
of PAtom.Bytestring: v.isByteString
of PAtom.Symbol: v.isSymbol
of PatternKind.Pembedded:
result = v.isEmbedded
of PatternKind.Pbind:
if match(bindings, p.pbind.pattern, v):
bindings[toPreserve(p.pbind.pattern, Ref)] = v
result = true
of PatternKind.Pand:
for pp in p.pand.patterns:
result = match(bindings, pp, v)
if not result: break
of PatternKind.Pnot:
var b: Bindings
result = not match(b, p.pnot.pattern, v)
of PatternKind.Lit:
result = p.lit.value == v
of PatternKind.PCompound:
case p.pcompound.orKind
of PCompoundKind.rec:
if v.isRecord and
p.pcompound.rec.label == v.label and
p.pcompound.rec.fields.len == v.arity:
result = true
of PatternKind.Pand:
for pp in p.pand.patterns:
result = walk(bindings, pp, v)
if not result: break
of PatternKind.Pnot:
var b: Bindings
result = not walk(b, p.pnot.pattern, v)
of PatternKind.Lit:
result = p.lit.value == v
of PatternKind.Pcompound:
let
ctor = p.pcompound.ctor
case ctor.orKind
of ConstructorspecKind.Crec:
if v.isRecord and
ctor.crec.label == v.label and
ctor.crec.arity == v.arity:
for key, pp in p.pcompound.members:
if not key.isInteger:
result = false
else:
result = walk(bindings, pp, v.record[key.int])
if not result: break
of ConstructorspecKind.Carr:
if v.isSequence and ctor.carr.arity == v.sequence.len:
for key, pp in p.pcompound.members:
result =
if not key.isInteger: false
else: walk(bindings, pp, v.sequence[key.int])
if not result: break
of ConstructorspecKind.Cdict:
if v.isDictionary:
for key, pp in p.pcompound.members:
let vv = v[key]
result =
if vv.isFalse: false
else: walk(bindings, pp, vv)
if not result: break
for i, pp in p.pcompound.rec.fields:
if not match(bindings, pp, v[i]):
result = false
break
of PCompoundKind.arr:
if v.isSequence and p.pcompound.arr.items.len == v.sequence.len:
result = true
for i, pp in p.pcompound.arr.items:
if not match(bindings, pp, v[i]):
result = false
break
of PCompoundKind.dict:
if v.isDictionary:
result = true
for key, pp in p.pcompound.dict.entries:
let vv = v[key]
if vv.isFalse or not match(bindings, pp, vv):
result = true
break
proc match(p: Pattern; v: Assertion): Option[Bindings] =
var b: Bindings
if walk(b, p, v): result = some b
if match(b, p, v):
result = some b
proc instantiate(t: Template; bindings: Bindings): Assertion =
proc walk(t: Template): Assertion =
case t.orKind
of TemplateKind.Tattenuate:
let v = walk(t.tattenuate.template)
if not v.isEmbedded:
raise newException(ValueError, "Attempt to attenuate non-capability: " & $v)
result = embed(attenuate(v.embed, t.tattenuate.attenuation))
of TemplateKind.Tref:
let n = $t.tref.binding
try: result = bindings[toPreserve(n, Ref)]
except KeyError:
raise newException(ValueError, "unbound reference: " & n)
of TemplateKind.Lit:
result = t.lit.value
of TemplateKind.Tcompound:
let ctor = t.tcompound.ctor
case ctor.orKind
of ConstructorspecKind.Crec:
result = initRecord(ctor.crec.label, ctor.crec.arity)
for key, tt in t.tcompound.members:
result.record[key.int] = walk(tt)
of ConstructorspecKind.Carr:
result = initSequence[Ref](ctor.carr.arity)
for key, tt in t.tcompound.members:
result.sequence[key.int] = walk(tt)
of ConstructorspecKind.Cdict:
result = initDictionary[Ref]()
for key, tt in t.tcompound.members:
result[key] = walk(tt)
walk(t)
case t.orKind
of TemplateKind.Tattenuate:
let v = instantiate(t.tattenuate.template, bindings)
if not v.isEmbedded:
raise newException(ValueError, "Attempt to attenuate non-capability")
result = embed(attenuate(v.embed, t.tattenuate.attenuation))
of TemplateKind.TRef:
let n = $t.tref.binding
try: result = bindings[toPreserve(n, Ref)]
except KeyError:
raise newException(ValueError, "unbound reference: " & n)
of TemplateKind.Lit:
result = t.lit.value
of TemplateKind.Tcompound:
case t.tcompound.orKind
of TCompoundKind.rec:
result = initRecord(t.tcompound.rec.label, t.tcompound.rec.fields.len)
for i, tt in t.tcompound.rec.fields:
result[i] = instantiate(tt, bindings)
of TCompoundKind.arr:
result = initSequence[Ref](t.tcompound.arr.items.len)
for i, tt in t.tcompound.arr.items:
result[i] = instantiate(tt, bindings)
of TCompoundKind.dict:
result = initDictionary[Ref]()
for key, tt in t.tcompound.dict.entries:
result[key] = instantiate(tt, bindings)
proc rewrite(r: Rewrite; v: Assertion): Assertion =
let bindings = match(r.pattern, v)