diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-01-19 12:28:19 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-05-28 10:19:19 +0200 |
commit | 10229316dbf7afa7545d8e279b5960da6ee3db7d (patch) | |
tree | cfa50a3207aa5c1b2ce17ffba0fe1413a6f0dd53 /test | |
parent | e0bbe0af094b9055942c24fcaaa290a31415fa0a (diff) | |
download | scala-10229316dbf7afa7545d8e279b5960da6ee3db7d.tar.gz scala-10229316dbf7afa7545d8e279b5960da6ee3db7d.tar.bz2 scala-10229316dbf7afa7545d8e279b5960da6ee3db7d.zip |
refactors macro compilation
Upgrades the way that macro defs are compiled by factoring out most of
the logic in typedMacroBody and related errors in ContextErrors into an
standalone cake. This leads to tighter cohesion and better code reuse
as the cake is isolated from the rest of the compiler and is much easier
to evolve than just a method body.
Increased convenience of coding macro compilation allowed me to further
clarify the implementation of the macro engine (e.g. take a look at
Validators.scala) and to easily implement additional features, namely:
1) Parameters and return type of macro implementations can now be plain
c.Tree's instead of previously mandatory c.Expr's. This makes macros more
lightweight as there are a lot of situations when one doesn't need to
splice macro params (the only motivation to use exprs over trees). Also
as we're on the verge of having quasiquotes in trunk, there soon will be
no reason to use exprs at all, since quasiquotes can splice everything.
2) Macro implementations can now be defined in bundles, standalone cakes
built around a macro context: http://docs.scala-lang.org/overviews/macros/bundles.html.
This further reduces boilerplate by simplifying implementations complex
macros due to the fact that macro programmers no longer need to play
path-dependent games to use helpers.
Diffstat (limited to 'test')
-rw-r--r-- | test/files/neg/macro-invalidimpl.check | 30 | ||||
-rw-r--r-- | test/files/neg/macro-invalidret.check | 4 | ||||
-rw-r--r-- | test/files/neg/macro-invalidshape.check | 14 | ||||
-rw-r--r-- | test/files/neg/macro-invalidsig-params-badtype.check | 6 | ||||
-rw-r--r-- | test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala | 2 | ||||
-rw-r--r-- | test/files/neg/macro-invalidsig.check | 26 | ||||
-rw-r--r-- | test/files/neg/t5689.check | 2 | ||||
-rw-r--r-- | test/files/run/macro-bodyexpandstoimpl/Impls_1.scala | 2 | ||||
-rw-r--r-- | test/files/run/macro-bundle.check | 3 | ||||
-rw-r--r-- | test/files/run/macro-bundle.flags | 1 | ||||
-rw-r--r-- | test/files/run/macro-bundle/Impls_Macros_1.scala | 13 | ||||
-rw-r--r-- | test/files/run/macro-bundle/Test_2.scala | 5 | ||||
-rw-r--r-- | test/files/run/macro-toplevel-companion-b/Test_2.scala | 2 | ||||
-rw-r--r-- | test/files/run/macro-toplevel-companion-c.scala | 2 |
14 files changed, 71 insertions, 41 deletions
diff --git a/test/files/neg/macro-invalidimpl.check b/test/files/neg/macro-invalidimpl.check index 7177a8cdee..aaf4f88fc2 100644 --- a/test/files/neg/macro-invalidimpl.check +++ b/test/files/neg/macro-invalidimpl.check @@ -1,15 +1,23 @@ -Macros_Test_2.scala:5: error: macro implementation must be in statically accessible object +Macros_Test_2.scala:5: error: macro implementation reference has wrong shape. required: +macro [<static object>].<method name>[[<type args>]] or +macro [<macro bundle>].<method name>[[<type args>]] def foo(x: Any) = macro impls.foo - ^ -Macros_Test_2.scala:10: error: macro implementation must be in statically accessible object + ^ +Macros_Test_2.scala:10: error: macro implementation reference has wrong shape. required: +macro [<static object>].<method name>[[<type args>]] or +macro [<macro bundle>].<method name>[[<type args>]] def foo(x: Any) = macro impls.foo - ^ -Macros_Test_2.scala:18: error: macro implementation must be in statically accessible object + ^ +Macros_Test_2.scala:18: error: macro implementation reference has wrong shape. required: +macro [<static object>].<method name>[[<type args>]] or +macro [<macro bundle>].<method name>[[<type args>]] def foo(x: Any) = macro Impls3.foo - ^ -Macros_Test_2.scala:22: error: macro implementation must be in statically accessible object + ^ +Macros_Test_2.scala:22: error: macro implementation reference has wrong shape. required: +macro [<static object>].<method name>[[<type args>]] or +macro [<macro bundle>].<method name>[[<type args>]] def foo(x: Any) = macro Impls4.foo - ^ + ^ Macros_Test_2.scala:26: error: ambiguous reference to overloaded definition, both method foo in object Impls5 of type (c: scala.reflect.macros.Context)(x: c.Expr[Any], y: c.Expr[Any])Nothing and method foo in object Impls5 of type (c: scala.reflect.macros.Context)(x: c.Expr[Any])Nothing @@ -27,17 +35,17 @@ Macros_Test_2.scala:31: error: macro implementation has wrong shape: found : (c: scala.reflect.macros.Context)(): c.Expr[Unit] number of parameter sections differ def foo1 = macro Impls6.fooEmpty - ^ + ^ Macros_Test_2.scala:32: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(): c.Expr[Unit] found : (c: scala.reflect.macros.Context): c.Expr[Unit] number of parameter sections differ def bar1() = macro Impls6.fooNullary - ^ + ^ Macros_Test_2.scala:36: error: type arguments [String] do not conform to method foo's type parameter bounds [U <: Int] def foo = macro Impls7.foo[String] ^ Macros_Test_2.scala:53: error: macro implementation must be public def foo = macro Impls8.impl - ^ + ^ 10 errors found diff --git a/test/files/neg/macro-invalidret.check b/test/files/neg/macro-invalidret.check index d6664e6882..8c6ed4eb45 100644 --- a/test/files/neg/macro-invalidret.check +++ b/test/files/neg/macro-invalidret.check @@ -3,11 +3,11 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: found : (c: scala.reflect.macros.Context): Int type mismatch for return type: Int does not conform to c.Expr[Any] def foo1 = macro Impls.foo1 - ^ + ^ Macros_Test_2.scala:3: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] found : (c: scala.reflect.macros.Context): reflect.runtime.universe.Literal type mismatch for return type: reflect.runtime.universe.Literal does not conform to c.Expr[Any] def foo2 = macro Impls.foo2 - ^ + ^ two errors found diff --git a/test/files/neg/macro-invalidshape.check b/test/files/neg/macro-invalidshape.check index cefc95b763..40a2952569 100644 --- a/test/files/neg/macro-invalidshape.check +++ b/test/files/neg/macro-invalidshape.check @@ -1,17 +1,15 @@ -Macros_Test_2.scala:2: error: macro body has wrong shape: - required: macro [<implementation object>].<method name>[[<type args>]] +Macros_Test_2.scala:2: error: macro implementation reference has wrong shape. required: +macro [<static object>].<method name>[[<type args>]] or +macro [<macro bundle>].<method name>[[<type args>]] def foo1(x: Any) = macro 2 ^ -Macros_Test_2.scala:3: error: macro body has wrong shape: - required: macro [<implementation object>].<method name>[[<type args>]] +Macros_Test_2.scala:3: error: macro implementation reference has wrong shape. required: +macro [<static object>].<method name>[[<type args>]] or +macro [<macro bundle>].<method name>[[<type args>]] def foo2(x: Any) = macro Impls.foo(null)(null) ^ -Macros_Test_2.scala:4: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - def foo3(x: Any) = macro {2; Impls.foo} - ^ Macros_Test_2.scala:4: error: missing arguments for method foo in object Impls; follow this method with `_' if you want to treat it as a partially applied function def foo3(x: Any) = macro {2; Impls.foo} ^ -one warning found three errors found diff --git a/test/files/neg/macro-invalidsig-params-badtype.check b/test/files/neg/macro-invalidsig-params-badtype.check index 3ec40d7e5b..3cc1c9abf1 100644 --- a/test/files/neg/macro-invalidsig-params-badtype.check +++ b/test/files/neg/macro-invalidsig-params-badtype.check @@ -1,7 +1,7 @@ Impls_Macros_1.scala:8: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] - found : (c: scala.reflect.macros.Context)(x: c.universe.Tree): Nothing -type mismatch for parameter x: c.Expr[Int] does not conform to c.universe.Tree + found : (c: scala.reflect.macros.Context)(x: Int): Nothing +type mismatch for parameter x: c.Expr[Int] does not conform to Int def foo(x: Int) = macro Impls.foo - ^ + ^ one error found diff --git a/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala index ab90b85881..175683d6d3 100644 --- a/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala +++ b/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala @@ -1,7 +1,7 @@ import scala.reflect.macros.{Context => Ctx} object Impls { - def foo(c: Ctx)(x: c.universe.Tree) = ??? + def foo(c: Ctx)(x: Int) = ??? } object Macros { diff --git a/test/files/neg/macro-invalidsig.check b/test/files/neg/macro-invalidsig.check index 52074cf783..cbdaf51081 100644 --- a/test/files/neg/macro-invalidsig.check +++ b/test/files/neg/macro-invalidsig.check @@ -3,67 +3,67 @@ Macros_Test_2.scala:2: error: macro implementation has wrong shape: found : (c: scala.reflect.macros.Context)(implicit evidence$2: Numeric[U]): c.universe.Literal macro implementations cannot have implicit parameters other than WeakTypeTag evidences def foo[U] = macro Impls1.foo[U] - ^ + ^ Macros_Test_2.scala:6: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] found : : Nothing number of parameter sections differ def foo = macro Impls2.foo - ^ + ^ Macros_Test_2.scala:10: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] found : (c: scala.reflect.api.Universe): Nothing type mismatch for parameter c: scala.reflect.macros.Context does not conform to scala.reflect.api.Universe def foo = macro Impls3.foo - ^ + ^ Macros_Test_2.scala:14: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] found : (cs: scala.reflect.macros.Context*): Nothing types incompatible for parameter cs: corresponding is not a vararg parameter def foo = macro Impls4.foo - ^ + ^ Macros_Test_2.scala:18: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Any]): c.Expr[Any] found : (c: scala.reflect.macros.Context): Nothing number of parameter sections differ def foo(x: Any) = macro Impls5.foo - ^ + ^ Macros_Test_2.scala:22: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Unit] found : (c: scala.reflect.macros.Context)(implicit x: c.Expr[Int]): c.Expr[Unit] macro implementations cannot have implicit parameters other than WeakTypeTag evidences def foo[U](x: Int) = macro Impls6.foo[T, U] - ^ + ^ Macros_Test_2.scala:26: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] found : (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): Nothing parameter lists have different length, found extra parameter y: c.Expr[Int] def foo(x: Int) = macro Impls7.foo - ^ + ^ Macros_Test_2.scala:30: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int]): c.Expr[Any] found : (c: scala.reflect.macros.Context)(x: c.universe.Symbol): Nothing type mismatch for parameter x: c.Expr[Int] does not conform to c.universe.Symbol def foo(x: Int) = macro Impls8.foo - ^ + ^ Macros_Test_2.scala:34: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any] found : (c: scala.reflect.macros.Context)(xs: c.Expr[Int]*): Nothing parameter lists have different length, required extra parameter y: c.Expr[Int] def foo(x: Int, y: Int) = macro Impls9.foo - ^ + ^ Macros_Test_2.scala:38: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any] found : (c: scala.reflect.macros.Context)(y: c.Expr[Int], x: c.Expr[Int]): Nothing parameter names differ: x != y def foo(x: Int, y: Int) = macro Impls10.foo - ^ + ^ Macros_Test_2.scala:42: error: macro implementation has wrong shape: required: (c: scala.reflect.macros.Context): c.Expr[Any] found : (c: scala.reflect.macros.Context)(U: c.universe.Type): Nothing number of parameter sections differ def foo[U] = macro Impls11.foo[U] - ^ + ^ Macros_Test_2.scala:46: error: type arguments [U] do not conform to method foo's type parameter bounds [U <: String] def foo[U] = macro Impls12.foo[U] ^ @@ -72,10 +72,10 @@ Macros_Test_2.scala:50: error: type arguments [U] do not conform to method foo's ^ Macros_Test_2.scala:54: error: wrong number of type parameters for method foo: [U](c: scala.reflect.macros.Context)(implicit evidence$4: c.WeakTypeTag[U])Nothing def foo = macro Impls14.foo - ^ + ^ Macros_Test_2.scala:59: error: wrong number of type parameters for method foo: [T, U, V](c: scala.reflect.macros.Context)(implicit evidence$5: c.WeakTypeTag[T], implicit evidence$6: c.WeakTypeTag[U], implicit V: c.WeakTypeTag[V])c.Expr[Unit] def foo15[V] = macro Impls15.foo - ^ + ^ Macros_Test_2.scala:60: error: wrong number of type parameters for method foo: [T, U, V](c: scala.reflect.macros.Context)(implicit evidence$7: c.WeakTypeTag[T], implicit evidence$8: c.WeakTypeTag[U], implicit V: c.WeakTypeTag[V])c.Expr[Unit] def foo16[V] = macro Impls16.foo[V] ^ diff --git a/test/files/neg/t5689.check b/test/files/neg/t5689.check index 50aaa7dbfe..ad9b79cdcb 100644 --- a/test/files/neg/t5689.check +++ b/test/files/neg/t5689.check @@ -3,5 +3,5 @@ t5689.scala:4: error: macro implementation has wrong shape: found : (c: scala.reflect.macros.Context)(i: c.Expr[Double]): c.Expr[Int] type mismatch for return type: c.Expr[Int] does not conform to c.Expr[String] def returnsString(i: Double): String = macro returnsIntImpl - ^ + ^ one error found diff --git a/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala b/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala index 9c1e4ee46d..56c5252f31 100644 --- a/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala +++ b/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala @@ -7,6 +7,8 @@ object Impls { def refToFoo_impl(c: Ctx)(dummy: c.Expr[Int]) = { import c.universe._ val body = Select(Ident(TermName("Impls")), TermName("foo")) + val global = c.universe.asInstanceOf[scala.tools.nsc.Global] + global.analyzer.markMacroImplRef(body.asInstanceOf[global.Tree]) c.Expr[Int](body) } }
\ No newline at end of file diff --git a/test/files/run/macro-bundle.check b/test/files/run/macro-bundle.check new file mode 100644 index 0000000000..2107454960 --- /dev/null +++ b/test/files/run/macro-bundle.check @@ -0,0 +1,3 @@ +() +Int +() diff --git a/test/files/run/macro-bundle.flags b/test/files/run/macro-bundle.flags new file mode 100644 index 0000000000..cd66464f2f --- /dev/null +++ b/test/files/run/macro-bundle.flags @@ -0,0 +1 @@ +-language:experimental.macros
\ No newline at end of file diff --git a/test/files/run/macro-bundle/Impls_Macros_1.scala b/test/files/run/macro-bundle/Impls_Macros_1.scala new file mode 100644 index 0000000000..3f651c9a43 --- /dev/null +++ b/test/files/run/macro-bundle/Impls_Macros_1.scala @@ -0,0 +1,13 @@ +import scala.reflect.macros.Context +import scala.reflect.macros.Macro + +trait Impl extends Macro { + def mono = c.literalUnit + def poly[T: c.WeakTypeTag] = c.literal(c.weakTypeOf[T].toString) + def weird = macro mono +} + +object Macros { + def mono = macro Impl.mono + def poly[T] = macro Impl.poly[T] +}
\ No newline at end of file diff --git a/test/files/run/macro-bundle/Test_2.scala b/test/files/run/macro-bundle/Test_2.scala new file mode 100644 index 0000000000..428f809f9d --- /dev/null +++ b/test/files/run/macro-bundle/Test_2.scala @@ -0,0 +1,5 @@ +object Test extends App { + println(Macros.mono) + println(Macros.poly[Int]) + println(new Impl{val c = ???}.weird) +}
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-b/Test_2.scala b/test/files/run/macro-toplevel-companion-b/Test_2.scala index ca202d053f..4e766bde89 100644 --- a/test/files/run/macro-toplevel-companion-b/Test_2.scala +++ b/test/files/run/macro-toplevel-companion-b/Test_2.scala @@ -7,5 +7,5 @@ import Macros._ object Test extends App { val tb = cm.mkToolBox() try tb.compile(Select(Ident(TermName("Macros")), TermName("foo"))) - catch { case ToolBoxError(message, _) => println("""macroSynthetic-.*?\.scala""".r.replaceAllIn(message, "<synthetic file name>")) } + catch { case ToolBoxError(message, _) => println("""(Found in|and) .*?compileLateSynthetic-.*?\.scala""".r.replaceAllIn(message, m => m.group(1) + " <synthetic file name>")) } }
\ No newline at end of file diff --git a/test/files/run/macro-toplevel-companion-c.scala b/test/files/run/macro-toplevel-companion-c.scala index 0e99903158..c315f8b942 100644 --- a/test/files/run/macro-toplevel-companion-c.scala +++ b/test/files/run/macro-toplevel-companion-c.scala @@ -45,7 +45,7 @@ object Test extends DirectTest { log("Compiling Test_2...") if (compileTest()) log("Success!") else log("Failed...") } - println("""macroSynthetic-.*?\.scala""".r.replaceAllIn(baos.toString, "<synthetic file name>")) + println("""(Found in|and) .*?compileLateSynthetic-.*?\.scala""".r.replaceAllIn(baos.toString, m => m.group(1) + " <synthetic file name>")) System.setErr(prevErr) } }
\ No newline at end of file |