reflection - Scala macros: convert Context#TypeTag to JavaUniverse#TypeTag -


i want use macros generate code instantiates objects this:

import scala.reflect.runtime.universe._ case class example[t: typetag] {   val tpe = implicitly[typetag[t]].tpe } 

this, obviously, translates following:

import scala.reflect.runtime.universe._ case class example[t](implicit ev: typetag[t]) {   val tpe = ev.tpe } 

then if class instantiated in regular code scala compiler provides typetag instance automatically.

however, want generate code instantiates several instances of class different ts, concrete ts depend on user input, like

sealed trait test case class subtest1 extends test case class subtest2 extends test  val examples = generate[test] // want ^^^^^^^^^^^^^^ expand this: val examples = seq(example[subtest1], example[subtest2]) 

i know how subclasses of sealed trait, can access c.weaktypetag[subtest1] , c.weaktypetag[subtest2] in macro code. not know how turn them typetags expected example.apply method. thought of using in() method seems allow transferring typetags between universes, requires destination mirror, , don't know how runtime mirror @ compile time inside macro.

here code have far (i have added several annotations , statements clearer):

object examplemacro {   def collect[t] = macro collect_impl    def collect_impl[t: c.weaktypetag](c: context): c.expr[seq[example[_]]] = {     import c.universe._      val symbol = weaktypeof[t].typesymbol      if (symbol.isclass && symbol.asclass.istrait && symbol.asclass.issealed) {       val children = symbol.asclass.knowndirectsubclasses.tolist        if (!children.forall(c => c.isclass && c.asclass.iscaseclass)) {         c.abort(c.enclosingposition, "all children of sealed trait must case classes")       }        val args: list[c.tree] = children.map { ch: symbol =>           val childtpe = c.weaktypetag(ch.typesignature)  // or c.typetag(ch.typesignature)            val runtimechildtpe: c.expr[scala.reflect.runtime.universe.typetag[_]] = ???  // should go here?            apply(select(reify(example).tree, newtermname("apply")), runtimechildtpe.tree)       }        apply(select(reify(seq).tree, newtermname("apply")), args)     } else {       c.abort(c.enclosingposition, "can construct sequence sealed trait")     }   } } 

you looking this:

c.reifytype(treebuild.mkruntimeuniverseref, emptytree, childtpe) 

the above code work assuming import c.universe._.

it create tree evaluate desired scala.reflect.runtime.universe.typetag[_] in runtime.

on second thought, think manual generation of tree may not needed @ all. tree returned macro undergoes more typechecking means compiler may able fill implicit typetags you. needs tested, though. try using this:

typeapply(select(reify(example).tree, newtermname("apply")), typetree().settype(childtpe)) 

Comments

Popular posts from this blog

Unable to remove the www from url on https using .htaccess -