-
-
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
"undeclared identifier" error when using fmt from strformat on devel inside a template #10977
Comments
Hm, it looks like the fundamental problem behind #7632 hasn't been solved actually? The most basic example still doesn't compile for me: import strformat
template formatMsg(s: string): string =
&"test {s}"
echo formatMsg("x") |
@bluenote10 That would require a new language feature like template t(s): untyped =
let x {.inject.} = s
&"test {x}" |
I recommend this workaround: template t(s): untyped =
block:
let x {.inject.} = s
&"test {x}" Inject makes the template non hygienic. The block makes the template hygienic again. |
Btw it's only semi-hygienic with |
While this hasn't been enabled, the limitations of |
re-opening because this is a common gotcha, and, even though the problem was documented, it's still not fixed, and it's a solvable problem using a compiler extension.
It's worth fixing IMO. minimized example using only when true:
import macros
macro fmt2(a: static string): untyped =
let ret1 = parseExpr(a)
result = quote do:
var ret = "{"
add(ret, $`ret1`)
add(ret, "}")
ret
template main()= # fails: Error: undeclared identifier: 'x1'
# proc main()= # works
let x1 = 123
let a = fmt2("x1")
main() |
@timotheecour Thanks! Just last week, I was working with templates, and I needed to make a conscious effort to use |
my proposal: option 1add a magic proc (handled in # in macros.nim:
proc interp*(a: string, fmt: string): untyped {.magic.}
interp("foo {a} {2*2} bar", "{}") is replaced by: ["foo ", a, " ", 2*2, " bar"] (untyped AST) this will allow code like this: template bar() =
let a = 3
echo "foo {a}".interp.fmt
{.emit: "void fn1(int {a});".interp.}
{.emit:"void fn2(int `a`){}".interp("``").} # custom {}
asm "auto x = {a}".interp to work, thus fixing all related issues (and avoiding the need for this style of emits: option 2A variant of this proposal is a pragma macro fmt(args...) {.pregensym.} = ...
template bar() =
let a = 3
echo fmt"foo {a}" # gets expanded before bar is gensym'd in `semTemplBody` but this only makes sense for macros that have only untyped/litteral arguments |
The text was updated successfully, but these errors were encountered: