Closed zerbina closed 4 months ago
- identifiers in definition positions aren't turned into gensyms; they stay as is
Is there some rationale for this? I expect that this will make using quote
a lot harder.
Is there some rationale for this? I expect that this will make using
quote
a lot harder.
That's just a consequence of quote
now doing quasi-quoting. Previously, quote
was just sugar for a template definition + expansion, which is where the symbol binding and gensym behaviour came from.
Are there plans to allow gensym to happen to unquoted identifiers in the future? quote
was very handy in allowing for easy generation of helper statements without bloating my macro with a bunch of explicit genSym
s
Are there plans to allow gensym to happen to unquoted identifiers in the future?
No, at least not from my side. quote
should only do quasi-quoting, nothing else. However, that doesn't preclude things such as allowing the .gensym
pragma on definitions in macro output, or making macros open a new shadow scope by default.
Edit: For my answer, I've assumed that with "unquoted identifier" you mean "identifiers that are not accent-quoted".
In the meantime, you can either use genAst
(which effectively works the same as the old quote
, minus the unquoting behaviour), or use a custom quote operator, like so:
template gensymQuote(bl: untyped): untyped {.dirty.} =
block:
let name = genSym(nskTemplate, "templ")
quote do:
template `name`(): untyped =
bl
`name`()
Depending on the quoted AST, you can also just wrap the code in an if true:
in order to confine the identifiers to their own scope.
Per the discussion in matrix, concern around being able to get the old behaviour have been resolved per @zerbina's solution.
In the meantime, you can either use
genAst
(which effectively works the same as the oldquote
, minus the unquoting behaviour), or use a custom quote operator, like so:template gensymQuote(bl: untyped): untyped {.dirty.} = block: let name = genSym(nskTemplate, "templ") quote do: template `name`(): untyped = bl `name`()
Depending on the quoted AST, you can also just wrap the code in an
if true:
in order to confine the identifiers to their own scope.
/merge
Merge requested by: @zerbina
Contents after the first section break of the PR description has been removed and preserved below:
## To-Do - [x] write a proper commit message ## Notes for Reviewers * the test and library changes provide a good overview of how users of `quote` are affected
Summary
quote
now keeps the quoted block as is, which means that:.gensym
and.inject
pragmas within the quoted block don't affect the ASTSymbols thus need to be bound or created explicitly, via
bindSym
andgenSym
, respectively. This is a breaking change.Details
Motivation For The Change
quote
's scope being bound is error-prone, leading to confusing compilation errorsquote
already said it does quasi- quoting (even though it didn't)New Behaviour
Implementation
semQuoteAst
transforms thequote
call into a call to the internalquoteImpl
procedureevalToAst
magic procedure is used for evaluating the unquoted expressions.newLit
cannot be used here, as the trees it produces forobject
values are only valid when all the type's fields are exportedquoteImpl
Standard Library And Test Changes
bindSym
orgenSym
. Outside-visible behaviour doesn't changet7875.nim
test relied on the gensym behaviour. The definition outside the macro is not relevant to the issue the test guards against, so it can just be removedtsizeof.nim
are wrapped in blocks in order to prevent the identifiers from colliding