Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Macro-powered structural types
import scala.annotation.StaticAnnotation
import scala.reflect.macros.Macro
import language.experimental.macros
class body(tree: Any) extends StaticAnnotation
trait Macros extends Macro {
import c.universe._
def selFieldImpl = {
val field = c.macroApplication.symbol
val bodyAnn = field.annotations.filter(_.tpe <:< typeOf[body]).head
bodyAnn.scalaArgs.head
}
def mkObjectImpl(xs: c.Tree*) = {
val kvps = xs.toList map { case q"${_}(${Literal(Constant(name: String))}).->[${_}]($value)" => name -> value }
val fields = kvps map { case (k, v) => q"@body($v) def ${TermName(k)} = macro Macros.selFieldImpl" }
q"class Workaround { ..$fields }; new Workaround{}"
}
}
object mkObject {
def apply(xs: Any*) = macro Macros.mkObjectImpl
}
=================
object Test {
def main(args: Array[String]) = {
val foo = mkObject("x" -> "2", "y" -> 3)
println(foo.x)
println(foo.y)
// println(foo.z) => will result in a compilation error
}
}
@xeno-by

This comment has been minimized.

Copy link
Owner Author

commented Jul 10, 2013

No reflection involved!

18:37 ~/Projects/Kepler_structural/sandbox (topic/structural)$ scalac Macros.scala && scalac Test.scala -Xprint:cleanup
[[syntax trees at end of                   cleanup]] // Test.scala
package <empty> {
  object Test extends Object {
    def main(args: Array[String]): Unit = {
      val foo: Object = {
        {
          new anonymous class anon$1()
        }
      };
      scala.this.Predef.println("2");
      scala.this.Predef.println(scala.Int.box(3))
    };
    def <init>(): Test.type = {
      Test.super.<init>();
      ()
    }
  };
  class Test$Workaround$1 extends Object {
    def <init>(): Test$Workaround$1 = {
      Test$Workaround$1.super.<init>();
      ()
    }
  };
  final class anon$1 extends Test$Workaround$1 {
    def <init>(): anonymous class anon$1 = {
      anon$1.super.<init>();
      ()
    }
  }
}

 // compileLateSynthetic-fbb25380ed1946c68a1246b286a54476.scala
package scala.reflect.macros.synthetic {
  class MacrosInvoker extends Object with Macros {
    def selFieldImpl(): reflect.macros.Universe$TreeContextApi = Macros$class.selFieldImpl(MacrosInvoker.this);
    def mkObjectImpl(xs: Seq): reflect.macros.Universe$TreeContextApi = Macros$class.mkObjectImpl(MacrosInvoker.this, xs);
    <paramaccessor> private[this] val c: reflect.macros.Context = _;
    <stable> <accessor> <paramaccessor> def c(): reflect.macros.Context = MacrosInvoker.this.c;
    def <init>(c: reflect.macros.Context): scala.reflect.macros.synthetic.MacrosInvoker = {
      MacrosInvoker.this.c = c;
      MacrosInvoker.super.<init>();
      Macros$class./*Macros$class*/$init$(MacrosInvoker.this);
      ()
    }
  }
}

warning: there were 2 feature warning(s); re-run with -feature for details
one warning found
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.