tcollect.nim 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. discard """
  2. output: '''@[2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4]
  3. @[0, 1, 2, 3]'''
  4. """
  5. const data = [1,2,3,4,5,6]
  6. import macros
  7. macro collect(body): untyped =
  8. # analyse the body, find the deepest expression 'it' and replace it via
  9. # 'result.add it'
  10. let res = genSym(nskVar, "collectResult")
  11. when false:
  12. proc detectForLoopVar(n: NimNode): NimNode =
  13. if n.kind == nnkForStmt:
  14. result = n[0]
  15. else:
  16. for x in n:
  17. result = detectForLoopVar(x)
  18. if result != nil: return result
  19. return nil
  20. proc t(n, res: NimNode): NimNode =
  21. case n.kind
  22. of nnkStmtList, nnkStmtListExpr, nnkBlockStmt, nnkBlockExpr,
  23. nnkWhileStmt,
  24. nnkForStmt, nnkIfExpr, nnkIfStmt, nnkTryStmt, nnkCaseStmt,
  25. nnkElifBranch, nnkElse, nnkElifExpr:
  26. result = copyNimTree(n)
  27. if n.len >= 1:
  28. result[^1] = t(n[^1], res)
  29. else:
  30. if true: #n == it:
  31. template adder(res, it) =
  32. res.add it
  33. result = getAst adder(res, n)
  34. else:
  35. result = n
  36. when false:
  37. let it = detectForLoopVar(body)
  38. if it == nil: error("no for loop in body", body)
  39. let v = newTree(nnkVarSection,
  40. newTree(nnkIdentDefs, res, newTree(nnkBracketExpr, bindSym"seq",
  41. newCall(bindSym"type", body)), newEmptyNode()))
  42. result = newTree(nnkStmtListExpr, v, t(body, res), res)
  43. #echo repr result
  44. let stuff = collect:
  45. var i = -1
  46. while i < 4:
  47. inc i
  48. for it in data:
  49. if it < 5 and it > 1:
  50. it
  51. echo stuff
  52. echo collect(for i in 0..3: i)