64 lines
2.3 KiB
Nim
64 lines
2.3 KiB
Nim
# SPDX-License-Identifier: ISC
|
|
|
|
import std/[macros, typetraits]
|
|
import ../preserves
|
|
|
|
type RecordClass*[EmbeddedType] = object
|
|
## Type of a preserves record.
|
|
label*: PreserveGen[EmbeddedType]
|
|
arity*: Natural
|
|
|
|
proc `$`*(rec: RecordClass): string =
|
|
$rec.label & "/" & $rec.arity
|
|
|
|
proc isClassOf*(rec: RecordClass; val: Preserve): bool =
|
|
## Compare the label and arity of ``val`` to the record type ``rec``.
|
|
if val.kind == pkRecord:
|
|
assert(val.record.len > 0)
|
|
result = val.label == rec.label and rec.arity == val.arity
|
|
|
|
proc classOf*[E](val: PreserveGen[E]): RecordClass[E] =
|
|
## Derive the ``RecordClass`` of ``val``.
|
|
if val.kind != pkRecord:
|
|
raise newException(Defect, "cannot derive class of non-record value " & $val)
|
|
assert(val.record.len > 0)
|
|
RecordClass[E](label: val.label, arity: val.arity)
|
|
|
|
proc classOf*[T](x: T; E = void): RecordClass[E] =
|
|
## Derive the ``RecordClass`` of ``x``.
|
|
when not T.hasCustomPragma(record): {.error: "no {.record.} pragma on " & $T.}
|
|
result.label = preserves.symbol(T.getCustomPragmaVal(record), E)
|
|
for k, v in x.fieldPairs: inc(result.arity)
|
|
|
|
proc classOf*(T: typedesc[tuple]): RecordClass =
|
|
## Derive the ``RecordClass`` of ``T``.
|
|
when not T.hasCustomPragma(record): {.error: "no {.record.} pragma on " & $T.}
|
|
RecordClass(
|
|
label: preserves.symbol(T.getCustomPragmaVal(record)),
|
|
arity: tupleLen(T))
|
|
|
|
proc init*(rec: RecordClass; fields: varargs[Preserve, toPreserve]): Preserve =
|
|
## Initialize a new record value.
|
|
assert(fields.len == rec.arity, $(fields.toPreserve) & " (arity " & $fields.len & ") is not of arity " & $rec.arity)
|
|
result = initRecord(rec.label, fields)
|
|
|
|
proc init*(T: typedesc[tuple]; fields: varargs[Preserve, toPreserve]): Preserve =
|
|
## Initialize a new record value.
|
|
init(classOf(T), fields)
|
|
|
|
proc `%`*(rec: RecordClass; fields: openArray[Preserve]): Preserve =
|
|
## Initialize a simple record value.
|
|
init(rec, fields)
|
|
|
|
proc `%`*(rec: RecordClass; field: Preserve): Preserve =
|
|
## Initialize a simple record value.
|
|
init(rec, [field])
|
|
|
|
proc `%`*[T](rec: RecordClass; field: T): Preserve =
|
|
## Initialize a simple record value.
|
|
init(rec, [toPreserve field])
|
|
|
|
proc `%`*(T: typedesc[tuple]; fields: varargs[Preserve, toPreserve]): Preserve =
|
|
## Initialize a new record value.
|
|
`%`(classOf(T), fields)
|