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:
parent
74da21f3d5
commit
416af8ff5f
|
@ -1,6 +1,6 @@
|
||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "20240106"
|
version = "20240107"
|
||||||
author = "Emery Hemingway"
|
author = "Emery Hemingway"
|
||||||
description = "data model and serialization format"
|
description = "data model and serialization format"
|
||||||
license = "Unlicense"
|
license = "Unlicense"
|
||||||
|
|
|
@ -6,10 +6,7 @@
|
||||||
# the schema module must be regenerated!
|
# the schema module must be regenerated!
|
||||||
# nim c --path:../../../nim --path:.. -r ./preserves_schema_nim ../../../preserves/schema/schema.bin
|
# nim c --path:../../../nim --path:.. -r ./preserves_schema_nim ../../../preserves/schema/schema.bin
|
||||||
|
|
||||||
# This module formally parameterized types wherever embedded values were found.
|
import std/[hashes, sets, strutils, tables]
|
||||||
# This is no longer the case but some of that code is lingering around.
|
|
||||||
|
|
||||||
import std/[hashes, strutils, sets, tables]
|
|
||||||
|
|
||||||
# Cannot use std/macros, must use compiler modules because
|
# Cannot use std/macros, must use compiler modules because
|
||||||
# we are generating code at run-time.
|
# we are generating code at run-time.
|
||||||
|
@ -126,6 +123,23 @@ proc deref(loc: Location; r: Ref): (Location, Definition) =
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise newException(KeyError, "reference not found in bundle: " & $r)
|
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
|
proc hash(r: Ref): Hash = r.toPreserves.hash
|
||||||
type RefSet = HashSet[Ref]
|
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 =
|
proc attrs(loc: Location; sp: SimplePattern; seen: RefSet): Attributes =
|
||||||
case sp.orKind
|
case sp.orKind
|
||||||
of SimplepatternKind.atom, SimplepatternKind.lit, SimplepatternKind.any: {}
|
of SimplepatternKind.atom, SimplepatternKind.lit, SimplepatternKind.any: {}
|
||||||
of SimplepatternKind.embedded:
|
of SimplepatternKind.embedded: {embedded}
|
||||||
attrs(loc, sp.embedded.interface, seen)
|
|
||||||
of SimplepatternKind.seqof:
|
of SimplepatternKind.seqof:
|
||||||
attrs(loc, sp.seqof.pattern, seen)
|
attrs(loc, sp.seqof.pattern, seen)
|
||||||
of SimplepatternKind.setof:
|
of SimplepatternKind.setof:
|
||||||
|
@ -297,6 +310,7 @@ proc isLiteral(loc: Location; sp: SimplePattern): bool =
|
||||||
of SimplepatternKind.lit:
|
of SimplepatternKind.lit:
|
||||||
result = true
|
result = true
|
||||||
of SimplepatternKind.embedded:
|
of SimplepatternKind.embedded:
|
||||||
|
if not loc.schema.hasEmbeddedType:
|
||||||
result = isLiteral(loc, sp.embedded.interface)
|
result = isLiteral(loc, sp.embedded.interface)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
@ -436,8 +450,12 @@ proc typeIdent(loc: Location; sp: SimplePattern): TypeSpec =
|
||||||
result.attrs = key.attrs + val.attrs
|
result.attrs = key.attrs + val.attrs
|
||||||
of SimplepatternKind.Ref:
|
of SimplepatternKind.Ref:
|
||||||
result = TypeSpec(node: ident(sp.ref), attrs: attrs(loc, sp))
|
result = TypeSpec(node: ident(sp.ref), attrs: attrs(loc, sp))
|
||||||
|
result.node = parameterize(loc, result)
|
||||||
of SimplepatternKind.embedded:
|
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)
|
incl(result.attrs, embedded)
|
||||||
of SimplepatternKind.any, SimplepatternKind.lit:
|
of SimplepatternKind.any, SimplepatternKind.lit:
|
||||||
result = TypeSpec(node: ident"Value")
|
result = TypeSpec(node: ident"Value")
|
||||||
|
@ -466,6 +484,7 @@ proc toStrLit(loc: Location; sp: SimplePattern): PNode =
|
||||||
var (loc, def) = deref(loc, sp.ref)
|
var (loc, def) = deref(loc, sp.ref)
|
||||||
result = toStrLit(loc, def)
|
result = toStrLit(loc, def)
|
||||||
of SimplePatternKind.embedded:
|
of SimplePatternKind.embedded:
|
||||||
|
doAssert not loc.schema.hasEmbeddedType
|
||||||
result = PNode(kind: nkStrLit, strVal: "#!" & toStrLit(loc, sp.embedded.interface).strVal)
|
result = PNode(kind: nkStrLit, strVal: "#!" & toStrLit(loc, sp.embedded.interface).strVal)
|
||||||
else: raiseAssert $sp
|
else: raiseAssert $sp
|
||||||
|
|
||||||
|
@ -484,6 +503,9 @@ proc toFieldIdent(loc: Location, label: string; pat: Pattern): PNode =
|
||||||
|
|
||||||
proc newEmpty(): PNode = newNode(nkEmpty)
|
proc newEmpty(): PNode = newNode(nkEmpty)
|
||||||
|
|
||||||
|
proc embeddingParams(loc: Location; embeddable: bool): PNode =
|
||||||
|
newEmpty()
|
||||||
|
|
||||||
proc identDef(scm: Schema; a, b: PNode; embeddable: bool): PNode =
|
proc identDef(scm: Schema; a, b: PNode; embeddable: bool): PNode =
|
||||||
nkIdentDefs.newTree(a, b, newEmpty())
|
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 =
|
proc typeDef(loc: Location; name: string; pat: Pattern; ty: PNode): PNode =
|
||||||
let
|
let
|
||||||
embedParams = newEmpty()
|
embedParams = embeddingParams(loc, isEmbedded(loc, pat))
|
||||||
id = name.ident.toExport
|
id = name.ident.toExport
|
||||||
case pat.orKind
|
case pat.orKind
|
||||||
of PatternKind.CompoundPattern:
|
of PatternKind.CompoundPattern:
|
||||||
|
@ -576,7 +598,7 @@ proc typeDef(loc: Location; name: string; def: Definition; ty: PNode): PNode =
|
||||||
nkPragmaExpr.newTree(
|
nkPragmaExpr.newTree(
|
||||||
name.ident.accQuote.toExport,
|
name.ident.accQuote.toExport,
|
||||||
pragma),
|
pragma),
|
||||||
newEmpty(),
|
embeddingParams(loc, isEmbedded(loc, def)),
|
||||||
ty)
|
ty)
|
||||||
of DefinitionKind.and:
|
of DefinitionKind.and:
|
||||||
var pragma = nkPragma.newNode
|
var pragma = nkPragma.newNode
|
||||||
|
@ -586,7 +608,7 @@ proc typeDef(loc: Location; name: string; def: Definition; ty: PNode): PNode =
|
||||||
nkPragmaExpr.newTree(
|
nkPragmaExpr.newTree(
|
||||||
name.ident.accQuote.toExport,
|
name.ident.accQuote.toExport,
|
||||||
pragma),
|
pragma),
|
||||||
newEmpty(),
|
embeddingParams(loc, isEmbedded(loc, def)),
|
||||||
ty)
|
ty)
|
||||||
of DefinitionKind.Pattern:
|
of DefinitionKind.Pattern:
|
||||||
typeDef(loc, name, def.pattern, ty)
|
typeDef(loc, name, def.pattern, ty)
|
||||||
|
@ -682,7 +704,7 @@ proc addFields(recList: PNode; loc: Location; known: var TypeTable; parentName:
|
||||||
nkPragmaExpr.newTree(
|
nkPragmaExpr.newTree(
|
||||||
ident(cp.tuplePrefix.variable, parentName).accQuote.toExport,
|
ident(cp.tuplePrefix.variable, parentName).accQuote.toExport,
|
||||||
nkPragma.newTree(ident"preservesTupleTail")),
|
nkPragma.newTree(ident"preservesTupleTail")),
|
||||||
variableType.node,
|
parameterize(loc, variableType),
|
||||||
variableType.isEmbedded)
|
variableType.isEmbedded)
|
||||||
of CompoundPatternKind.dict:
|
of CompoundPatternKind.dict:
|
||||||
for nameVal, nsp in cp.dict.entries:
|
for nameVal, nsp in cp.dict.entries:
|
||||||
|
@ -794,6 +816,8 @@ proc nimTypeOf(loc: Location; known: var TypeTable; name: string; orDef: Definit
|
||||||
known[memberPath] =
|
known[memberPath] =
|
||||||
typeDef(loc, memberTypeName, na.pattern, ty.node)
|
typeDef(loc, memberTypeName, na.pattern, ty.node)
|
||||||
addAttrs(result, memberType)
|
addAttrs(result, memberType)
|
||||||
|
memberType.node = parameterize(
|
||||||
|
loc, memberType.node, isEmbedded(loc, na.pattern))
|
||||||
branchRecList.add nkIdentDefs.newTree(
|
branchRecList.add nkIdentDefs.newTree(
|
||||||
toFieldIdent(loc, na.variantLabel.normalize, na.pattern),
|
toFieldIdent(loc, na.variantLabel.normalize, na.pattern),
|
||||||
memberType.node, newEmpty())
|
memberType.node, newEmpty())
|
||||||
|
@ -982,18 +1006,15 @@ proc renderNimBundle*(bundle: Bundle): Table[string, string] =
|
||||||
var
|
var
|
||||||
typeSection = newNode nkTypeSection
|
typeSection = newNode nkTypeSection
|
||||||
procs: seq[PNode]
|
procs: seq[PNode]
|
||||||
unembeddableType, embeddableType: PNode
|
unembeddableType: PNode
|
||||||
for name, def in scm.field0.definitions.pairs:
|
for name, def in scm.field0.definitions.pairs:
|
||||||
if isLiteral(loc, def):
|
if isLiteral(loc, def):
|
||||||
generateConstProcs(procs, scm, string name, def)
|
generateConstProcs(procs, scm, string name, def)
|
||||||
else:
|
else:
|
||||||
var name = string name
|
var name = string name
|
||||||
name[0] = name[0].toUpperAscii
|
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 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)
|
let typeSpec = nimTypeOf(loc, typeDefs, name, def)
|
||||||
typeDefs[scmPath & @[Symbol name]] = typeDef(loc, name, def, typeSpec.node)
|
typeDefs[scmPath & @[Symbol name]] = typeDef(loc, name, def, typeSpec.node)
|
||||||
|
@ -1003,45 +1024,12 @@ proc renderNimBundle*(bundle: Bundle): Table[string, string] =
|
||||||
if typepath.hasPrefix(scmPath):
|
if typepath.hasPrefix(scmPath):
|
||||||
add(typeSection, typeDef)
|
add(typeSection, typeDef)
|
||||||
|
|
||||||
|
|
||||||
let imports = nkImportStmt.newNode.add(ident"preserves")
|
let imports = nkImportStmt.newNode.add(ident"preserves")
|
||||||
block:
|
block:
|
||||||
var importSet: HashSet[string]
|
var importSet: HashSet[string]
|
||||||
collectRefImports(importSet, loc, scm)
|
collectRefImports(importSet, loc, scm)
|
||||||
for module in importSet:
|
for module in importSet:
|
||||||
add(imports, ident(module))
|
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:
|
if not unembeddableType.isNil:
|
||||||
procs.add nkProcDef.newTree(
|
procs.add nkProcDef.newTree(
|
||||||
"$".toFieldIdent,
|
"$".toFieldIdent,
|
||||||
|
|
Loading…
Reference in New Issue