preserves_schema_nim: represent embeds with EmbeddedRef

Use EmbeddedRef for embbeded values, unless a schema does not name
an embedded type.
This commit is contained in:
Emery Hemingway 2024-01-06 19:28:14 +02:00
parent 74da21f3d5
commit 416af8ff5f
2 changed files with 40 additions and 52 deletions

View File

@ -1,6 +1,6 @@
# Package
version = "20240106"
version = "20240107"
author = "Emery Hemingway"
description = "data model and serialization format"
license = "Unlicense"

View File

@ -6,10 +6,7 @@
# the schema module must be regenerated!
# nim c --path:../../../nim --path:.. -r ./preserves_schema_nim ../../../preserves/schema/schema.bin
# This module formally parameterized types wherever embedded values were found.
# This is no longer the case but some of that code is lingering around.
import std/[hashes, strutils, sets, tables]
import std/[hashes, sets, strutils, tables]
# Cannot use std/macros, must use compiler modules because
# we are generating code at run-time.
@ -126,6 +123,23 @@ proc deref(loc: Location; r: Ref): (Location, Definition) =
except KeyError:
raise newException(KeyError, "reference not found in bundle: " & $r)
proc hasEmbeddedType(scm: Schema): bool =
case scm.field0.embeddedType.orKind
of EmbeddedtypenameKind.false: false
of EmbeddedtypenameKind.Ref: true
proc embeddedIdentString(scm: Schema): string =
doAssert $scm.field0.embeddedType.ref.name != ""
"Value"
proc embeddedIdent(scm: Schema): PNode =
ident(embeddedIdentString(scm))
proc parameterize(loc: Location; node: PNode; embeddable: bool): PNode = node
proc parameterize(loc: Location; spec: TypeSpec): PNode =
parameterize(loc, spec.node, spec.isEmbedded)
proc hash(r: Ref): Hash = r.toPreserves.hash
type RefSet = HashSet[Ref]
@ -138,8 +152,7 @@ proc attrs(loc: Location; n: NamedAlternative|NamedPattern; seen: RefSet): Attri
proc attrs(loc: Location; sp: SimplePattern; seen: RefSet): Attributes =
case sp.orKind
of SimplepatternKind.atom, SimplepatternKind.lit, SimplepatternKind.any: {}
of SimplepatternKind.embedded:
attrs(loc, sp.embedded.interface, seen)
of SimplepatternKind.embedded: {embedded}
of SimplepatternKind.seqof:
attrs(loc, sp.seqof.pattern, seen)
of SimplepatternKind.setof:
@ -297,7 +310,8 @@ proc isLiteral(loc: Location; sp: SimplePattern): bool =
of SimplepatternKind.lit:
result = true
of SimplepatternKind.embedded:
result = isLiteral(loc, sp.embedded.interface)
if not loc.schema.hasEmbeddedType:
result = isLiteral(loc, sp.embedded.interface)
else: discard
proc isLiteral(loc: Location; np: NamedPattern): bool =
@ -436,8 +450,12 @@ proc typeIdent(loc: Location; sp: SimplePattern): TypeSpec =
result.attrs = key.attrs + val.attrs
of SimplepatternKind.Ref:
result = TypeSpec(node: ident(sp.ref), attrs: attrs(loc, sp))
result.node = parameterize(loc, result)
of SimplepatternKind.embedded:
result = typeIdent(loc, sp.embedded.interface)
if loc.schema.hasEmbeddedType:
result = TypeSpec(node: ident"EmbeddedRef")
else:
result = TypeSpec(node: ident"Value")
incl(result.attrs, embedded)
of SimplepatternKind.any, SimplepatternKind.lit:
result = TypeSpec(node: ident"Value")
@ -466,6 +484,7 @@ proc toStrLit(loc: Location; sp: SimplePattern): PNode =
var (loc, def) = deref(loc, sp.ref)
result = toStrLit(loc, def)
of SimplePatternKind.embedded:
doAssert not loc.schema.hasEmbeddedType
result = PNode(kind: nkStrLit, strVal: "#!" & toStrLit(loc, sp.embedded.interface).strVal)
else: raiseAssert $sp
@ -484,6 +503,9 @@ proc toFieldIdent(loc: Location, label: string; pat: Pattern): PNode =
proc newEmpty(): PNode = newNode(nkEmpty)
proc embeddingParams(loc: Location; embeddable: bool): PNode =
newEmpty()
proc identDef(scm: Schema; a, b: PNode; embeddable: bool): PNode =
nkIdentDefs.newTree(a, b, newEmpty())
@ -534,7 +556,7 @@ proc typeDef(loc: Location; name: string; pat: SimplePattern; ty: PNode): PNode
proc typeDef(loc: Location; name: string; pat: Pattern; ty: PNode): PNode =
let
embedParams = newEmpty()
embedParams = embeddingParams(loc, isEmbedded(loc, pat))
id = name.ident.toExport
case pat.orKind
of PatternKind.CompoundPattern:
@ -576,7 +598,7 @@ proc typeDef(loc: Location; name: string; def: Definition; ty: PNode): PNode =
nkPragmaExpr.newTree(
name.ident.accQuote.toExport,
pragma),
newEmpty(),
embeddingParams(loc, isEmbedded(loc, def)),
ty)
of DefinitionKind.and:
var pragma = nkPragma.newNode
@ -586,7 +608,7 @@ proc typeDef(loc: Location; name: string; def: Definition; ty: PNode): PNode =
nkPragmaExpr.newTree(
name.ident.accQuote.toExport,
pragma),
newEmpty(),
embeddingParams(loc, isEmbedded(loc, def)),
ty)
of DefinitionKind.Pattern:
typeDef(loc, name, def.pattern, ty)
@ -682,7 +704,7 @@ proc addFields(recList: PNode; loc: Location; known: var TypeTable; parentName:
nkPragmaExpr.newTree(
ident(cp.tuplePrefix.variable, parentName).accQuote.toExport,
nkPragma.newTree(ident"preservesTupleTail")),
variableType.node,
parameterize(loc, variableType),
variableType.isEmbedded)
of CompoundPatternKind.dict:
for nameVal, nsp in cp.dict.entries:
@ -794,6 +816,8 @@ proc nimTypeOf(loc: Location; known: var TypeTable; name: string; orDef: Definit
known[memberPath] =
typeDef(loc, memberTypeName, na.pattern, ty.node)
addAttrs(result, memberType)
memberType.node = parameterize(
loc, memberType.node, isEmbedded(loc, na.pattern))
branchRecList.add nkIdentDefs.newTree(
toFieldIdent(loc, na.variantLabel.normalize, na.pattern),
memberType.node, newEmpty())
@ -982,19 +1006,16 @@ proc renderNimBundle*(bundle: Bundle): Table[string, string] =
var
typeSection = newNode nkTypeSection
procs: seq[PNode]
unembeddableType, embeddableType: PNode
unembeddableType: PNode
for name, def in scm.field0.definitions.pairs:
if isLiteral(loc, def):
generateConstProcs(procs, scm, string name, def)
else:
var name = string name
name[0] = name[0].toUpperAscii
var defIdent = ident(name)
var defIdent = parameterize(loc, ident(name), isEmbedded(loc, def))
if not isSymbolEnum(loc, def) and not isAny(loc, def):
if isEmbedded(loc, def):
mergeType(embeddableType, defIdent)
else:
mergeType(unembeddableType, defIdent)
mergeType(unembeddableType, defIdent)
let typeSpec = nimTypeOf(loc, typeDefs, name, def)
typeDefs[scmPath & @[Symbol name]] = typeDef(loc, name, def, typeSpec.node)
generateProcs(procs, scm, name, def)
@ -1003,45 +1024,12 @@ proc renderNimBundle*(bundle: Bundle): Table[string, string] =
if typepath.hasPrefix(scmPath):
add(typeSection, typeDef)
let imports = nkImportStmt.newNode.add(ident"preserves")
block:
var importSet: HashSet[string]
collectRefImports(importSet, loc, scm)
for module in importSet:
add(imports, ident(module))
if not embeddableType.isNil:
let genericParams = newEmpty()
procs.add nkProcDef.newTree(
"$".toFieldIdent,
newEmpty(),
genericParams,
nkFormalParams.newTree(
ident"string",
nkIdentDefs.newTree(
ident"x",
embeddableType,
newEmpty())),
newEmpty(),
newEmpty(),
nkStmtList.newTree(
nkCall.newTree(ident"$",
nkCall.newTree(ident"toPreserves", ident"x"))))
procs.add nkProcDef.newTree(
"encode".ident.toExport,
newEmpty(),
genericParams,
nkFormalParams.newTree(
nkBracketExpr.newTree(ident"seq", ident"byte"),
nkIdentDefs.newTree(
ident"x",
embeddableType,
newEmpty())),
newEmpty(),
newEmpty(),
nkStmtList.newTree(
nkCall.newTree(ident"encode",
nkCall.newTree(ident"toPreserves", ident"x"))))
if not unembeddableType.isNil:
procs.add nkProcDef.newTree(
"$".toFieldIdent,