Refactor preserves_schema_nim
This commit is contained in:
parent
efd5cf62df
commit
7edc05a35d
|
@ -40,16 +40,17 @@ proc ident(sn: SchemaNode): PNode =
|
|||
case sn.kind
|
||||
of snkAlt:
|
||||
s = sn.altLabel.nimIdentNormalize
|
||||
s[0] = s[0].toLowerAscii
|
||||
of snkLiteral: s = $sn.value
|
||||
of snkRecord:
|
||||
s = $sn.nodes[0]
|
||||
s = sn.nodes[0].value.symbol
|
||||
of snkNamed:
|
||||
s = sn.name
|
||||
of snkDictionary, snkVariableTuple:
|
||||
s = "data"
|
||||
else:
|
||||
raiseAssert("no ident for " & $sn.kind & " " & $sn)
|
||||
ident(s)
|
||||
s.ident.accQuote
|
||||
|
||||
proc typeIdent(sn: SchemaNode): PNode =
|
||||
case sn.kind
|
||||
|
@ -85,6 +86,17 @@ proc isConst(scm: Schema; sn: SchemaNode): bool =
|
|||
result = isConst(scm, scm.definitions[sn.refPath[0]])
|
||||
else: discard
|
||||
|
||||
proc literal(scm: Schema; sn: SchemaNode): Preserve =
|
||||
case sn.kind
|
||||
of snkLiteral: result = sn.value
|
||||
of snkRef:
|
||||
if sn.refPath.len == 1:
|
||||
result = literal(scm, scm.definitions[sn.refPath[0]])
|
||||
else:
|
||||
raiseAssert("not convertable to a literal: " & $sn)
|
||||
else:
|
||||
raiseAssert("not convertable to a literal: " & $sn)
|
||||
|
||||
proc isSymbolEnum(sn: SchemaNode): bool =
|
||||
if sn.kind == snkOr:
|
||||
for bn in sn.nodes:
|
||||
|
@ -133,7 +145,7 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
|
|||
if not isConst(scm, bn.altBranch.nodes[1]):
|
||||
let label = bn.ident
|
||||
recList.add nkIdentDefs.newNode.add(
|
||||
label.accQuote.toExport,
|
||||
label.toExport,
|
||||
nimTypeOf(scm, known, bn.altBranch.nodes[1], $label),
|
||||
newEmpty())
|
||||
else:
|
||||
|
@ -141,7 +153,7 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
|
|||
if i > 0 and (not isConst(scm, field)):
|
||||
let label = field.ident
|
||||
recList.add nkIdentDefs.newNode.add(
|
||||
label.accQuote.toExport,
|
||||
label.toExport,
|
||||
nimTypeOf(scm, known, field, $label),
|
||||
newEmpty())
|
||||
else:
|
||||
|
@ -150,7 +162,7 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
|
|||
else:
|
||||
let label = bn.ident
|
||||
recList.add(nkIdentDefs.newNode.add(
|
||||
label.accQuote,
|
||||
label,
|
||||
nimTypeOf(scm, known, bn.altBranch, $label),
|
||||
newEmpty()))
|
||||
let disc = nkDotExpr.newNode.add(
|
||||
|
@ -186,7 +198,6 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
|
|||
nkBracketExpr, ident"HashSet", ident"Preserve")
|
||||
of pkDictionary: nn(
|
||||
nkBracketExpr, ident"Table", ident"Preserve", ident"Preserve")
|
||||
of pkEmbedded: nn(nkDiscardStmt, newEmpty()) # TODO: is this possible?
|
||||
of snkSequenceOf:
|
||||
result = nkBracketExpr.newNode.add(
|
||||
ident"seq",
|
||||
|
@ -197,7 +208,7 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
|
|||
nimTypeOf(scm, known, sn.child))
|
||||
of snkDictOf:
|
||||
result = nkBracketExpr.newNode.add(
|
||||
ident"TableRef",
|
||||
ident"Table",
|
||||
nimTypeOf(scm, known, sn.nodes[0]),
|
||||
nimTypeOf(scm, known, sn.nodes[1]))
|
||||
of snkRecord:
|
||||
|
@ -213,31 +224,53 @@ proc nimTypeOf(scm: Schema; known: var TypeTable; sn: SchemaNode; name = ""): PN
|
|||
if i > 0:
|
||||
let id = field.ident
|
||||
recList.add nkIdentDefs.newNode.add(
|
||||
id.accQuote.toExport,
|
||||
id.toExport,
|
||||
nimTypeOf(scm, known, field, $id),
|
||||
newEmpty())
|
||||
result = nn(nkRefTy, nn(nkObjectTy,
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
recList))
|
||||
of snkTuple, snkVariableTuple:
|
||||
of snkTuple:
|
||||
# TODO: the variable part
|
||||
result = nkTupleTy.newNode
|
||||
for tn in sn.nodes:
|
||||
result.add nkIdentDefs.newNode.add(
|
||||
tn.ident.accQuote, nimTypeOf(scm, known, tn), newEmpty())
|
||||
if not isConst(scm, sn):
|
||||
result.add nkIdentDefs.newNode.add(
|
||||
tn.ident, nimTypeOf(scm, known, tn), newEmpty())
|
||||
of snkVariableTuple:
|
||||
result = nkTupleTy.newNode
|
||||
for i, tn in sn.nodes:
|
||||
if not isConst(scm, sn):
|
||||
if i == sn.nodes.high:
|
||||
result.add nkIdentDefs.newNode.add(
|
||||
tn.ident,
|
||||
nn(nkBracketExpr, ident"seq", nimTypeOf(scm, known, tn)),
|
||||
newEmpty())
|
||||
else:
|
||||
result.add nkIdentDefs.newNode.add(
|
||||
tn.ident, nimTypeOf(scm, known, tn), newEmpty())
|
||||
of snkDictionary:
|
||||
result = nkTupleTy.newNode
|
||||
for i in countup(0, sn.nodes.high, 2):
|
||||
let id = ident(sn.nodes[i+0])
|
||||
result.add nkIdentDefs.newNode.add(
|
||||
id.accQuote,
|
||||
id,
|
||||
nimTypeOf(scm, known, sn.nodes[i+1], $id),
|
||||
newEmpty())
|
||||
of snkNamed:
|
||||
result = nimTypeOf(scm, known, sn.pattern, name)
|
||||
of snkRef:
|
||||
result = typeIdent(sn)
|
||||
if sn.refPath.len == 1:
|
||||
let
|
||||
refName = sn.refPath[0]
|
||||
refDef = scm.definitions[refName]
|
||||
case refDef.kind
|
||||
of snkDictOf:
|
||||
result = nimTypeOf(scm, known, refDef, refName)
|
||||
else: result = typeIdent(sn)
|
||||
else:
|
||||
result = typeIdent(sn)
|
||||
else:
|
||||
result = nkCommentStmt.newNode
|
||||
result.comment.add("Missing type generator for " & $sn.kind & " " & $sn)
|
||||
|
@ -254,9 +287,7 @@ proc generateConstProcs(result: var seq[PNode]; name: string; def: SchemaNode) =
|
|||
of pkSymbol:
|
||||
discard stmts.add nn(nkCall,
|
||||
ident"symbol",
|
||||
PNode(kind: nkStrLit,
|
||||
strVal: def.value.symbol),
|
||||
ident"EmbeddedType")
|
||||
PNode(kind: nkStrLit, strVal: def.value.symbol))
|
||||
else:
|
||||
raiseAssert("conversion of " & $def & " to a Nim literal is not implemented")
|
||||
var procId = name
|
||||
|
@ -279,23 +310,126 @@ proc toNimLit(sn: SchemaNode): PNode =
|
|||
of pkSymbol:
|
||||
nkCall.newNode.add(
|
||||
ident"symbol",
|
||||
PNode(kind: nkStrLit, strVal: sn.value.symbol),
|
||||
ident"EmbeddedType")
|
||||
PNode(kind: nkStrLit, strVal: sn.value.symbol))
|
||||
else:
|
||||
raiseAssert("no Nim literal for " & $sn)
|
||||
|
||||
proc generateProcs(result: var seq[PNode]; name: string; sn: SchemaNode) =
|
||||
proc literalToPreserveCall(pr: Preserve): PNode =
|
||||
var prConstr = nn(nkObjConstr, ident"Preserve")
|
||||
proc constr(kind, field: string; lit: PNode) =
|
||||
prConstr.add nn(nkExprColonExpr, ident"kind", ident(kind))
|
||||
prConstr.add nn(nkExprColonExpr, ident(field), lit)
|
||||
case pr.kind
|
||||
of pkBoolean:
|
||||
constr($pr.kind, "bool", if pr.bool: ident"true" else: ident"false")
|
||||
of pkFloat:
|
||||
constr($pr.kind, "float", newFloatNode(nkFloat32Lit, pr.float))
|
||||
of pkDouble:
|
||||
constr($pr.kind, "double", newFloatNode(nkFloat64Lit, pr.double))
|
||||
of pkSignedInteger:
|
||||
constr($pr.kind, "int", newIntNode(nkInt64Lit, pr.int))
|
||||
of pkString:
|
||||
constr($pr.kind, "string", newStrNode(nkTripleStrLit, pr.string))
|
||||
of pkByteString:
|
||||
return nn(nkCall, ident"parsePreserves", newStrNode(nkTripleStrLit, $pr))
|
||||
of pkSymbol:
|
||||
constr($pr.kind, "symbol", newStrNode(nkStrLit, pr.symbol))
|
||||
else:
|
||||
raise newException(ValueError, "refusing to convert to a literal: " & $pr)
|
||||
prConstr
|
||||
|
||||
proc tupleConstructor(scm: Schema; sn: SchemaNode; ident: PNode): Pnode =
|
||||
let seqBracket = nn(nkBracket)
|
||||
for i, field in sn.nodes:
|
||||
if isConst(scm, field):
|
||||
seqBracket.add literalToPreserveCall(literal(scm, field))
|
||||
elif sn.kind == snkTuple or i < sn.nodes.high:
|
||||
seqBracket.add nn(nkCall,
|
||||
ident"toPreserve",
|
||||
nn(nkDotExpr, ident, field.ident))
|
||||
let seqConstr = nn(nkPrefix, ident"@", seqBracket)
|
||||
let colonExpr = nn(nkExprColonExpr, ident"sequence")
|
||||
if sn.kind == snkTuple:
|
||||
colonExpr.add seqConstr
|
||||
else:
|
||||
colonExpr.add nn(nkInfix,
|
||||
ident"&",
|
||||
seqConstr,
|
||||
nn(nkDotExpr,
|
||||
nn(nkCall, ident"toPreserve",
|
||||
nn(nkDotExpr,
|
||||
ident, sn.nodes[sn.nodes.high].ident)),
|
||||
ident"sequence"))
|
||||
nn(nkObjConstr,
|
||||
ident"Preserve",
|
||||
nn(nkExprColonExpr, ident"kind", ident"pkSequence"),
|
||||
colonExpr)
|
||||
|
||||
proc generateProcs(result: var seq[PNode]; scm: Schema; name: string; sn: SchemaNode) =
|
||||
case sn.kind
|
||||
of snkOr:
|
||||
var
|
||||
enumId = name.ident
|
||||
paramId = name.toLowerAscii.ident.accQuote
|
||||
orStmts = nn(nkStmtList)
|
||||
if sn.isSymbolEnum:
|
||||
let caseStmt = nn(nkCaseStmt, paramId)
|
||||
for bn in sn.nodes:
|
||||
caseStmt.add nn(nkOfBranch,
|
||||
nn(nkDotExpr,
|
||||
enumId,
|
||||
bn.altLabel.nimIdentNormalize.ident.accQuote),
|
||||
nn(nkCall,
|
||||
ident"symbol", PNode(kind: nkStrLit, strVal: $bn.altLabel)))
|
||||
orStmts.add caseStmt
|
||||
else:
|
||||
let caseStmt = nn(nkCaseStmt, nn(nkDotExpr, paramId, ident"kind"))
|
||||
proc genStmts(stmts: PNode; fieldId: PNode; sn: SchemaNode) =
|
||||
case sn.kind
|
||||
of snkLiteral:
|
||||
stmts.add literalToPreserveCall(literal(scm, sn))
|
||||
of snkOr, snkRecord, snkRef:
|
||||
if sn.kind == snkRef and sn.refPath.len == 1:
|
||||
let refDef = scm.definitions[sn.refPath[0]]
|
||||
genStmts(stmts, fieldId, refDef)
|
||||
else:
|
||||
stmts.add nn(nkCall,
|
||||
ident"toPreserve",
|
||||
nn(nkDotExpr, paramId, fieldId))
|
||||
of snkTuple, snkVariableTuple:
|
||||
stmts.add tupleConstructor(scm, sn, nn(nkDotExpr, paramId, fieldId))
|
||||
else:
|
||||
raiseAssert("no case statement for " & $sn.kind & " " & $sn)
|
||||
for bn in sn.nodes:
|
||||
let stmts = nn(nkStmtList)
|
||||
genStmts(stmts, bn.ident, bn.altBranch)
|
||||
caseStmt.add nn(nkOfBranch,
|
||||
nn(nkDotExpr,
|
||||
ident(name & "Kind"),
|
||||
bn.altLabel.nimIdentNormalize.ident.accQuote),
|
||||
stmts)
|
||||
orStmts.add caseStmt
|
||||
result.add nn(nkProcDef,
|
||||
exportIdent("toPreserveHook"),
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkFormalParams,
|
||||
ident"Preserve",
|
||||
nn(nkIdentDefs,
|
||||
paramId, ident(name), newEmpty())),
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
orStmts)
|
||||
of snkRecord:
|
||||
var
|
||||
params = nn(nkFormalParams, ident"Preserve")
|
||||
initRecordCall = nn(nkCall,
|
||||
nn(nkBracketExpr, ident"initRecord", ident"EmbeddedType"),
|
||||
ident"initRecord",
|
||||
sn.nodes[0].toNimLit)
|
||||
for i, field in sn.nodes:
|
||||
if i > 0:
|
||||
let
|
||||
id = field.ident.accQuote
|
||||
id = field.ident
|
||||
var fieldType = field.typeIdent
|
||||
if fieldType.kind != nkIdent or fieldType.ident.s != "Preserve":
|
||||
fieldType =
|
||||
|
@ -306,7 +440,7 @@ proc generateProcs(result: var seq[PNode]; name: string; sn: SchemaNode) =
|
|||
params.add nn(nkIdentDefs,
|
||||
id, fieldType, newEmpty())
|
||||
initRecordCall.add(
|
||||
nn(nkCall, ident"toPreserve", id, ident"EmbeddedType"))
|
||||
nn(nkCall, ident"toPreserve", id))
|
||||
var procId = name
|
||||
procId[0] = procId[0].toLowerAscii
|
||||
result.add nn(nkProcDef,
|
||||
|
@ -321,6 +455,40 @@ proc generateProcs(result: var seq[PNode]; name: string; sn: SchemaNode) =
|
|||
kind: nkCommentStmt,
|
||||
comment: "Preserves constructor for ``" & name & "``."),
|
||||
initRecordCall))
|
||||
block:
|
||||
let paramId = name.toLowerAscii.ident.accQuote
|
||||
initRecordCall = nn(nkCall,
|
||||
ident"initRecord",
|
||||
sn.nodes[0].toNimLit)
|
||||
for i, field in sn.nodes:
|
||||
if i > 0:
|
||||
initRecordCall.add nn(nkCall,
|
||||
ident"toPreserve",
|
||||
nn(nkDotExpr, paramId, field.ident))
|
||||
result.add nn(nkProcDef,
|
||||
exportIdent("toPreserveHook"),
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkFormalParams,
|
||||
ident"Preserve",
|
||||
nn(nkIdentDefs,
|
||||
paramId, ident(name), newEmpty())),
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkStmtList, initRecordCall))
|
||||
of snkTuple, snkVariableTuple:
|
||||
let paramId = name.toLowerAscii.ident.accQuote
|
||||
result.add nn(nkProcDef,
|
||||
exportIdent("toPreserveHook"),
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkFormalParams,
|
||||
ident"Preserve",
|
||||
nn(nkIdentDefs,
|
||||
paramId, ident(name), newEmpty())),
|
||||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkStmtList, tupleConstructor(scm, sn, paramId)))
|
||||
else: discard
|
||||
|
||||
proc collectRefImports(imports: PNode; sn: SchemaNode) =
|
||||
|
@ -350,22 +518,6 @@ proc generateNimFile*(scm: Schema; path: string) =
|
|||
typeSection = newNode nkTypeSection
|
||||
procs: seq[PNode]
|
||||
megaType: PNode
|
||||
if scm.embeddedType == "":
|
||||
typeSection.add nn(nkTypeDef,
|
||||
exportIdent"EmbeddedType",
|
||||
newEmpty(),
|
||||
ident"void")
|
||||
else:
|
||||
typeSection.add nn(nkTypeDef,
|
||||
exportIdent"EmbeddedType",
|
||||
newEmpty(),
|
||||
scm.embeddedType.ident)
|
||||
typeSection.add nn(nkTypeDef,
|
||||
ident"Preserve",
|
||||
newEmpty(),
|
||||
nn(nkBracketExpr,
|
||||
ident"PreserveGen",
|
||||
ident"EmbeddedType"))
|
||||
for name, def in scm.definitions.pairs:
|
||||
if isConst(scm, def):
|
||||
generateConstProcs(procs, name, def)
|
||||
|
@ -416,7 +568,7 @@ proc generateNimFile*(scm: Schema; path: string) =
|
|||
else:
|
||||
knownTypes[name] = nn(nkTypeDef,
|
||||
name.ident.toExport, newEmpty(), t)
|
||||
generateProcs(procs, name, def)
|
||||
generateProcs(procs, scm, name, def)
|
||||
for typeDef in knownTypes.values:
|
||||
typeSection.add typeDef
|
||||
var imports = nkImportStmt.newNode.add(
|
||||
|
@ -436,7 +588,7 @@ proc generateNimFile*(scm: Schema; path: string) =
|
|||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkStmtList,
|
||||
nn(nkCall, ident"$", nn(nkCall, ident"toPreserve", ident"x", ident"EmbeddedType"))))
|
||||
nn(nkCall, ident"$", nn(nkCall, ident"toPreserve", ident"x"))))
|
||||
procs.add nn(nkProcDef,
|
||||
"encode".ident.accQuote.toExport,
|
||||
newEmpty(),
|
||||
|
@ -450,7 +602,7 @@ proc generateNimFile*(scm: Schema; path: string) =
|
|||
newEmpty(),
|
||||
newEmpty(),
|
||||
nn(nkStmtList,
|
||||
nn(nkCall, ident"encode", nn(nkCall, ident"toPreserve", ident"x", ident"EmbeddedType"))))
|
||||
nn(nkCall, ident"encode", nn(nkCall, ident"toPreserve", ident"x"))))
|
||||
var module = newNode(nkStmtList).add(
|
||||
imports,
|
||||
typeSection
|
||||
|
|
|
@ -116,9 +116,6 @@ proc `$`*(n: SchemaNode): string =
|
|||
case n.value.kind
|
||||
of pkBoolean, pkFloat, pkDouble, pkSignedInteger, pkString, pkByteString:
|
||||
result.add $n.value
|
||||
of pkSymbol:
|
||||
result.add '='
|
||||
result.add n.value.symbol
|
||||
else:
|
||||
result.add "<<lit>" & $n.value & ">"
|
||||
of snkSequenceOf:
|
||||
|
|
Loading…
Reference in New Issue