summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-02-19 15:35:36 -0800
committerPaul Phillips <paulp@improving.org>2012-02-19 17:38:42 -0800
commite512518d25818b4b0381e4a078137734f8eab12f (patch)
tree8f6c4a4acc08e520d7a58e9e3809c6fa202004e0 /src
parent63d9ae6dc4fccc97a35819d69c379073e6342bc1 (diff)
downloadscala-e512518d25818b4b0381e4a078137734f8eab12f.tar.gz
scala-e512518d25818b4b0381e4a078137734f8eab12f.tar.bz2
scala-e512518d25818b4b0381e4a078137734f8eab12f.zip
Streamlining skolemization, specialization.
Skolemization code doesn't belong in Typers. I carved out a little place for it. Also simplifications in specialization.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/ExistentialsAndSkolems.scala50
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala1
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala37
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala34
6 files changed, 75 insertions, 58 deletions
diff --git a/src/compiler/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/compiler/scala/reflect/internal/ExistentialsAndSkolems.scala
new file mode 100644
index 0000000000..47f794681c
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/ExistentialsAndSkolems.scala
@@ -0,0 +1,50 @@
+/* NSC -- new scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package internal
+
+import scala.collection.{ mutable, immutable }
+import util._
+
+/** The name of this trait defines the eventual intent better than
+ * it does the initial contents.
+ */
+trait ExistentialsAndSkolems {
+ self: SymbolTable =>
+
+ /** Map a list of type parameter symbols to skolemized symbols, which
+ * can be deskolemized to the original type parameter. (A skolem is a
+ * representation of a bound variable when viewed inside its scope.)
+ * !!!Adriaan: this does not work for hk types.
+ */
+ def deriveFreshSkolems(tparams: List[Symbol]): List[Symbol] = {
+ class Deskolemizer extends LazyType {
+ override val typeParams = tparams
+ val typeSkolems = typeParams map (_.newTypeSkolem setInfo this)
+ override def complete(sym: Symbol) {
+ // The info of a skolem is the skolemized info of the
+ // actual type parameter of the skolem
+ sym setInfo sym.deSkolemize.info.substSym(typeParams, typeSkolems)
+ }
+ }
+ (new Deskolemizer).typeSkolems
+ }
+
+ /** Convert to corresponding type parameters all skolems of method
+ * parameters which appear in `tparams`.
+ */
+ def deskolemizeTypeParams(tparams: List[Symbol])(tp: Type): Type = {
+ class DeSkolemizeMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) if sym.isTypeSkolem && (tparams contains sym.deSkolemize) =>
+ mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
+ case _ =>
+ mapOver(tp)
+ }
+ }
+ new DeSkolemizeMap mapOver tp
+ }
+}
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index 1973a97279..b3c62bffbf 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -15,6 +15,7 @@ abstract class SymbolTable extends api.Universe
with Symbols
with Types
with Kinds
+ with ExistentialsAndSkolems
with Scopes
with Definitions
with Constants
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 8e9788e8b6..ce85d65050 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -2714,6 +2714,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def cloneSymbolsAndModify(syms: List[Symbol], infoFn: Type => Type): List[Symbol] =
cloneSymbols(syms) map (_ modifyInfo infoFn)
+ def cloneSymbolsAtOwnerAndModify(syms: List[Symbol], owner: Symbol, infoFn: Type => Type): List[Symbol] =
+ cloneSymbolsAtOwner(syms, owner) map (_ modifyInfo infoFn)
/** Functions which perform the standard clone/substituting on the given symbols and type,
* then call the creator function with the new symbols and type as arguments.
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index fddb379a07..8f02194486 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1226,18 +1226,18 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val body: mutable.Map[Symbol, Tree] = new mutable.HashMap
/** Map a specializable method to its value parameter symbols. */
- val parameters: mutable.Map[Symbol, List[List[Symbol]]] = new mutable.HashMap
+ val parameters = mutable.HashMap[Symbol, List[Symbol]]()
/** Collect method bodies that are concrete specialized methods.
*/
class CollectMethodBodies extends Traverser {
override def traverse(tree: Tree) = tree match {
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ case DefDef(mods, name, tparams, vparams :: Nil, tpt, rhs) =>
if (concreteSpecMethods(tree.symbol) || tree.symbol.isConstructor) {
debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
body(tree.symbol) = rhs
// body(tree.symbol) = tree // whole method
- parameters(tree.symbol) = mmap(vparamss)(_.symbol)
+ parameters(tree.symbol) = vparams.map(_.symbol)
concreteSpecMethods -= tree.symbol
} // no need to descend further down inside method bodies
@@ -1531,12 +1531,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
- private def reskolemize(tparams: List[TypeDef]): (List[Symbol], List[Symbol]) = {
- val saved = tparams map (_.symbol)
- localTyper skolemizeTypeParams tparams
- (saved, tparams map (_.symbol))
- }
-
private def duplicateBody(tree: DefDef, source: Symbol) = {
val symbol = tree.symbol
val meth = addBody(tree, source)
@@ -1560,8 +1554,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def addBody(tree: DefDef, source: Symbol): DefDef = {
val symbol = tree.symbol
- debuglog("specializing body of" + symbol.fullName + ": " + symbol.info)
- val DefDef(mods, name, tparams, vparamss, tpt, _) = tree
+ debuglog("specializing body of" + symbol.defString)
+ val DefDef(mods, name, tparams, vparams :: Nil, tpt, _) = tree
// val (_, origtparams) = splitParams(source.typeParams)
val env = typeEnv(symbol)
val boundTvars = env.keySet
@@ -1569,12 +1563,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("substituting " + origtparams + " for " + symbol.typeParams)
// skolemize type parameters
- val (oldtparams, newtparams) = reskolemize(tparams)
+ val oldtparams = tparams map (_.symbol)
+ val newtparams = deriveFreshSkolems(oldtparams)
+ map2(tparams, newtparams)(_ setSymbol _)
// create fresh symbols for value parameters to hold the skolem types
- val vparamss1 = List(for (vdef <- vparamss.head; param = vdef.symbol) yield {
- ValDef(param cloneSymbol symbol substInfo (oldtparams, newtparams))
- })
+ val newSyms = cloneSymbolsAtOwnerAndModify(vparams map (_.symbol), symbol, _.substSym(oldtparams, newtparams))
// replace value and type parameters of the old method with the new ones
// log("Adding body for " + tree.symbol + " - origtparams: " + origtparams + "; tparams: " + tparams)
@@ -1582,14 +1576,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// log("Type env of: " + tree.symbol + ": " + boundTvars)
// log("newtparams: " + newtparams)
val symSubstituter = new ImplementationAdapter(
- parameters(source).flatten ::: origtparams,
- vparamss1.flatten.map(_.symbol) ::: newtparams,
+ parameters(source) ::: origtparams,
+ newSyms ::: newtparams,
source.enclClass,
false) // don't make private fields public
- val tmp = symSubstituter(body(source).duplicate)
+
+ val newBody = symSubstituter(body(source).duplicate)
tpt.tpe = tpt.tpe.substSym(oldtparams, newtparams)
- treeCopy.DefDef(tree, mods, name, tparams, vparamss1, tpt, tmp)
+ treeCopy.DefDef(tree, mods, name, tparams, List(newSyms map ValDef), tpt, newBody)
}
/** Create trees for specialized members of 'sClass', based on the
@@ -1610,9 +1605,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (m.isMethod) {
if (info(m).target.hasAccessorFlag) hasSpecializedFields = true
if (m.isClassConstructor) {
- val origParamss = parameters(info(m).target)
+ val origParams = parameters(info(m).target)
val vparams = (
- map2(m.info.paramTypes, origParamss(0))((tp, sym) =>
+ map2(m.info.paramTypes, origParams)((tp, sym) =>
m.newValue(specializedName(sym, typeEnv(sClass)), sym.pos, sym.flags) setInfo tp
)
)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 51542ec757..3347d2e767 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1299,7 +1299,7 @@ trait Namers extends MethodSynthesis {
catch typeErrorHandler(tree, ErrorType)
result match {
- case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm => typer.deskolemizeTypeParams(tparams)(result)
+ case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm => deskolemizeTypeParams(tparams)(result)
case _ => result
}
}
@@ -1439,8 +1439,11 @@ trait Namers extends MethodSynthesis {
private val ownerSym = owner.symbol
override val typeParams = tparams map (_.symbol) //@M
override val tree = restp.tree
- if (ownerSym.isTerm)
- typer skolemizeTypeParams tparams
+
+ if (ownerSym.isTerm) {
+ val skolems = deriveFreshSkolems(tparams map (_.symbol))
+ map2(tparams, skolems)(_ setSymbol _)
+ }
def completeImpl(sym: Symbol) = {
// @M an abstract type's type parameters are entered.
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 17c0bdf304..1c1f35aac2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3036,40 +3036,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
packSymbols(localSyms.toList, normalizedTpe)
}
- /** Replace type parameters with their TypeSkolems, which can later
- * be deskolemized to the original type param. (A skolem is a
- * representation of a bound variable when viewed inside its scope)
- * !!!Adriaan: this does not work for hk types.
- */
- def skolemizeTypeParams(tparams: List[TypeDef]): List[TypeDef] = {
- class Deskolemizer extends LazyType {
- override val typeParams = tparams map (_.symbol)
- val typeSkolems = typeParams map (_.newTypeSkolem setInfo this)
- // Replace the symbols
- def substitute() = map2(tparams, typeSkolems)(_ setSymbol _)
- override def complete(sym: Symbol) {
- // The info of a skolem is the skolemized info of the
- // actual type parameter of the skolem
- sym setInfo sym.deSkolemize.info.substSym(typeParams, typeSkolems)
- }
- }
- (new Deskolemizer).substitute()
- }
- /** Convert to corresponding type parameters all skolems of method
- * parameters which appear in `tparams`.
- */
- def deskolemizeTypeParams(tparams: List[Symbol])(tp: Type): Type = {
- class DeSkolemizeMap extends TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) if sym.isTypeSkolem && (tparams contains sym.deSkolemize) =>
- mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
- case _ =>
- mapOver(tp)
- }
- }
- new DeSkolemizeMap mapOver tp
- }
-
def typedClassOf(tree: Tree, tpt: Tree, noGen: Boolean = false) =
if (!checkClassType(tpt, true, false) && noGen) tpt
else atPos(tree.pos)(gen.mkClassOf(tpt.tpe))