ttypedef_macro.nim 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. import macros
  2. macro makeref(s): untyped =
  3. expectKind s, nnkTypeDef
  4. result = newTree(nnkTypeDef, s[0], s[1], newTree(nnkRefTy, s[2]))
  5. type
  6. Obj {.makeref.} = object
  7. a: int
  8. doAssert Obj is ref
  9. doAssert Obj(a: 3)[].a == 3
  10. macro multiply(amount: static int, s): untyped =
  11. let name = $s[0].basename
  12. result = newNimNode(nnkTypeSection)
  13. for i in 1 .. amount:
  14. result.add(newTree(nnkTypeDef, ident(name & $i), s[1], s[2]))
  15. type
  16. Foo = object
  17. Bar {.multiply: 2.} = object
  18. x, y, z: int
  19. Baz = object
  20. let bar1 = Bar1(x: 1, y: 2, z: 3)
  21. let bar2 = Bar2(x: bar1.x, y: bar1.y, z: bar1.z)
  22. doAssert Bar1 isnot Bar2
  23. doAssert not declared(Bar)
  24. doAssert not declared(Bar3)
  25. # https://github.com/nim-lang/RFCs/issues/219
  26. macro inferKind(td): untyped =
  27. let name = $td[0].basename
  28. var rhs = td[2]
  29. while rhs.kind in {nnkPtrTy, nnkRefTy}: rhs = rhs[0]
  30. if rhs.kind != nnkObjectTy:
  31. result = td
  32. else:
  33. for n in rhs[^1]:
  34. if n.kind == nnkRecCase and n[0][^2].eqIdent"_":
  35. let kindTypeName = ident(name & "Kind")
  36. let en = newTree(nnkEnumTy, newEmptyNode())
  37. for i in 1 ..< n.len:
  38. let branch = n[i]
  39. if branch.kind == nnkOfBranch:
  40. for j in 0 ..< branch.len - 1:
  41. en.add(branch[j])
  42. n[0][^2] = kindTypeName
  43. return newTree(nnkTypeSection,
  44. newTree(nnkTypeDef, kindTypeName, newEmptyNode(), en),
  45. td)
  46. type Node {.inferKind.} = ref object
  47. case kind: _
  48. of opValue: value: int
  49. of opAdd, opSub, opMul, opCall: kids: seq[Node]
  50. doAssert opValue is NodeKind
  51. let node = Node(kind: opMul, kids: @[
  52. Node(kind: opValue, value: 3),
  53. Node(kind: opValue, value: 5)
  54. ])
  55. doAssert node.kind == opMul
  56. doAssert node.kids[0].value * node.kids[1].value == 15