Skip to content

Commit 8414eba

Browse files
committed
added existential types
1 parent 6ad83da commit 8414eba

File tree

12 files changed

+416
-163
lines changed

12 files changed

+416
-163
lines changed

src/compiler/scala/tools/nsc/Interpreter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
720720
case rawType => rawType
721721
}
722722

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

src/compiler/scala/tools/nsc/ast/NodePrinters.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ abstract class NodePrinters {
185185
traverse(tparams(i), level + 2, i < n-1)
186186
println(" ),")
187187
}
188+
println(tpt+",")
188189
traverse(rhs, level + 1, false)
189190
printcln(")")
190191
case EmptyTree =>

src/compiler/scala/tools/nsc/ast/TreePrinters.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ abstract class TreePrinters {
252252
case Throw(expr) =>
253253
print("throw "); print(expr)
254254

255+
case Pack(expr) =>
256+
print("pack("); print(expr); print(")")
257+
258+
case Unpack(expr) =>
259+
print("unpack("); print(expr); print(")")
260+
255261
case New(tpe) =>
256262
print("new "); print(tpe)
257263

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

336+
case ExistentialTypeTree(tpt, whereClauses) =>
337+
print(tpt);
338+
printColumn(whereClauses, " for_some { ", ";", "}")
339+
330340
case tree =>
331341
print("<unknown tree of class "+tree.getClass+">")
332342
}

src/compiler/scala/tools/nsc/ast/Trees.scala

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import java.io.{PrintWriter, StringWriter}
1111
import scala.tools.nsc.symtab.Flags
1212
import scala.tools.nsc.symtab.Flags._
1313
import scala.tools.nsc.util.{HashSet, Position, NoPosition, SourceFile}
14+
import scala.collection.mutable.ListBuffer
1415

1516

1617
trait Trees {
@@ -98,6 +99,16 @@ trait Trees {
9899

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

102+
/** Apply `f' to each subtree */
103+
def foreach(f: Tree => Unit): Unit = new ForeachTraverser(f).traverse(this)
104+
105+
/** Find all subtrees matching predicate `p' */
106+
def filter(f: Tree => Boolean): List[Tree] = {
107+
val ft = new FilterTraverser(f)
108+
ft.traverse(this)
109+
ft.hits.toList
110+
}
111+
101112
override def toString(): String = {
102113
val buffer = new StringWriter()
103114
val printer = treePrinters.create(new PrintWriter(buffer))
@@ -585,6 +596,14 @@ trait Trees {
585596
case class Throw(expr: Tree)
586597
extends TermTree
587598

599+
/** Pack skolemized type, yielding existential */
600+
case class Pack(expr: Tree)
601+
extends TermTree
602+
603+
/** Unpack existential, yielding skolemized type */
604+
case class Unpack(expr: Tree)
605+
extends TermTree
606+
588607
/** Object instantiation
589608
* One should always use factory method below to build a user level new.
590609
*
@@ -787,6 +806,10 @@ trait Trees {
787806
// try block catch { catches } finally finalizer where catches: List[CaseDef]
788807
case Throw(expr) =>
789808
// throw expr
809+
case Pack(expr) => (eliminated by erasure)
810+
// internal: pack existential type
811+
case Unpack(expr) => (eliminated by erasure)
812+
// internal: unpack existential type
790813
case New(tpt) =>
791814
// new tpt always in the context: new tpt.<init>[targs](args)
792815
case Typed(expr, tpt) => (eliminated by erasure)
@@ -853,6 +876,8 @@ trait Trees {
853876
def Return(tree: Tree, expr: Tree): Return
854877
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
855878
def Throw(tree: Tree, expr: Tree): Throw
879+
def Pack(tree: Tree, expr: Tree): Pack
880+
def Unpack(tree: Tree, expr: Tree): Unpack
856881
def New(tree: Tree, tpt: Tree): New
857882
def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
858883
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
@@ -928,6 +953,10 @@ trait Trees {
928953
new Try(block, catches, finalizer).copyAttrs(tree)
929954
def Throw(tree: Tree, expr: Tree) =
930955
new Throw(expr).copyAttrs(tree)
956+
def Pack(tree: Tree, expr: Tree) =
957+
new Pack(expr).copyAttrs(tree)
958+
def Unpack(tree: Tree, expr: Tree) =
959+
new Unpack(expr).copyAttrs(tree)
931960
def New(tree: Tree, tpt: Tree) =
932961
new New(tpt).copyAttrs(tree)
933962
def Typed(tree: Tree, expr: Tree, tpt: Tree) =
@@ -1104,6 +1133,16 @@ trait Trees {
11041133
if expr0 == expr => t
11051134
case _ => copy.Throw(tree, expr)
11061135
}
1136+
def Pack(tree: Tree, expr: Tree) = tree match {
1137+
case t @ Pack(expr0)
1138+
if expr0 == expr => t
1139+
case _ => copy.Pack(tree, expr)
1140+
}
1141+
def Unpack(tree: Tree, expr: Tree) = tree match {
1142+
case t @ Unpack(expr0)
1143+
if expr0 == expr => t
1144+
case _ => copy.Unpack(tree, expr)
1145+
}
11071146
def New(tree: Tree, tpt: Tree) = tree match {
11081147
case t @ New(tpt0)
11091148
if tpt0 == tpt => t
@@ -1275,6 +1314,10 @@ trait Trees {
12751314
copy.Try(tree, transform(block), transformCaseDefs(catches), transform(finalizer))
12761315
case Throw(expr) =>
12771316
copy.Throw(tree, transform(expr))
1317+
case Pack(expr) =>
1318+
copy.Pack(tree, transform(expr))
1319+
case Unpack(expr) =>
1320+
copy.Unpack(tree, transform(expr))
12781321
case New(tpt) =>
12791322
copy.New(tree, transform(tpt))
12801323
case Typed(expr, tpt) =>
@@ -1423,6 +1466,10 @@ trait Trees {
14231466
traverse(block); traverseTrees(catches); traverse(finalizer)
14241467
case Throw(expr) =>
14251468
traverse(expr)
1469+
case Pack(expr) =>
1470+
traverse(expr)
1471+
case Unpack(expr) =>
1472+
traverse(expr)
14261473
case New(tpt) =>
14271474
traverse(tpt)
14281475
case Typed(expr, tpt) =>
@@ -1544,6 +1591,15 @@ trait Trees {
15441591
}
15451592
}
15461593

1594+
class ForeachTraverser(f: Tree => Unit) extends Traverser {
1595+
override def traverse(t: Tree) = f(t)
1596+
}
1597+
1598+
class FilterTraverser(p: Tree => Boolean) extends Traverser {
1599+
val hits = new ListBuffer[Tree]
1600+
override def traverse(t: Tree) = if (p(t)) hits += t
1601+
}
1602+
15471603
object resetPos extends Traverser {
15481604
override def traverse(t: Tree): unit = {
15491605
if (t != EmptyTree) t.setPos(NoPosition)

src/compiler/scala/tools/nsc/symtab/Flags.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ object Flags extends Enumeration {
6666
// local value has been lifted out to class level
6767
// todo: make LIFTED = latePRIVATE?
6868
final val MIXEDIN = 0x800000000L // term member has been mixed in
69+
final val EXISTENTIAL = 0x800000000L // type is an existential parameter or skolem
6970

7071
final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix
7172
final val IMPLCLASS = 0x2000000000L // symbol is an implementation class

src/compiler/scala/tools/nsc/symtab/Symbols.scala

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,6 @@ trait Symbols {
115115
}
116116
final def newThisSym(pos: Position) =
117117
newValue(pos, nme.this_).setFlag(SYNTHETIC)
118-
final def newThisSkolem: Symbol =
119-
new ThisSkolem(owner, pos, name, this)
120-
.setFlag(SYNTHETIC | FINAL)
121118
final def newImport(pos: Position) =
122119
newValue(pos, nme.IMPORT)
123120
final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol =
@@ -196,14 +193,18 @@ trait Symbols {
196193
final def isStaticModule = isModule && isStatic && !isMethod
197194
final def isPackage = isModule && hasFlag(PACKAGE)
198195
final def isThisSym = isTerm && owner.thisSym == this
199-
final def isThisSkolem = isTerm && deSkolemize != this
200196
final def isMonomorphicType = isType && hasFlag(MONOMORPHIC)
201197
final def isError = hasFlag(IS_ERROR)
202198
final def isErroneous = isError || isInitialized && tpe.isErroneous
203199
final def isTrait = isClass & hasFlag(TRAIT)
200+
final def isSkolem = deSkolemize != this
204201
final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
205-
final def isTypeParameter = isTypeParameterOrSkolem && deSkolemize == this
206-
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
202+
final def isTypeParameter = isTypeParameterOrSkolem && !isSkolem
203+
final def isTypeSkolem = isTypeParameterOrSkolem && isSkolem
204+
final def isExistential = isType && hasFlag(EXISTENTIAL)
205+
final def isExistentialQuantified = isExistential && !isSkolem
206+
final def isExistentialSkolem = isExistential && isSkolem
207+
final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
207208
final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME)
208209
// startsWith necessary because name may grow when lifted and also because of anonymous function classes
209210
final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes
@@ -1129,17 +1130,6 @@ trait Symbols {
11291130
}
11301131
}
11311132

1132-
/** A class for type parameters viewed from inside their scopes */
1133-
class ThisSkolem(initOwner: Symbol, initPos: Position,
1134-
initName: Name, clazz: Symbol)
1135-
extends TermSymbol(initOwner, initPos, initName) {
1136-
override def deSkolemize = clazz
1137-
override def cloneSymbolImpl(owner: Symbol): Symbol = {
1138-
throw new Error("should not clone a this skolem")
1139-
}
1140-
override def nameString: String = clazz.name.toString() + ".this"
1141-
}
1142-
11431133
/** A class of type symbols. Alias and abstract types are direct instances
11441134
* of this class. Classes are instances of a subclass.
11451135
*/
@@ -1168,7 +1158,8 @@ trait Symbols {
11681158
else unsafeTypeParams map (_.typeConstructor) //@M! use typeConstructor to generate dummy type arguments,
11691159
// sym.tpe should not be called on a symbol that's supposed to be a higher-kinded type
11701160
// memberType should be used instead, that's why it uses tpeHK and not tpe
1171-
tpeCache = typeRef(if (isTypeParameterOrSkolem) NoPrefix else owner.thisType, this, targs)
1161+
tpeCache = typeRef(if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType,
1162+
this, targs)
11721163
}
11731164
}
11741165
assert(tpeCache ne null/*, "" + this + " " + phase*/)//debug
@@ -1177,7 +1168,8 @@ trait Symbols {
11771168

11781169
override def typeConstructor: Type = {
11791170
if ((tyconCache eq null) || tyconRunId != currentRunId) {
1180-
tyconCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, List())
1171+
tyconCache = typeRef(if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType,
1172+
this, List())
11811173
tyconRunId = currentRunId
11821174
}
11831175
assert(tyconCache ne null)

0 commit comments

Comments
 (0)