# 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)