nim-works / nimskull

An in development statically typed systems programming language; with sustainability at its core. We, the community of users, maintain it.
https://nim-works.github.io/nimskull/index.html
Other
279 stars 39 forks source link

macros: make `quote` a proper quasi-quoting operator #1393

Closed zerbina closed 4 months ago

zerbina commented 4 months ago

Summary

quote now keeps the quoted block as is, which means that:

Symbols thus need to be bound or created explicitly, via bindSym and genSym, respectively. This is a breaking change.

Details

Motivation For The Change

New Behaviour

Implementation

Standard Library And Test Changes

alaviss commented 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.

zerbina commented 4 months ago

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.

alaviss commented 4 months ago

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 genSyms

zerbina commented 4 months ago

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.

saem commented 4 months ago

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 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.

zerbina commented 4 months ago

/merge

github-actions[bot] commented 4 months ago

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