@@ -7,14 +7,67 @@ import scala.tools.nsc.ReflectGlobal
7
7
import scala .tools .nsc .CompilerCommand
8
8
import scala .tools .nsc .Global
9
9
import scala .tools .nsc .typechecker .Modes
10
+ import scala .tools .nsc .io .VirtualDirectory
11
+ import scala .tools .nsc .interpreter .AbstractFileClassLoader
12
+ import reflect .{mirror => rm }
13
+ import scala .tools .nsc .util .FreshNameCreator
14
+ import scala .reflect .internal .Flags
15
+ import scala .tools .nsc .util .NoSourceFile
16
+ import java .lang .{Class => jClass }
10
17
11
18
trait ToolBoxes extends { self : Universe =>
12
19
13
20
class ToolBox (val reporter : Reporter = new StoreReporter , val options : String = " " ) {
14
21
15
- lazy val compiler : Global = {
22
+ class ToolBoxGlobal (settings : scala.tools.nsc.Settings , reporter : scala.tools.nsc.reporters.Reporter )
23
+ extends ReflectGlobal (settings, reporter) {
24
+ import definitions ._
25
+
26
+ private final val wrapperMethodName = " wrapper"
27
+
28
+ private def isFree (t : Tree ) = t.isInstanceOf [Ident ] && t.symbol.isInstanceOf [FreeVar ]
29
+
30
+ def wrapInClass (expr : Tree , fvs : List [Symbol ]): ClassDef = {
31
+ val clazz = EmptyPackageClass .newAnonymousClass(NoPosition )
32
+ clazz setInfo ClassInfoType (List (ObjectClass .tpe), new Scope , clazz)
33
+ val meth = clazz.newMethod(NoPosition , wrapperMethodName)
34
+ meth setFlag Flags .STATIC
35
+ meth setInfo MethodType (meth.owner.newSyntheticValueParams(fvs map (_.tpe)), expr.tpe)
36
+ clazz.info.decls enter meth
37
+ val methdef = DefDef (meth, expr)
38
+ val clazzdef = ClassDef (clazz, NoMods , List (List ()), List (List ()), List (methdef), NoPosition )
39
+ clazzdef
40
+ }
41
+
42
+ def wrapInCompilationUnit (tree : Tree ): CompilationUnit = {
43
+ val unit = new CompilationUnit (NoSourceFile )
44
+ unit.body = tree
45
+ unit
46
+ }
47
+
48
+ def compileExpr (expr : Tree , fvs : List [Symbol ]): String = {
49
+ val cdef = wrapInClass(expr, fvs)
50
+ val unit = wrapInCompilationUnit(cdef)
51
+ val run = new Run
52
+ run.compileUnits(List (unit), run.namerPhase)
53
+ cdef.name.toString
54
+ }
55
+
56
+ def runExpr (expr : Tree ): Any = {
57
+ val fvs = (expr filter isFree map (_.symbol)).distinct
58
+ val className = compileExpr(expr, fvs)
59
+ val jclazz = jClass.forName(className, true , classLoader)
60
+ val jmeth = jclazz.getDeclaredMethods.find(_.getName == wrapperMethodName).get
61
+ jmeth.invoke(null , fvs map (sym => sym.asInstanceOf [FreeVar ].value.asInstanceOf [AnyRef ]): _* )
62
+ }
63
+ }
64
+
65
+ lazy val virtualDirectory = new VirtualDirectory (" (memory)" , None )
66
+
67
+ lazy val compiler : ToolBoxGlobal = {
16
68
val command = new CompilerCommand (options.split(" " ).toList, reporter.error(scala.tools.nsc.util.NoPosition , _))
17
- new ReflectGlobal (command.settings, reporter)
69
+ command.settings.outputDirs setSingleOutput virtualDirectory
70
+ new ToolBoxGlobal (command.settings, reporter)
18
71
}
19
72
20
73
lazy val importer = new compiler.Importer {
@@ -23,20 +76,23 @@ trait ToolBoxes extends { self: Universe =>
23
76
24
77
lazy val exporter = importer.reverse
25
78
26
- def typeCheck (tree : reflect.mirror.Tree , expectedType : reflect.mirror.Type ): reflect.mirror.Tree = {
79
+ lazy val classLoader = new AbstractFileClassLoader (virtualDirectory, getClass.getClassLoader)
80
+
81
+
82
+ def typeCheck (tree : rm.Tree , expectedType : rm.Type ): rm.Tree = {
27
83
if (compiler.settings.verbose.value) println(" typing " + tree+ " , pt = " + expectedType)
28
84
val run = new compiler.Run
29
85
compiler.phase = run.refchecksPhase
30
86
val ctree : compiler.Tree = importer.importTree(tree.asInstanceOf [Tree ])
31
87
val pt : compiler.Type = importer.importType(expectedType.asInstanceOf [Type ])
32
88
val ttree : compiler.Tree = compiler.typer.typed(ctree, compiler.analyzer.EXPRmode , pt)
33
- exporter.importTree(ttree).asInstanceOf [reflect.mirror .Tree ]
89
+ exporter.importTree(ttree).asInstanceOf [rm .Tree ]
34
90
}
35
91
36
- def typeCheck (tree : reflect.mirror. Tree ): reflect.mirror .Tree =
37
- typeCheck(tree, WildcardType .asInstanceOf [reflect.mirror .Type ])
92
+ def typeCheck (tree : rm. Tree ): rm .Tree =
93
+ typeCheck(tree, WildcardType .asInstanceOf [rm .Type ])
38
94
39
- def showAttributed (tree : reflect.mirror .Tree ): String = {
95
+ def showAttributed (tree : rm .Tree ): String = {
40
96
val saved = compiler.settings.printtypes.value
41
97
try {
42
98
compiler.settings.printtypes.value = true
0 commit comments