diff options
Diffstat (limited to 'src/compiler/scala/reflect/internal/Types.scala')
-rw-r--r-- | src/compiler/scala/reflect/internal/Types.scala | 66 |
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 |