Skip to content

Commit b8362d6

Browse files
committed
SI-6392 wraps non-terms before typecheck/eval
Wrap non-term arguments of typecheck and eval, so that toolboxes can work with full-fledged files (except for package declarations).
1 parent 2f9f8d5 commit b8362d6

File tree

5 files changed

+33
-2
lines changed

5 files changed

+33
-2
lines changed

src/compiler/scala/tools/reflect/ToolBoxFactory.scala

+13-2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
7070
}
7171
}
7272

73+
def wrapIntoTerm(tree: Tree): Tree =
74+
if (!tree.isTerm) Block(List(tree), Literal(Constant(()))) else tree
75+
76+
def unwrapFromTerm(tree: Tree): Tree = tree match {
77+
case Block(List(tree), Literal(Constant(()))) => tree
78+
case tree => tree
79+
}
80+
7381
def extractFreeTerms(expr0: Tree, wrapFreeTermRefs: Boolean): (Tree, scala.collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]) = {
7482
val freeTerms = expr0.freeTerms
7583
val freeTermNames = scala.collection.mutable.LinkedHashMap[FreeTermSymbol, TermName]()
@@ -102,7 +110,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
102110
// need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars
103111
var (expr, freeTerms) = extractFreeTerms(expr0, wrapFreeTermRefs = false)
104112
val dummies = freeTerms.map{ case (freeTerm, name) => ValDef(NoMods, name, TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark"))) }.toList
105-
expr = Block(dummies, expr)
113+
expr = Block(dummies, wrapIntoTerm(expr))
106114

107115
// [Eugene] how can we implement that?
108116
// !!! Why is this is in the empty package? If it's only to make
@@ -137,6 +145,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
137145
}
138146
}.transform(unwrapped)
139147
new TreeTypeSubstituter(dummies1 map (_.symbol), dummies1 map (dummy => SingleType(NoPrefix, invertedIndex(dummy.symbol.name)))).traverse(unwrapped)
148+
unwrapped = if (expr0.isTerm) unwrapped else unwrapFromTerm(unwrapped)
140149
unwrapped
141150
}
142151

@@ -170,7 +179,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf =>
170179
}
171180
})
172181

173-
def compile(expr: Tree): () => Any = {
182+
def compile(expr0: Tree): () => Any = {
183+
val expr = wrapIntoTerm(expr0)
184+
174185
val freeTerms = expr.freeTerms // need to calculate them here, because later on they will be erased
175186
val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order
176187
verify(expr)

test/files/run/t6392a.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
()

test/files/run/t6392a.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.reflect.runtime.universe._
2+
import scala.reflect.runtime.{currentMirror => cm}
3+
import scala.tools.reflect.ToolBox
4+
5+
object Test extends App {
6+
val tb = cm.mkToolBox()
7+
val c = tb.parse("object C")
8+
println(tb.eval(c))
9+
}

test/files/run/t6392b.check

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ModuleDef(Modifiers(), newTermName("C"), Template(List(Select(Ident(scala#PK), newTypeName("AnyRef")#TPE)), emptyValDef, List(DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(Apply(Select(Super(This(newTypeName("C")), tpnme.EMPTY), nme.CONSTRUCTOR#PCTOR), List())), Literal(Constant(())))))))

test/files/run/t6392b.scala

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.reflect.runtime.universe._
2+
import scala.reflect.runtime.{currentMirror => cm}
3+
import scala.tools.reflect.ToolBox
4+
5+
object Test extends App {
6+
val tb = cm.mkToolBox()
7+
val c = tb.parse("object C")
8+
println(showRaw(tb.typeCheck(c), printKinds = true))
9+
}

0 commit comments

Comments
 (0)