Last active
December 19, 2015 17:48
-
-
Save mandubian/5993771 to your computer and use it in GitHub Desktop.
I want to call recursively the macro mkObject in itself...
But it can't compile because the @Body trick doesn't accept an instance generated by mkObject itself...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//The huge error | |
[error] | |
[error] while compiling: /Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/core/src/main/scala/Test.scala | |
[error] during phase: pickler | |
[error] library version: version 2.10.0 | |
[error] compiler version: version 2.10.0 | |
[error] reconstructed args: -d /Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/core/target/scala-2.10/classes -bootclasspath /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/classes:/Users/pvo/.sbt/boot/scala-2.10.0/lib/scala-library.jar -classpath /Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/core/target/scala-2.10/classes:/Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/macros/target/scala-2.10/classes:/Users/pvo/.ivy2/cache/org.scala-lang.macro-paradise/scala-reflect/jars/scala-reflect-2.10.2-SNAPSHOT.jar | |
[error] | |
[error] last tree to typer: Literal(Constant(10)) | |
[error] symbol: null | |
[error] symbol definition: null | |
[error] tpe: Int(10) | |
[error] symbol owners: | |
[error] context owners: anonymous class $anon -> value <local Workaround> -> class Workaround -> value foo -> object Test -> package <empty> | |
[error] | |
[error] == Enclosing template or block == | |
[error] | |
[error] ClassDef( // class $anon extends Workaround | |
[error] 0 | |
[error] "$anon" | |
[error] [] | |
[error] Template( // val <local $anon>: <notype>, tree.tpe=Workaround | |
[error] "Test.Workaround.Workaround" // parents | |
[error] ValDef( | |
[error] private | |
[error] "_" | |
[error] <tpt> | |
[error] <empty> | |
[error] ) | |
[error] DefDef( // def <init>(): Workaround | |
[error] <method> <triedcooking> | |
[error] "<init>" | |
[error] [] | |
[error] List(Nil) | |
[error] <tpt> // tree.tpe=Workaround | |
[error] Block( // tree.tpe=Unit | |
[error] Apply( // def <init>(): Workaround in class Workaround, tree.tpe=Workaround | |
[error] $anon.super."<init>" // def <init>(): Workaround in class Workaround, tree.tpe=()Workaround | |
[error] Nil | |
[error] ) | |
[error] () | |
[error] ) | |
[error] ) | |
[error] ) | |
[error] ) | |
[error] | |
[error] == Expanded type of tree == | |
[error] | |
[error] ConstantType(value = Constant(10)) | |
[error] | |
[error] uncaught exception during compilation: java.lang.AssertionError | |
[trace] Stack trace suppressed: run last core/compile:compile for the full output. | |
[error] (core/compile:compile) java.lang.AssertionError: assertion failed: | |
[error] while compiling: /Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/core/src/main/scala/Test.scala | |
[error] during phase: pickler | |
[error] library version: version 2.10.0 | |
[error] compiler version: version 2.10.0 | |
[error] reconstructed args: -d /Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/core/target/scala-2.10/classes -bootclasspath /Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/sunrsasign.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/lib/JObjC.jar:/Library/Java/JavaVirtualMachines/jdk1.7.0_21.jdk/Contents/Home/jre/classes:/Users/pvo/.sbt/boot/scala-2.10.0/lib/scala-library.jar -classpath /Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/core/target/scala-2.10/classes:/Users/pvo/zenexity/work/macrotest/sbt-example-paradise210/macros/target/scala-2.10/classes:/Users/pvo/.ivy2/cache/org.scala-lang.macro-paradise/scala-reflect/jars/scala-reflect-2.10.2-SNAPSHOT.jar | |
[error] | |
[error] last tree to typer: Literal(Constant(10)) | |
[error] symbol: null | |
[error] symbol definition: null | |
[error] tpe: Int(10) | |
[error] symbol owners: | |
[error] context owners: anonymous class $anon -> value <local Workaround> -> class Workaround -> value foo -> object Test -> package <empty> | |
[error] | |
[error] == Enclosing template or block == | |
[error] | |
[error] ClassDef( // class $anon extends Workaround | |
[error] 0 | |
[error] "$anon" | |
[error] [] | |
[error] Template( // val <local $anon>: <notype>, tree.tpe=Workaround | |
[error] "Test.Workaround.Workaround" // parents | |
[error] ValDef( | |
[error] private | |
[error] "_" | |
[error] <tpt> | |
[error] <empty> | |
[error] ) | |
[error] DefDef( // def <init>(): Workaround | |
[error] <method> <triedcooking> | |
[error] "<init>" | |
[error] [] | |
[error] List(Nil) | |
[error] <tpt> // tree.tpe=Workaround | |
[error] Block( // tree.tpe=Unit | |
[error] Apply( // def <init>(): Workaround in class Workaround, tree.tpe=Workaround | |
[error] $anon.super."<init>" // def <init>(): Workaround in class Workaround, tree.tpe=()Workaround | |
[error] Nil | |
[error] ) | |
[error] () | |
[error] ) | |
[error] ) | |
[error] ) | |
[error] ) | |
[error] | |
[error] == Expanded type of tree == | |
[error] | |
[error] ConstantType(value = Constant(10))*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Here is the generated class: | |
{ | |
class Workaround extends scala.AnyRef { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
@new body({ | |
class Workaround extends scala.AnyRef { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
@new body(4) <macro> def y = Macros.selFieldImpl; | |
@new body(10) <macro> def z = Macros.selFieldImpl | |
}; | |
{ | |
class $anon extends Workaround { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
<empty> | |
}; | |
new $anon() | |
} | |
}) <macro> def x = Macros.selFieldImpl | |
}; | |
{ | |
class $anon extends Workaround { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
<empty> | |
}; | |
new $anon() | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.reflect.macros.Context | |
// uses the technique described in: | |
// http://docs.scala-lang.org/overviews/macros/overview.html#writing_bigger_macros | |
class Helper[C <: Context](val c: C) extends QuasiquoteCompat { | |
import c.universe._ | |
def mkObject(xs: c.Tree*): c.Tree = { | |
val fields = xs.toList map { | |
case q"${_}(${Literal(Constant(name: String))}).->[${_}](${tup}(..$value))" => | |
// Here I call recursively the macro and put the result in @body | |
val r = mkObject(value:_*) | |
val res = q""" | |
@body($r) def ${newTermName(name)} = macro Macros.selFieldImpl | |
""" | |
res | |
case q"${_}(${Literal(Constant(name: String))}).->[${_}]($value)" => | |
q""" | |
@body($value) def ${newTermName(name)} = macro Macros.selFieldImpl | |
""" | |
} | |
val r = q"""class Workaround { | |
..$fields | |
}; new Workaround{}""" | |
println("r:"+r) | |
r | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import language.experimental.macros | |
import scala.reflect.macros.Context | |
import scala.annotation.StaticAnnotation | |
class body(tree: Any) extends StaticAnnotation | |
object Macros { | |
def selFieldImpl(c: Context) = { | |
val field = c.macroApplication.symbol | |
val bodyAnn = field.annotations.filter(_.tpe <:< c.typeOf[body]).head | |
c.Expr[Any](bodyAnn.scalaArgs.head) | |
} | |
def mkObject(xs: Any*) = macro mkObjectImpl | |
def mkObjectImpl(c: Context)(xs: c.Expr[Any]*) = { | |
val helper = new Helper[c.type](c) | |
c.Expr[Any](helper.mkObject(xs.map(_.tree):_*)) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.language.experimental.macros | |
import scala.reflect.macros.Context | |
object Test extends App { | |
val foo = Macros.mkObject("x" -> ("y" -> 4, "z" -> 10)) | |
println(foo.x.y) | |
} | |
// Here is the generated class: | |
{ | |
class Workaround extends scala.AnyRef { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
@new body({ | |
class Workaround extends scala.AnyRef { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
@new body(4) <macro> def y = Macros.selFieldImpl; | |
@new body(10) <macro> def z = Macros.selFieldImpl | |
}; | |
{ | |
class $anon extends Workaround { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
<empty> | |
}; | |
new $anon() | |
} | |
}) <macro> def x = Macros.selFieldImpl | |
}; | |
{ | |
class $anon extends Workaround { | |
def <init>() = { | |
super.<init>(); | |
() | |
}; | |
<empty> | |
}; | |
new $anon() | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment