Change behavior of grabType

Make grabType grab a single composite value that can be converted
to the type being grabbed instead of just the fields of the type.

The old behavior is available in grabTypeFlat and the alias `?:`
still points there.
This commit is contained in:
Emery Hemingway 2024-05-07 15:44:53 +02:00
parent 4fb0285190
commit 3a4dc1f133
3 changed files with 17 additions and 14 deletions

View File

@ -22,7 +22,7 @@ proc `?`*[T](val: T): Pattern {.inline.} =
patterns.drop[T](val) patterns.drop[T](val)
proc `?:`*(typ: static typedesc): Pattern {.inline.} = proc `?:`*(typ: static typedesc): Pattern {.inline.} =
patterns.grabType(typ) patterns.grabTypeFlat(typ)
proc `?:`*(typ: static typedesc; bindings: sink openArray[(int, Pattern)]): Pattern {.inline.} = proc `?:`*(typ: static typedesc; bindings: sink openArray[(int, Pattern)]): Pattern {.inline.} =
patterns.grab(typ, bindings) patterns.grab(typ, bindings)

View File

@ -109,7 +109,7 @@ proc grab*[T](x: T): Pattern {.
deprecated: "use drop unless you wish to capture the provided value".} = deprecated: "use drop unless you wish to capture the provided value".} =
PatternBind(pattern: drop x).toPattern PatternBind(pattern: drop x).toPattern
proc grabType*(typ: static typedesc): Pattern = proc grabTypeFlat*(typ: static typedesc): Pattern =
## Derive a `Pattern` from type `typ`. ## Derive a `Pattern` from type `typ`.
## This works for `tuple` and `object` types but in the ## This works for `tuple` and `object` types but in the
## general case will return a wildcard binding. ## general case will return a wildcard binding.
@ -117,36 +117,36 @@ proc grabType*(typ: static typedesc): Pattern =
import preserves import preserves
from std/unittest import check from std/unittest import check
check: check:
$grabType(array[3, int]) == $grabTypeFlat(array[3, int]) ==
"""<group <arr> {0: <bind <_>> 1: <bind <_>> 2: <bind <_>> 3: <bind <_>>}>""" """<group <arr> {0: <bind <_>> 1: <bind <_>> 2: <bind <_>> 3: <bind <_>>}>"""
type type
Point = tuple[x: int; y: int] Point = tuple[x: int; y: int]
Rect {.preservesRecord: "rect".} = tuple[a: Point; B: Point] Rect {.preservesRecord: "rect".} = tuple[a: Point; B: Point]
ColoredRect {.preservesDictionary.} = tuple[color: string; rect: Rect] ColoredRect {.preservesDictionary.} = tuple[color: string; rect: Rect]
check: check:
$(grabType Point) == $(grabTypeFlat Point) ==
"<group <arr> {0: <bind <_>> 1: <bind <_>>}>" "<group <arr> {0: <bind <_>> 1: <bind <_>>}>"
$(grabType Rect) == $(grabTypeFlat Rect) ==
"<group <rec rect> {0: <group <arr> {0: <bind <_>> 1: <bind <_>>}> 1: <group <arr> {0: <bind <_>> 1: <bind <_>>}>}>" "<group <rec rect> {0: <group <arr> {0: <bind <_>> 1: <bind <_>>}> 1: <group <arr> {0: <bind <_>> 1: <bind <_>>}>}>"
$(grabType ColoredRect) == $(grabTypeFlat ColoredRect) ==
"<group <dict> {color: <bind <_>> rect: <group <rec rect> {0: <group <arr> {0: <bind <_>> 1: <bind <_>>}> 1: <group <arr> {0: <bind <_>> 1: <bind <_>>}>}>}>" "<group <dict> {color: <bind <_>> rect: <group <rec rect> {0: <group <arr> {0: <bind <_>> 1: <bind <_>>}> 1: <group <arr> {0: <bind <_>> 1: <bind <_>>}>}>}>"
when typ is ref: when typ is ref:
grabType(pointerBase(typ)) grabTypeFlat(pointerBase(typ))
elif typ.hasPreservesRecordPragma: elif typ.hasPreservesRecordPragma:
var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`rec`)) var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`rec`))
group.`type`.rec.label = typ.recordLabel.toSymbol group.`type`.rec.label = typ.recordLabel.toSymbol
for _, f in fieldPairs(default typ): for _, f in fieldPairs(default typ):
group.entries[group.entries.len.toPreserves] = grabType(typeof f) group.entries[group.entries.len.toPreserves] = grabTypeFlat(typeof f)
group.toPattern group.toPattern
elif typ.hasPreservesDictionaryPragma: elif typ.hasPreservesDictionaryPragma:
var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`dict`)) var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`dict`))
for key, val in fieldPairs(default typ): for key, val in fieldPairs(default typ):
group.entries[key.toSymbol] = grabType(typeof val) group.entries[key.toSymbol] = grabTypeFlat(typeof val)
group.toPattern group.toPattern
elif typ is tuple: elif typ is tuple:
var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`arr`)) var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`arr`))
for _, f in fieldPairs(default typ): for _, f in fieldPairs(default typ):
group.entries[group.entries.len.toPreserves] = grabType(typeof f) group.entries[group.entries.len.toPreserves] = grabTypeFlat(typeof f)
group.toPattern group.toPattern
elif typ is array: elif typ is array:
var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`arr`)) var group = PatternGroup(`type`: GroupType(orKind: GroupTypeKind.`arr`))
@ -180,6 +180,9 @@ proc dropType*(typ: static typedesc): Pattern =
else: else:
drop() drop()
proc grabType*(typ: static typedesc): Pattern =
PatternBind(pattern: typ.dropType).toPattern
proc bindEntries(group: var PatternGroup; bindings: openArray[(int, Pattern)]) = proc bindEntries(group: var PatternGroup; bindings: openArray[(int, Pattern)]) =
## Set `bindings` for a `group`. ## Set `bindings` for a `group`.
for (i, pat) in bindings: group.entries[toPreserves i] = pat for (i, pat) in bindings: group.entries[toPreserves i] = pat
@ -214,10 +217,10 @@ proc grabLit*(): Pattern =
from std/unittest import check from std/unittest import check
check: check:
$grabLit() == """<group <rec lit> {0: <bind <_>>}>""" $grabLit() == """<group <rec lit> {0: <bind <_>>}>"""
grabType(dataspacePatterns.PatternLit) grabTypeFlat(dataspacePatterns.PatternLit)
proc grabDict*(): Pattern = proc grabDict*(): Pattern =
grabType(dataspacePatterns.GroupTypeDict) grabTypeFlat(dataspacePatterns.GroupTypeDict)
proc unpackLiterals*(pr: Value): Value = proc unpackLiterals*(pr: Value): Value =
result = pr result = pr
@ -321,7 +324,7 @@ proc depattern*(pat: Pattern; values: sink seq[Value]): Value =
import preserves import preserves
type Foo {.preservesRecord: "foo".} = object type Foo {.preservesRecord: "foo".} = object
a, b: int a, b: int
let pat = grabType Foo let pat = grabTypeFlat Foo
let val = depattern(pat, @[1.toPreserves, 5.toPreserves]) let val = depattern(pat, @[1.toPreserves, 5.toPreserves])
check $val == "<foo 1 5>" check $val == "<foo 1 5>"
var index: int var index: int

View File

@ -1,6 +1,6 @@
# Package # Package
version = "20240504" version = "20240507"
author = "Emery Hemingway" author = "Emery Hemingway"
description = "Syndicated actors for conversational concurrency" description = "Syndicated actors for conversational concurrency"
license = "Unlicense" license = "Unlicense"