Skip to content

Commit

Permalink
update examples + tests with varargs[typed]
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed May 31, 2021
1 parent 2eb1036 commit 5598e88
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
16 changes: 10 additions & 6 deletions lib/core/macros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
28 changes: 24 additions & 4 deletions tests/stdlib/tmacros.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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"

0 comments on commit 5598e88

Please sign in to comment.