tvar_macro.nim 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import macros
  2. block: # test usage
  3. macro modify(sec) =
  4. result = copy sec
  5. result[0][0] = ident(repr(result[0][0]) & "Modified")
  6. block:
  7. let foo {.modify.} = 3
  8. doAssert fooModified == 3
  9. block: # in section
  10. let
  11. a = 1
  12. b {.modify.} = 2
  13. c = 3
  14. doAssert (a, bModified, c) == (1, 2, 3)
  15. block: # with single argument
  16. macro appendToName(name: static string, sec) =
  17. result = sec
  18. result[0][0] = ident(repr(result[0][0]) & name)
  19. block:
  20. let foo {.appendToName: "Bar".} = 3
  21. doAssert fooBar == 3
  22. block:
  23. let
  24. a = 1
  25. b {.appendToName("").} = 2
  26. c = 3
  27. doAssert (a, b, c) == (1, 2, 3)
  28. macro appendToNameAndAdd(name: static string, incr: static int, sec) =
  29. result = sec
  30. result[0][0] = ident(repr(result[0][0]) & name)
  31. result[0][2] = infix(result[0][2], "+", newLit(incr))
  32. block: # with multiple arguments
  33. block:
  34. let foo {.appendToNameAndAdd("Bar", 5).} = 3
  35. doAssert fooBar == 8
  36. block:
  37. let
  38. a = 1
  39. b {.appendToNameAndAdd("", 15).} = 2
  40. c = 3
  41. doAssert (a, b, c) == (1, 17, 3)
  42. block: # in other kinds of sections
  43. block:
  44. const
  45. a = 1
  46. b {.appendToNameAndAdd("", 15).} = 2
  47. c = 3
  48. doAssert (a, b, c) == (1, 17, 3)
  49. doAssert static(b) == b
  50. block:
  51. var
  52. a = 1
  53. b {.appendToNameAndAdd("", 15).} = 2
  54. c = 3
  55. doAssert (a, b, c) == (1, 17, 3)
  56. b += a
  57. c += b
  58. doAssert (a, b, c) == (1, 18, 21)
  59. block: # with other pragmas
  60. macro appendToNameAndAdd(name: static string, incr, sec) =
  61. result = sec
  62. result[0][0][0] = ident(repr(result[0][0][0]) & name)
  63. result[0][0][1].add(ident"deprecated")
  64. result[0][2] = infix(result[0][2], "+", incr)
  65. var
  66. a = 1
  67. foo {.exportc: "exportedFooBar", appendToNameAndAdd("Bar", {'0'..'9'}), used.} = {'a'..'z', 'A'..'Z'}
  68. b = 2
  69. doAssert (a, b) == (1, 2)
  70. let importedFooBar {.importc: "exportedFooBar", nodecl.}: set[char]
  71. doAssert importedFooBar == fooBar #[tt.Warning
  72. ^ fooBar is deprecated
  73. ]#
  74. block: # with stropping
  75. macro `cast`(def) =
  76. let def = def[0]
  77. let
  78. lhs = def[0]
  79. typ = def[1]
  80. ex = def[2]
  81. addrTyp = if typ.kind == nnkEmpty: typ else: newTree(nnkPtrTy, typ)
  82. result = quote do:
  83. let tmp: `addrTyp` = unsafeAddr(`ex`)
  84. template `lhs`: untyped = tmp[]
  85. macro assign(def) =
  86. result = getAst(`cast`(def))
  87. block:
  88. let s = @["foo", "bar"]
  89. let a {.`assign`.} = s[0]
  90. doAssert a == "foo"
  91. doAssert a[0].addr == s[0][0].addr
  92. block:
  93. let
  94. s = @["foo", "bar"]
  95. a {.`cast`.} = s[0]
  96. doAssert a == "foo"
  97. doAssert a[0].addr == s[0][0].addr
  98. block: # bug #15920
  99. macro foo(def) =
  100. result = def
  101. proc fun1()=
  102. let a {.foo.} = 1
  103. template fun2()=
  104. let a {.foo.} = 1
  105. fun1() # ok
  106. fun2() # BUG