diff options
author | Martin Odersky <odersky@gmail.com> | 2011-09-30 16:47:34 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-09-30 16:47:34 +0000 |
commit | b939e8fbaba0bcbf3fc92bd8e915e2641b7e4ddf (patch) | |
tree | 0bcf076e3b078b30e8a765605b869d5396d56a9a /src/compiler | |
parent | a2e9a1b465c9e9baeabfbea2474ab63fa57e5100 (diff) | |
download | scala-b939e8fbaba0bcbf3fc92bd8e915e2641b7e4ddf.tar.gz scala-b939e8fbaba0bcbf3fc92bd8e915e2641b7e4ddf.tar.bz2 scala-b939e8fbaba0bcbf3fc92bd8e915e2641b7e4ddf.zip |
First untested attempt to create a runtime comp...
First untested attempt to create a runtime compiler. Review by
extempore.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/reflect/runtime/ToolBoxes.scala | 70 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 26 |
2 files changed, 76 insertions, 20 deletions
diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index cc40d8ca43..9b0f8a33b4 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -7,14 +7,67 @@ import scala.tools.nsc.ReflectGlobal import scala.tools.nsc.CompilerCommand import scala.tools.nsc.Global import scala.tools.nsc.typechecker.Modes +import scala.tools.nsc.io.VirtualDirectory +import scala.tools.nsc.interpreter.AbstractFileClassLoader +import reflect.{mirror => rm} +import scala.tools.nsc.util.FreshNameCreator +import scala.reflect.internal.Flags +import scala.tools.nsc.util.NoSourceFile +import java.lang.{Class => jClass} trait ToolBoxes extends { self: Universe => class ToolBox(val reporter: Reporter = new StoreReporter, val options: String = "") { - lazy val compiler: Global = { + class ToolBoxGlobal(settings: scala.tools.nsc.Settings, reporter: scala.tools.nsc.reporters.Reporter) + extends ReflectGlobal(settings, reporter) { + import definitions._ + + private final val wrapperMethodName = "wrapper" + + private def isFree(t: Tree) = t.isInstanceOf[Ident] && t.symbol.isInstanceOf[FreeVar] + + def wrapInClass(expr: Tree, fvs: List[Symbol]): ClassDef = { + val clazz = EmptyPackageClass.newAnonymousClass(NoPosition) + clazz setInfo ClassInfoType(List(ObjectClass.tpe), new Scope, clazz) + val meth = clazz.newMethod(NoPosition, wrapperMethodName) + meth setFlag Flags.STATIC + meth setInfo MethodType(meth.owner.newSyntheticValueParams(fvs map (_.tpe)), expr.tpe) + clazz.info.decls enter meth + val methdef = DefDef(meth, expr) + val clazzdef = ClassDef(clazz, NoMods, List(List()), List(List()), List(methdef), NoPosition) + clazzdef + } + + def wrapInCompilationUnit(tree: Tree): CompilationUnit = { + val unit = new CompilationUnit(NoSourceFile) + unit.body = tree + unit + } + + def compileExpr(expr: Tree, fvs: List[Symbol]): String = { + val cdef = wrapInClass(expr, fvs) + val unit = wrapInCompilationUnit(cdef) + val run = new Run + run.compileUnits(List(unit), run.namerPhase) + cdef.name.toString + } + + def runExpr(expr: Tree): Any = { + val fvs = (expr filter isFree map (_.symbol)).distinct + val className = compileExpr(expr, fvs) + val jclazz = jClass.forName(className, true, classLoader) + val jmeth = jclazz.getDeclaredMethods.find(_.getName == wrapperMethodName).get + jmeth.invoke(null, fvs map (sym => sym.asInstanceOf[FreeVar].value.asInstanceOf[AnyRef]): _*) + } + } + + lazy val virtualDirectory = new VirtualDirectory("(memory)", None) + + lazy val compiler: ToolBoxGlobal = { val command = new CompilerCommand(options.split(" ").toList, reporter.error(scala.tools.nsc.util.NoPosition, _)) - new ReflectGlobal(command.settings, reporter) + command.settings.outputDirs setSingleOutput virtualDirectory + new ToolBoxGlobal(command.settings, reporter) } lazy val importer = new compiler.Importer { @@ -23,20 +76,23 @@ trait ToolBoxes extends { self: Universe => lazy val exporter = importer.reverse - def typeCheck(tree: reflect.mirror.Tree, expectedType: reflect.mirror.Type): reflect.mirror.Tree = { + lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, getClass.getClassLoader) + + + def typeCheck(tree: rm.Tree, expectedType: rm.Type): rm.Tree = { if (compiler.settings.verbose.value) println("typing "+tree+", pt = "+expectedType) val run = new compiler.Run compiler.phase = run.refchecksPhase val ctree: compiler.Tree = importer.importTree(tree.asInstanceOf[Tree]) val pt: compiler.Type = importer.importType(expectedType.asInstanceOf[Type]) val ttree: compiler.Tree = compiler.typer.typed(ctree, compiler.analyzer.EXPRmode, pt) - exporter.importTree(ttree).asInstanceOf[reflect.mirror.Tree] + exporter.importTree(ttree).asInstanceOf[rm.Tree] } - def typeCheck(tree: reflect.mirror.Tree): reflect.mirror.Tree = - typeCheck(tree, WildcardType.asInstanceOf[reflect.mirror.Type]) + def typeCheck(tree: rm.Tree): rm.Tree = + typeCheck(tree, WildcardType.asInstanceOf[rm.Type]) - def showAttributed(tree: reflect.mirror.Tree): String = { + def showAttributed(tree: rm.Tree): String = { val saved = compiler.settings.printtypes.value try { compiler.settings.printtypes.value = true diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index ca50979e9c..604379d33f 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -997,24 +997,24 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb return } - val startTime = currentTime - reporter.reset(); - { - val first :: rest = sources - val unit = new CompilationUnit(first) - addUnit(unit) - checkDeprecatedSettings(unit) - - for (source <- rest) - addUnit(new CompilationUnit(source)) - } - globalPhase = firstPhase + compileUnits(sources map (new CompilationUnit(_)), firstPhase) + } + /** Compile list of units, starting with phase `fromPhase` + */ + def compileUnits(units: List[CompilationUnit], fromPhase: Phase) { + units foreach addUnit if (opt.profileAll) { inform("starting CPU profiling on compilation run") profiler.startProfiling() } - while (globalPhase != terminalPhase && !reporter.hasErrors) { + val startTime = currentTime + + reporter.reset() + checkDeprecatedSettings(unitbuf.head) + globalPhase = firstPhase + + while (globalPhase != terminalPhase && !reporter.hasErrors) { val startTime = currentTime phase = globalPhase |