aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/parsing/Parsers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-03-01 13:17:05 +0100
committerMartin Odersky <odersky@gmail.com>2014-03-01 13:41:00 +0100
commitd8356b6dc9221bfc38b1f167e5cfafcc9261f3d7 (patch)
tree3bb6fda0feb33680f68f61908a7076162159701e /src/dotty/tools/dotc/parsing/Parsers.scala
parent5a8f4c822be82e23a0c230071673425423664442 (diff)
downloaddotty-d8356b6dc9221bfc38b1f167e5cfafcc9261f3d7.tar.gz
dotty-d8356b6dc9221bfc38b1f167e5cfafcc9261f3d7.tar.bz2
dotty-d8356b6dc9221bfc38b1f167e5cfafcc9261f3d7.zip
Reorganization of template parents.
Template parents always were constructor calls before. This is not correct because in a situation like the one elaborated in templateParents, the trait D has the class C as supertype, but it does not call its constructor (in fact, if we added a () parameter list to make it into a constructor this would be wrong because C takes parameters. Now parents can be either types or constructor calls. The logic in Namer and Typer that deals with parents is cleaned up. In particular, we now construct any synthetic class parent as a full type, before calling normalizeToClassRefs. This obviates the forwardRefs logic that needed to be done in a cleanup of Namers. Also added two more checks: (1) All parents except the first one must point to traits. (2) A trait may not call a parent class constructor.
Diffstat (limited to 'src/dotty/tools/dotc/parsing/Parsers.scala')
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala39
1 files changed, 20 insertions, 19 deletions
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index ceb4ebe42..37a0a3ce1 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -1050,9 +1050,12 @@ object Parsers {
case NEW =>
canApply = false
val start = in.skipToken()
- templateOrNew(emptyConstructor()) match {
- case impl: Template => atPos(start) { New(impl) }
- case nu => adjustStart(start) { nu }
+ val (impl, missingBody) = template(emptyConstructor())
+ impl.parents match {
+ case parent :: Nil if missingBody =>
+ if (parent.isType) ensureApplied(wrapNew(parent)) else parent
+ case _ =>
+ New(impl)
}
case _ =>
if (isLiteral) literal()
@@ -1825,38 +1828,36 @@ object Parsers {
/** ConstrApp ::= SimpleType {ParArgumentExprs}
*/
- val constrApp = () =>
- ensureApplied(parArgumentExprss(wrapNew(simpleType())))
+ val constrApp = () => {
+ val t = simpleType()
+ if (in.token == LPAREN) parArgumentExprss(wrapNew(t))
+ else t
+ }
/** Template ::= ConstrApps [TemplateBody] | TemplateBody
* ConstrApps ::= ConstrApp {`with' ConstrApp}
+ *
+ * @return a pair consisting of the template, and a boolean which indicates
+ * whether the template misses a body (i.e. no {...} part).
*/
- def template(constr: DefDef): Template = templateOrNew(constr) match {
- case impl: Template => impl
- case parent => Template(constr, parent :: Nil, EmptyValDef, Nil)
- }
-
- /** Same as template, but if {...} is missing and there's only one
- * parent return the parent instead of a template. Called from New.
- */
- def templateOrNew(constr: DefDef): Tree = {
+ def template(constr: DefDef): (Template, Boolean) = {
newLineOptWhenFollowedBy(LBRACE)
- if (in.token == LBRACE) templateBodyOpt(constr, Nil)
+ if (in.token == LBRACE) (templateBodyOpt(constr, Nil), false)
else {
val parents = tokenSeparated(WITH, constrApp)
newLineOptWhenFollowedBy(LBRACE)
- if (in.token != LBRACE && parents.length == 1) parents.head
- else templateBodyOpt(constr, parents)
+ val missingBody = in.token != LBRACE
+ (templateBodyOpt(constr, parents), missingBody)
}
}
/** TemplateOpt = [`extends' Template | TemplateBody]
*/
def templateOpt(constr: DefDef): Template =
- if (in.token == EXTENDS) { in.nextToken(); template(constr) }
+ if (in.token == EXTENDS) { in.nextToken(); template(constr)._1 }
else {
newLineOptWhenFollowedBy(LBRACE)
- if (in.token == LBRACE) template(constr)
+ if (in.token == LBRACE) template(constr)._1
else Template(constr, Nil, EmptyValDef, Nil).withPos(constr.pos.toSynthetic)
}