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 /src/compiler/scala/tools/nsc/Global.scala | |
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 'src/compiler/scala/tools/nsc/Global.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 21 |
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?) */ |