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