From 4a6e95bbcec8bc575c8d186d4633a4b0c4635e66 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Sun, 15 Oct 2023 12:11:10 +0100 Subject: [PATCH] patterns: add Literal[T] type for literal capture --- src/syndicate/patterns.nim | 37 +++++++++++++++++++++++++++++++++++++ syndicate.nimble | 2 +- tests/test_patterns.nim | 24 +++++++++++++++++++++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/syndicate/patterns.nim b/src/syndicate/patterns.nim index 2dc94d0..f833568 100644 --- a/src/syndicate/patterns.nim +++ b/src/syndicate/patterns.nim @@ -289,6 +289,43 @@ proc grabDictionary*(bindings: sink openArray[(string, Pattern)]): Pattern = for (key, val) in bindings.items: result.dcompound.dict.entries[key.toSymbol(Cap)] = val +func depattern(comp: DCompound): Preserve[Cap] + +func depattern(pat: Pattern): Preserve[Cap] = + case pat.orKind + of PatternKind.DDiscard, PatternKind.DBind: + discard + of PatternKind.DLit: + result = pat.dlit.value.toPreserve(Cap) + of PatternKind.DCompound: + result = depattern(pat.dcompound) + +func depattern(comp: DCompound): Preserve[Cap] = + case comp.orKind + of DCompoundKind.rec: + result = initRecord(comp.rec.label, comp.rec.fields.len) + for i, f in comp.rec.fields: + result[i] = depattern(f) + of DCompoundKind.arr: + result = initSequence(comp.arr.items.len, Cap) + for i, e in comp.arr.items: + result[i] = depattern(e) + of DCompoundKind.dict: + result = initDictionary(Cap) + for key, val in comp.dict.entries: + result[key] = depattern(val) + +type Literal*[T] = object + ## A wrapper type to deserialize patterns to native values. + value*: T + +proc fromPreserveHook*[T, E](lit: var Literal[T]; pr: Preserve[E]): bool = + var pat: Pattern + pat.fromPreserve(pr) and lit.value.fromPreserve(depattern pat) + +proc toPreserveHook*[T](lit: Literal[T]; E: typedesc): Preserve[E] = + lit.grab.toPreserve(E) + type Path* = seq[Value] Paths* = seq[Path] diff --git a/syndicate.nimble b/syndicate.nimble index 9ab8184..f49945b 100644 --- a/syndicate.nimble +++ b/syndicate.nimble @@ -1,6 +1,6 @@ # Package -version = "20231013" +version = "20231014" author = "Emery Hemingway" description = "Syndicated actors for conversational concurrency" license = "Unlicense" diff --git a/tests/test_patterns.nim b/tests/test_patterns.nim index f56d38a..6707628 100644 --- a/tests/test_patterns.nim +++ b/tests/test_patterns.nim @@ -1,7 +1,7 @@ # SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense -import std/unittest +import std/[tables, unittest] import preserves, syndicate from syndicate/protocols/dataspace import Observe @@ -34,3 +34,25 @@ test "dictionaries": let values = capture(pat, source) check $values == "@[1, 2, 3]" + +type + File {.preservesDictionary.} = object + name: string + path: string + size: BiggestInt + `type`: string + Files = Table[Symbol, File] + Fields = Table[Symbol, string] + + Request {.preservesRecord: "request".} = object + seq: BiggestInt + fields: Fields + files: Files + +test "literals": + const txt = """ date: notes: title: }> path: size: type: }>}>]>""" + var pr = parsePreserves(txt, Cap) + + var capture: Literal[Request] + check capture.fromPreserve(pr) + echo capture.value