2021-10-28 17:43:20 +00:00
|
|
|
# SPDX-FileCopyrightText: ☭ 2021 Emery Hemingway
|
|
|
|
# SPDX-License-Identifier: Unlicense
|
|
|
|
|
2021-12-11 18:36:31 +00:00
|
|
|
import std/[macros, 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
|
|
|
|
|
2021-10-29 12:06:00 +00:00
|
|
|
export dataspacePatterns.`$`
|
|
|
|
|
2021-10-28 17:43:20 +00:00
|
|
|
type
|
2022-03-07 23:53:05 +00:00
|
|
|
AnyAtom = dataspacePatterns.AnyAtom[Ref]
|
|
|
|
DBind = dataspacePatterns.DBind[Ref]
|
2021-10-29 12:06:00 +00:00
|
|
|
DCompound* = dataspacePatterns.DCompound[Ref]
|
2022-03-07 23:53:05 +00:00
|
|
|
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]
|
|
|
|
|
2021-10-29 12:06:00 +00:00
|
|
|
proc `?`*(d: DBind): Pattern =
|
|
|
|
Pattern(orKind: PatternKind.DBind, dbind: d)
|
|
|
|
|
|
|
|
proc `?`*(d: DLit): Pattern =
|
|
|
|
Pattern(orKind: PatternKind.DLit, dlit: d)
|
|
|
|
|
|
|
|
proc `?`*(d: DCompound): Pattern =
|
|
|
|
Pattern(orKind: PatternKind.DCompound, dcompound: d)
|
|
|
|
|
2022-03-07 23:53:05 +00:00
|
|
|
proc `?`*(x: bool): Pattern =
|
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`bool`, bool: x))
|
|
|
|
|
|
|
|
proc `?`*(x: float32): Pattern =
|
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`float`, float: x))
|
|
|
|
|
|
|
|
proc `?`*(x: float64): Pattern =
|
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`double`, double: x))
|
|
|
|
|
|
|
|
proc `?`*(x: int): Pattern =
|
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`int`, int: x))
|
|
|
|
|
2021-11-02 11:58:51 +00:00
|
|
|
proc `?`*(s: string): Pattern =
|
2022-03-07 23:53:05 +00:00
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`string`, string: s))
|
|
|
|
|
|
|
|
proc `?`*(x: seq[byte]): Pattern =
|
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`bytes`, bytes: x))
|
|
|
|
|
|
|
|
proc `?`*(x: Symbol): Pattern =
|
|
|
|
?DLit(value: AnyAtom(orKind: AnyAtomKind.`symbol`, symbol: x))
|
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-03-07 23:53:05 +00:00
|
|
|
proc `?`*(T: typedesc; bindings: sink openArray[(int, Pattern)]): Pattern =
|
2021-10-29 12:06:00 +00:00
|
|
|
## Pattern constructor operator.
|
2022-03-07 23:53:05 +00:00
|
|
|
# TODO: get a pattern for T and then replace the inner patterns with bindings.
|
2021-10-29 12:06:00 +00:00
|
|
|
when T.hasCustomPragma(preservesRecord):
|
2022-03-07 23:53:05 +00:00
|
|
|
var
|
|
|
|
label = tosymbol(T.getCustomPragmaVal(preservesRecord), Ref)
|
|
|
|
fields = newSeq[Pattern]()
|
|
|
|
for (i, pat) in bindings:
|
|
|
|
if i > fields.high: fields.setLen(succ i)
|
|
|
|
fields[i] = pat
|
2021-10-29 12:06:00 +00:00
|
|
|
result = ?DCompound(
|
|
|
|
orKind: DCompoundKind.rec,
|
|
|
|
rec: DCompoundRec(
|
2022-03-07 23:53:05 +00:00
|
|
|
label: label, fields: fields))
|
2021-12-11 18:36:31 +00:00
|
|
|
elif T is ref:
|
|
|
|
`?`(pointerBase(T), bindings)
|
2021-11-02 11:58:51 +00:00
|
|
|
else:
|
2022-03-07 23:53:05 +00:00
|
|
|
{.error: "no preserves pragma on " & $T.}
|
|
|
|
|
|
|
|
proc `?`*(T: typedesc): Pattern =
|
|
|
|
## Derive a `Pattern` from type `T`.
|
|
|
|
## This works for `tuple` and `object` types but in the
|
|
|
|
## general case will return a wildcard binding.
|
|
|
|
when T.hasCustomPragma(preservesRecord):
|
|
|
|
var
|
|
|
|
label = tosymbol(T.getCustomPragmaVal(preservesRecord), Ref)
|
|
|
|
fields = newSeq[Pattern]()
|
|
|
|
dummy: ptr T
|
|
|
|
for key, val in fieldPairs(dummy[]):
|
|
|
|
fields.add grab()
|
|
|
|
result = ?DCompound(
|
|
|
|
orKind: DCompoundKind.rec,
|
|
|
|
rec: DCompoundRec(
|
|
|
|
label: label, fields: fields))
|
|
|
|
elif T is tuple:
|
|
|
|
var
|
|
|
|
arr = DCompoundArr()
|
|
|
|
dummy: ptr T
|
|
|
|
for key, val in fieldPairs(dummy[]):
|
|
|
|
arr.items.add ?(typeOf val)
|
|
|
|
result = ?DCompound(
|
|
|
|
orKind: DCompoundKind.arr,
|
|
|
|
arr: arr)
|
|
|
|
elif T is object:
|
|
|
|
var
|
|
|
|
dict = DCompoundDict()
|
|
|
|
dummy: ptr T
|
|
|
|
for key, val in fieldPairs(dummy[]):
|
|
|
|
dict.entries[key.toSymbol(Ref)] = grab() #?(typeOf val)
|
|
|
|
result = ?DCompound(
|
|
|
|
orKind: DCompoundKind.dict,
|
|
|
|
dict: dict)
|
|
|
|
elif T is ref:
|
|
|
|
?pointerBase(T)
|
|
|
|
else:
|
|
|
|
grab() # capture any value
|