From 0e8aca889214066dea78fca5a4bdc7a6b3cc8a6f Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 12 Jan 2022 12:24:56 +0100 Subject: [PATCH] More general quoting --- syndicate/patterns.py | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/syndicate/patterns.py b/syndicate/patterns.py index 400df68..a617a99 100644 --- a/syndicate/patterns.py +++ b/syndicate/patterns.py @@ -15,25 +15,38 @@ class unquote: def __init__(self, pattern): self.pattern = pattern +uCAPTURE = unquote(CAPTURE) +u_ = unquote(_) + +# Given +# +# Run = +# +# then these all produce the same pattern: +# +# P.rec('Observe', P.quote(P.rec('run', P.lit('N'), P.unquote(P.CAPTURE), P.bind(P.unquote(P._)))), P._) +# +# P.rec('Observe', P.quote(P.quote(Run('N', P.unquote(P.uCAPTURE), P.unquote(P.bind(P.u_))))), P._) +# +# P.quote(Record(Symbol('Observe'), +# [P.quote(Run('N', P.unquote(P.uCAPTURE), P.unquote(P.bind(P.u_)))), +# P.u_])) + # Simple, stupid single-level quasiquotation. def quote(p): if isinstance(p, unquote): return p.pattern - if p.VARIANT == P.Pattern.DDiscard.VARIANT: - return lit(preserve(p)) - if p.VARIANT == P.Pattern.DBind.VARIANT: - return rec('bind', quote(p.value.pattern)) - if p.VARIANT == P.Pattern.DLit.VARIANT: - return lit(preserve(p)) - if p.VARIANT == P.Pattern.DCompound.VARIANT: - p = p.value - if p.VARIANT == P.DCompound.rec.VARIANT: - return rec('rec', lit(p.label), arr(*map(quote, p.fields))) - if p.VARIANT == P.DCompound.arr.VARIANT: - return rec('arr', arr(*map(quote, p.items))) - if p.VARIANT == P.DCompound.dict.VARIANT: - return rec('dict', dict(*map(lambda kv: (kv[0], quote(kv[1])), p.entries.items()))) - raise Exception(f'Unhandled case in quote: {repr(p)}') + p = preserve(p) + if isinstance(p, list) or isinstance(p, tuple): + return arr(*map(quote, p)) + elif isinstance(p, set) or isinstance(p, frozenset): + raise Exception('Cannot represent literal set in dataspace pattern') + elif isinstance(p, _dict): + return dict(*((k, quote(pp)) for (k, pp) in p.items())) + elif isinstance(p, Record): + return _rec(p.key, *map(quote, p.fields)) + else: + return P.Pattern.DLit(P.DLit(P.AnyAtom.decode(p))) def lit(v): if isinstance(v, list) or isinstance(v, tuple):