summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/internal/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-08-23 11:58:15 +0000
committerMartin Odersky <odersky@gmail.com>2011-08-23 11:58:15 +0000
commite69822117c99a6c79a69a5b4dde3a82040400bb3 (patch)
tree0fee23c32b028e948c3c1445df8aeb325cc77166 /src/compiler/scala/reflect/internal/Types.scala
parenta93134b4832e95ff014f162f4cc8667f8136cb7d (diff)
downloadscala-e69822117c99a6c79a69a5b4dde3a82040400bb3.tar.gz
scala-e69822117c99a6c79a69a5b4dde3a82040400bb3.tar.bz2
scala-e69822117c99a6c79a69a5b4dde3a82040400bb3.zip
New reification code for symbols and types.
Diffstat (limited to 'src/compiler/scala/reflect/internal/Types.scala')
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 7bcc0f8913..952925a7cc 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -65,7 +65,6 @@ import util.Statistics._
// inst is the instantiation and constr is a list of bounds.
case DeBruijnIndex(level, index)
// for dependent method types: a type referring to a method parameter.
- // Not presently used, it seems.
*/
trait Types extends api.Types { self: SymbolTable =>
@@ -2735,6 +2734,23 @@ A type's typeSymbol should never be inspected directly.
override def safeToString: String = name.toString +": "+ tp
}
+ /** A De Bruijn index referring to a previous type argument. Only used
+ * as a serialization format.
+ */
+ case class DeBruijnIndex(level: Int, idx: Int, args: List[Type]) extends Type {
+ override def safeToString: String = "De Bruijn index("+level+","+idx+")"
+ }
+
+ /** A binder defining data associated with De Bruijn indices. Only used
+ * as a serialization format.
+ */
+ case class DeBruijnBinder(pnames: List[Name], ptypes: List[Type], restpe: Type) extends Type {
+ override def safeToString = {
+ val kind = if (pnames.head.isTypeName) "poly" else "method"
+ "De Bruijn "+kind+"("+(pnames mkString ",")+";"+(ptypes mkString ",")+";"+restpe+")"
+ }
+ }
+
/** A class representing an as-yet unevaluated type.
*/
abstract class LazyType extends Type {
@@ -3103,6 +3119,50 @@ A type's typeSymbol should never be inspected directly.
}
}
+ object toDeBruijn extends TypeMap {
+ private var paramStack: List[List[Symbol]] = Nil
+ def mkDebruijnBinder(params: List[Symbol], restpe: Type) = {
+ paramStack = params :: paramStack
+ try {
+ DeBruijnBinder(params map (_.name), params map (p => this(p.info)), this(restpe))
+ } finally paramStack = paramStack.tail
+ }
+ def apply(tp: Type): Type = tp match {
+ case PolyType(tparams, restpe) =>
+ mkDebruijnBinder(tparams, restpe)
+ case MethodType(params, restpe) =>
+ mkDebruijnBinder(params, restpe)
+ case TypeRef(NoPrefix, sym, args) =>
+ val level = paramStack indexWhere (_ contains sym)
+ if (level < 0) mapOver(tp)
+ else DeBruijnIndex(level, paramStack(level) indexOf sym, args mapConserve this)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ def fromDeBruijn(owner: Symbol) = new TypeMap {
+ private var paramStack: List[List[Symbol]] = Nil
+ def apply(tp: Type): Type = tp match {
+ case DeBruijnBinder(pnames, ptypes, restpe) =>
+ val isType = pnames.head.isTypeName
+ val newParams = for (name <- pnames) yield
+ if (isType) owner.newTypeParameter(NoPosition, name.toTypeName)
+ else owner.newValueParameter(NoPosition, name)
+ paramStack = newParams :: paramStack
+ try {
+ (newParams, ptypes).zipped foreach ((p, t) => p setInfo this(t))
+ val restpe1 = this(restpe)
+ if (isType) PolyType(newParams, restpe1)
+ else MethodType(newParams, restpe1)
+ } finally paramStack = paramStack.tail
+ case DeBruijnIndex(level, idx, args) =>
+ TypeRef(NoPrefix, paramStack(level)(idx), args map this)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
// Hash consing --------------------------------------------------------------
private val initialUniquesCapacity = 4096
@@ -3315,6 +3375,10 @@ A type's typeSymbol should never be inspected directly.
if ((annots1 eq annots) && (atp1 eq atp)) tp
else if (annots1.isEmpty) atp1
else AnnotatedType(annots1, atp1, selfsym)
+ case DeBruijnIndex(shift, idx, args) =>
+ val args1 = args mapConserve this
+ if (args1 eq args) tp
+ else DeBruijnIndex(shift, idx, args1)
/*
case ErrorType => tp
case WildcardType => tp