summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-05-17 02:02:16 -0700
committerJason Zaugg <jzaugg@gmail.com>2013-05-17 02:02:16 -0700
commit7415430ca7f7995f870dd81b2f020afeeb6e316e (patch)
treeb4547056abf2bfd45fe6fc90a017e43718749dd6
parent988e27adf95ba5177603b52c52cbae180d577b1a (diff)
parentbc1071580203eda3f90433d930739f55a696a131 (diff)
downloadscala-7415430ca7f7995f870dd81b2f020afeeb6e316e.tar.gz
scala-7415430ca7f7995f870dd81b2f020afeeb6e316e.tar.bz2
scala-7415430ca7f7995f870dd81b2f020afeeb6e316e.zip
Merge pull request #2497 from scalamacros/topic/macro-qqq
easy way of writing not implemented macros
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala47
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
-rw-r--r--test/files/neg/macro-qmarkqmarkqmark.check13
-rw-r--r--test/files/neg/macro-qmarkqmarkqmark.scala13
-rw-r--r--test/files/pos/macro-qmarkqmarkqmark.check0
-rw-r--r--test/files/pos/macro-qmarkqmarkqmark.scala7
7 files changed, 66 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index e0dbe98780..b9cff5b2d3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -1307,6 +1307,11 @@ trait ContextErrors {
throw MacroBodyTypecheckException // don't call fail, because we don't need IS_ERROR
}
+ def MacroDefIsQmarkQmarkQmark() = {
+ macroLogVerbose("typecheck terminated unexpectedly: macro is ???")
+ throw MacroBodyTypecheckException
+ }
+
def MacroFeatureNotEnabled() = {
macroLogVerbose("typecheck terminated unexpectedly: language.experimental.macros feature is not enabled")
fail()
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 5ad568b1e6..816f977890 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -412,6 +412,9 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
// Phase II: typecheck the right-hand side of the macro def
val typed = typecheckRhs(macroDdef.rhs)
typed match {
+ case MacroImplReference(_, meth, _) if meth == Predef_??? =>
+ bindMacroImpl(macroDef, typed)
+ MacroDefIsQmarkQmarkQmark()
case MacroImplReference(owner, meth, targs) =>
if (!meth.isMethod) MacroDefInvalidBodyError()
if (!meth.isPublic) MacroImplNotPublicError()
@@ -521,26 +524,30 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val methName = binding.methName
macroLogVerbose(s"resolved implementation as $className.$methName")
- // I don't use Scala reflection here, because it seems to interfere with JIT magic
- // whenever you instantiate a mirror (and not do anything with in, just instantiate), performance drops by 15-20%
- // I'm not sure what's the reason - for me it's pure voodoo
- // upd. my latest experiments show that everything's okay
- // it seems that in 2.10.1 we can easily switch to Scala reflection
- try {
- macroLogVerbose(s"loading implementation class: $className")
- macroLogVerbose(s"classloader is: ${ReflectionUtils.show(macroClassloader)}")
- val implObj = ReflectionUtils.staticSingletonInstance(macroClassloader, className)
- // relies on the fact that macro impls cannot be overloaded
- // so every methName can resolve to at maximum one method
- val implMeths = implObj.getClass.getDeclaredMethods.find(_.getName == methName)
- val implMeth = implMeths getOrElse { throw new NoSuchMethodException(s"$className.$methName") }
- macroLogVerbose(s"successfully loaded macro impl as ($implObj, $implMeth)")
- args => implMeth.invoke(implObj, ((args.c +: args.others) map (_.asInstanceOf[AnyRef])): _*)
- } catch {
- case ex: Exception =>
- macroLogVerbose(s"macro runtime failed to load: ${ex.toString}")
- macroDef setFlag IS_ERROR
- null
+ if (binding.className == Predef_???.owner.fullName.toString && binding.methName == Predef_???.name.encoded) {
+ args => throw new AbortMacroException(args.c.enclosingPosition, "macro implementation is missing")
+ } else {
+ // I don't use Scala reflection here, because it seems to interfere with JIT magic
+ // whenever you instantiate a mirror (and not do anything with in, just instantiate), performance drops by 15-20%
+ // I'm not sure what's the reason - for me it's pure voodoo
+ // upd. my latest experiments show that everything's okay
+ // it seems that in 2.10.1 we can easily switch to Scala reflection
+ try {
+ macroLogVerbose(s"loading implementation class: $className")
+ macroLogVerbose(s"classloader is: ${ReflectionUtils.show(macroClassloader)}")
+ val implObj = ReflectionUtils.staticSingletonInstance(macroClassloader, className)
+ // relies on the fact that macro impls cannot be overloaded
+ // so every methName can resolve to at maximum one method
+ val implMeths = implObj.getClass.getDeclaredMethods.find(_.getName == methName)
+ val implMeth = implMeths getOrElse { throw new NoSuchMethodException(s"$className.$methName") }
+ macroLogVerbose(s"successfully loaded macro impl as ($implObj, $implMeth)")
+ args => implMeth.invoke(implObj, ((args.c +: args.others) map (_.asInstanceOf[AnyRef])): _*)
+ } catch {
+ case ex: Exception =>
+ macroLogVerbose(s"macro runtime failed to load: ${ex.toString}")
+ macroDef setFlag IS_ERROR
+ null
+ }
}
})
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b89b570cd8..c59ef4ebda 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -5792,7 +5792,7 @@ trait Typers extends Modes with Adaptations with Tags {
tree1
}
- val isMacroBodyOkay = !tree.symbol.isErroneous && !(tree1 exists (_.isErroneous))
+ val isMacroBodyOkay = !tree.symbol.isErroneous && !(tree1 exists (_.isErroneous)) && tree1 != EmptyTree
val shouldInheritMacroImplReturnType = ddef.tpt.isEmpty
if (isMacroBodyOkay && shouldInheritMacroImplReturnType) computeMacroDefTypeFromMacroImpl(ddef, tree1.symbol) else AnyClass.tpe
}
diff --git a/test/files/neg/macro-qmarkqmarkqmark.check b/test/files/neg/macro-qmarkqmarkqmark.check
new file mode 100644
index 0000000000..afd49e7d90
--- /dev/null
+++ b/test/files/neg/macro-qmarkqmarkqmark.check
@@ -0,0 +1,13 @@
+macro-qmarkqmarkqmark.scala:5: error: macro implementation is missing
+ foo1
+ ^
+macro-qmarkqmarkqmark.scala:8: error: macros cannot be partially applied
+ foo2
+ ^
+macro-qmarkqmarkqmark.scala:9: error: macro implementation is missing
+ foo2(1)
+ ^
+macro-qmarkqmarkqmark.scala:12: error: macro implementation is missing
+ foo3[Int]
+ ^
+four errors found
diff --git a/test/files/neg/macro-qmarkqmarkqmark.scala b/test/files/neg/macro-qmarkqmarkqmark.scala
new file mode 100644
index 0000000000..c8d8550fd8
--- /dev/null
+++ b/test/files/neg/macro-qmarkqmarkqmark.scala
@@ -0,0 +1,13 @@
+import language.experimental.macros
+
+object Macros {
+ def foo1 = macro ???
+ foo1
+
+ def foo2(x: Int) = macro ???
+ foo2
+ foo2(1)
+
+ def foo3[T] = macro ???
+ foo3[Int]
+} \ No newline at end of file
diff --git a/test/files/pos/macro-qmarkqmarkqmark.check b/test/files/pos/macro-qmarkqmarkqmark.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/pos/macro-qmarkqmarkqmark.check
diff --git a/test/files/pos/macro-qmarkqmarkqmark.scala b/test/files/pos/macro-qmarkqmarkqmark.scala
new file mode 100644
index 0000000000..a91e4320b6
--- /dev/null
+++ b/test/files/pos/macro-qmarkqmarkqmark.scala
@@ -0,0 +1,7 @@
+import language.experimental.macros
+
+object Macros {
+ def foo1 = macro ???
+ def foo2(x: Int) = macro ???
+ def foo3[T] = macro ???
+} \ No newline at end of file