Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

varargs[untyped] doesn't work with 0 arguments, creating an extraneous nnkHiddenStdConv varargs[untyped] node #8706

Closed
timotheecour opened this issue Aug 21, 2018 · 1 comment
Labels

Comments

@timotheecour
Copy link
Member

timotheecour commented Aug 21, 2018

see all mentions of BUG below:

see also workaround in case6 to create a macro varargsToTuple

this is a serious bug as it affects generic code (eg I had to work around it for #8679)

import macros

macro varargsToTuple(args:varargs[untyped]):untyped=
  result = newTree(nnkTupleConstr)
  for a in args:
    result.add a

macro varargsLen(args:varargs[untyped]):untyped=
  # BUG: should be 0 for case2, not 1
  result = newLit(args.len)

template foo(args:varargs[untyped]): untyped =
  varargsLen(args)

when defined(case1):
  doAssert foo(10) == 1
  doAssert foo(10, 20) == 2

when defined(case2):
  # fail
  # doAssert foo() == 0
  echo foo() # BUG: got 1


when defined(case3):
  macro varargsFirst(args:varargs[untyped]):untyped=
    echo args[0].kind # BUG: nnkHiddenStdConv ??

    result = args[0]

  template foo2(args:varargs[untyped]): untyped =
    varargsFirst(args)

  doAssert foo2(10) == 10
  # BUG: Error: invalid type: 'varargs[untyped]' for let
  let a = foo2()

when defined(case4):
  template foo2(args:varargs[untyped]): untyped =
    varargsToTuple(args)

  doAssert foo2(10) == (10,)
  doAssert foo2(10, 20) == (10, 20)
  when defined(case4a):
    # BUG: Error: invalid type: 'varargs[untyped]' in this context: 'tuple of (varargs[untyped])' for let
    let a = foo2()
  when defined(case4b):
     # BUG: Error: invalid type: 'untyped' in this context: 'iterator (x: tuple of (varargs[untyped])): RootObj{.inline, noSideEffect.}' for proc
    echo foo2()

when defined(case5):
  macro bar(arg:typed):untyped=
    result = newLit arg.repr

  template foo2(args:varargs[untyped]): untyped =
    bar(varargsToTuple(args))

  echo foo2(1) #(1,)
  echo foo2(1, 2) #(1, 2)
  echo foo2() # BUG: ([],)


when defined(case6):
  # workaround
  macro varargsToTuple2(args:varargs[untyped]):untyped=
    result = newTree(nnkTupleConstr)
    if args.len != 1:
      for a in args:
        result.add a
    else:
      # workaround for BUG with empty args `()`
      if args[0].kind != nnkHiddenStdConv:
          result.add args[0]

  template foo2(args:varargs[untyped]): untyped =
    varargsToTuple2(args)

  doAssert foo2(10) == (10,)
  doAssert foo2(10, 20) == (10, 20)
  echo foo2()
@mratsim
Copy link
Collaborator

mratsim commented Aug 21, 2018

This is especially annoying when we want to overload [] for indexing and still allow dereferencing.

In Arraymancer this is blocking dereferencing my computation graph mratsim/Arraymancer#185, (and related macro to workaround does not work mratsim/Arraymancer#241 (comment))

LemonBoy added a commit to LemonBoy/Nim that referenced this issue Aug 21, 2018
When an empty nkArgList `varargs[untyped]` is passed around it is now
reused for efficiency sake and to prevent the introduction of a spurious
element: before this commit we'd pass the caller a
nkArgList[nkHiddenStdConv[nkBracket]] node instead of just an empty
nkArgList.

Fixes nim-lang#8706
LemonBoy added a commit to LemonBoy/Nim that referenced this issue Aug 21, 2018
When an empty nkArgList `varargs[untyped]` is passed around it is now
reused for efficiency sake and to prevent the introduction of a spurious
element: before this commit we'd pass the caller a
nkArgList[nkHiddenStdConv[nkBracket]] node instead of just an empty
nkArgList.

Fixes nim-lang#8706
Araq pushed a commit that referenced this issue Aug 31, 2018
When an empty nkArgList `varargs[untyped]` is passed around it is now
reused for efficiency sake and to prevent the introduction of a spurious
element: before this commit we'd pass the caller a
nkArgList[nkHiddenStdConv[nkBracket]] node instead of just an empty
nkArgList.

Fixes #8706
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants