diff options
author | Martin Odersky <odersky@gmail.com> | 2007-02-19 13:56:55 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-02-19 13:56:55 +0000 |
commit | 68508bdd74fbb6e14143132b5e9bdaf89e4adf06 (patch) | |
tree | 53d5c39fe5d0f77aaca88484cc8b1479a58a67ce | |
parent | ce7fe41d5f7d831648068c8d82b7c6caa27aa3f5 (diff) | |
download | scala-68508bdd74fbb6e14143132b5e9bdaf89e4adf06.tar.gz scala-68508bdd74fbb6e14143132b5e9bdaf89e4adf06.tar.bz2 scala-68508bdd74fbb6e14143132b5e9bdaf89e4adf06.zip |
added explicit self defs
21 files changed, 212 insertions, 139 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala index 6ea4d43143..c8115cf7b4 100644 --- a/src/compiler/scala/tools/nsc/Interpreter.scala +++ b/src/compiler/scala/tools/nsc/Interpreter.scala @@ -184,7 +184,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter) val unit = new CompilationUnit( new SourceFile("<console>", code.toCharArray())) - new compiler.syntaxAnalyzer.Parser(unit).templateStatSeq + new compiler.syntaxAnalyzer.Parser(unit).templateStatSeq._2 } // parse the main code along with the imports diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala index 9179533e43..038daeb815 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala @@ -260,7 +260,7 @@ abstract class TreeBrowsers { case DocDef(comment, definition) => Pair("DocDef", EMPTY) - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(mods, name, tparams, self, impl) => Pair("ClassDef", name) case PackageDef(packaged, impl) => @@ -395,10 +395,10 @@ abstract class TreeBrowsers { case DocDef(comment, definition) => List(definition) - case ClassDef(mods, name, tparams, tpt, impl) => { + case ClassDef(mods, name, tparams, self, impl) => { var children: List[Tree] = List() children = tparams ::: children - tpt :: impl :: children + self :: impl :: children } case PackageDef(name, stats) => diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index 5d2afcc332..89fc896003 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -121,12 +121,22 @@ abstract class TreePrinters { case EmptyTree => print("<empty>") - case ClassDef(mods, name, tparams, tp, impl) => + case ClassDef(mods, name, tparams, self, impl) => printAnnotations(tree) printModifiers(tree, mods) print((if (mods hasFlag TRAIT) "trait " else "class ") + symName(tree, name)) printTypeParams(tparams) - printOpt(" requires ", tp); print(" extends "); print(impl) + print(" extends "); + printRow(impl.parents, " with ") + if (!impl.body.isEmpty) { + print(" {"); + if (self.name != nme.WILDCARD) { + print(" "); print(self.name); printOpt(": ", self.tpt); print(" => ") + } else if (!self.tpt.isEmpty) { + print(" _ : "); print(self); print(" => ") + } + } + printColumn(impl.body, "", ";", "}") case PackageDef(packaged, stats) => printAnnotations(tree) diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index abcbcf3cf6..b385760a80 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -222,7 +222,7 @@ trait Trees requires Global { } /** Class definition */ - case class ClassDef(mods: Modifiers, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template) + case class ClassDef(mods: Modifiers, name: Name, tparams: List[AbsTypeDef], self: ValDef, impl: Template) extends ImplDef /** @@ -235,7 +235,7 @@ trait Trees requires Global { ClassDef(Modifiers(sym.flags), sym.name, sym.typeParams map AbsTypeDef, - if (sym.thisSym == sym) EmptyTree else TypeTree(sym.typeOfThis), + if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym), impl) setSymbol sym } @@ -298,6 +298,8 @@ trait Trees requires Global { def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) + object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(), EmptyTree) + /** Method definition * * @param mods @@ -695,7 +697,7 @@ trait Trees requires Global { /* A standard pattern match case EmptyTree => case PackageDef(name, stats) => - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(mods, name, tparams, self, impl) => case ModuleDef(mods, name, impl) => (eliminated by refcheck) case ValDef(mods, name, tpt, rhs) => case DefDef(mods, name, tparams, vparamss, tpt, rhs) => @@ -741,7 +743,7 @@ trait Trees requires Global { */ abstract class TreeCopier { - def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template): ClassDef + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], self: ValDef, impl: Template): ClassDef def PackageDef(tree: Tree, name: Name, stats: List[Tree]): PackageDef def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef @@ -788,8 +790,8 @@ trait Trees requires Global { } class StrictTreeCopier extends TreeCopier { - def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template) = - new ClassDef(mods, name, tparams, tpt, impl).copyAttrs(tree); + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], self: ValDef, impl: Template) = + new ClassDef(mods, name, tparams, self, impl).copyAttrs(tree); def PackageDef(tree: Tree, name: Name, stats: List[Tree]) = new PackageDef(name, stats).copyAttrs(tree) def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template) = @@ -880,10 +882,10 @@ trait Trees requires Global { class LazyTreeCopier(copy: TreeCopier) extends TreeCopier { def this() = this(new StrictTreeCopier) - def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template) = tree match { - case t @ ClassDef(mods0, name0, tparams0, tpt0, impl0) - if (mods0 == mods && (name0 == name) && (tparams0 == tparams) && (tpt0 == tpt) && (impl0 == impl)) => t - case _ => copy.ClassDef(tree, mods, name, tparams, tpt, impl) + def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[AbsTypeDef], self: ValDef, impl: Template) = tree match { + case t @ ClassDef(mods0, name0, tparams0, self0, impl0) + if (mods0 == mods && (name0 == name) && (tparams0 == tparams) && (self0 == self) && (impl0 == impl)) => t + case _ => copy.ClassDef(tree, mods, name, tparams, self, impl) } def PackageDef(tree: Tree, name: Name, stats: List[Tree]) = tree match { case t @ PackageDef(name0, stats0) @@ -1115,22 +1117,22 @@ trait Trees requires Global { atOwner(tree.symbol.moduleClass) { copy.PackageDef(tree, name, transformStats(stats, currentOwner)) } - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(mods, name, tparams, self, impl) => atOwner(tree.symbol) { copy.ClassDef(tree, mods, name, transformAbsTypeDefs(tparams), - transform(tpt), transformTemplate(impl)) + transformValDef(self), transformTemplate(impl)) } case ModuleDef(mods, name, impl) => - atOwner(tree.symbol.moduleClass) { - copy.ModuleDef(tree, mods, name, transformTemplate(impl)) + atOwner(tree.symbol.moduleClass) { + copy.ModuleDef(tree, mods, name, transformTemplate(impl)) } case ValDef(mods, name, tpt, rhs) => - atOwner(tree.symbol) { - copy.ValDef(tree, mods, name, transform(tpt), transform(rhs)) + atOwner(tree.symbol) { + copy.ValDef(tree, mods, name, transform(tpt), transform(rhs)) } case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - atOwner(tree.symbol) { - copy.DefDef( + atOwner(tree.symbol) { + copy.DefDef( tree, mods, name, transformAbsTypeDefs(tparams), transformValDefss(vparamss), transform(tpt), transform(rhs)) } case AbsTypeDef(mods, name, lo, hi) => @@ -1225,10 +1227,12 @@ trait Trees requires Global { transform(tree: Tree).asInstanceOf[Template] def transformAbsTypeDefs(trees: List[AbsTypeDef]): List[AbsTypeDef] = List.mapConserve(trees)(tree => transform(tree).asInstanceOf[AbsTypeDef]) + def transformValDef(tree: ValDef): ValDef = + transform(tree).asInstanceOf[ValDef] def transformValDefs(trees: List[ValDef]): List[ValDef] = - List.mapConserve(trees)(tree => transform(tree).asInstanceOf[ValDef]) + List.mapConserve(trees)(transformValDef) def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] = - List.mapConserve(treess)(tree => transformValDefs(tree)) + List.mapConserve(treess)(transformValDefs) def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] = List.mapConserve(trees)(tree => transform(tree).asInstanceOf[CaseDef]) def transformIdents(trees: List[Ident]): List[Ident] = @@ -1257,9 +1261,9 @@ trait Trees requires Global { atOwner(tree.symbol.moduleClass) { traverseTrees(stats) } - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(mods, name, tparams, self, impl) => atOwner(tree.symbol) { - traverseTrees(tparams); traverse(tpt); traverse(impl) + traverseTrees(tparams); traverse(self); traverse(impl) } case ModuleDef(mods, name, impl) => atOwner(tree.symbol.moduleClass) { diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 8934906b26..9affe5be75 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -279,7 +279,6 @@ trait Parsers requires SyntaxAnalyzer { case Typed(Ident(name), tpe) => ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree) case _ => - Console.println("CTP "+tree) //debug syntaxError(tree.pos, "not a legal formal parameter", false) throw new Error() ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree, EmptyTree) @@ -802,6 +801,10 @@ trait Parsers requires SyntaxAnalyzer { ts.toList } + private final val Local = 0 + private final val InBlock = 1 + private final val InTemplate = 2 + /** Expr ::= (Bindings | Id) `=>' Expr * | PostfixExpr `:' Type * | Expr1 @@ -826,10 +829,8 @@ trait Parsers requires SyntaxAnalyzer { * | `:' Annotation {Annotation} * | `:' `_' `*' */ - def expr(): Tree = exprImpl(false) - def blockStatExpr(): Tree = exprImpl(true) - - private def exprImpl(isInBlock: boolean): Tree = in.token match { + def expr(): Tree = expr(Local) + def expr(location: int): Tree = in.token match { case IF => val pos = in.skipToken() accept(LPAREN) @@ -930,7 +931,7 @@ trait Parsers requires SyntaxAnalyzer { } } else if (annots.isEmpty || isTypeIntro) { t = atPos(pos) { - val tpt = if (isInBlock) compoundType(false) else typ() + val tpt = if (location != Local) compoundType(false) else typ() // this does not correspond to syntax, but is necessary to // accept closures. We might restrict closures to be between {...} only! Typed(t, (tpt /: annots) (makeAnnotated)) @@ -946,9 +947,9 @@ trait Parsers requires SyntaxAnalyzer { Match(stripParens(t), cases) } } - if (in.token == ARROW) { + if (in.token == ARROW && location != InTemplate) { t = atPos(in.skipToken()) { - Function(convertToParams(t), if (isInBlock) block() else expr()) + Function(convertToParams(t), if (location == Local) expr() else block()) } } stripParens(t) @@ -1059,8 +1060,9 @@ trait Parsers requires SyntaxAnalyzer { parents += annotType(false) } newLineOptWhenFollowedBy(LBRACE) - val stats = if (in.token == LBRACE) templateBody() else List() - makeNew(parents.toList, stats, argss.toList) + val Pair(self, stats) = if (in.token == LBRACE) templateBody() + else Pair(emptyValDef, List()) + makeNew(parents.toList, self, stats, argss.toList) } canApply = false case _ => @@ -1969,12 +1971,14 @@ trait Parsers requires SyntaxAnalyzer { else Pair(accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE))) val thistpe = requiresTypeOpt() - val template = classTemplate(mods, name, constrMods withAnnotations constrAnnots, vparamss) + val Pair(self0, template) = + classTemplate(mods, name, constrMods withAnnotations constrAnnots, vparamss) val mods1 = if (mods.hasFlag(Flags.TRAIT) && (template.body forall treeInfo.isInterfaceMember)) mods | Flags.INTERFACE else mods - val result = ClassDef(mods1, name, tparams, thistpe, template) + val self = if (thistpe.isEmpty) self0 else makeSelfDef(nme.WILDCARD, thistpe) + val result = ClassDef(mods1, name, tparams, self, template) implicitClassViews = savedViews result } @@ -1984,7 +1988,14 @@ trait Parsers requires SyntaxAnalyzer { def objectDef(mods: Modifiers): ModuleDef = atPos(in.skipToken()) { val name = ident() - val template = classTemplate(mods, name, NoMods, List()) + val Pair(self, template0) = classTemplate(mods, name, NoMods, List()) + val template = self match { + case ValDef(mods, name, tpt, EmptyTree) if (name != nme.WILDCARD) => + val vd = ValDef(mods, name, tpt, This(nme.EMPTY.toTypeName)) setPos self.pos + Template(template0.parents, vd :: template0.body) + case _ => + template0 + } ModuleDef(mods, name, template) } @@ -1993,59 +2004,61 @@ trait Parsers requires SyntaxAnalyzer { * TraitTemplate ::= [extends MixinParents] [TemplateBody] * MixinParents ::= AnnotType {with AnnotType} */ - def classTemplate(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): Template = - atPos(in.currentPos) { - def acceptEmptyTemplateBody(msg: String): unit = { - if (in.token == LPAREN && settings.migrate.value) - syntaxErrorMigrate("traits may not have parameters") - if (!(isStatSep || in.token == COMMA || in.token == RBRACE || in.token == EOF)) - syntaxError(msg, true) - } - val parents = new ListBuffer[Tree] - val argss = new ListBuffer[List[Tree]] - if (in.token == EXTENDS) { + def classTemplate(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): Pair[ValDef, Template] = { + val pos = in.currentPos; + def acceptEmptyTemplateBody(msg: String): unit = { + if (in.token == LPAREN && settings.migrate.value) + syntaxErrorMigrate("traits may not have parameters") + if (!(isStatSep || in.token == COMMA || in.token == RBRACE || in.token == EOF)) + syntaxError(msg, true) + } + val parents = new ListBuffer[Tree] + val argss = new ListBuffer[List[Tree]] + if (in.token == EXTENDS) { + in.nextToken() + val parent = annotType(false) + // System.err.println("classTempl: " + parent) + parents += parent + if (in.token == LPAREN && !mods.hasFlag(Flags.TRAIT)) + do { argss += argumentExprs() } while (in.token == LPAREN) + else argss += List() + while (in.token == WITH) { in.nextToken() - val parent = annotType(false) - // System.err.println("classTempl: " + parent) - parents += parent - if (in.token == LPAREN && !mods.hasFlag(Flags.TRAIT)) - do { argss += argumentExprs() } while (in.token == LPAREN) - else argss += List() - while (in.token == WITH) { - in.nextToken() - parents += annotType(false) - } - } else { - if (in.token == WITH && settings.migrate.value) - syntaxErrorMigrate("`extends' needed before `with'") - newLineOptWhenFollowedBy(LBRACE) - if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected") - argss += List() - } - if (name != nme.ScalaObject.toTypeName) - parents += scalaScalaObjectConstr - if (mods.hasFlag(Flags.CASE)) { - parents += productConstr + parents += annotType(false) } - val ps = parents.toList + } else { + if (in.token == WITH && settings.migrate.value) + syntaxErrorMigrate("`extends' needed before `with'") newLineOptWhenFollowedBy(LBRACE) - var body = - if (in.token == LBRACE) templateBody() - else { acceptEmptyTemplateBody("`{' expected"); List() } - if (!mods.hasFlag(Flags.TRAIT)) Template(ps, constrMods, vparamss, argss.toList, body) - else Template(ps, body) + if (in.token != LBRACE) acceptEmptyTemplateBody("`extends' or `{' expected") + argss += List() + } + if (name != nme.ScalaObject.toTypeName) + parents += scalaScalaObjectConstr + if (mods.hasFlag(Flags.CASE)) { + parents += productConstr } + val ps = parents.toList + newLineOptWhenFollowedBy(LBRACE) + val Pair(self, body) = + if (in.token == LBRACE) templateBody() + else { acceptEmptyTemplateBody("`{' expected"); Pair(emptyValDef, List()) } + Pair(self, + atPos(pos) { + if (!mods.hasFlag(Flags.TRAIT)) Template(ps, constrMods, vparamss, argss.toList, body) + else Template(ps, body) + }) + } ////////// TEMPLATES //////////////////////////////////////////////////////////// - /** TemplateBody ::= [nl] `{' TemplateStat {semi TemplateStat} `}' + /** TemplateBody ::= [nl] `{' TemplateStatSeq `}' */ - def templateBody(): List[Tree] = { + def templateBody(): Pair[ValDef, List[Tree]] = { accept(LBRACE) - var body = templateStatSeq() - if (body.isEmpty) body = List(EmptyTree) + val result = templateStatSeq() accept(RBRACE) - body + result } /** Refinement ::= [nl] `{' RefineStat {semi RefineStat} `}' @@ -2103,20 +2116,32 @@ trait Parsers requires SyntaxAnalyzer { stats.toList } - /** TemplateStatSeq ::= TemplateStat {semi TemplateStat} + /** TemplateStatSeq ::= [id [`:' Type] `=>'] TemplateStat {semi TemplateStat} * TemplateStat ::= Import * | Annotations Modifiers Def * | Annotations Modifiers Dcl - * | Expr + * | Expr1 * | */ - def templateStatSeq(): List[Tree] = { + def templateStatSeq(): Pair[ValDef, List[Tree]] = { + var self: ValDef = emptyValDef val stats = new ListBuffer[Tree] + if (isExprIntro) { + val first = expr(InTemplate) + if (in.token == ARROW) { + convertToParam(first) match { + case ValDef(_, name, tpt, EmptyTree) if (name != nme.ERROR) => + self = makeSelfDef(name, tpt) + case _ => + } + in.nextToken() + } else stats += first + } while (in.token != RBRACE && in.token != EOF) { if (in.token == IMPORT) { stats ++= importClause() } else if (isExprIntro) { - stats += expr() + stats += expr(InTemplate) } else if (isDefIntro || isModifier || in.token == LBRACKET /*todo: remove */ || in.token == AT) { val annots = annotations() stats ++ joinComment(defOrDcl(modifiers() withAnnotations annots)) @@ -2125,7 +2150,7 @@ trait Parsers requires SyntaxAnalyzer { } if (in.token != RBRACE && in.token != EOF) acceptStatSep() } - stats.toList + Pair(self, if (!stats.hasNext) List(EmptyTree) else stats.toList) } /** RefineStatSeq ::= RefineStat {semi RefineStat} @@ -2170,7 +2195,7 @@ trait Parsers requires SyntaxAnalyzer { stats ++= importClause() acceptStatSep() } else if (isExprIntro) { - stats += blockStatExpr() + stats += expr(InBlock) if (in.token != RBRACE && in.token != CASE) acceptStatSep() } else if (isDefIntro) { localDef(NoMods) diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index f3685365d2..5118d12236 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -107,6 +107,9 @@ abstract class TreeBuilder { case Annotation(constr, elements) => Annotated(constr, elements, t) setPos attr.pos } + def makeSelfDef(name: Name, tpt: Tree): ValDef = + ValDef(Modifiers(PRIVATE), name, tpt, EmptyTree) + /** If tree is a variable pattern, return Some("its name and type"). * Otherwise return none */ private def matchVarPattern(tree: Tree): Option[Pair[Name, Tree]] = tree match { @@ -138,14 +141,14 @@ abstract class TreeBuilder { } /** Create tree representing an object creation <new parents { stats }> */ - def makeNew(parents: List[Tree], stats: List[Tree], argss: List[List[Tree]]): Tree = + def makeNew(parents: List[Tree], self: ValDef, stats: List[Tree], argss: List[List[Tree]]): Tree = if (parents.tail.isEmpty && stats.isEmpty) New(parents.head, argss) else { val x = nme.ANON_CLASS_NAME.toTypeName Block( List(ClassDef( - Modifiers(FINAL | SYNTHETIC), x, List(), TypeTree(), + Modifiers(FINAL | SYNTHETIC), x, List(), self, Template(parents, NoMods, List(List()), argss, stats))), New(Ident(x), List(List()))) } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 0219442b8a..be74fe4e78 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -78,7 +78,7 @@ abstract class GenICode extends SubComponent { case PackageDef(name, stats) => gen(stats, ctx setPackage name) - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(mods, name, _, _, impl) => log("Generating class: " + tree.symbol.fullNameString) ctx setClass (new IClass(tree.symbol) setCompilationUnit unit) addClassFields(ctx, tree.symbol); diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 5d2e5220d4..5c58352a36 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -189,7 +189,7 @@ trait Symbols requires SymbolTable { final def isModule = isTerm && hasFlag(MODULE) final def isStaticModule = isModule && isStatic && !isMethod final def isPackage = isModule && hasFlag(PACKAGE) - final def isThisSym = isTerm && name == nme.this_ + final def isThisSym = isTerm && owner.thisSym == this final def isThisSkolem = isTerm && deSkolemize != this final def isError = hasFlag(IS_ERROR) final def isErroneous = isError || isInitialized && tpe.isErroneous @@ -1252,7 +1252,10 @@ trait Symbols requires SymbolTable { override def cloneSymbolImpl(owner: Symbol): Symbol = { assert(!isModuleClass) val clone = new ClassSymbol(owner, pos, name) - if (thisSym != this) clone.typeOfThis = typeOfThis + if (thisSym != this) { + clone.typeOfThis = typeOfThis + clone.thisSym.name = thisSym.name + } clone } diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 27bc11ff67..163683401a 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1285,7 +1285,7 @@ trait Types requires SymbolTable { abstract class LazyType extends Type { override def isComplete: boolean = false override def complete(sym: Symbol): unit - override def toString = "LazyType" + override def toString = "<?>" } /** A class representing a lazy type with known type parameters. diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 78ab6c0d34..f1ed8f36c0 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -105,7 +105,7 @@ abstract class Pickler extends SubComponent { putSymbol(sym.owner) putSymbol(sym.privateWithin) putType(sym.info) - if (sym.thisSym != sym) + if (sym.thisSym.tpe != sym.tpe) putType(sym.typeOfThis); putSymbol(sym.alias) if (!sym.children.isEmpty) @@ -236,7 +236,7 @@ abstract class Pickler extends SubComponent { tag case sym: ClassSymbol => val posOffset = writeSymInfo(sym) - if (sym.thisSym != sym) writeRef(sym.typeOfThis) + if (sym.thisSym.tpe != sym.tpe) writeRef(sym.typeOfThis) CLASSsym + posOffset case sym: TypeSymbol => val posOffset = writeSymInfo(sym) diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 5b264a33e8..64f2bf2625 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -301,9 +301,9 @@ abstract class AddInterfaces extends InfoTransform { override def transform(tree: Tree): Tree = { val sym = tree.symbol val tree1 = tree match { - case ClassDef(mods, name, tparams, tpt, impl) if (sym.needsImplClass) => + case ClassDef(mods, name, tparams, self, impl) if (sym.needsImplClass) => implClass(sym).initialize // to force lateDEFERRED flags - copy.ClassDef(tree, mods | INTERFACE, name, tparams, tpt, ifaceTemplate(impl)) + copy.ClassDef(tree, mods | INTERFACE, name, tparams, self, ifaceTemplate(impl)) case DefDef(mods, name, tparams, vparamss, tpt, rhs) if (sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass) => copy.DefDef(tree, mods, name, tparams, vparamss, tpt, diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 29e1ceeb1d..76ad75e317 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -184,8 +184,8 @@ abstract class Constructors extends Transform { override def transform(tree: Tree): Tree = { tree match { - case ClassDef(mods, name, tparams, tpt, impl) if !tree.symbol.hasFlag(INTERFACE) => - copy.ClassDef(tree, mods, name, tparams, tpt, transformClassTemplate(impl)) + case ClassDef(mods, name, tparams, self, impl) if !tree.symbol.hasFlag(INTERFACE) => + copy.ClassDef(tree, mods, name, tparams, self, transformClassTemplate(impl)) case _ => super.transform(tree) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 8d70c8360c..ed540ea1f4 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -717,10 +717,10 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { override def transform(tree: Tree): Tree = { if (tree.symbol == ArrayClass) return tree val tree1 = tree match { - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(mods, name, tparams, self, impl) => if (settings.debug.value) log("defs of " + tree.symbol + " = " + tree.symbol.info.decls) - copy.ClassDef(tree, mods, name, List(), tpt, impl) + copy.ClassDef(tree, mods, name, List(), emptyValDef, impl) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => copy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs) case AbsTypeDef(_, _, _, _) => diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index d47a209ebe..9d370bcc6f 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -319,8 +319,8 @@ abstract class LambdaLift extends InfoTransform { sym.updateInfo( lifted(MethodType(sym.info.paramTypes ::: (ps map (.tpe)), sym.info.resultType))); copy.DefDef(tree, mods, name, tparams, List(vparams ::: freeParams), tpt, rhs) - case ClassDef(mods, name, tparams, tpt, impl @ Template(parents, body)) => - copy.ClassDef(tree, mods, name, tparams, tpt, + case ClassDef(mods, name, tparams, self, impl @ Template(parents, body)) => + copy.ClassDef(tree, mods, name, tparams, self, copy.Template(impl, parents, body ::: freeParams)) } case None => @@ -397,10 +397,10 @@ abstract class LambdaLift extends InfoTransform { /** Transform statements and add lifted definitions to them. */ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { def addLifted(stat: Tree): Tree = stat match { - case ClassDef(mods, name, tparams, tpt, impl @ Template(parents, body)) => + case ClassDef(mods, name, tparams, self, impl @ Template(parents, body)) => val lifted = liftedDefs(stat.symbol).toList map addLifted val result = copy.ClassDef( - stat, mods, name, tparams, tpt, copy.Template(impl, parents, body ::: lifted)) + stat, mods, name, tparams, self, copy.Template(impl, parents, body ::: lifted)) liftedDefs -= stat.symbol result case _ => diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index 3a633bb2c7..db27ab88fe 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -124,12 +124,12 @@ abstract class LiftCode extends Transform { val rhs_ = reify(rhs) reflect.ValDef(sym, rhs_) - case cd @ ClassDef(mods, name, tparams, tpt, impl) => + case cd @ ClassDef(mods, name, tparams, self, impl) => if(!tparams.isEmpty) throw new TypeError("cannot handle polymorphic ClassDef ("+name+"): " + tparams) val rsym = reify(cd.symbol) val rimp = reify(impl) - val rtpe = reify(tpt.tpe) + val rtpe = reify(self.tpe) //todo: update reflect.ClassDef(rsym, rtpe, rimp.asInstanceOf[reflect.Template]) case tmpl @ Template(parents, body) => @@ -299,7 +299,7 @@ abstract class LiftCode extends Transform { // case EmptyTree => // case LiftPoint(tree) => // case PackageDef(name, stats) => -// case ClassDef(mods, name, tparams, tpt, impl) => +// case ClassDef(mods, name, tparams, self, impl) => // case ValDef(mods, name, tpt, rhs) => // case DefDef(mods, name, tparams, vparamss, tpt, rhs) => // case AbsTypeDef(mods, name, lo, hi) => diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 82ff45a644..f35eb5dcc4 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -365,7 +365,7 @@ abstract class Mixin extends InfoTransform { tree.tpe = ifacetpe } tree - case ValDef(_, _, _, _) if (currentOwner.isImplClass) => + case ValDef(_, _, _, _) if (currentOwner.isImplClass && tree != emptyValDef) => EmptyTree case _ => tree diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index c83430f265..1fc2f43e3e 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -180,7 +180,7 @@ abstract class TailCalls extends Transform case EmptyTree => tree case PackageDef(name, stats) => super.transform(tree) - case ClassDef(mods, name, tparams, tpt, impl) => + case ClassDef(_, name, _, _, _) => log("Entering class " + name) val res = super.transform(tree) log("Leaving class " + name) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index d7025f3dc1..000c57d766 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -432,11 +432,25 @@ trait Namers requires Analyzer { ClassInfoType(parents, decls, clazz) } - private def classSig(tparams: List[AbsTypeDef], tpt: Tree, impl: Template): Type = { + private def classSig(tparams: List[AbsTypeDef], self: ValDef, impl: Template): Type = { + val clazz = context.owner val tparamSyms = typer.reenterTypeParams(tparams) - if (!tpt.isEmpty) - context.owner.typeOfThis = selfTypeCompleter(tpt) - else tpt.tpe = NoType + if (!self.tpt.isEmpty) { + clazz.typeOfThis = selfTypeCompleter(self.tpt) + self.symbol = clazz.thisSym + } else { + self.tpt.tpe = NoType + if (self.name != nme.WILDCARD) { + clazz.typeOfThis = clazz.tpe + self.symbol = clazz.thisSym + } else { + self.symbol = clazz.newThisSym(self.pos) setInfo clazz.tpe + } + } + if (self.name != nme.WILDCARD) { + context.scope enter self.symbol + clazz.thisSym.name = self.name + } makePolyType(tparamSyms, templateSig(impl)) } @@ -561,8 +575,8 @@ trait Namers requires Analyzer { try { val sym: Symbol = tree.symbol tree match { - case ClassDef(_, _, tparams, tpt, impl) => - new Namer(makeNewScope(context, tree, sym)).classSig(tparams, tpt, impl) + case ClassDef(_, _, tparams, self, impl) => + new Namer(makeNewScope(context, tree, sym)).classSig(tparams, self, impl) case ModuleDef(_, _, impl) => val clazz = sym.moduleClass diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 2afb6dd493..7a06d45cb5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -458,7 +458,7 @@ abstract class RefChecks extends InfoTransform { def transformStat(tree: Tree, index: int): List[Tree] = tree match { case ModuleDef(mods, name, impl) => val sym = tree.symbol - val cdef = ClassDef(mods | MODULE, name, List(), EmptyTree, impl) + val cdef = ClassDef(mods | MODULE, name, List(), emptyValDef, impl) .setPos(tree.pos) .setSymbol(sym.moduleClass) .setType(NoType); @@ -577,7 +577,7 @@ abstract class RefChecks extends InfoTransform { val sym = tree.symbol var result = tree tree match { - case ClassDef(mods, name, tparams, tpe, impl) => + case ClassDef(mods, name, tparams, _, impl) => validateVariance(sym, sym.info, CoVariance) validateVariance(sym, sym.typeOfThis, CoVariance) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index c05c17a0a2..dc82bfdc9c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -833,11 +833,17 @@ trait Typers requires Analyzer { val clazz = cdef.symbol reenterTypeParams(cdef.tparams) val tparams1 = List.mapConserve(cdef.tparams)(typedAbsTypeDef) - val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(cdef.tpt)) - val impl1 = newTyper(context.make(cdef.impl, clazz, newScope)) + val self1 = cdef.self match { + case ValDef(mods, name, tpt, EmptyTree) => + val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt)) + copy.ValDef(cdef.self, mods, name, tpt1, EmptyTree) setType NoType + } + val implScope = newScope + if (self1.name != nme.WILDCARD) implScope enter self1.symbol + val impl1 = newTyper(context.make(cdef.impl, clazz, implScope)) .typedTemplate(cdef.impl, parentTypes(cdef.impl)) val impl2 = addSyntheticMethods(impl1, clazz, context.unit) - val ret = copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl2) + val ret = copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, self1, impl2) .setType(NoType) ret } @@ -1847,17 +1853,6 @@ trait Typers requires Analyzer { (context.unit ne null) && defSym.sourceFile != context.unit.source.file)) defSym = NoSymbol -/* - /*<unapply>*/ - if(settings.Xunapply.value) - // unapply: in patterns, look for an object if can't find type - if (!defSym.exists && !impSym.exists && name.isTypeName && (mode & PATTERNmode) != 0) { - val mod = typedIdent(name.toTermName) - return tree setSymbol mod.symbol setType mod.tpe - } - /*</unapply>*/ -*/ - if (defSym.exists) { if (impSym.exists) ambiguousError( @@ -1904,10 +1899,13 @@ trait Typers requires Analyzer { } } if (defSym.owner.isPackageClass) pre = defSym.owner.thisType - val tree1 = if (qual == EmptyTree) tree - else atPos(tree.pos)(Select(qual, name)) - // atPos necessary because qualifier might come from startContext - stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt) + if (defSym.isThisSym) typed1(This(defSym.owner), mode, pt) + else { + val tree1 = if (qual == EmptyTree) tree + else atPos(tree.pos)(Select(qual, name)) + // atPos necessary because qualifier might come from startContext + stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt) + } } // begin typed1 diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala index 108cb07f44..65b0df4979 100644 --- a/src/library/scala/collection/immutable/Map.scala +++ b/src/library/scala/collection/immutable/Map.scala @@ -132,6 +132,22 @@ trait Map[A, +B] extends collection.Map[A, B] { def -- (keys: Iterator[A]): Map[A, B] = (this /: keys) ((m, key) => m - key) + + /** The same map with a given default function */ + def withDefault[B1 >: B](d: A => B1): Map[A, B1] = new Map[A, B1] { + def size = Map.this.size + def get(key: A) = Map.this.get(key) + def elements = Map.this.elements + def empty[C] = Map.this.empty + def update [B2 >: B1](key: A, value: B2): Map[A, B2] = + Map.this.update(key, value) withDefault d + def -(key: A): Map[A, B1] = Map.this - key withDefault d + override def default(key: A): B1 = d(key) + } + + /** The same map with a given default value */ + def withDefaultValue[B1 >: B](d: B1): Map[A, B1] = withDefault(x => d) + /** This function transforms all the values of mappings contained * in this map with function <code>f</code>. * |