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