make json.to work with the more restricted case objects

This commit is contained in:
Araq 2019-05-27 15:33:17 +02:00 • committed by Andreas Rumpf
commit 383147f5cb
2 changed files with 14 additions and 17 deletions

View file

@ -1111,11 +1111,11 @@ proc processObjField(field, jsonNode: NimNode): seq[NimNode] =
exprColonExpr.add(createConstructor(typeNode, indexedJsonNode)) exprColonExpr.add(createConstructor(typeNode, indexedJsonNode))
of nnkRecCase: of nnkRecCase:
# A "case" field that introduces a variant. # A "case" field that introduces a variant.
let exprColonExpr = newNimNode(nnkExprColonExpr) let exprEqExpr = newNimNode(nnkExprEqExpr)
result.add(exprColonExpr) result.add(exprEqExpr)
# Add the "case" field name (usually "kind"). # Add the "case" field name (usually "kind").
exprColonExpr.add(toIdentNode(field[0])) exprEqExpr.add(toIdentNode(field[0]))
# -> jsonNode["`field[0]`"] # -> jsonNode["`field[0]`"]
let kindJsonNode = createJsonIndexer(jsonNode, $field[0]) let kindJsonNode = createJsonIndexer(jsonNode, $field[0])
@ -1125,7 +1125,7 @@ proc processObjField(field, jsonNode: NimNode): seq[NimNode] =
let getEnumSym = bindSym("getEnum") let getEnumSym = bindSym("getEnum")
let astStrLit = toStrLit(kindJsonNode) let astStrLit = toStrLit(kindJsonNode)
let getEnumCall = newCall(getEnumSym, kindJsonNode, astStrLit, kindType) let getEnumCall = newCall(getEnumSym, kindJsonNode, astStrLit, kindType)
exprColonExpr.add(getEnumCall) exprEqExpr.add(getEnumCall)
# Iterate through each `of` branch. # Iterate through each `of` branch.
for i in 1 ..< field.len: for i in 1 ..< field.len:
@ -1475,20 +1475,18 @@ proc postProcess(node: NimNode): NimNode =
# TODO: Placing `node[0]` inside quote is buggy # TODO: Placing `node[0]` inside quote is buggy
var resType = toIdentNode(node[0]) var resType = toIdentNode(node[0])
result.add( var objConstr = newTree(nnkObjConstr, resType)
quote do: result.add newVarStmt(resIdent, objConstr)
var `resIdent` = `resType`();
)
# Process each ExprColonExpr. # Process each ExprColonExpr.
for i in 1..<len(node): for i in 1..<len(node):
if node[i].kind == nnkExprEqExpr:
objConstr.add newTree(nnkExprColonExpr, node[i][0], node[i][1])
else:
result.add postProcessExprColonExpr(node[i], resIdent) result.add postProcessExprColonExpr(node[i], resIdent)
# Return the `res` variable. # Return the `res` variable.
result.add( result.add(resIdent)
quote do:
`resIdent`
)
macro to*(node: JsonNode, T: typedesc): untyped = macro to*(node: JsonNode, T: typedesc): untyped =
@ -1539,7 +1537,6 @@ macro to*(node: JsonNode, T: typedesc): untyped =
let `temp` = `node` let `temp` = `node`
let constructor = createConstructor(typeNode[1], temp) let constructor = createConstructor(typeNode[1], temp)
# TODO: Rename postProcessValue and move it (?)
result.add(postProcessValue(constructor)) result.add(postProcessValue(constructor))
# echo(treeRepr(result)) # echo(treeRepr(result))

View file

@ -224,14 +224,14 @@ proc selectBranch(discVal, L: int,
a: ptr array[0x7fff, ptr TNimNode]): ptr TNimNode = a: ptr array[0x7fff, ptr TNimNode]): ptr TNimNode =
result = a[L] # a[L] contains the ``else`` part (but may be nil) result = a[L] # a[L] contains the ``else`` part (but may be nil)
if discVal <% L: if discVal <% L:
var x = a[discVal] let x = a[discVal]
if x != nil: result = x if x != nil: result = x
proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int, proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
a: ptr array[0x7fff, ptr TNimNode], a: ptr array[0x7fff, ptr TNimNode],
L: int) {.compilerProc.} = L: int) {.compilerProc.} =
var oldBranch = selectBranch(oldDiscVal, L, a) let oldBranch = selectBranch(oldDiscVal, L, a)
var newBranch = selectBranch(newDiscVal, L, a) let newBranch = selectBranch(newDiscVal, L, a)
when defined(nimOldCaseObjects): when defined(nimOldCaseObjects):
if newBranch != oldBranch and oldDiscVal != 0: if newBranch != oldBranch and oldDiscVal != 0:
sysFatal(FieldError, "assignment to discriminant changes object branch") sysFatal(FieldError, "assignment to discriminant changes object branch")