Use dedicated types for record alternates

This commit is contained in:
Emery Hemingway 2021-09-22 14:23:36 +02:00
parent ea50b05bad
commit 2451b441ad
1 changed files with 38 additions and 20 deletions

View File

@ -118,6 +118,21 @@ proc toEnumDef(name: string; sn: SchemaNode): PNode =
newEmpty(),
sn.toEnumTy)
proc typeDef(sn: SchemaNode; name: string; ty: PNode): PNode =
case sn.kind
of snkRecord:
nn(nkTypeDef,
nn(nkPragmaExpr,
name.ident.toExport,
nn(nkPragma,
nn(nkExprColonExpr,
ident"record",
PNode(kind: nkStrLit, strVal: sn.nodes[0].value.symbol)))),
newEmpty(),
ty)
else:
nn(nkTypeDef, name.ident.toExport, newEmpty(), ty)
proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PNode =
case sn.kind
of snkOr:
@ -136,6 +151,16 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
newEmpty()))
for bn in sn.nodes:
assert(bn.kind == snkAlt, $bn.kind)
doAssert(name != "", " no name for " & $sn)
var memberTypeIdent: PNode
if bn.altbranch.kind == snkRef:
memberTypeIdent = bn.altBranch.typeIdent
else:
let memberTypeName = name & bn.altLabel.nimIdentNormalize
memberTypeIdent = ident memberTypeName
if memberTypeName notin known:
let ty = nimTypeOf(scm, known, bn.altBranch, memberTypeName)
known[memberTypeName] = typeDef(bn.altBranch, memberTypeName, ty)
var recList = nkRecList.newNode
case bn.altBranch.kind
of snkRecord:
@ -149,13 +174,10 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
nimTypeOf(scm, known, bn.altBranch.nodes[1], $label),
newEmpty())
else:
for i, field in bn.altBranch.nodes:
if i > 0 and (not isConst(scm, field)):
let label = field.ident
recList.add nkIdentDefs.newNode.add(
label.toExport,
nimTypeOf(scm, known, field, $label),
newEmpty())
recList.add nkIdentDefs.newNode.add(
bn.ident.toExport,
memberTypeIdent,
newEmpty())
else:
if isConst(scm, bn.altBranch):
recList.add nkDiscardStmt.newNode.add(newEmpty())
@ -168,7 +190,10 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
let disc = nkDotExpr.newNode.add(
enumIdent, bn.altLabel.nimIdentNormalize.ident.accQuote)
if recList.len == 0:
recList.add nn(nkDiscardStmt, newEmpty())
recList.add nkIdentDefs.newNode.add(
bn.ident.toExport,
memberTypeIdent,
newEmpty())
recCase.add nkOfBranch.newNode.add(disc, recList)
result = nn(nkRefTy, nn(nkObjectTy,
newEmpty(),
@ -370,7 +395,7 @@ proc generateProcs(result: var seq[PNode]; scm: Schema; name: string; sn: Schema
of snkOr:
var
enumId = name.ident
paramId = name.toLowerAscii.ident.accQuote
paramId = ident"v"
orStmts = nn(nkStmtList)
if sn.isSymbolEnum:
let caseStmt = nn(nkCaseStmt, paramId)
@ -399,8 +424,9 @@ proc generateProcs(result: var seq[PNode]; scm: Schema; name: string; sn: Schema
of snkTuple, snkVariableTuple:
stmts.add tupleConstructor(scm, sn, nn(nkDotExpr, paramId, fieldId))
of snkAtom, snkSequenceOf:
# already handled by toPreserve
discard
stmts.add nn(nkCall,
ident"toPreserve",
nn(nkDotExpr, paramId, fieldId))
else:
raiseAssert("no case statement for " & $sn.kind & " " & $sn)
for bn in sn.nodes:
@ -539,15 +565,7 @@ proc generateNimFile*(scm: Schema; path: string) =
name.ident.toExport, newEmpty(), t)
else:
if def.kind == snkRecord:
knownTypes[name] = nn(nkTypeDef,
nn(nkPragmaExpr,
name.ident.toExport,
nn(nkPragma,
nn(nkExprColonExpr,
ident"record",
PNode(kind: nkStrLit, strVal: $def.nodes[0].value.symbol)))),
newEmpty(),
t)
knownTypes[name] = typeDef(def, name, t)
else:
case t.kind
of nkEnumTy: