diff options
author | Martin Odersky <odersky@gmail.com> | 2007-04-12 18:23:58 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-04-12 18:23:58 +0000 |
commit | eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043 (patch) | |
tree | d6e914ff40d9b3499ac64856e6f37b7c394298c9 /src/compiler/scala/tools | |
parent | 5d449bfbc1a39aaf2cb78f04241990c8c6c37d5f (diff) | |
download | scala-eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043.tar.gz scala-eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043.tar.bz2 scala-eecb5e5c4cdc96c2ea4e58a0c4b735eeffbee043.zip |
added early field initialization.
Diffstat (limited to 'src/compiler/scala/tools')
9 files changed, 159 insertions, 96 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index c94ed6c94e..dd837012d9 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -452,11 +452,19 @@ trait Trees requires Global { ret.symbol = vd.symbol ret })) + val (vdefs, rest) = body span treeInfo.isPreSuper + val (lvdefs, gvdefs) = List.unzip { + vdefs map { + case vdef @ ValDef(mods, name, tpt, rhs) => + (copy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs), + copy.ValDef(vdef, mods, name, TypeTree(), EmptyTree)) + } + } val constrs = if (constrMods hasFlag TRAIT) { if (body forall treeInfo.isInterfaceMember) List() else List( - DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(), Literal(())))) + DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(())))) } else { if (vparamss1.isEmpty || !vparamss1.head.isEmpty && (vparamss1.head.head.mods.flags & IMPLICIT) != 0) @@ -464,9 +472,9 @@ trait Trees requires Global { val superRef: Tree = Select(Super(nme.EMPTY.toTypeName, nme.EMPTY.toTypeName), nme.CONSTRUCTOR) val superCall = posAssigner.atPos(parents.head.pos) { (superRef /: argss) (Apply) } List( - DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(List(superCall), Literal(())))) + DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(())))) } - Template(parents, List.flatten(vparamss) ::: constrs ::: body) + Template(parents, gvdefs ::: List.flatten(vparamss) ::: constrs ::: rest) } /** Block of expressions (semicolon separated expressions) */ diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 1868ab2108..45beab0d28 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1009,7 +1009,7 @@ trait Parsers requires SyntaxAnalyzer { } } - /* SimpleExpr ::= new AnnotType {`(' [Exprs [`,']] `)'} {`with' AnnotType} [TemplateBody] + /* SimpleExpr ::= new ClassTemplate * | BlockExpr * | SimpleExpr1 * SimpleExpr1 ::= literal @@ -1047,19 +1047,8 @@ trait Parsers requires SyntaxAnalyzer { canApply = false case NEW => t = atPos(in.skipToken()) { - val parents = new ListBuffer[Tree] + annotType(false) - val argss = new ListBuffer[List[Tree]] - if (in.token == LPAREN) - do { argss += argumentExprs() } while (in.token == LPAREN) - else argss += List() - while (in.token == WITH) { - in.nextToken() - parents += annotType(false) - } - newLineOptWhenFollowedBy(LBRACE) - val (self, stats) = if (in.token == LBRACE) templateBody() - else (emptyValDef, List()) - makeNew(parents.toList, self, stats, argss.toList) + val (parents, argss, self, stats) = template(false) + makeNew(parents, self, stats, argss) } canApply = false case _ => @@ -1133,50 +1122,54 @@ trait Parsers requires SyntaxAnalyzer { ts.toList } - /** CaseClause : =>= case Pattern [if PostfixExpr] `=>' Block + /** CaseClause ::= case Pattern [Guard] `=>' Block */ def caseClause(): CaseDef = atPos(accept(CASE)) { val pat = pattern() - val guard = - if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) } - else EmptyTree - makeCaseDef(pat, guard, atPos(accept(ARROW))(block())) + val gd = guard() + makeCaseDef(pat, gd, atPos(accept(ARROW))(block())) } + /** Guard ::= if PostfixExpr + */ + def guard(): Tree = + if (in.token == IF) { in.nextToken(); stripParens(postfixExpr()) } + else EmptyTree + /** Enumerators ::= Generator {semi Enumerator} - * Enumerator ::= Generator - * | val Pattern1 `=' Expr - * | Expr + * Enumerator ::= Generator + * | Guard + * | val Pattern1 `=' Expr */ def enumerators(): List[Enumerator] = { val newStyle = in.token != VAL - val enums = new ListBuffer[Enumerator] + generator(false) + val enums = new ListBuffer[Enumerator] + generator(enums, false) while (isStatSep) { in.nextToken() - enums += { - if (newStyle) { - if (in.token == IF) { in.nextToken(); Filter(expr()) } - else generator(true) - } else { - if (in.token == VAL) generator(true) - else Filter(expr()) - } + if (newStyle) { + if (in.token == IF) enums += Filter(guard()) + else generator(enums, true) + } else { + if (in.token == VAL) generator(enums, true) + else enums += Filter(expr()) } } enums.toList } - /** Generator ::= val Pattern1 `<-' Expr + /** Generator ::= val Pattern1 `<-' Expr [Guard] */ - def generator(eqOK: boolean): Enumerator = { + def generator(enums: ListBuffer[Enumerator], eqOK: boolean) { val pos = in.currentPos; if (in.token == VAL) in.nextToken() val pat = pattern1(false) val tok = in.token if (tok == EQUALS && eqOK) in.nextToken() else accept(LARROW) - makeGenerator(pos, pat, tok == EQUALS, expr) + enums += makeGenerator(pos, pat, tok == EQUALS, expr) + if (in.token == IF) enums += Filter(guard()) } //////// PATTERNS //////////////////////////////////////////////////////////// @@ -1972,8 +1965,8 @@ trait Parsers requires SyntaxAnalyzer { } /** ClassDef ::= Id [TypeParamClause] Annotations - [AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplate - * TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplate + [AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplateOpt + * TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplateOpt */ def classDef(mods: Modifiers): ClassDef = atPos(in.skipToken()) { @@ -1992,7 +1985,7 @@ trait Parsers requires SyntaxAnalyzer { else (accessModifierOpt(), paramClauses(name, implicitClassViews, mods.hasFlag(Flags.CASE))) val thistpe = requiresTypeOpt() val (self0, template) = - classTemplate(mods, name, constrMods withAnnotations constrAnnots, vparamss) + templateOpt(mods, name, constrMods withAnnotations constrAnnots, vparamss) val mods1 = if (mods.hasFlag(Flags.TRAIT) && (template.body forall treeInfo.isInterfaceMember)) mods | Flags.INTERFACE @@ -2003,12 +1996,12 @@ trait Parsers requires SyntaxAnalyzer { result } - /** ObjectDef ::= Id ClassTemplate + /** ObjectDef ::= Id ClassTemplateOpt */ def objectDef(mods: Modifiers): ModuleDef = atPos(in.skipToken()) { val name = ident() - val (self, template0) = classTemplate(mods, name, NoMods, List()) + val (self, template0) = templateOpt(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 @@ -2019,12 +2012,58 @@ trait Parsers requires SyntaxAnalyzer { ModuleDef(mods, name, template) } - /** ClassTemplate ::= [extends TemplateParents] [TemplateBody] - * TemplateParents ::= AnnotType {`(' [Exprs] `)'} {`with' AnnotType} - * TraitTemplate ::= [extends MixinParents] [TemplateBody] - * MixinParents ::= AnnotType {with AnnotType} + + /** ClassParents ::= AnnotType {`(' [Exprs [`,']] `)'} {with AnnotType} + * TraitParents ::= AnnotType {with AnnotType} + */ + def templateParents(isTrait: boolean): (List[Tree], List[List[Tree]]) = { + val parents = new ListBuffer[Tree] + annotType(false) + val argss = new ListBuffer[List[Tree]] + if (in.token == LPAREN && !isTrait) + do { argss += argumentExprs() } while (in.token == LPAREN) + else argss += List() + while (in.token == WITH) { + in.nextToken() + parents += annotType(false) + } + (parents.toList, argss.toList) + } + + /** ClassTemplate ::= [EarlyDefs with] ClassParents [TemplateBody] + * TraitTemplate ::= [EarlyDefs with] TraitParents [TemplateBody] + * EarlyDefs ::= `{' [EarlyDef {semi EarlyDef}] `}' + * EarlyDef ::= Annotations Modifiers PatDef */ - def classTemplate(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): (ValDef, Template) = { + def template(isTrait: boolean): (List[Tree], List[List[Tree]], ValDef, List[Tree]) = { + newLineOptWhenFollowedBy(LBRACE) + if (in.token == LBRACE) { + val (self, body) = templateBody() + if (in.token == WITH && (self eq emptyValDef)) { + val vdefs: List[ValDef] = body flatMap { + case vdef @ ValDef(mods, name, tpt, rhs) if !(mods hasFlag Flags.DEFERRED) => + List(copy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs)) + case stat => + syntaxError(stat.pos, "only concrete field definitions allowed in early object initialization section", false) + List() + } + in.nextToken() + val (parents, argss) = templateParents(isTrait) + val (self1, body1) = templateBodyOpt() + (parents, argss, self1, vdefs ::: body1) + } else { + (List(), List(List()), self, body) + } + } else { + val (parents, argss) = templateParents(isTrait) + val (self, body) = templateBodyOpt() + (parents, argss, self, body) + } + } + + /** ClassTemplateOpt ::= [extends ClassTemplate | TemplateBody] + * TraitTemplateOpt ::= [extends TraitTemplate | TemplateBody] + */ + def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]]): (ValDef, Template) = { val pos = in.currentPos; def acceptEmptyTemplateBody(msg: String): unit = { if (in.token == LPAREN && settings.migrate.value) @@ -2032,38 +2071,21 @@ trait Parsers requires SyntaxAnalyzer { 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) { + val (parents0, argss, self, body) = + if (in.token == EXTENDS) { in.nextToken() - parents += annotType(false) + template(mods hasFlag Flags.TRAIT) + } else { + newLineOptWhenFollowedBy(LBRACE) + val (self, body) = + if (in.token == LBRACE) templateBody() + else { acceptEmptyTemplateBody("`extends' or `{' expected"); (emptyValDef, List()) } + (List(), List(List()), self, body) } - } 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 - } - val ps = parents.toList - newLineOptWhenFollowedBy(LBRACE) - val (self, body) = - if (in.token == LBRACE) templateBody() - else { acceptEmptyTemplateBody("`{' expected"); (emptyValDef, List()) } - (self, atPos(pos) { Template(ps, constrMods, vparamss, argss.toList, body) }) + var parents = parents0 + if (name != nme.ScalaObject.toTypeName) parents = parents ::: List(scalaScalaObjectConstr) + if (mods.hasFlag(Flags.CASE)) parents = parents ::: List(productConstr) + (self, atPos(pos) { Template(parents, constrMods, vparamss, argss, body) }) } ////////// TEMPLATES //////////////////////////////////////////////////////////// @@ -2077,6 +2099,12 @@ trait Parsers requires SyntaxAnalyzer { if (stats.isEmpty) (self, List(EmptyTree)) else result } + def templateBodyOpt(): (ValDef, List[Tree]) = { + newLineOptWhenFollowedBy(LBRACE) + if (in.token == LBRACE) templateBody() + else (emptyValDef, List()) + } + /** Refinement ::= [nl] `{' RefineStat {semi RefineStat} `}' */ def refinement(): List[Tree] = { diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index a0fffdbbef..ae712c7deb 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -123,6 +123,10 @@ trait Definitions requires SymbolTable { typeRef(sym.typeConstructor.prefix, sym, elems) } else NoType; + var ProductRootClass: Symbol = _ + def Product_productArity = getMember(ProductRootClass, nme.productArity) + def Product_productElement = getMember(ProductRootClass, nme.productElement) + def Product_productPrefix = getMember(ProductRootClass, nme.productPrefix) val MaxProductArity = 22 /* <unapply> */ val ProductClass: Array[Symbol] = new Array(MaxProductArity + 1) @@ -791,6 +795,7 @@ trait Definitions requires SymbolTable { //UnsealedClass = getClass("scala.unsealed") //todo: remove once 2.4 is out. UncheckedClass = getClass("scala.unchecked") OptionClass = getClass("scala.Option") + ProductRootClass = getClass("scala.Product") for (val i <- 1 to MaxTupleArity) { TupleClass(i) = getClass( "scala.Tuple" + i) diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala index 2566e687b0..3e8e7792ae 100644 --- a/src/compiler/scala/tools/nsc/symtab/Flags.scala +++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala @@ -113,7 +113,7 @@ object Flags { ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC final val FieldFlags = - MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL + MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL | PRESUPER final val AccessFlags = PRIVATE | PROTECTED final val VARIANCES = COVARIANT | CONTRAVARIANT diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index fcb09f31e9..f7f7a7869d 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -1319,7 +1319,7 @@ trait Types requires SymbolTable { if(attributes.isEmpty) "" else - attributes.mkString("", " ", "") + attributes.mkString("@", " @", " ") attString + tp } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index d9355bf24e..71f9c9d828 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -120,7 +120,25 @@ abstract class Constructors extends Transform { val defBuf = new ListBuffer[Tree] val constrStatBuf = new ListBuffer[Tree] val constrPrefixBuf = new ListBuffer[Tree] - constrBody.stats foreach (constrStatBuf +=) + val presupers = treeInfo.preSuperFields(stats) + for (val stat <- constrBody.stats) { + constrStatBuf += stat + stat match { + case ValDef(mods, name, _, _) if (mods hasFlag PRESUPER) => + constrStatBuf += + localTyper.typed { + atPos(stat.pos) { + val fields = presupers filter ( + vdef => nme.localToGetter(vdef.name) == name) + assert(fields.length == 1) + Assign( + gen.mkAttributedRef(clazz.thisType, fields.head.symbol), + Ident(stat.symbol)) + } + } + case _ => + } + } for (val stat <- stats) stat match { case DefDef(mods, name, tparams, vparamss, tpt, rhs) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index eafe154756..d7554ea95d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -305,7 +305,8 @@ trait Namers requires Analyzer { case ValDef(mods, name, tp, rhs) => if (context.owner.isClass && (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL)) { val accflags = ACCESSOR | - (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE else mods.flags | STABLE) + (if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE & ~PRESUPER + else mods.flags & ~PRESUPER | STABLE) val getter = owner.newMethod(tree.pos, name).setFlag(accflags) getter.setInfo(namerOf(getter).getterTypeCompleter(tree)) setPrivateWithin(tree, getter, mods) @@ -668,7 +669,7 @@ trait Namers requires Analyzer { ErrorType } else { tpt.tpe = deconstIfNotFinal(sym, - newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType)) + newTyper(typer1.context.make(vdef, sym)).computeType(rhs, WildcardType)) tpt.tpe } } else typer1.typedType(tpt).tpe diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index b66a534c89..07b95fe0f7 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -40,16 +40,17 @@ trait SyntheticMethods requires Analyzer { */ def addSyntheticMethods(templ: Template, clazz: Symbol, unit: CompilationUnit): Template = { - def hasImplementation(name: Name): Boolean = { + def hasImplementation(name: Name): boolean = { val sym = clazz.info.nonPrivateMember(name) - (sym.isTerm && - (sym.owner == clazz || - !(ObjectClass isNonBottomSubClass sym.owner) && !(sym hasFlag DEFERRED))) + sym.isTerm && !(sym hasFlag DEFERRED) } - def hasDirectImplementation(name: Name): Boolean = { - val sym = clazz.info.nonPrivateMember(name) - (sym.isTerm && sym.owner == clazz) + def hasOverridingImplementation(meth: Symbol): boolean = { + val sym = clazz.info.nonPrivateMember(meth.name) + sym.alternatives exists { sym => + sym != meth && !(sym hasFlag DEFERRED) && + (clazz.thisType.memberType(sym) matches clazz.thisType.memberType(meth)) + } } def syntheticMethod(name: Name, flags: Int, tpe: Type) = @@ -239,22 +240,22 @@ trait SyntheticMethods requires Analyzer { if (clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod if (clazz.isModuleClass) { - if (!hasImplementation(nme.toString_)) ts += moduleToStringMethod + if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod } else { - if (!hasImplementation(nme.hashCode_)) ts += forwardingMethod(nme.hashCode_) - if (!hasImplementation(nme.toString_)) ts += forwardingMethod(nme.toString_) - if (!hasImplementation(nme.equals_)) ts += equalsMethod + if (!hasOverridingImplementation(Object_hashCode)) ts += forwardingMethod(nme.hashCode_) + if (!hasOverridingImplementation(Object_toString)) ts += forwardingMethod(nme.toString_) + if (!hasOverridingImplementation(Object_equals)) ts += equalsMethod } - if (!hasDirectImplementation(nme.productPrefix)) ts += productPrefixMethod + if (!hasOverridingImplementation(Product_productPrefix)) ts += productPrefixMethod val accessors = clazz.caseFieldAccessors if (!hasImplementation("arity")) // remove after starr update ts += OLDproductArityMethod(accessors.length) - if (!hasImplementation(nme.productArity)) + if (!hasOverridingImplementation(Product_productArity)) ts += productArityMethod(accessors.length) if (!hasImplementation("element")) // remove after starr update ts += OLDproductElementMethod(accessors) - if (!hasImplementation(nme.productElement)) + if (!hasOverridingImplementation(Product_productElement)) ts += productElementMethod(accessors) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 5d1b3e6310..cde3d11de2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -6,6 +6,8 @@ //todo: rewrite or disllow new T where T is a mixin (currently: <init> not a member of T) //todo: use inherited type info also for vars and values +//todo: disallow C#D in superclass +//todo: treat :::= correctly package scala.tools.nsc.typechecker import scala.collection.mutable.{HashMap, ListBuffer} |