summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-04-10 17:51:34 +0000
committerMartin Odersky <odersky@gmail.com>2007-04-10 17:51:34 +0000
commit28d40d21d0d29ff4c2f002090eeafd2c53817c64 (patch)
tree2db2d5a6bd0b8f611d2e73f6ba68415d155605c4 /src/compiler/scala
parente732589d1d33d298b0df6d7e8dc6caaaf446d8f8 (diff)
downloadscala-28d40d21d0d29ff4c2f002090eeafd2c53817c64.tar.gz
scala-28d40d21d0d29ff4c2f002090eeafd2c53817c64.tar.bz2
scala-28d40d21d0d29ff4c2f002090eeafd2c53817c64.zip
more changes to support early inits.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala52
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala121
3 files changed, 100 insertions, 76 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index e47183f146..66dc60fe45 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -117,28 +117,22 @@ abstract class TreeInfo {
/** Is tree a self constructor call?
*/
- def isSelfConstrCall(tree: Tree): boolean = tree match {
- case Ident(nme.CONSTRUCTOR) =>
- true
- case Select(This(_), nme.CONSTRUCTOR) =>
- true
- case TypeApply(constr, _) =>
- isSelfConstrCall(constr)
- case Apply(constr, _) =>
- isSelfConstrCall(constr)
- case _ =>
- false
+ def isSelfConstrCall(tree: Tree): boolean = methPart(tree) match {
+ case Ident(nme.CONSTRUCTOR)
+ | Select(This(_), nme.CONSTRUCTOR) => true
+ case _ => false
}
- def isSuperConstrCall(tree: Tree): boolean = tree match {
- case Select(Super(_, _), nme.CONSTRUCTOR) =>
- true
- case TypeApply(constr, _) =>
- isSuperConstrCall(constr)
- case Apply(constr, _) =>
- isSuperConstrCall(constr)
- case _ =>
- false
+ def isSuperConstrCall(tree: Tree): boolean = methPart(tree) match {
+ case Select(Super(_, _), nme.CONSTRUCTOR) => true
+ case _ => false
+ }
+
+ def isSelfOrSuperConstrCall(tree: Tree): boolean = methPart(tree) match {
+ case Ident(nme.CONSTRUCTOR)
+ | Select(This(_), nme.CONSTRUCTOR)
+ | Select(Super(_, _), nme.CONSTRUCTOR) => true
+ case _ => false
}
/** Is tree a variable pattern */
@@ -155,15 +149,9 @@ abstract class TreeInfo {
case _ :: stats1 => firstConstructor(stats1)
}
- /** The reference to super in the body of a primary constructor */
- def superRef(tree: Tree): Tree = tree match {
- case Block(stats, _) if !stats.isEmpty => superRef(stats.last)
- case Apply(sr, _) => sr
- case _ => EmptyTree
- }
-
/** The value definitions marked PRESUPER in this statement sequence */
- def preSuperFields(stats: List[Tree]) = stats filter isPreSuper
+ def preSuperFields(stats: List[Tree]): List[ValDef] =
+ for (val vdef @ ValDef(mods, _, _, _) <- stats; mods hasFlag PRESUPER) yield vdef
def isPreSuper(tree: Tree) = tree match {
case ValDef(mods, _, _, _) => mods hasFlag PRESUPER
@@ -273,6 +261,14 @@ abstract class TreeInfo {
case _ => tree
}
+ def firstArgument(tree: Tree): Tree = tree match {
+ case Apply(fn, args) =>
+ val f = firstArgument(fn)
+ if (f == EmptyTree && !args.isEmpty) args.head else f
+ case _ =>
+ EmptyTree
+ }
+
/** Top-level definition sequence contains a leading import of Predef or scala.Predef
*/
def containsLeadingPredefImport(defs: List[Tree]): boolean = defs match {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 061aab47a9..1868ab2108 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1170,7 +1170,8 @@ trait Parsers requires SyntaxAnalyzer {
/** Generator ::= val Pattern1 `<-' Expr
*/
def generator(eqOK: boolean): Enumerator = {
- val pos = accept(VAL)
+ val pos = in.currentPos;
+ if (in.token == VAL) in.nextToken()
val pat = pattern1(false)
val tok = in.token
if (tok == EQUALS && eqOK) in.nextToken()
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 60cfcac73f..326597fe99 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -125,8 +125,7 @@ trait Typers requires Analyzer {
private def funMode(mode: int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode
private def argMode(fun: Tree, mode: int) =
- if (treeInfo.isSelfConstrCall(fun) || treeInfo.isSuperConstrCall(fun)) mode | SCCmode
- else mode
+ if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
private var xxx = 10;
class Typer(context0: Context) {
@@ -566,7 +565,7 @@ trait Typers requires Analyzer {
inferExprInstance(tree, tparams, pt)
adapt(tree, mode, pt)
} else {
- val typer1 = constrTyperIf(treeInfo.isSelfConstrCall(tree) || treeInfo.isSuperConstrCall(tree))
+ val typer1 = constrTyperIf(treeInfo.isSelfOrSuperConstrCall(tree))
typer1.typed(typer1.applyImplicitArgs(tree), mode, pt)
}
case mt: MethodType
@@ -738,19 +737,18 @@ trait Typers requires Analyzer {
if (member(qual, name) != NoSymbol) qual
else adaptToMember(qual, name, WildcardType)
- private def completeParentType(tpt: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]], superargs: List[Tree]): Type = {
+ private def typePrimaryConstrBody(cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
enclTparams foreach context.scope.enter
namer.enterValueParams(context.owner, vparamss)
- val newTree = New(tpt)
- .setType(PolyType(tparams, appliedType(tpt.tpe, tparams map (.tpe))))
- val tree = typed(atPos(tpt.pos)(Apply(Select(newTree, nme.CONSTRUCTOR), superargs)))
- if (settings.debug.value) log("superconstr "+tree+" co = "+context.owner);//debug
- tree.tpe
+ typed(cbody)
}
- def parentTypes(templ: Template): List[Tree] = try {
+ def parentTypes(templ: Template): List[Tree] =
if (templ.parents.isEmpty) List()
- else {
+ else try {
+ val clazz = context.owner
+
+ // Normalize supertype and mixins so that supertype is always a class, not a trait.
var supertpt = typedTypeConstructor(templ.parents.head)
val firstParent = supertpt.tpe.symbol
var mixins = templ.parents.tail map typedType
@@ -762,43 +760,71 @@ trait Typers requires Analyzer {
supertpt = TypeTree(supertpt1.tpe.parents.head) setOriginal supertpt /* setPos supertpt.pos */
}
}
- val constr = treeInfo.firstConstructor(templ.body)
- if (supertpt.tpe.symbol != firstParent) {
- constr match {
- case DefDef(_, _, _, _, _, Block(List(Apply(_, superargs)), _)) =>
- if (!superargs.isEmpty)
- error(superargs.head.pos, firstParent+" is a trait; does not take constructor arguments")
- case _ =>
- }
+
+ // Determine
+ // - supertparams: Missing type parameters from supertype
+ // - supertpe: Given supertype, polymorphic in supertparams
+ val supertparams = if (supertpt.hasSymbol) supertpt.symbol.typeParams else List()
+ var supertpe = supertpt.tpe
+ if (!supertparams.isEmpty)
+ supertpe = PolyType(supertparams, appliedType(supertpe, supertparams map (.tpe)))
+
+ // A method to replace a super reference by a New in a supercall
+ def transformSuperCall(scall: Tree): Tree = (scall: @unchecked) match {
+ case Apply(fn, args) =>
+ copy.Apply(scall, transformSuperCall(fn), args)
+ case Select(Super(_, _), nme.CONSTRUCTOR) =>
+ copy.Select(
+ scall,
+ New(TypeTree(supertpe) setOriginal supertpt) setType supertpe setPos supertpt.pos,
+ nme.CONSTRUCTOR)
}
- if (supertpt.hasSymbol) {
- val tparams = supertpt.symbol.typeParams
- if (!tparams.isEmpty) {
- constr match {
- case EmptyTree =>
- error(supertpt.pos, "missing type arguments")
- case DefDef(_, _, _, vparamss, _, Block(List(Apply(_, superargs)), _)) =>
- val outercontext = context.outer
- supertpt = TypeTree(
- newTyper(makeNewScope(outercontext, constr, outercontext.owner))
- .completeParentType(
- supertpt,
- tparams,
- context.owner.unsafeTypeParams,
- vparamss map (.map(.duplicate)),
- superargs map (.duplicate))) setOriginal supertpt /* setPos supertpt.pos */
+
+ treeInfo.firstConstructor(templ.body) match {
+ case constr @ DefDef(_, _, _, vparamss, _, cbody @ Block(cstats, cunit)) =>
+ // Convert constructor body to block in environment and typecheck it
+ val cstats1: List[Tree] = cstats map (.duplicate)
+ val scall = if (cstats.isEmpty) EmptyTree else cstats.last
+ val cbody1 = scall match {
+ case Apply(_, _) =>
+ copy.Block(cbody, cstats1.init,
+ if (supertparams.isEmpty) cunit.duplicate
+ else transformSuperCall(scall))
+ case _ =>
+ copy.Block(cbody, cstats1, cunit.duplicate)
}
- }
+
+ val outercontext = context.outer
+ val cbody2 =
+ newTyper(makeNewScope(outercontext, constr, outercontext.owner))
+ .typePrimaryConstrBody(
+ cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (.map(.duplicate)))
+
+ scall match {
+ case Apply(_, _) =>
+ val sarg = treeInfo.firstArgument(scall)
+ if (sarg != EmptyTree && supertpe.symbol != firstParent)
+ error(sarg.pos, firstParent+" is a trait; does not take constructor arguments")
+ if (!supertparams.isEmpty) supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos
+ case _ =>
+ if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
+ }
+
+ List.map2(cstats1, treeInfo.preSuperFields(templ.body)) {
+ (ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe
+ }
+ case _ =>
+ if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
}
- //Console.println("parents("+context.owner+") = "+supertpt :: mixins);//DEBUG
- List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(context.owner, tpt))
+
+ //Console.println("parents("+clazz") = "+supertpt :: mixins);//DEBUG
+ List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(clazz, tpt))
+ } catch {
+ case ex: TypeError =>
+ templ.tpe = null
+ reportTypeError(templ.pos, ex)
+ List(TypeTree(AnyRefClass.tpe))
}
- } catch {
- case ex: TypeError =>
- templ.tpe = null
- reportTypeError(templ.pos, ex)
- List(TypeTree(AnyRefClass.tpe))
- }
/** <p>Check that</p>
* <ul>
@@ -1339,10 +1365,11 @@ trait Typers requires Analyzer {
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
val result = checkDead(localTyper.typed(stat))
- if (treeInfo.isSelfConstrCall(stat) || treeInfo.isSuperConstrCall(stat))
+ if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
- if (treeInfo.isSelfConstrCall(result) && result.symbol.pos >= exprOwner.enclMethod.pos)
- error(stat.pos, "called constructor's definition must precede calling constructor's definition")
+ if (treeInfo.isSelfConstrCall(result) && result.symbol.pos >= exprOwner.enclMethod.pos)
+ error(stat.pos, "called constructor's definition must precede calling constructor's definition")
+ }
result
}
}