Skip to content

non-hygenic behavior for gensymmed name in template #24260

Open
@arnetheduck

Description

@arnetheduck

Description

import std/macros

macro evalOnceAs*(exp, alias: untyped): untyped =
  expectKind(alias, nnkIdent)

  let
    body = nnkStmtList.newTree()
    val =
      if exp.kind == nnkSym:
        # The symbol can be used directly
        # TODO dot expressions? etc..
        exp
      else:
        let val = genSym(ident = "evalOnce_" & $alias)
        body.add newLetStmt(val, exp)
        val
  body.add(
    newProc(
      name = genSym(nskTemplate, $alias),
      params = [getType(untyped)],
      body = val,
      procType = nnkTemplateDef,
    )
  )

  body

type ArrayBuf = object
  buf: array[32, byte]
  n: int

template data*(bParam: ArrayBuf): openArray =
  bParam.evalOnceAs(b)
  b.buf.toOpenArray(0, b.n - 1)


proc f() =
  var b: int
  var a: ArrayBuf

  echo a.data()

  echo b

var b: int

proc f2() =
  var a: ArrayBuf

  echo a.data()

  echo b

the name b is local to the template and not dirty - it should neither conflict with the other b nor leak out of the template

A variation, when b is in a different scope:


var b: int
proc f() =
  var a: ArrayBuf

  echo a.data()

  echo b

f()

Here, (buf: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], n: 0) gets printed.

Nim Version

2.0.8

Current Output

testit.nim(26, 20) Error: redefinition of 'b'; previous declaration here: /home/arnetheduck/status/nimbus-eth1/_exper/testit.nim(45, 7)

Expected Output

No response

Known Workarounds

No response

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions