-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
untyped macro nested in template: getting sym instead of idents #11091
Comments
Macros need to be able to handle syms and sym choices. We must be able to do "partial" symbol lookups in templates. |
Workaroundtemplate baz(): untyped {.dirty.} =
foo:
proc bar[T](a, b: seq[T]): seq[T] Templates bind all their identifiers, so that templates can call functions that are not exported in the same module. This is expected behavior, but in your case it is totally unwanted, and I can see that it causes other problems as well. To avoid this early symbol binding, you should use the |
@krux02 regarding dirty I'm aware of it, the main issue is that I want to have a template scope1(): untyped =
var a {.compileTime.} = input("a") # This is a custom AST type for my compiler
let b {.compileTime.} = input("b")
static:
a += b
compile([a, b]):
proc foobar[T](a: var T, b: T)
template scope2(): untyped =
let
a {.compileTime.} = input("a") # This is a custom AST type for my compiler
b {.compileTime.} = input("b")
c {.compileTime.} = input("c")
foo {.compileTime.} = a + b + c
bar {.compileTime.} = foo * 2
compile([a, b, c, foo, bar]):
proc foobar[T](a, b, c: T): tuple[foo, bar: T] I would have a conflict of variable if those templates were dirty and in the same file. @Araq, the main issue is that with untyped macro I expect to have the raw parsed AST and this is what is described in the manual for untyped as well. Furthermore when you have scope nesting (if/case/block/for loop block) the inner scope shadows the outer scope usually but for template with inner macro, the template applies first. If it's not possible to have inner scope macro expansion done before outer scope template symbol resolution, I see 2 workarounds forward.
template scope1(): untyped =
var a {.compileTime.} = input("a") # This is a custom AST type for my compiler
let b {.compileTime.} = input("b")
static:
a += b
{.dirty.}:
compile([a, b]):
proc foobar[T](a: var T, b: T) It's ugly in my opinion but well.
I basically have to unresolve symbols in many of my projects and expanding the standard library starts to get quite costly due to similar symbol resolution issues, see Note that working with types in macro, for example with getTypeInst, is also hard (nim-lang/RFCs#44) because it also requires to unresolve symbols, see |
We could introduce a |
Well, I have no idea what you are doing, but you can leave out |
When an untyped macro is nested in a template, the identifiers are transformed into nnkSym instead of being left as raw nnkIdent. We also get the OpenSymChoice instead of nnkBracketExpr.
Test case:
First parsing output:
Second:
The text was updated successfully, but these errors were encountered: