Now there is macro hasCustomPragma, it is fine within normal proc:

template table(name: string) {.pragma.}

type
   User {.table("tuser").} = object
      id: int
      name: string
      age: int

echo User.hasCustomPragma(table)

But when I need call it in another macro, I don't know how to do it, anyone know there is a workaround, thanks.

## doesn't works
macro m1(T: typedesc): untyped =
   echo T.hasCustomPragma(table)

2018-04-15 07:45:09

Here are 2 ways.

There is something special about hasCustomPragma or typedesc in macros I think. For some reason the getAST version is crashing but it should work and the quote do version only works on Nim #devel.

import macros

template table(name: string) {.pragma.}

type
   User {.table("tuser").} = object
      id: int
      name: string
      age: int

echo User.hasCustomPragma(table)


# macro m1(T: typedesc): untyped =
#   getAST hasCustomPragma(T, table)

# echo m1(User) # Oops crash

macro m2(T: typedesc): untyped =
  
  result = quote do:
    `T`.hasCustomPragma(table)

echo m2(User)

2018-04-15 09:07:23
@mratsim Thanks. 'quote do' is not what I want. I want the code can return the result(true or false), not the code can be called in the program. For example:
macro m2(T: typedesc): untyped =
  if some_proc_call_has_custom_param(T, table):
     ......
  else:
     ......
2018-04-15 10:57:05
Well, actually hasCustomPragma should NOT be a macro but a compile-time proc (with a macro wrapper, at most). It's always easier to write a proc operating on AST and then add a macro adjusting it to typed arguments compared to the opposite. Still, if you look at hasCustomPragma implementation, it's not that difficult to produce such a proc, it works pretty similarly. Just be sure to use typed, not untyped or else you won't be able to get a symbol's implementation (as it will be an identifier, not a symbol).
2018-04-15 21:30:23
Yes, it is not so difficult to implements 'hasCustomPragma' proc which can be called in the macros. But I try to find a way we can call macro from another macro. In fact, call macro in a macro with triditional macro semantics is meanless from my point of view, I think when a macro is called from another macro, it should be called just like a proc call a proc, a macro is just like a proc with parameter type is NimNode(except static[T] and typedesc type). So the following code should give same result:
import macros

template table(name: string) {.pragma.}

type
   User {.table("tuser").} = object
      id: int
      name: string
      age: int

macro m2(T: typedesc): untyped =
   echo T.hasCustomPragma(table)

# output true
echo User.hasCustomPragma(table)

#should output true too
m2(User)
2018-04-16 00:45:59
I agree hasCustomPragma has to be a compiletime proc with macro wrapper on top. PRs are welcome... 2018-04-16 11:33:07
@slangmgh That's not true. You could implement a macro which gives you nice syntax for some macro manipulations. breeze library provides some.
2018-04-16 12:30:13
@Udiknedormin
  • breeze make the macro easy to write. Yes.
  • We can rewrite hasCustomPragma as proc. Yes.
  • Call a macro in another macro with macro semantics is useful? Please give me an example.
2018-04-16 12:40:59

Call a macro in another macro with macro semantics is useful? Please give me an example.

Ever used > or != or notin in a macro? These are templates, simple forms of a macro in Nim.

2018-04-16 13:28:26

@slangmgh

I've already gave you one. What breeze does IS a macro with macro semantics. And just like Araq said, you can use templates or macros without even realizing it.

2018-04-16 14:00:40
<<<••12••>>>