summary refs log tree commit diff stats
path: root/tests/pragmas/tvar_macro.nim
blob: 3fb6e3e530fbf8326c8467bb55dc468d333959a4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import macros

block: # test usage
  macro modify(sec) =
    result = copy sec
    result[0][0] = ident(repr(result[0][0]) & "Modified")

  block:
    let foo {.modify.} = 3
    doAssert fooModified == 3

  block: # in section 
    let
      a = 1
      b {.modify.} = 2
      c = 3
    doAssert (a, bModified, c) == (1, 2, 3)

block: # with single argument
  macro appendToName(name: static string, sec) =
    result = sec
    result[0][0] = ident(repr(result[0][0]) & name)

  block:
    let foo {.appendToName: "Bar".} = 3
    doAssert fooBar == 3

  block:
    let
      a = 1
      b {.appendToName("").} = 2
      c = 3
    doAssert (a, b, c) == (1, 2, 3)

macro appendToNameAndAdd(name: static string, incr: static int, sec) =
  result = sec
  result[0][0] = ident(repr(result[0][0]) & name)
  result[0][2] = infix(result[0][2], "+", newLit(incr))

block: # with multiple arguments
  block:
    let foo {.appendToNameAndAdd("Bar", 5).} = 3
    doAssert fooBar == 8

  block:
    let
      a = 1
      b {.appendToNameAndAdd("", 15).} = 2
      c = 3
    doAssert (a, b, c) == (1, 17, 3)

block: # in other kinds of sections
  block:
    const
      a = 1
      b {.appendToNameAndAdd("", 15).} = 2
      c = 3
    doAssert (a, b, c) == (1, 17, 3)
    doAssert static(b) == b

  block:
    var
      a = 1
      b {.appendToNameAndAdd("", 15).} = 2
      c = 3
    doAssert (a, b, c) == (1, 17, 3)
    b += a
    c += b
    doAssert (a, b, c) == (1, 18, 21)

block: # with other pragmas
  macro appendToNameAndAdd(name: static string, incr, sec) =
    result = sec
    result[0][0][0] = ident(repr(result[0][0][0]) & name)
    result[0][0][1].add(ident"deprecated")
    result[0][2] = infix(result[0][2], "+", incr)

  var
    a = 1
    foo {.exportc: "exportedFooBar", appendToNameAndAdd("Bar", {'0'..'9'}), used.} = {'a'..'z', 'A'..'Z'}
    b = 2
  
  doAssert (a, b) == (1, 2)

  let importedFooBar {.importc: "exportedFooBar", nodecl.}: set[char]

  doAssert importedFooBar == fooBar #[tt.Warning
                             ^ fooBar is deprecated
  ]#
  

block: # with stropping
  macro `cast`(def) =
    let def = def[0]
    let
      lhs = def[0]
      typ = def[1]
      ex = def[2]
      addrTyp = if typ.kind == nnkEmpty: typ else: newTree(nnkPtrTy, typ)
    result = quote do:
      let tmp: `addrTyp` = unsafeAddr(`ex`)
      template `lhs`: untyped = tmp[]
  
  macro assign(def) =
    result = getAst(`cast`(def))

  block:
    let s = @["foo", "bar"]
    let a {.`assign`.} = s[0]
    doAssert a == "foo"
    doAssert a[0].addr == s[0][0].addr

  block:
    let
      s = @["foo", "bar"]
      a {.`cast`.} = s[0]
    doAssert a == "foo"
    doAssert a[0].addr == s[0][0].addr

block: # bug #15920
  macro foo(def) =
    result = def
  proc fun1()=
    let a {.foo.} = 1
  template fun2()=
    let a {.foo.} = 1
  fun1() # ok
  fun2() # BUG