Hi!
I need to generate a parametrized template with a proc defined in it, which accepts a type and returns the type instance.
When I define such proc manually, there's no issue. But when I define it within the tempale, compilation fails with undefined identifier error. Here's the minimal code sample that reproduces the issue:
import macros
type Typ = object
template makeTmpl(param: int): untyped =
template tmpl(body: untyped): untyped =
let otherParam = param * 2
proc prc(T: type): T = echo otherParam
macro mac(param: int, body: untyped): untyped =
result = newStmtList()
result.add getAst(makeTmpl(param))
result.add body
# This causes compilation error
mac 42:
tmpl:
discard Typ.prc()
# This works fine
let otherParam = 123
proc prc2(T: type): T = echo otherParam
discard Typ.prc2()
Any help would be extremely valuable as I'm completely lost. As far as my understanding goes, templates are just a way to insert raw code chunks, so defining a proc manually and inserting it with a template should be the same thing. And this code sample shows me that I am misunderstanding something.
P.S. I'm deliberately not explaining the reasons behind me wanting to write specifically this code because 1) this would be too long and 2) I really want to strip the issue alone disregarding the context and understand why this happens.
UPD: It compiled when I made both templates {.dirty.}. So the issue is solved (we really need a way to update thread titles).
However, if anyone could explain why that helped, I'd be really grateful.
Whether a symbol that is declared in a template is exposed to the instantiation scope is controlled by the inject and gensym pragmas: gensym'ed symbols are not exposed but inject'ed are.
The default for symbols of entity type, var, let and const is gensym and for proc, iterator, converter, template, macro is inject. However, if the name of the entity is passed as a template parameter, it is an inject'ed symbol
try this:
prc[A](T: type[A]): A = echo otherParam
For that matter I'm not even sure
proc prc2(T: type): T = echo otherParam
is supposed to compile. Your supposed to pass types to procs with the [] syntax if you want to use them in your parameter list or as a return type. Luckily if you declare the proc like:
proc prc[A](T: type[A]): A = echo otherParam
you can still call it like
prc(int)
as the A parameter contained within [] will be inferred. One of the nim developers could probably clear up whether your way of declaring the proc is supposed to work.