Reputation: 2098
I would like to use a macro that uses a type defined by the "type" keyword. How do I reference it?
My starting code is
import scala.reflect.macros.Context
import scala.language.experimental.macros
trait Demo6 {
type T
def add(param: Any): T = macro Demo6.addImpl[T]
def fullAdd(param: Any, toStringBasedOnAST: String): T = {
doesSomeThing_and_returnsSomething_OfTypeT
}
def doesSomeThing_and_returnsSomething_OfTypeT: T //just to allow compilation
}
object Demo6 {
def addImpl[T: c.WeakTypeTag](c: Context)(param: c.Expr[Any]): c.Expr[T] = {
import c.universe._
reify { (c.Expr[Demo6](c.prefix.tree)).splice.fullAdd(param.splice,
c.literal(show(param.tree)).splice) }
// ^ - type mismatch; found : org.autotdd.scalamacros.Demo6#T
// required: T
}
}
I have marked up the compiler error in the example. It's pretty clear what is happening: the type T defined by keyword isn't the same as the type T that I am passing in.
Things I've tried There isn't a lot of documentation yet on scala-macros. The section in http://docs.scala-lang.org/overviews/macros/overview.html was very helpful in getting me this far, but its example uses a class level and a method level generic. I've browsed the code for Expecty and macrocosm, which are projects referenced in the documentation, but couldn't find code like this.
Upvotes: 4
Views: 408
Reputation: 38045
Your code is almost correct, just change type parameter of Expr
:
val expr = reify { ... }
c.Expr[T](expr.tree)
Without reify
you should return this:
c.Expr[T](Apply(Select(c.prefix.tree, newTermName("fullAdd")),
List(param.tree, Literal(Constant(show(param.tree))))))
reify
creates the same, but with wrong type parameter.
See this answer for showRaw
usage.
In this case:
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> {
| object Demo { def fullAdd(param1: Any, param2: String): String = "result" }
| showRaw{ reify { Demo.fullAdd("param1", "param2") } }
| }
res0: String = Expr(Apply(Select(Ident(newTermName("Demo")), newTermName("fullAdd")), List(Literal(Constant("param1")), Literal(Constant("param2")))))
Replace Ident(newTermName("Demo"))
with c.prefix.tree
, Literal(Constant("param1"))
with param.tree
and "param2"
with show(param.tree)
and you'll get your result.
Upvotes: 4