diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2021-05-31 01:51:20 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-31 10:51:20 +0200 |
commit | 18b477431138d944b90e7a6e6e0412496634b518 (patch) | |
tree | 23c74b9eb166c38d2fce05fb33321cf6135d4689 | |
parent | 98ea61f09b4bfdc13c911b1ff3fb404dfc0d1338 (diff) | |
download | Nim-18b477431138d944b90e7a6e6e0412496634b518.tar.gz |
document macros.unpackVarargs (#18106)
* deprecate macros.unpackVarargs * un-deprecate unpackVarargs and add docs+runnableExamples * update examples + tests with varargs[typed]
-rw-r--r-- | lib/core/macros.nim | 15 | ||||
-rw-r--r-- | tests/destructor/tatomicptrs.nim | 1 | ||||
-rw-r--r-- | tests/stdlib/tmacros.nim | 50 |
3 files changed, 66 insertions, 0 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 79c3ba28b..89f90a23b 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1682,6 +1682,21 @@ macro getCustomPragmaVal*(n: typed, cp: typed): untyped = error(n.repr & " doesn't have a pragma named " & cp.repr, n) macro unpackVarargs*(callee: untyped; args: varargs[untyped]): untyped = + ## Calls `callee` with `args` unpacked as individual arguments. + ## This is useful in 2 cases: + ## * when forwarding `varargs[T]` for some typed `T` + ## * when forwarding `varargs[untyped]` when `args` can potentially be empty, + ## due to a compiler limitation + runnableExamples: + template call1(fun: typed; args: varargs[untyped]): untyped = + unpackVarargs(fun, args) + # when varargsLen(args) > 0: fun(args) else: fun() # this would also work + template call2(fun: typed; args: varargs[typed]): untyped = + unpackVarargs(fun, args) + proc fn1(a = 0, b = 1) = discard (a, b) + call1(fn1, 10, 11) + call1(fn1) # `args` is empty in this case + if false: call2(echo, 10, 11) # would print 1011 result = newCall(callee) for i in 0 ..< args.len: result.add args[i] diff --git a/tests/destructor/tatomicptrs.nim b/tests/destructor/tatomicptrs.nim index 7313afbf5..36f0cab8a 100644 --- a/tests/destructor/tatomicptrs.nim +++ b/tests/destructor/tatomicptrs.nim @@ -72,6 +72,7 @@ template `.=`*[T](s: SharedPtr[T]; field, value: untyped) = from macros import unpackVarargs template `.()`*[T](s: SharedPtr[T]; field: untyped, args: varargs[untyped]): untyped = + # xxx this isn't used, the test should be improved unpackVarargs(s.x.field, args) diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim index effe1032f..52ea1e898 100644 --- a/tests/stdlib/tmacros.nim +++ b/tests/stdlib/tmacros.nim @@ -10,3 +10,53 @@ block: # hasArgOfName block: # bug #17454 proc f(v: NimNode): string {.raises: [].} = $v + +block: # unpackVarargs + block: + proc bar1(a: varargs[int]): string = + for ai in a: result.add " " & $ai + proc bar2(a: varargs[int]) = + let s1 = bar1(a) + let s2 = unpackVarargs(bar1, a) # `unpackVarargs` makes no difference here + doAssert s1 == s2 + bar2(1, 2, 3) + bar2(1) + bar2() + + block: + template call1(fun: typed; args: varargs[untyped]): untyped = + unpackVarargs(fun, args) + template call2(fun: typed; args: varargs[untyped]): untyped = + # fun(args) # works except for last case with empty `args`, pending bug #9996 + when varargsLen(args) > 0: fun(args) + else: fun() + + proc fn1(a = 0, b = 1) = discard (a, b) + + call1(fn1) + call1(fn1, 10) + call1(fn1, 10, 11) + + call2(fn1) + call2(fn1, 10) + call2(fn1, 10, 11) + + block: + template call1(fun: typed; args: varargs[typed]): untyped = + unpackVarargs(fun, args) + template call2(fun: typed; args: varargs[typed]): untyped = + # xxx this would give a confusing error message: + # required type for a: varargs[typed] [varargs] but expression '[10]' is of type: varargs[typed] [varargs] + when varargsLen(args) > 0: fun(args) + else: fun() + macro toString(a: varargs[typed, `$`]): string = + var msg = genSym(nskVar, "msg") + result = newStmtList() + result.add quote do: + var `msg` = "" + for ai in a: + result.add quote do: `msg`.add $`ai` + result.add quote do: `msg` + doAssert call1(toString) == "" + doAssert call1(toString, 10) == "10" + doAssert call1(toString, 10, 11) == "1011" |