diff --git a/src/syndicate/actors.nim b/src/syndicate/actors.nim index 8f88e51..c1e3b16 100644 --- a/src/syndicate/actors.nim +++ b/src/syndicate/actors.nim @@ -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)