Skip to content

Commit

Permalink
added existential types
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Jun 9, 2007
1 parent 6ad83da commit 8414eba
Show file tree
Hide file tree
Showing 12 changed files with 416 additions and 163 deletions.
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/Interpreter.scala
Expand Up @@ -720,7 +720,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
case rawType => rawType
}

map + name -> cleanedType.toString
map + name -> compiler.atPhase(objRun.typerPhase.next) { cleanedType.toString }
})
}

Expand Down
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/ast/NodePrinters.scala
Expand Up @@ -185,6 +185,7 @@ abstract class NodePrinters {
traverse(tparams(i), level + 2, i < n-1)
println(" ),")
}
println(tpt+",")
traverse(rhs, level + 1, false)
printcln(")")
case EmptyTree =>
Expand Down
10 changes: 10 additions & 0 deletions src/compiler/scala/tools/nsc/ast/TreePrinters.scala
Expand Up @@ -252,6 +252,12 @@ abstract class TreePrinters {
case Throw(expr) =>
print("throw "); print(expr)

case Pack(expr) =>
print("pack("); print(expr); print(")")

case Unpack(expr) =>
print("unpack("); print(expr); print(")")

case New(tpe) =>
print("new "); print(tpe)

Expand Down Expand Up @@ -327,6 +333,10 @@ abstract class TreePrinters {
case WildcardTypeTree(lo, hi) =>
print("_ "); printOpt(" >: ", lo); printOpt(" <: ", hi)

case ExistentialTypeTree(tpt, whereClauses) =>
print(tpt);
printColumn(whereClauses, " for_some { ", ";", "}")

case tree =>
print("<unknown tree of class "+tree.getClass+">")
}
Expand Down
56 changes: 56 additions & 0 deletions src/compiler/scala/tools/nsc/ast/Trees.scala
Expand Up @@ -11,6 +11,7 @@ import java.io.{PrintWriter, StringWriter}
import scala.tools.nsc.symtab.Flags
import scala.tools.nsc.symtab.Flags._
import scala.tools.nsc.util.{HashSet, Position, NoPosition, SourceFile}
import scala.collection.mutable.ListBuffer


trait Trees {
Expand Down Expand Up @@ -98,6 +99,16 @@ trait Trees {

def isErroneous = (tpe ne null) && tpe.isErroneous

/** Apply `f' to each subtree */
def foreach(f: Tree => Unit): Unit = new ForeachTraverser(f).traverse(this)

/** Find all subtrees matching predicate `p' */
def filter(f: Tree => Boolean): List[Tree] = {
val ft = new FilterTraverser(f)
ft.traverse(this)
ft.hits.toList
}

override def toString(): String = {
val buffer = new StringWriter()
val printer = treePrinters.create(new PrintWriter(buffer))
Expand Down Expand Up @@ -585,6 +596,14 @@ trait Trees {
case class Throw(expr: Tree)
extends TermTree

/** Pack skolemized type, yielding existential */
case class Pack(expr: Tree)
extends TermTree

/** Unpack existential, yielding skolemized type */
case class Unpack(expr: Tree)
extends TermTree

/** Object instantiation
* One should always use factory method below to build a user level new.
*
Expand Down Expand Up @@ -787,6 +806,10 @@ trait Trees {
// try block catch { catches } finally finalizer where catches: List[CaseDef]
case Throw(expr) =>
// throw expr
case Pack(expr) => (eliminated by erasure)
// internal: pack existential type
case Unpack(expr) => (eliminated by erasure)
// internal: unpack existential type
case New(tpt) =>
// new tpt always in the context: new tpt.<init>[targs](args)
case Typed(expr, tpt) => (eliminated by erasure)
Expand Down Expand Up @@ -853,6 +876,8 @@ trait Trees {
def Return(tree: Tree, expr: Tree): Return
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
def Throw(tree: Tree, expr: Tree): Throw
def Pack(tree: Tree, expr: Tree): Pack
def Unpack(tree: Tree, expr: Tree): Unpack
def New(tree: Tree, tpt: Tree): New
def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
Expand Down Expand Up @@ -928,6 +953,10 @@ trait Trees {
new Try(block, catches, finalizer).copyAttrs(tree)
def Throw(tree: Tree, expr: Tree) =
new Throw(expr).copyAttrs(tree)
def Pack(tree: Tree, expr: Tree) =
new Pack(expr).copyAttrs(tree)
def Unpack(tree: Tree, expr: Tree) =
new Unpack(expr).copyAttrs(tree)
def New(tree: Tree, tpt: Tree) =
new New(tpt).copyAttrs(tree)
def Typed(tree: Tree, expr: Tree, tpt: Tree) =
Expand Down Expand Up @@ -1104,6 +1133,16 @@ trait Trees {
if expr0 == expr => t
case _ => copy.Throw(tree, expr)
}
def Pack(tree: Tree, expr: Tree) = tree match {
case t @ Pack(expr0)
if expr0 == expr => t
case _ => copy.Pack(tree, expr)
}
def Unpack(tree: Tree, expr: Tree) = tree match {
case t @ Unpack(expr0)
if expr0 == expr => t
case _ => copy.Unpack(tree, expr)
}
def New(tree: Tree, tpt: Tree) = tree match {
case t @ New(tpt0)
if tpt0 == tpt => t
Expand Down Expand Up @@ -1275,6 +1314,10 @@ trait Trees {
copy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
case Throw(expr) =>
copy.Throw(tree, transform(expr))
case Pack(expr) =>
copy.Pack(tree, transform(expr))
case Unpack(expr) =>
copy.Unpack(tree, transform(expr))
case New(tpt) =>
copy.New(tree, transform(tpt))
case Typed(expr, tpt) =>
Expand Down Expand Up @@ -1423,6 +1466,10 @@ trait Trees {
traverse(block); traverseTrees(catches); traverse(finalizer)
case Throw(expr) =>
traverse(expr)
case Pack(expr) =>
traverse(expr)
case Unpack(expr) =>
traverse(expr)
case New(tpt) =>
traverse(tpt)
case Typed(expr, tpt) =>
Expand Down Expand Up @@ -1544,6 +1591,15 @@ trait Trees {
}
}

class ForeachTraverser(f: Tree => Unit) extends Traverser {
override def traverse(t: Tree) = f(t)
}

class FilterTraverser(p: Tree => Boolean) extends Traverser {
val hits = new ListBuffer[Tree]
override def traverse(t: Tree) = if (p(t)) hits += t
}

object resetPos extends Traverser {
override def traverse(t: Tree): unit = {
if (t != EmptyTree) t.setPos(NoPosition)
Expand Down
1 change: 1 addition & 0 deletions src/compiler/scala/tools/nsc/symtab/Flags.scala
Expand Up @@ -66,6 +66,7 @@ object Flags extends Enumeration {
// local value has been lifted out to class level
// todo: make LIFTED = latePRIVATE?
final val MIXEDIN = 0x800000000L // term member has been mixed in
final val EXISTENTIAL = 0x800000000L // type is an existential parameter or skolem

final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix
final val IMPLCLASS = 0x2000000000L // symbol is an implementation class
Expand Down
30 changes: 11 additions & 19 deletions src/compiler/scala/tools/nsc/symtab/Symbols.scala
Expand Up @@ -115,9 +115,6 @@ trait Symbols {
}
final def newThisSym(pos: Position) =
newValue(pos, nme.this_).setFlag(SYNTHETIC)
final def newThisSkolem: Symbol =
new ThisSkolem(owner, pos, name, this)
.setFlag(SYNTHETIC | FINAL)
final def newImport(pos: Position) =
newValue(pos, nme.IMPORT)
final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol =
Expand Down Expand Up @@ -196,14 +193,18 @@ trait Symbols {
final def isStaticModule = isModule && isStatic && !isMethod
final def isPackage = isModule && hasFlag(PACKAGE)
final def isThisSym = isTerm && owner.thisSym == this
final def isThisSkolem = isTerm && deSkolemize != this
final def isMonomorphicType = isType && hasFlag(MONOMORPHIC)
final def isError = hasFlag(IS_ERROR)
final def isErroneous = isError || isInitialized && tpe.isErroneous
final def isTrait = isClass & hasFlag(TRAIT)
final def isSkolem = deSkolemize != this
final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
final def isTypeParameter = isTypeParameterOrSkolem && deSkolemize == this
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
final def isTypeParameter = isTypeParameterOrSkolem && !isSkolem
final def isTypeSkolem = isTypeParameterOrSkolem && isSkolem
final def isExistential = isType && hasFlag(EXISTENTIAL)
final def isExistentialQuantified = isExistential && !isSkolem
final def isExistentialSkolem = isExistential && isSkolem
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME)
// startsWith necessary because name may grow when lifted and also because of anonymous function classes
final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes
Expand Down Expand Up @@ -1129,17 +1130,6 @@ trait Symbols {
}
}

/** A class for type parameters viewed from inside their scopes */
class ThisSkolem(initOwner: Symbol, initPos: Position,
initName: Name, clazz: Symbol)
extends TermSymbol(initOwner, initPos, initName) {
override def deSkolemize = clazz
override def cloneSymbolImpl(owner: Symbol): Symbol = {
throw new Error("should not clone a this skolem")
}
override def nameString: String = clazz.name.toString() + ".this"
}

/** A class of type symbols. Alias and abstract types are direct instances
* of this class. Classes are instances of a subclass.
*/
Expand Down Expand Up @@ -1168,7 +1158,8 @@ trait Symbols {
else unsafeTypeParams map (_.typeConstructor) //@M! use typeConstructor to generate dummy type arguments,
// sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
// memberType should be used instead, that's why it uses tpeHK and not tpe
tpeCache = typeRef(if (isTypeParameterOrSkolem) NoPrefix else owner.thisType, this, targs)
tpeCache = typeRef(if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType,
this, targs)
}
}
assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
Expand All @@ -1177,7 +1168,8 @@ trait Symbols {

override def typeConstructor: Type = {
if ((tyconCache eq null) || tyconRunId != currentRunId) {
tyconCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, List())
tyconCache = typeRef(if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType,
this, List())
tyconRunId = currentRunId
}
assert(tyconCache ne null)
Expand Down

0 comments on commit 8414eba

Please sign in to comment.