2021-10-28 17:43:20 +00:00
|
|
|
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
|
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
|
2022-06-16 03:27:25 +00:00
|
|
|
import std/[sequtils, tables, typetraits]
|
2021-10-28 17:43:20 +00:00
|
|
|
|
|
|
|
import preserves
|
2021-11-02 11:58:51 +00:00
|
|
|
import ./protocols/dataspacePatterns
|
2021-10-28 17:43:20 +00:00
|
|
|
from ./actors import Ref
|
|
|
|
|
2022-03-11 05:43:54 +00:00
|
|
|
export dataspacePatterns.`$`, PatternKind, DCompoundKind
|
2021-10-29 12:06:00 +00:00
|
|
|
|
2021-10-28 17:43:20 +00:00
|
|
|
type
|
2022-06-16 03:27:25 +00:00
|
|
|
Assertion = Preserve[Ref]
|
2022-03-11 05:43:54 +00:00
|
|
|
AnyAtom* = dataspacePatterns.AnyAtom[Ref]
|
2022-04-24 01:01:30 +00:00
|
|
|
DBind* = dataspacePatterns.DBind[Ref]
|
|
|
|
DCompound* = dataspacePatterns.DCompound[Ref]
|
|
|
|
DCompoundArr* = dataspacePatterns.DCompoundArr[Ref]
|
|
|
|
DCompoundDict* = dataspacePatterns.DCompoundDict[Ref]
|
|
|
|
DCompoundRec* = dataspacePatterns.DCompoundRec[Ref]
|
|
|
|
DLit* = dataspacePatterns.DLit[Ref]
|
2021-10-28 17:43:20 +00:00
|
|
|
Pattern* = dataspacePatterns.Pattern[Ref]
|
|
|
|
|
2022-06-16 03:27:25 +00:00
|
|
|
proc `?`*(d: sink DBind): Pattern =
|
2021-10-29 12:06:00 +00:00
|
|
|
Pattern(orKind: PatternKind.DBind, dbind: d)
|
|
|
|
|
2022-06-16 03:27:25 +00:00
|
|
|
proc `?`*(d: sink DLit): Pattern =
|
2021-10-29 12:06:00 +00:00
|
|
|
Pattern(orKind: PatternKind.DLit, dlit: d)
|
|
|
|
|
2022-06-16 03:27:25 +00:00
|
|
|
proc `?`*(aa: sink AnyAtom): Pattern =
|
|
|
|
?DLit(value: aa)
|
|
|
|
|
|
|
|
proc `?`*(d: sink DCompound): Pattern =
|
2021-10-29 12:06:00 +00:00
|
|
|
Pattern(orKind: PatternKind.DCompound, dcompound: d)
|
|
|
|
|
2022-06-16 03:27:25 +00:00
|
|
|
proc `?`*(d: sink DCompoundRec): Pattern =
|
2022-06-10 15:46:57 +00:00
|
|
|
?DCompound(orKind: DCompoundKind.rec, rec: d)
|
|
|
|
|
2022-06-16 03:27:25 +00:00
|
|
|
proc `?`*(d: sink DCompoundArr): Pattern =
|
|
|
|
?DCompound(orKind: DCompoundKind.arr, arr: d)
|
|
|
|
|
|
|
|
proc `?`*(d: sink DCompoundDict): Pattern =
|
|
|
|
?DCompound(orKind: DCompoundKind.dict, dict: d)
|
|
|
|
|
2022-03-07 23:53:05 +00:00
|
|
|
proc `?`*(x: bool): Pattern =
|
2022-06-16 03:27:25 +00:00
|
|
|
?AnyAtom(orKind: AnyAtomKind.`bool`, bool: x)
|
2022-03-07 23:53:05 +00:00
|
|
|
|
|
|
|
proc `?`*(x: float32): Pattern =
|
2022-06-16 03:27:25 +00:00
|
|
|
?AnyAtom(orKind: AnyAtomKind.`float`, float: x)
|
2022-03-07 23:53:05 +00:00
|
|
|
|
|
|
|
proc `?`*(x: float64): Pattern =
|
2022-06-16 03:27:25 +00:00
|
|
|
?AnyAtom(orKind: AnyAtomKind.`double`, double: x)
|
2022-03-07 23:53:05 +00:00
|
|
|
|
|
|
|
proc `?`*(x: int): Pattern =
|
2022-06-16 03:27:25 +00:00
|
|
|
?AnyAtom(orKind: AnyAtomKind.`int`, int: x)
|
|
|
|
|
|
|
|
proc `?`*(s: sink string): Pattern =
|
|
|
|
?AnyAtom(orKind: AnyAtomKind.`string`, string: s)
|
|
|
|
|
|
|
|
proc `?`*(x: sink seq[byte]): Pattern =
|
|
|
|
?AnyAtom(orKind: AnyAtomKind.`bytes`, bytes: x)
|
|
|
|
|
|
|
|
proc `?`*(x: sink Symbol): Pattern =
|
|
|
|
?AnyAtom(orKind: AnyAtomKind.`symbol`, symbol: x)
|
|
|
|
|
|
|
|
proc `?`*[T](pr: Preserve[T]): Pattern =
|
|
|
|
assert not pr.embedded
|
|
|
|
case pr.kind
|
|
|
|
of pkBoolean: ?pr.bool
|
|
|
|
of pkFloat: ?pr.float
|
|
|
|
of pkDouble: ?pr.double
|
|
|
|
of pkSignedInteger: ?(int pr.int) # TODO: overflow!
|
|
|
|
of pkString: ?pr.string
|
|
|
|
of pkByteString: ?pr.bytes
|
|
|
|
of pkSymbol: ?pr.symbol
|
|
|
|
of pkRecord:
|
|
|
|
?DCompoundRec(
|
|
|
|
label: pr.label,
|
|
|
|
fields: map[Preserve[T], Pattern](pr.fields, `?`[T]))
|
|
|
|
of pkSequence:
|
|
|
|
?DCompoundArr(items: map(pr.sequence, `?`[T]))
|
|
|
|
of pkSet: raise newException(
|
|
|
|
ValueError, "cannot construct a pattern over a set literal")
|
|
|
|
of pkDictionary:
|
|
|
|
var dict = DCompoundDict()
|
|
|
|
for key, val in pr.pairs: dict.entries[key] = ?val
|
|
|
|
?dict
|
|
|
|
of pkEmbedded:
|
|
|
|
raiseAssert "cannot construct a pattern over a embedded literal"
|
|
|
|
|
|
|
|
proc `??`*(pat: Pattern): Pattern =
|
|
|
|
## Construct a `Pattern` that matches a `Pattern`.
|
|
|
|
case pat.orKind
|
|
|
|
of PatternKind.DDiscard, PatternKind.DBind:
|
|
|
|
result = pat
|
|
|
|
of PatternKind.DLit:
|
|
|
|
result = ?(pat.toPreserve(Ref))
|
|
|
|
of PatternKind.DCompound:
|
|
|
|
case pat.dcompound.orKind
|
|
|
|
of DCompoundKind.rec:
|
|
|
|
var fields = move pat.dcompound.rec.fields
|
|
|
|
result = ?(pat.toPreserve(Ref))
|
|
|
|
result.dcompound.rec.fields[1].dcompound.arr.items = fields
|
|
|
|
of DCompoundKind.arr:
|
|
|
|
var items = move pat.dcompound.arr.items
|
|
|
|
result = ?(pat.toPreserve(Ref))
|
|
|
|
result.dcompound.rec.fields[0].dcompound.arr.items = items
|
|
|
|
of DCompoundKind.dict:
|
|
|
|
# var entries = move pat.dcompound.dict.entries
|
|
|
|
# result = ?(pat.toPreserve(Ref))
|
|
|
|
stderr.writeLine "pattern construction from DCompoundKind not implemented"
|
|
|
|
raiseAssert "not implemented"
|
2021-11-02 11:58:51 +00:00
|
|
|
|
2021-12-11 18:36:31 +00:00
|
|
|
proc drop*(): Pattern = Pattern(orKind: PatternKind.DDiscard)
|
|
|
|
proc grab*(): Pattern = ?DBind(pattern: drop())
|
2021-11-02 11:58:51 +00:00
|
|
|
|
2021-12-11 18:36:31 +00:00
|
|
|
proc `?_`*(): Pattern = drop()
|
|
|
|
proc `?*`*(): Pattern = grab()
|
2021-10-29 12:06:00 +00:00
|
|
|
|
2022-06-09 01:19:12 +00:00
|
|
|
proc `?`*[A, B](table: TableRef[A,B]): Pattern =
|
|
|
|
raiseAssert "not implemented"
|
|
|
|
|
2022-06-10 15:46:57 +00:00
|
|
|
proc recordPattern*(label: Preserve[Ref], fields: varargs[Pattern]): Pattern =
|
|
|
|
?DCompoundRec(label: label, fields: fields.toSeq)
|
|
|
|
|
2022-03-11 05:43:54 +00:00
|
|
|
type
|
|
|
|
Value = Preserve[Ref]
|
|
|
|
Path = seq[Value]
|
|
|
|
Analysis* = tuple
|
|
|
|
constPaths: seq[Path]
|
|
|
|
constValues: seq[Value]
|
|
|
|
capturePaths: seq[Path]
|
|
|
|
|
|
|
|
func walk(result: var Analysis; path: var Path; p: Pattern)
|
|
|
|
|
|
|
|
func walk(result: var Analysis; path: var Path; key: int|Value; pat: Pattern) =
|
|
|
|
path.add(key.toPreserve(Ref))
|
|
|
|
walk(result, path, pat)
|
|
|
|
discard path.pop
|
|
|
|
|
|
|
|
func walk(result: var Analysis; path: var Path; p: Pattern) =
|
|
|
|
case p.orKind
|
|
|
|
of PatternKind.DCompound:
|
|
|
|
case p.dcompound.orKind
|
|
|
|
of DCompoundKind.rec:
|
|
|
|
for k, e in p.dcompound.rec.fields: walk(result, path, k, e)
|
|
|
|
of DCompoundKind.arr:
|
|
|
|
for k, e in p.dcompound.arr.items: walk(result, path, k, e)
|
|
|
|
of DCompoundKind.dict:
|
|
|
|
for k, e in p.dcompound.dict.entries: walk(result, path, k, e)
|
|
|
|
of PatternKind.DBind:
|
|
|
|
result.capturePaths.add(path)
|
|
|
|
walk(result, path, p.dbind.pattern)
|
|
|
|
of PatternKind.DDiscard: discard
|
|
|
|
of PatternKind.DLit:
|
|
|
|
result.constPaths.add(path)
|
|
|
|
result.constValues.add(p.dlit.value.toPreserve(Ref))
|
|
|
|
|
|
|
|
func analyse*(p: Pattern): Analysis =
|
|
|
|
var path: Path
|
|
|
|
walk(result, path, p)
|