diff options
author | Martin Odersky <odersky@gmail.com> | 2007-02-23 17:13:37 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-02-23 17:13:37 +0000 |
commit | fca1d7499a02cee13c6845cb3cffe77c8dc73231 (patch) | |
tree | a517da50092dc38243b1653810267d7a9808cd23 /src/compiler | |
parent | b4a6ccf03370c8ea5b1ce8fdf26f9219f2040e47 (diff) | |
download | scala-fca1d7499a02cee13c6845cb3cffe77c8dc73231.tar.gz scala-fca1d7499a02cee13c6845cb3cffe77c8dc73231.tar.bz2 scala-fca1d7499a02cee13c6845cb3cffe77c8dc73231.zip |
prepared the ground for duck typing.
Diffstat (limited to 'src/compiler')
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 } |