Skip to content

Instantly share code, notes, and snippets.

@xeno-by
Created July 10, 2013 12:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xeno-by/5965822 to your computer and use it in GitHub Desktop.
Save xeno-by/5965822 to your computer and use it in GitHub Desktop.
import scala.reflect.macros.Context
import language.experimental.macros
object Macros {
def impl1(c: Context) = {
import c.universe._
q"new { def x = macro Macros.impl2 }"
}
def foo = macro impl1
def impl2(c: Context) = {
import c.universe._
q"2"
}
def bar = macro impl2
}
============
object Test extends App {
val foo = Macros.foo
println(foo.x)
}
=============
14:14 ~/Projects/Paradise/sandbox (paradise/macros)$ ls
Macros.scala Test.scala
14:14 ~/Projects/Paradise/sandbox (paradise/macros)$ scalac Macros.scala
14:14 ~/Projects/Paradise/sandbox (paradise/macros)$ scalac Test.scala -Xprint:cleanup
[[syntax trees at end of cleanup]] // Test.scala
package <empty> {
object Test extends Object with App {
<stable> <accessor> def executionStart(): Long = Test.this.executionStart;
private[this] val executionStart: Long = _;
final <accessor> def _args(): Array[String] = Test.this._args;
private[this] var _args: Array[String] = _;
final <accessor> def _args_=(x$1: Array[String]): Unit = Test.this._args = x$1;
final <stable> <accessor> def initCode(): collection.mutable.ListBuffer = Test.this.initCode;
private[this] val initCode: collection.mutable.ListBuffer = _;
<accessor> def scala$App$_setter_$executionStart_=(x$1: Long): Unit = Test.this.executionStart = x$1;
<accessor> def initCode_=(x$1: collection.mutable.ListBuffer): Unit = Test.this.initCode = x$1;
def args(): Array[String] = scala.App$class.args(Test.this);
override def delayedInit(body: Function0): Unit = scala.App$class.delayedInit(Test.this, body);
def main(args: Array[String]): Unit = scala.App$class.main(Test.this, args);
private[this] val foo: Object = _;
<stable> <accessor> def foo(): Object = Test.this.foo;
final <synthetic> def delayedEndpoint$Test$1: Unit = {
Test.this.foo = {
new anonymous class anon$1()
};
scala.this.Predef.println(scala.Int.box(2));
()
};
def <init>(): Test.type = {
Test.super.<init>();
scala.App$class./*App$class*/$init$(Test.this);
Test.this.delayedInit(new Test$delayedInit$body(Test.this));
()
}
};
final class anon$1 extends Object {
def <init>(): anonymous class anon$1 = {
anon$1.super.<init>();
()
}
};
final <synthetic> class Test$delayedInit$body extends runtime.AbstractFunction0 {
<paramaccessor> private[this] val $outer: Test.type = _;
final def apply(): Object = {
Test$delayedInit$body.this.$outer.delayedEndpoint$Test$1();
scala.runtime.BoxedUnit.UNIT
};
def <init>($outer: Test.type): Test$delayedInit$body = {
if ($outer.eq(null))
throw null
else
Test$delayedInit$body.this.$outer = $outer;
Test$delayedInit$body.super.<init>();
()
}
}
}
warning: there were 1 feature warning(s); re-run with -feature for details
one warning found
14:15 ~/Projects/Paradise/sandbox (paradise/macros)$ scala Test
2
@xeno-by
Copy link
Author

xeno-by commented Jul 10, 2013

The warning is funny:

Test.scala:3: warning: reflective access of structural type member macro method x should be enabled
by making the implicit value scala.language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
  println(foo.x)
              ^

@xeno-by
Copy link
Author

xeno-by commented Jul 10, 2013

Ha! Also works in 2.10.x if I apply the workaround suggested by Travis Brown in http://stackoverflow.com/questions/14370842/getting-a-structural-type-with-an-anonymous-classs-methods-from-a-macro.

-q"new { def x = macro Macros.impl2 }"
+q"class C { def x = macro Macros.impl2 }; new C {}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment