Re: how to get unmodified / uninterpreted source code/AST of expression in macro?
It works when the macro parameter is untyped, I guess constant folding happens during the typing process: import macros macro mylog(x:untyped): untyped = result = newNimNode(nnkStmtList, x) result.add(newCall("write", newIdentNode("stdout"), toStrLit(x))) result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(":"))) result.add(newCall("writeLine", newIdentNode("stdout"), x)) var x=1 mylog(x+1) # x + 1:2 (OK but I'd rather want exact source code with spacing eg: `x+1:2`) mylog(1+1) # 2:2 (not OK, I want: 1+1: 2)
Re: a proc returning void creates 1 arg, not 0: breaking generic code
Oh, right! I guess it's testing it on untyped rather than the actual type in the macro. Anyways, this one is definitely working, it just tests for void-typed arguments: import macros import typetraits import strformat macro fun*(n: varargs[typed]): typed = result = newNimNode(nnkStmtList, n) var echoedCount = 0 for x in n: if x.getTypeInst.typeKind != ntyVoid: result.add(newCall("echo", x)) echoedCount += 1 result.add(newCall("echo", newStrLitNode($(echoedCount proc bar() = echo "ok" fun(1+1) # n.len=1 fun() # n.len=0 # comment this to make it work fun(bar()) > isn't that a better behavior? if not what would be downsides of that? No, I think automatically filtering void arguments in a macro is not a better or intuitive behavior. What if you remove a return type from a function and the compiler just silently starts ignoring it in argument lists instead of producing a type mismatch error? That seems like it could be an interesting source of bugs. I guess what you're asking for is not SFINAE, but it feels similar -- it's a hack used to make template systems have some limited metaprogramming. I think that you'll find that sort of thing is not necessary with Nim, you can just write a macro that does what you want. Is there something specific that you're trying to do that requires the argument-ignoring approach used in D? Maybe we could help you come up with a good solution for it in Nim.
Re: How to call a macro from a template with a constructed identifier argument?
Thanks for the suggestions. @mratsim I had no idea you could put a template inside a macro and get its evaluated AST. Cool! This will be very useful. @Lando Interesting, I guess this works because quote doesn't touch the passed in backticked identifier and this is then returned intact to the template? Maybe I should treat identifiers-like NimNodes as more of a black box in the future to allow this sort of thing.
Re: How to call a macro from a template with a constructed identifier argument?
Yes, that compiles, but the macro produces the code let x = 1000 instead of the code let xExtra = 1000 I'm trying to get the identifier to be constructed before passing it into the macro, but I'm not sure if that's possible.
How to call a macro from a template with a constructed identifier argument?
I have a macro that creates a type and associated functions, and I'm calling that from a template. I want to use identifier construction to append a suffix to the template parameter, but the whole backticked AST (instead of the constructed identifier) gets passed in to the macro. Is there some way to generate an identifier before the macro is evaluated? I've included a simplified example below. macro defthing(name: untyped): untyped = return parseStmt("let $1 = 1000".format($name.ident)) template calldefthing(name: untyped): untyped {.dirty.} = defthing name # argument is an identifier defthing `name Extra` # argument is not an identifier, I'd like to evaluate the `name Extra` before the macro is called calldefthing x
Re: Emscripten/WebAssembly GC considerations?
@yglukhov Thanks, that makes sense, I can just call GC_step at the start of each emscripten_set_main_loop callback. By the way, thanks for writing jsbind, it has been very helpful! @mashingan I copied most of the nim.cfg from here: [https://forum.nim-lang.org/t/2991](https://forum.nim-lang.org/t/2991). Then follow the Emscripten installation instructions: [https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html) (be sure to source ./emsdk_env.sh in the console before using the Nim compiler). To compile, run something like nim c -d:emscripten -d:wasm -d:release -o:main-wasm.html main.nim and it will just.. work. If I have time, I'll put together a simple example repo. FYI, I could only get it to work on Linux (or Windows Linux), the Windows command prompt had some issues.
Emscripten/WebAssembly GC considerations?
I've been using Nim to generate WebAssembly using Emscripten and everything seems to be working very well. Are there any special considerations I should make for the GC? I know that it's impossible to scan the stack in WASM, but that shouldn't be much of a problem for Nim due to reference counting. However, cycle detection also has to run, which (I'm assuming) does need to scan the stack to find roots. Will that be called automatically? Or do I need to call it manually? I imagine I could occasionally call it on Emscripten's frame callback emscripten_set_main_loop when the Nim stack is basically empty.