Refactor match and instantiate
This commit is contained in:
parent
d1e196f6f0
commit
0bf6b684fe
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue