diff --git a/lib/core/macros.nim b/lib/core/macros.nim index b5e847a0f086e..13be759fc9939 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1683,16 +1683,20 @@ macro getCustomPragmaVal*(n: typed, cp: typed): untyped = macro unpackVarargs*(callee: untyped; args: varargs[untyped]): untyped = ## Calls `callee` with `args` unpacked as individual arguments. - ## This is only useful in the case where `args` can potentially be empty, due - ## to a compiler limitation, see examples. + ## 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 call(fun: typed; args: varargs[untyped]): untyped = + 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) - call(fn1, 10, 11) - call(fn1, 10) - call(fn1) # `args` is empty in this case + call1(fn1, 10, 11) + call1(fn1) # `args` is empty in this case + if true: call2(echo, 10, 11) # would print 1011 result = newCall(callee) for i in 0 ..< args.len: result.add args[i] diff --git a/tests/stdlib/tmacros.nim b/tests/stdlib/tmacros.nim index 3b7a4b43b1227..52ea1e89874ac 100644 --- a/tests/stdlib/tmacros.nim +++ b/tests/stdlib/tmacros.nim @@ -33,10 +33,30 @@ block: # unpackVarargs proc fn1(a = 0, b = 1) = discard (a, b) - call1(fn1, 10, 11) - call1(fn1, 10) call1(fn1) + call1(fn1, 10) + call1(fn1, 10, 11) - call2(fn1, 10, 11) - call2(fn1, 10) 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"