summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/Global.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-01-19 12:28:19 +0100
committerEugene Burmako <xeno.by@gmail.com>2013-05-28 10:19:19 +0200
commit10229316dbf7afa7545d8e279b5960da6ee3db7d (patch)
treecfa50a3207aa5c1b2ce17ffba0fe1413a6f0dd53 /src/compiler/scala/tools/nsc/Global.scala
parente0bbe0af094b9055942c24fcaaa290a31415fa0a (diff)
downloadscala-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 'src/compiler/scala/tools/nsc/Global.scala')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index f1fccd6069..a08633ffc8 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -9,6 +9,7 @@ package nsc
import java.io.{ File, FileOutputStream, PrintWriter, IOException, FileNotFoundException }
import java.nio.charset.{ Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException }
+import java.util.UUID._
import scala.compat.Platform.currentTime
import scala.collection.{ mutable, immutable }
import io.{ SourceReader, AbstractFile, Path }
@@ -16,6 +17,7 @@ import reporters.{ Reporter, ConsoleReporter }
import util.{ ClassPath, MergedClassPath, StatisticsInfo, returning, stackTraceString, stackTraceHeadString }
import scala.reflect.internal.util.{ OffsetPosition, SourceFile, NoSourceFile, BatchSourceFile, ScriptSourceFile }
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
+import scala.reflect.io.VirtualFile
import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers }
import symtab.classfile.Pickler
import plugins.Plugins
@@ -1621,6 +1623,25 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
}
}
+ // TODO: provide a way to specify a pretty name for debugging purposes
+ private def randomFileName() = (
+ "compileLateSynthetic-" + randomUUID().toString.replace("-", "") + ".scala"
+ )
+
+ def compileLate(code: PackageDef) {
+ // compatibility with SBT
+ // on the one hand, we need to specify some jfile here, otherwise sbt crashes with an NPE (SI-6870)
+ // on the other hand, we can't specify the obvious enclosingUnit, because then sbt somehow fails to run tests using type macros
+ // okay, now let's specify a guaranteedly non-existent file in an existing directory (so that we don't run into permission problems)
+ val syntheticFileName = randomFileName()
+ val fakeJfile = new java.io.File(syntheticFileName)
+ val virtualFile = new VirtualFile(syntheticFileName) { override def file = fakeJfile }
+ val sourceFile = new BatchSourceFile(virtualFile, code.toString)
+ val unit = new CompilationUnit(sourceFile)
+ unit.body = code
+ compileLate(unit)
+ }
+
/** Reset package class to state at typer (not sure what this
* is needed for?)
*/