Hi! I've noticed that it's possible to annotate the fields of an object type with custom pragmas, and that the treeRepr output for the type statement will reflects it. However, the structure returned by getTypeImpl etc. doesn't seem to contain anything about pragmas, custom or otherwise. Is there any way to get pragma information from a typedesc? On a semi-related note, is it possible for custom pragmas to receive arguments? I apologize if these questions are stupid. I've been using Nim for just a few days, and I couldn't find the answers in the manual. 2018-02-11 06:47:38

Feature is relatively new. Arguments are of course possible or custom pragmas were of no practical use. The main thing to remember that pragmas are attached to symbols (type NimSym or NimNode of nnkSym kind), so you need look for a way to get a symbol from what you have. Here is an example:

import macros

template mykey(s: string{lit}) {.pragma.}

type
  MyObj = object
    a1 {.mykey("a").} : int

macro my(t: typedesc): untyped =
  echo t.getTypeInst[1].symbol.getImpl.treeRepr

my(MyObj)

2018-02-11 17:43:04
I'm not sure I understand. So NimNodes of the nnkSym kind contain NimSyms that can be extracted with the symbol proc, and the NimSyms contain more NimNodes? Your example doesn't seem to compile. 2018-02-11 18:15:27

You need to use latest Nim dev version to compile my example.

You got it almost correct. Nim has a notion of Symbol. Symbols (procs, typedefs, variables and etc) have many attributes like scope, type and others. Most importantly, symbols have implementations that you can access using getImpl proc and symbol implementations will have pragmas you are looking for.

The rest as you say: NimNodes of the nnkSym kind contain NimSym that can be extract using symbol proc.

P.S. There is more doc in the very last section of https://github.com/nim-lang/Nim/blob/devel/doc/manual/pragmas.txt

2018-02-11 19:31:14
I see. My initial attempt looked something like this:
proc test(t: typedesc) {.compileTime.} =
    echo t.getTypeImpl.treeRepr

static:
    test(MyObj)
This did give me field names and types, but no pragmas. It seems like the pragma information isn't attached directly to the symbol, but to the NimNodes you can get from it, so why doesn't getTypeImpl (as used in my snippet) return the same NimNodes? I'm also confused about the argument received by the macro: it seems to be the unevaluated expression typedesc[MyObj]. Is MyObj just syntax sugar for that? Also, is there a workaround for custom pragmas with parameters in the last stable release, or do I have to use the latest dev version?
2018-02-11 19:47:07
In your example t is not a symbol, it is a type. These are two difference concepts. There is relation between the two, but not 1-to-1.
2018-02-11 21:39:51
I understand that. I just don't understand why calling getTypeImpl on a type gives you a different tree from the one that getImpl on a symbol returns. I would've thought that the latter would simply delegate the job to the former when the symbol is associated with a type. Is there some semantic sense behind it, or is it just an implementation quirk? [EDIT] To clarify, I don't understand why there isn't just one tree that both variations return, and why pragmas are specifically omitted when querying the type directly. 2018-02-11 21:57:43
The fact that trees looks similar is because you are lucky and objects being inspected are primitive. Internally in compiler, the representation for types is very different and have little in common with symbols AST. Add type aliases, generics, when statements into the type definition and you will start to see the differences. 2018-02-12 10:35:07
So the result returned by getTypeImpl is a reconstruction from some internal representation which only contains information relevant to the type, while getImpl on a symbol just returns the tree of the original definition? 2018-02-12 10:49:26
<<<••12••>>>