Move utilities for records to a seperate module
This commit is contained in:
parent
c7e8c301f9
commit
5aa5ccbd09
|
@ -236,19 +236,6 @@ proc symbol*(s: string): Preserve {.inline.} =
|
||||||
## Symbol constructor.
|
## Symbol constructor.
|
||||||
Preserve(kind: pkSymbol, symbol: s)
|
Preserve(kind: pkSymbol, symbol: s)
|
||||||
|
|
||||||
proc initRecord*(label: Preserve; args: varargs[Preserve]): Preserve =
|
|
||||||
## Record constructor.
|
|
||||||
result = Preserve(kind: pkRecord,
|
|
||||||
record: newSeqOfCap[Preserve](1+args.len))
|
|
||||||
for arg in args:
|
|
||||||
assertValid(arg)
|
|
||||||
result.record.add(arg)
|
|
||||||
result.record.add(label)
|
|
||||||
|
|
||||||
proc initRecord*(label: string; args: varargs[Preserve]): Preserve {.inline.} =
|
|
||||||
## Record constructor that converts ``label`` to a symbol.
|
|
||||||
initRecord(symbol(label), args)
|
|
||||||
|
|
||||||
proc label*(prs: Preserve): Preserve {.inline.} =
|
proc label*(prs: Preserve): Preserve {.inline.} =
|
||||||
## Return the label of a record value.
|
## Return the label of a record value.
|
||||||
prs.record[prs.record.high]
|
prs.record[prs.record.high]
|
||||||
|
@ -612,32 +599,6 @@ proc preserveTo*(prs: Preserve; T: typedesc): T =
|
||||||
## Reverse of `toPreserve`.
|
## Reverse of `toPreserve`.
|
||||||
fromPreserve(result, prs)
|
fromPreserve(result, prs)
|
||||||
|
|
||||||
type RecordClass* = object
|
|
||||||
## Type of a preserves record.
|
|
||||||
label*: Preserve
|
|
||||||
arity*: Natural
|
|
||||||
|
|
||||||
proc `$`*(rec: RecordClass): string =
|
|
||||||
$rec.label & "/" & $rec.arity
|
|
||||||
|
|
||||||
proc init*(rec: RecordClass; fields: varargs[Preserve]): Preserve =
|
|
||||||
## Initialize a new record value.
|
|
||||||
assert(fields.len == rec.arity)
|
|
||||||
result = initRecord(rec.label, fields)
|
|
||||||
|
|
||||||
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*(val: Preserve): RecordClass =
|
|
||||||
## Derive the ``RecordClass`` of ``val``.
|
|
||||||
if val.kind != pkRecord:
|
|
||||||
raise newException(ValueError, "cannot derive class of non-record value " & $val)
|
|
||||||
assert(val.record.len > 0)
|
|
||||||
RecordClass(label: val.label, arity: val.arity)
|
|
||||||
|
|
||||||
proc len*(prs: Preserve): int =
|
proc len*(prs: Preserve): int =
|
||||||
## Return the number of values one level below ``prs``.
|
## Return the number of values one level below ``prs``.
|
||||||
case prs.kind
|
case prs.kind
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
import std/[macros, typetraits]
|
||||||
|
import ../preserves
|
||||||
|
|
||||||
|
proc initRecord*(label: Preserve; args: varargs[Preserve, toPreserve]): Preserve =
|
||||||
|
## Record constructor.
|
||||||
|
result = Preserve(kind: pkRecord,
|
||||||
|
record: newSeqOfCap[Preserve](1+args.len))
|
||||||
|
for arg in args:
|
||||||
|
assertValid(arg)
|
||||||
|
result.record.add(arg)
|
||||||
|
result.record.add(label)
|
||||||
|
|
||||||
|
proc initRecord*(label: string; args: varargs[Preserve, toPreserve]): Preserve {.inline.} =
|
||||||
|
## Record constructor that converts ``label`` to a symbol.
|
||||||
|
initRecord(symbol(label), args)
|
||||||
|
|
||||||
|
type RecordClass* = object
|
||||||
|
## Type of a preserves record.
|
||||||
|
label*: Preserve
|
||||||
|
arity*: Natural
|
||||||
|
|
||||||
|
proc `$`*(rec: RecordClass): string =
|
||||||
|
$rec.label & "/" & $rec.arity
|
||||||
|
|
||||||
|
proc init*(rec: RecordClass; fields: varargs[Preserve, toPreserve]): Preserve =
|
||||||
|
## Initialize a new record value.
|
||||||
|
assert(fields.len == rec.arity)
|
||||||
|
result = initRecord(rec.label, fields)
|
||||||
|
|
||||||
|
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*(val: Preserve): RecordClass =
|
||||||
|
## 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(label: val.label, arity: val.arity)
|
||||||
|
|
||||||
|
proc classOf*[T](x: T): RecordClass =
|
||||||
|
## Derive the ``RecordClass`` of ``T``.
|
||||||
|
# TODO: would be nice to get the class of a type without an instance.
|
||||||
|
when not T.hasCustomPragma(record):
|
||||||
|
raise newException(Defect, "{.record: \"…\".} must be present to determine classOf")
|
||||||
|
else:
|
||||||
|
result.label = preserves.symbol(T.getCustomPragmaVal(record))
|
||||||
|
for k, v in x.fieldPairs: inc(result.arity)
|
|
@ -0,0 +1,34 @@
|
||||||
|
# SPDX-License-Identifier: ISC
|
||||||
|
|
||||||
|
import streams, strutils, unittest
|
||||||
|
import bigints, preserves, preserves/records
|
||||||
|
|
||||||
|
suite "conversions":
|
||||||
|
test "dictionary":
|
||||||
|
type Bar = tuple
|
||||||
|
s: string
|
||||||
|
type Foobar = object
|
||||||
|
a, b: int
|
||||||
|
c: Bar
|
||||||
|
let
|
||||||
|
c = Foobar(a: 1, b: 2, c: (s: "ku",))
|
||||||
|
b = toPreserve(c)
|
||||||
|
a = preserveTo(b, Foobar)
|
||||||
|
check(a == c)
|
||||||
|
check(b.kind == pkDictionary)
|
||||||
|
expect Defect:
|
||||||
|
checkpoint $classOf(c)
|
||||||
|
|
||||||
|
test "records":
|
||||||
|
type Bar {.record: "bar".} = tuple
|
||||||
|
s: string
|
||||||
|
type Foobar {.record: "foo".} = object
|
||||||
|
a, b: int
|
||||||
|
c: Bar
|
||||||
|
let
|
||||||
|
c = Foobar(a: 1, b: 2, c: (s: "ku",))
|
||||||
|
b = toPreserve(c)
|
||||||
|
a = preserveTo(b, Foobar)
|
||||||
|
check(a == c)
|
||||||
|
check(b.kind == pkRecord)
|
||||||
|
check(classOf(c) == RecordClass(label: symbol"foo", arity: 3))
|
Loading…
Reference in New Issue