patterns: drop unspecified type elements at T ?: {N:pat}

Emit a <_> pattern for unspecified elements rather than patterns
that would match metadata like record label and arity.
This commit is contained in:
Emery Hemingway 2024-01-06 16:48:12 +02:00
parent 6d2a401a2b
commit 59ece65f3b
2 changed files with 28 additions and 21 deletions

View File

@ -172,10 +172,10 @@ proc fieldCount(T: typedesc): int =
for _, _ in fieldPairs(default T): for _, _ in fieldPairs(default T):
inc result inc result
proc lookup[T](bindings: openArray[(int, Pattern)]; i: int; _: T): Pattern = proc lookup(bindings: openArray[(int, Pattern)]; i: int): Pattern =
for (j, b) in bindings: for (j, b) in bindings:
if i == j: return b if i == j: return b
return dropType(T) return drop()
proc grab*(typ: static typedesc; bindings: sink openArray[(int, Pattern)]): Pattern = proc grab*(typ: static typedesc; bindings: sink openArray[(int, Pattern)]): Pattern =
## Construct a `Pattern` from type `typ` that selectively captures fields. ## Construct a `Pattern` from type `typ` that selectively captures fields.
@ -186,7 +186,7 @@ proc grab*(typ: static typedesc; bindings: sink openArray[(int, Pattern)]): Patt
rec.fields.setLen(fieldCount typ) rec.fields.setLen(fieldCount typ)
var i: int var i: int
for _, f in fieldPairs(default typ): for _, f in fieldPairs(default typ):
rec.fields[i] = lookup(bindings, i, f) rec.fields[i] = lookup(bindings, i)
inc i inc i
result = rec.toPattern result = rec.toPattern
elif typ is tuple: elif typ is tuple:
@ -194,7 +194,7 @@ proc grab*(typ: static typedesc; bindings: sink openArray[(int, Pattern)]): Patt
arr.items.setLen(fieldCount typ) arr.items.setLen(fieldCount typ)
var i: int var i: int
for _, f in fieldPairs(default typ): for _, f in fieldPairs(default typ):
arr.items[i] = lookup(bindings, i, f) arr.items[i] = lookup(bindings, i)
inc i inc i
result = arr.toPattern result = arr.toPattern
else: else:

View File

@ -3,7 +3,7 @@
import std/[options, tables, unittest] import std/[options, tables, unittest]
import preserves, syndicate import preserves, syndicate, syndicate/protocols/gatekeeper
import ./test_schema import ./test_schema
@ -74,23 +74,30 @@ suite "captures":
checkpoint $pat checkpoint $pat
check pat.matches pr check pat.matches pr
suite "later-than": suite "protocol":
let test "Observe":
obsA = parsePreserves"""<Observe <rec later-than [<lit 1704113731.419243>]> #!#f>""" let pat = ?:Observe
obsB = parsePreserves"""<Observe <rec Observe [<rec rec [<lit later-than> <arr [<rec lit [<bind <_>>]>]>]> <_>]> #!#f>""" const text = """<rec Observe [<bind <_>> <bind <_>>]>"""
patA = """<rec later-than [<lit 1704113731.419243>]>""".parsePreserves.preservesTo(Pattern).get check $pat == text
patB = """<rec Observe [<rec rec [<lit later-than> <arr [<rec lit [<bind <_>>]>]>]> <_>]>""".parsePreserves.preservesTo(Pattern).get
patC = grab obsA test "later-than":
let
obsA = parsePreserves"""<Observe <rec later-than [<lit 1704113731.419243>]> #!#f>"""
obsB = parsePreserves"""<Observe <rec Observe [<rec rec [<lit later-than> <arr [<rec lit [<bind <_>>]>]>]> <_>]> #!#f>"""
patA = """<rec later-than [<lit 1704113731.419243>]>""".parsePreserves.preservesTo(Pattern).get
patB = """<rec Observe [<rec rec [<lit later-than> <arr [<rec lit [<bind <_>>]>]>]> <_>]>""".parsePreserves.preservesTo(Pattern).get
test $patC: patC = grab obsA
check patC.matches obsA
test $patB: test $patC:
checkpoint $obsA check patC.matches obsA
check patB.matches obsA
suite "Observe": test $patB:
let pat = ?:Observe checkpoint $obsA
const text = """<rec Observe [<bind <_>> <bind <_>>]>""" check patB.matches obsA
check $pat == text
test "TransportConnection":
let
pat = TransportConnection ?: { 2: ?:Rejected}
text = """<rec connect-transport [<_> <_> <rec rejected [<bind <_>>]>]>"""
check $pat == text