mirror of
https://github.com/status-im/nim-stew.git
synced 2025-01-09 11:45:42 +00:00
Use a simpler recursion in recordFields as it's no longer an iterator
This commit is contained in:
parent
b06a5b6e32
commit
3e1fa974a4
@ -34,88 +34,53 @@ template readPragma*(field: FieldDescription, pragmaName: static string): NimNod
|
|||||||
let p = findPragma(field.pragmas, bindSym(pragmaName))
|
let p = findPragma(field.pragmas, bindSym(pragmaName))
|
||||||
if p != nil and p.len == 2: p[1] else: p
|
if p != nil and p.len == 2: p[1] else: p
|
||||||
|
|
||||||
proc recordFields*(typeImpl: NimNode): seq[FieldDescription] =
|
proc recordFieldsAux(result: var seq[FieldDescription],
|
||||||
# TODO: This doesn't support inheritance yet
|
n: NimNode,
|
||||||
if typeImpl.isTuple:
|
parentCaseField: NimNode = nil,
|
||||||
for i in 1 ..< typeImpl.len:
|
parentCaseBranch: NimNode = nil,
|
||||||
result.add FieldDescription(typ: typeImpl[i], name: ident("Field" & $(i - 1)))
|
isDiscriminator = false) =
|
||||||
return
|
|
||||||
|
|
||||||
var objectType = typeImpl[2]
|
|
||||||
if objectType.kind == nnkRefTy:
|
|
||||||
objectType = objectType[0]
|
|
||||||
|
|
||||||
let recList = objectType[2]
|
|
||||||
|
|
||||||
type
|
|
||||||
RecursionStackItem = tuple
|
|
||||||
currentNode: NimNode
|
|
||||||
currentChildItem: int
|
|
||||||
parentCaseField: NimNode
|
|
||||||
parentCaseBranch: NimNode
|
|
||||||
|
|
||||||
if recList.len > 0:
|
|
||||||
var traversalStack: seq[RecursionStackItem] = @[
|
|
||||||
(recList, 0, NimNode(nil), NimNode(nil))
|
|
||||||
]
|
|
||||||
|
|
||||||
template recuseInto(childNode: NimNode,
|
|
||||||
currentCaseField: NimNode = nil,
|
|
||||||
currentCaseBranch: NimNode = nil) =
|
|
||||||
traversalStack.add (childNode, 0, currentCaseField, currentCaseBranch)
|
|
||||||
|
|
||||||
while true:
|
|
||||||
doAssert traversalStack.len > 0
|
|
||||||
|
|
||||||
var stackTop = traversalStack[^1]
|
|
||||||
let recList = stackTop.currentNode
|
|
||||||
let idx = stackTop.currentChildItem
|
|
||||||
let n = recList[idx]
|
|
||||||
inc traversalStack[^1].currentChildItem
|
|
||||||
|
|
||||||
if idx == recList.len - 1:
|
|
||||||
discard traversalStack.pop
|
|
||||||
|
|
||||||
case n.kind
|
case n.kind
|
||||||
|
of nnkRecList:
|
||||||
|
for entry in n:
|
||||||
|
recordFieldsAux result, entry,
|
||||||
|
parentCaseField, parentCaseBranch
|
||||||
of nnkRecWhen:
|
of nnkRecWhen:
|
||||||
for i in countdown(n.len - 1, 0):
|
for branch in n:
|
||||||
let branch = n[i]
|
|
||||||
case branch.kind:
|
case branch.kind:
|
||||||
of nnkElifBranch:
|
of nnkElifBranch:
|
||||||
recuseInto branch[1]
|
recordFieldsAux result, branch[1],
|
||||||
|
parentCaseField, parentCaseBranch
|
||||||
of nnkElse:
|
of nnkElse:
|
||||||
recuseInto branch[0]
|
recordFieldsAux result, branch[0],
|
||||||
|
parentCaseField, parentCaseBranch
|
||||||
else:
|
else:
|
||||||
doAssert false
|
doAssert false
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
of nnkRecCase:
|
of nnkRecCase:
|
||||||
doAssert n.len > 0
|
recordFieldsAux result, n[0],
|
||||||
for i in countdown(n.len - 1, 1):
|
parentCaseField,
|
||||||
|
parentCaseBranch,
|
||||||
|
isDiscriminator = true
|
||||||
|
|
||||||
|
for i in 1 ..< n.len:
|
||||||
let branch = n[i]
|
let branch = n[i]
|
||||||
case branch.kind
|
case branch.kind
|
||||||
of nnkOfBranch:
|
of nnkOfBranch:
|
||||||
recuseInto branch[^1], n[0], branch
|
recordFieldsAux result, branch[^1], n[0], branch
|
||||||
of nnkElse:
|
of nnkElse:
|
||||||
recuseInto branch[0], n[0], branch
|
recordFieldsAux result, branch[0], n[0], branch
|
||||||
else:
|
else:
|
||||||
doAssert false
|
doAssert false
|
||||||
|
|
||||||
recuseInto newTree(nnkRecCase, n[0]),
|
|
||||||
stackTop.parentCaseField,
|
|
||||||
stackTop.parentCaseBranch
|
|
||||||
continue
|
|
||||||
|
|
||||||
of nnkIdentDefs:
|
of nnkIdentDefs:
|
||||||
let fieldType = n[^2]
|
let fieldType = n[^2]
|
||||||
for i in 0 ..< n.len - 2:
|
for i in 0 ..< n.len - 2:
|
||||||
var field: FieldDescription
|
var field: FieldDescription
|
||||||
field.name = n[i]
|
field.name = n[i]
|
||||||
field.typ = fieldType
|
field.typ = fieldType
|
||||||
field.caseField = stackTop.parentCaseField
|
field.caseField = parentCaseField
|
||||||
field.caseBranch = stackTop.parentCaseBranch
|
field.caseBranch = parentCaseBranch
|
||||||
field.isDiscriminator = recList.kind == nnkRecCase
|
field.isDiscriminator = isDiscriminator
|
||||||
|
|
||||||
if field.name.kind == nnkPragmaExpr:
|
if field.name.kind == nnkPragmaExpr:
|
||||||
field.pragmas = field.name[1]
|
field.pragmas = field.name[1]
|
||||||
@ -133,7 +98,19 @@ proc recordFields*(typeImpl: NimNode): seq[FieldDescription] =
|
|||||||
else:
|
else:
|
||||||
doAssert false, "Unexpected nodes in recordFields:\n" & n.treeRepr
|
doAssert false, "Unexpected nodes in recordFields:\n" & n.treeRepr
|
||||||
|
|
||||||
if traversalStack.len == 0: break
|
proc recordFields*(typeImpl: NimNode): seq[FieldDescription] =
|
||||||
|
# TODO: This doesn't support inheritance yet
|
||||||
|
if typeImpl.isTuple:
|
||||||
|
for i in 1 ..< typeImpl.len:
|
||||||
|
result.add FieldDescription(typ: typeImpl[i], name: ident("Field" & $(i - 1)))
|
||||||
|
return
|
||||||
|
|
||||||
|
var objectType = typeImpl[2]
|
||||||
|
if objectType.kind == nnkRefTy:
|
||||||
|
objectType = objectType[0]
|
||||||
|
|
||||||
|
let recList = objectType[2]
|
||||||
|
recordFieldsAux result, recList
|
||||||
|
|
||||||
macro field*(obj: typed, fieldName: static string): untyped =
|
macro field*(obj: typed, fieldName: static string): untyped =
|
||||||
newDotExpr(obj, ident fieldName)
|
newDotExpr(obj, ident fieldName)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user