summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-02-23 17:13:37 +0000
committerMartin Odersky <odersky@gmail.com>2007-02-23 17:13:37 +0000
commitfca1d7499a02cee13c6845cb3cffe77c8dc73231 (patch)
treea517da50092dc38243b1653810267d7a9808cd23 /src
parentb4a6ccf03370c8ea5b1ce8fdf26f9219f2040e47 (diff)
downloadscala-fca1d7499a02cee13c6845cb3cffe77c8dc73231.tar.gz
scala-fca1d7499a02cee13c6845cb3cffe77c8dc73231.tar.bz2
scala-fca1d7499a02cee13c6845cb3cffe77c8dc73231.zip
prepared the ground for duck typing.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala19
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala32
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala19
6 files changed, 65 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 057071f97f..794a86594d 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -335,6 +335,9 @@ abstract class TreeBrowsers {
case Apply(fun, args) =>
("Apply", EMPTY)
+ case ApplyDynamic(fun, args) =>
+ ("Apply", EMPTY)
+
case Super(qualif, mix) =>
("Super", qualif.toString() + ", mix: " + mix.toString())
@@ -482,6 +485,9 @@ abstract class TreeBrowsers {
case Apply(fun, args) =>
List(fun) ::: args
+ case ApplyDynamic(fun, args) =>
+ List(fun) ::: args
+
case Super(qualif, mix) =>
Nil
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index c592c01af0..e47e838722 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -262,6 +262,10 @@ abstract class TreePrinters {
case Apply(fun, vargs) =>
print(fun); printRow(vargs, "(", ", ", ")")
+ case ApplyDynamic(fun, vargs) =>
+ print("<apply-dynamic>("); print(fun); print("#"); print(tree.symbol.nameString)
+ printRow(vargs, ", (", ", ", "))")
+
case Super(qual, mix) =>
if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".")
print("super")
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index d4f400169d..c7c376ad96 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -598,6 +598,10 @@ trait Trees requires Global {
override def symbol_=(sym: Symbol): unit = { fun.symbol = sym }
}
+ /** Dynamic value application */
+ case class ApplyDynamic(fun: Tree, args: List[Tree])
+ extends TermTree with SymTree
+
/** Super reference */
case class Super(qual: Name, mix: Name)
extends TermTree with SymTree
@@ -727,13 +731,14 @@ trait Trees requires Global {
case Typed(expr, tpt) => (eliminated by erasure)
case TypeApply(fun, args) =>
case Apply(fun, args) =>
+ case ApplyDynamic(fun, args) (introduced by erasure, eliminated by cleanup)
case Super(qual, mix) =>
case This(qual) =>
case Select(qualifier, selector) =>
case Ident(name) =>
case Literal(value) =>
case TypeTree() => (introduced by refcheck)
- case Annotated(constr, elements, arg) => (eliminated by typer)
+ case Annotated(constr, elements, arg) => (eliminated by typer)
case AttributedTypeTree(attribs, tpt) => (eliminated by uncurry)
case SingletonTypeTree(ref) => (eliminated by uncurry)
case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry)
@@ -774,6 +779,7 @@ trait Trees requires Global {
def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply
+ def ApplyDynamic(tree: Tree, fun: Tree, args: List[Tree]): ApplyDynamic
def Super(tree: Tree, qual: Name, mix: Name): Super
def This(tree: Tree, qual: Name): This
def Select(tree: Tree, qualifier: Tree, selector: Name): Select
@@ -852,6 +858,8 @@ trait Trees requires Global {
new TypeApply(fun, args).copyAttrs(tree)
def Apply(tree: Tree, fun: Tree, args: List[Tree]) =
new Apply(fun, args).copyAttrs(tree)
+ def ApplyDynamic(tree: Tree, fun: Tree, args: List[Tree]) =
+ new ApplyDynamic(fun, args).copyAttrs(tree)
def Super(tree: Tree, qual: Name, mix: Name) =
new Super(qual, mix).copyAttrs(tree)
def This(tree: Tree, qual: Name) =
@@ -1038,6 +1046,11 @@ trait Trees requires Global {
if (fun0 == fun) && (args0 == args) => t
case _ => copy.Apply(tree, fun, args)
}
+ def ApplyDynamic(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
+ case t @ ApplyDynamic(fun0, args0)
+ if (fun0 == fun) && (args0 == args) => t
+ case _ => copy.ApplyDynamic(tree, fun, args)
+ }
def Super(tree: Tree, qual: Name, mix: Name) = tree match {
case t @ Super(qual0, mix0)
if (qual0 == qual) && (mix0 == mix) => t
@@ -1195,6 +1208,8 @@ trait Trees requires Global {
copy.TypeApply(tree, transform(fun), transformTrees(args))
case Apply(fun, args) =>
copy.Apply(tree, transform(fun), transformTrees(args))
+ case ApplyDynamic(fun, args) =>
+ copy.ApplyDynamic(tree, transform(fun), transformTrees(args))
case Super(qual, mix) =>
copy.Super(tree, qual, mix)
case This(qual) =>
@@ -1341,6 +1356,8 @@ trait Trees requires Global {
traverse(fun); traverseTrees(args)
case Apply(fun, args) =>
traverse(fun); traverseTrees(args)
+ case ApplyDynamic(fun, args) =>
+ traverse(fun); traverseTrees(args)
case Super(_, _) =>
;
case This(_) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index f0b18dc5ab..980dea08f1 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -222,6 +222,10 @@ trait Symbols requires SymbolTable {
final def isStable =
isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE))
+ /** Is this symbol a public */
+ final def isPublic: boolean =
+ !hasFlag(PRIVATE | PROTECTED) && privateWithin == NoSymbol
+
/** Is this symbol a private local */
final def isPrivateLocal =
hasFlag(PRIVATE) && hasFlag(LOCAL)
@@ -788,7 +792,7 @@ trait Symbols requires SymbolTable {
final def allOverriddenSymbols: List[Symbol] =
if (owner.isClass)
- for { val bc <- owner.info.baseClasses
+ for { val bc <- owner.info.baseClasses.tail
val s = overriddenSymbol(bc)
s != NoSymbol } yield s
else List()
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 6d6dca90a3..c75a5b460b 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -461,7 +461,14 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
/** A replacement for the standard typer's `typed1' method */
override protected def typed1(tree: Tree, mode: int, pt: Type): Tree = {
var tree1 = try {
- super.typed1(adaptMember(tree), mode, pt);
+ tree match {
+ case ApplyDynamic(fun, args) =>
+ val fun1 = typed(fun, AnyRefClass.tpe)
+ val args1 = List.mapConserve(args)(arg => typed(arg, AnyRefClass.tpe))
+ copy.ApplyDynamic(tree, fun1, args1) setType AnyRefClass.tpe
+ case _ =>
+ super.typed1(adaptMember(tree), mode, pt)
+ }
} catch {
case ex: Throwable =>
//if (settings.debug.value)
@@ -769,19 +776,20 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
}
case _ => tree
}
- else tree
+ else fn match {
+ case Select(qual, _) if (settings.Xexperimental.value &&
+ fn.symbol.owner.isRefinementClass &&
+ fn.symbol.allOverriddenSymbols.isEmpty) =>
+ ApplyDynamic(qual, args) setSymbol fn.symbol setPos tree.pos
+ case _ =>
+ tree
+ }
- case Select(qual, _) =>
+ case Select(_, _) =>
if (tree.symbol.owner.isRefinementClass) {
- var sym: Symbol = NoSymbol
- var bcs = tree.symbol.owner.info.baseClasses.tail
- //Console.println("resetting "+tree.symbol+tree.symbol.locationString+bcs)//DEBUG
- while (!bcs.isEmpty && sym == NoSymbol) {
- sym = tree.symbol.overriddenSymbol(bcs.head)
- bcs = bcs.tail
- }
- assert(sym != NoSymbol, tree.symbol)
- tree.symbol = sym
+ val overridden = tree.symbol.allOverriddenSymbols
+ assert(!overridden.isEmpty, tree.symbol)
+ tree.symbol = overridden.head
}
tree
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 85f63af910..136954a7af 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1156,11 +1156,13 @@ trait Typers requires Analyzer {
def anonymousClassRefinement(clazz: Symbol): Type = {
val tp = refinedType(clazz.info.parents, clazz.owner)
val thistp = tp.symbol.thisType
+ def canBeInRefinement(sym: Symbol) =
+ settings.Xexperimental.value ||
+ tp.nonPrivateMember(sym.name).filter { other =>
+ !other.isTerm || (thistp.memberType(other) matches thistp.memberType(sym))
+ } != NoSymbol
for (val sym <- clazz.info.decls.toList) {
- if (!sym.hasFlag(PRIVATE) && !sym.isClass && !sym.isConstructor &&
- tp.nonPrivateMember(sym.name).filter(other =>
- !other.isTerm || (thistp.memberType(other) matches thistp.memberType(sym)))
- != NoSymbol)
+ if (sym.isPublic && !sym.isClass && !sym.isConstructor && canBeInRefinement(sym))
addMember(thistp, tp, sym)
}
tp
@@ -1293,10 +1295,13 @@ trait Typers requires Analyzer {
val stats1 = typedStats(stats, NoSymbol)
for (val stat <- stats1; stat.isDef) {
val member = stat.symbol
- member setFlag OVERRIDE
if (context.owner.info.baseClasses.tail forall
- (bc => member.matchingSymbol(bc, context.owner.thisType) == NoSymbol))
- error(member.pos, member.toString+" does not refine a member of its base type")
+ (bc => member.matchingSymbol(bc, context.owner.thisType) == NoSymbol)) {
+ if (!settings.Xexperimental.value)
+ error(member.pos, member.toString+" does not refine a member of its base type")
+ } else {
+ member setFlag OVERRIDE
+ }
}
stats1
}