summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-08-25 03:59:03 -0700
committerEugene Burmako <xeno.by@gmail.com>2012-08-25 03:59:03 -0700
commita23edefac652e3be1474fceb3ee15d7eaecf1359 (patch)
treebffc3880864828ce34726e8d994f5a64e4c6c09a
parent07a0b702ab00223f6f849868f0982cdb7994af66 (diff)
parent5bdfddefd7ff13476185b67d869a92c6c9f94506 (diff)
downloadscala-a23edefac652e3be1474fceb3ee15d7eaecf1359.tar.gz
scala-a23edefac652e3be1474fceb3ee15d7eaecf1359.tar.bz2
scala-a23edefac652e3be1474fceb3ee15d7eaecf1359.zip
Merge pull request #1194 from scalamacros/ticket/6281
SI-6281 macroArgs for defs with implicit args
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala12
-rw-r--r--test/files/run/macro-expand-implicit-argument.check1
-rw-r--r--test/files/run/macro-expand-implicit-argument.flags1
-rw-r--r--test/files/run/macro-expand-implicit-argument/Macros_1.scala59
-rw-r--r--test/files/run/macro-expand-implicit-argument/Test_2.scala4
5 files changed, 70 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index dbafd01ebc..01e773e528 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -588,7 +588,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val nullaryArgsEmptyParams = exprArgs.isEmpty && macroDef.paramss == ListOfNil
if (argcDoesntMatch && !nullaryArgsEmptyParams) { typer.TyperErrorGen.MacroPartialApplicationError(expandee) }
- var argss: List[List[Any]] = exprArgs.toList
+ val argss: List[List[Any]] = exprArgs.toList
macroTraceVerbose("context: ")(context)
macroTraceVerbose("argss: ")(argss)
@@ -597,9 +597,6 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
if (fastTrack(macroDef) validate context) argss
else typer.TyperErrorGen.MacroPartialApplicationError(expandee)
} else {
- val binding = loadMacroImplBinding(macroDef)
- macroTraceVerbose("binding: ")(binding)
-
// if paramss have typetag context bounds, add an arglist to argss if necessary and instantiate the corresponding evidences
// consider the following example:
//
@@ -616,6 +613,8 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
// then T and U need to be inferred from the lexical scope of the call using `asSeenFrom`
// whereas V won't be resolved by asSeenFrom and need to be loaded directly from `expandee` which needs to contain a TypeApply node
// also, macro implementation reference may contain a regular type as a type argument, then we pass it verbatim
+ val binding = loadMacroImplBinding(macroDef)
+ macroTraceVerbose("binding: ")(binding)
val tags = binding.signature filter (_ != -1) map (paramPos => {
val targ = binding.targs(paramPos).tpe.typeSymbol
val tpe = if (targ.isTypeParameterOrSkolem) {
@@ -633,14 +632,13 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
targ.tpe
if (tpe.isConcrete) context.TypeTag(tpe) else context.AbsTypeTag(tpe)
})
- val hasImplicitParams = macroDef.paramss.flatten.lastOption exists (_.isImplicit)
- argss = if (hasImplicitParams) argss.dropRight(1) :+ (tags ++ argss.last) else argss :+ tags
+ macroTraceVerbose("tags: ")(tags)
// transforms argss taking into account varargness of paramss
// note that typetag context bounds are only declared on macroImpls
// so this optional arglist might not match macroDef's paramlist
// nb! varargs can apply to any parameter section, not necessarily to the last one
- mapWithIndex(argss)((as, i) => {
+ mapWithIndex(argss :+ tags)((as, i) => {
val mapsToParamss = macroDef.paramss.indices contains i
if (mapsToParamss) {
val ps = macroDef.paramss(i)
diff --git a/test/files/run/macro-expand-implicit-argument.check b/test/files/run/macro-expand-implicit-argument.check
new file mode 100644
index 0000000000..fb42345748
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-argument.check
@@ -0,0 +1 @@
+List(1, 2, 3)
diff --git a/test/files/run/macro-expand-implicit-argument.flags b/test/files/run/macro-expand-implicit-argument.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-argument.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-argument/Macros_1.scala b/test/files/run/macro-expand-implicit-argument/Macros_1.scala
new file mode 100644
index 0000000000..7629c5a9e2
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-argument/Macros_1.scala
@@ -0,0 +1,59 @@
+import annotation.tailrec
+import scala.math.{min, max}
+import scala.{specialized => spec}
+
+import language.experimental.macros
+
+import scala.reflect.{ClassTag, TypeTag}
+import scala.reflect.macros.Context
+
+object Macros {
+ def alloc[@spec A:ClassTag](src:Array[A], s1:Int, len:Int) = {
+ val as = Array.ofDim[A](len)
+ System.arraycopy(src, s1, as, 0, len)
+ as
+ }
+
+ /**
+ * Efficient alternative to Array.apply.
+ *
+ * "As seen on scala-internals!"
+ */
+ def array[A](as:A*)(implicit ct: ClassTag[A]) = macro arrayMacro[A]
+
+ /**
+ * Takes in something like:
+ * ArrayUtil.alloc[Int](11, 22, 33, 44)(ct)
+ *
+ * and builds a tree like:
+ * {
+ * val arr:Array[Int] = ct.newArray(4)
+ * arr.update(0, 11)
+ * arr.update(1, 22)
+ * arr.update(2, 33)
+ * arr.update(3, 44)
+ * arr
+ * }
+ */
+ def arrayMacro[A:c.AbsTypeTag](c:Context)(as:c.Expr[A]*)(ct: c.Expr[ClassTag[A]]): c.Expr[Array[A]] = {
+ import c.mirror._
+ import c.universe._
+ def const(x:Int) = Literal(Constant(x))
+
+ val n = as.length
+ val arr = newTermName("arr")
+
+ val create = Apply(Select(ct.tree, "newArray"), List(const(n)))
+ val arrtpe = TypeTree(implicitly[c.AbsTypeTag[Array[A]]].tpe)
+ val valdef = ValDef(Modifiers(), arr, arrtpe, create)
+
+ val updates = (0 until n).map {
+ i => Apply(Select(Ident(arr), "update"), List(const(i), as(i).tree))
+ }
+
+ val exprs = Seq(valdef) ++ updates ++ Seq(Ident(arr))
+ val block = Block(exprs:_*)
+
+ c.Expr[Array[A]](block)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-argument/Test_2.scala b/test/files/run/macro-expand-implicit-argument/Test_2.scala
new file mode 100644
index 0000000000..ce8a068fb4
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-argument/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros._
+ println(array(1, 2, 3).toList)
+} \ No newline at end of file