summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@epfl.ch>2009-06-25 11:38:05 +0000
committerLukas Rytz <lukas.rytz@epfl.ch>2009-06-25 11:38:05 +0000
commitae85676cb414628f4bcc2a302e7de8dd031b75e8 (patch)
tree1bfb20c27955f81873f0e5c18ab6c0c2975c5f70 /src
parent6c0ba3ee65cb5669efd2cdde7ea5cc1b6d59adc7 (diff)
downloadscala-ae85676cb414628f4bcc2a302e7de8dd031b75e8.tar.gz
scala-ae85676cb414628f4bcc2a302e7de8dd031b75e8.tar.bz2
scala-ae85676cb414628f4bcc2a302e7de8dd031b75e8.zip
named arguments only at top level in () paramet...
named arguments only at top level in () parameters.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala12
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Parsers.scala63
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala38
5 files changed, 65 insertions, 64 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 1b8777a642..6741a8bea5 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -690,7 +690,17 @@ trait Trees {
/** Assignment */
case class Assign(lhs: Tree, rhs: Tree)
- extends TermTree
+ extends TermTree {
+ def namedArg = false
+ }
+
+ /** Either an assignment or a named argument. Only appears in argument lists,
+ * eliminated by typecheck.
+ */
+ class AssignOrNamedArg(lhs: Tree, rhs: Tree)
+ extends Assign(lhs, rhs) {
+ override def namedArg = true
+ }
/** Conditional expression */
case class If(cond: Tree, thenp: Tree, elsep: Tree)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 442b9f5d5b..9d6a8af329 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -689,14 +689,8 @@ self =>
/** Types ::= Type {`,' Type}
*/
- def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] = {
- val ts = new ListBuffer[Tree] += argType(isPattern, isTypeApply, isFuncArg)
- while (in.token == COMMA) {
- in.nextToken()
- ts += argType(isPattern, isTypeApply, isFuncArg)
- }
- ts.toList
- }
+ def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] =
+ exprs(() => argType(isPattern, isTypeApply, isFuncArg))
/** Type ::= InfixType `=>' Type
* | `(' [`=>' Type] `)' `=>' Type
@@ -817,7 +811,7 @@ self =>
* | SimpleType `#' Id
* | StableId
* | Path `.' type
- * | `(' Types [`,'] `)'
+ * | `(' Types `)'
* | WildcardType
*/
def simpleType(isPattern: Boolean): Tree = {
@@ -914,11 +908,11 @@ self =>
/** Exprs ::= Expr {`,' Expr}
*/
- def exprs(): List[Tree] = {
- val ts = new ListBuffer[Tree] += expr()
+ def exprs(part: () => Tree = expr _): List[Tree] = {
+ val ts = new ListBuffer[Tree] += part()
while (in.token == COMMA) {
in.nextToken()
- ts += expr()
+ ts += part()
}
ts.toList
}
@@ -1155,7 +1149,7 @@ self =>
* SimpleExpr1 ::= literal
* | xLiteral
* | Path
- * | `(' [Exprs [`,']] `)'
+ * | `(' [Exprs] `)'
* | SimpleExpr `.' Id
* | SimpleExpr TypeArgs
* | SimpleExpr1 ArgumentExprs
@@ -1239,10 +1233,19 @@ self =>
}
}
- /** ArgumentExprs ::= `(' [Exprs [`,']] `)'
+ /** ArgumentExprs ::= `(' [Exprs] `)'
* | [nl] BlockExpr
*/
def argumentExprs(): List[Tree] = {
+ def args(): List[Tree] = exprs(() => {
+ val maybeNamed = isIdent
+ expr() match {
+ case a @ Assign(id, rhs) if maybeNamed =>
+ atPos(a.pos) { new AssignOrNamedArg(id, rhs) }
+ case e => e
+ }
+ })
+
// if arg has the form "x$1 => a = x$1" it's treated as "a = x$1" with x$1
// in placeholderParams. This allows e.g. "val f: Int => Int = foo(a = 1, b = _)"
def convertArg(arg: Tree): Tree = arg match {
@@ -1252,7 +1255,7 @@ self =>
rhs match {
case Ident(`pname1`) | Typed(Ident(`pname1`), _) =>
placeholderParams = vd :: placeholderParams
- atPos(arg.pos) { Assign(Ident(aname), Ident(pname1)) }
+ atPos(arg.pos) { new AssignOrNamedArg(Ident(aname), Ident(pname1)) }
case _ => arg
}
case _ => arg
@@ -1261,7 +1264,7 @@ self =>
if (in.token == LBRACE)
List(blockExpr())
else
- surround(LPAREN, RPAREN)(if (in.token == RPAREN) List() else (exprs() map convertArg), List())
+ surround(LPAREN, RPAREN)(if (in.token == RPAREN) List() else (args() map convertArg), List())
}
/** BlockExpr ::= `{' (CaseClauses | Block) `}'
@@ -1354,17 +1357,9 @@ self =>
/** Patterns ::= Pattern { `,' Pattern }
* SeqPatterns ::= SeqPattern { `,' SeqPattern }
- *
- * (also eats trailing comma if it finds one)
*/
- def patterns(seqOK: Boolean): List[Tree] = {
- val ts = new ListBuffer[Tree] += pattern(seqOK)
- while (in.token == COMMA) {
- in.nextToken()
- ts += pattern(seqOK)
- }
- ts.toList
- }
+ def patterns(seqOK: Boolean): List[Tree] =
+ exprs(() => pattern(seqOK))
/** Pattern ::= Pattern1 { `|' Pattern1 }
* SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }
@@ -1453,15 +1448,15 @@ self =>
* | `_'
* | literal
* | XmlPattern
- * | StableId [TypeArgs] [`(' [SeqPatterns [`,']] `)']
- * | `(' [Patterns [`,']] `)'
+ * | StableId [TypeArgs] [`(' [SeqPatterns] `)']
+ * | `(' [Patterns] `)'
* SimpleSeqPattern ::= varid
* | `_'
* | literal
* | XmlPattern
* | `<' xLiteralPattern
- * | StableId [TypeArgs] [`(' [SeqPatterns [`,']] `)']
- * | `(' [SeqPatterns [`,']] `)'
+ * | StableId [TypeArgs] [`(' [SeqPatterns] `)']
+ * | `(' [SeqPatterns] `)'
*
* XXX: Hook for IDE
*/
@@ -1833,11 +1828,7 @@ self =>
*/
def importClause(): List[Tree] = {
accept(IMPORT)
- val ts = new ListBuffer[Tree] += importExpr()
- while (in.token == COMMA) {
- in.nextToken(); ts += importExpr()
- }
- ts.toList
+ exprs(() => importExpr())
}
/** ImportExpr ::= StableId `.' (Id | `_' | ImportSelectors)
@@ -2208,7 +2199,7 @@ self =>
}
}
- /** ClassParents ::= AnnotType {`(' [Exprs [`,']] `)'} {with AnnotType}
+ /** ClassParents ::= AnnotType {`(' [Exprs] `)'} {with AnnotType}
* TraitParents ::= AnnotType {with AnnotType}
*/
def templateParents(isTrait: Boolean): (List[Tree], List[List[Tree]]) = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index d922d23f94..ba0a36cadf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -823,6 +823,8 @@ trait Infer {
sym2 == NoSymbol || isProperSubClassOrObject(sym1.owner, sym2.owner)
def isStrictlyMoreSpecific(ftpe1: Type, ftpe2: Type, sym1: Symbol, sym2: Symbol): Boolean =
+ // ftpe1 / ftpe2 are OverloadedTypes (possibly with one single alternative) if they
+ // denote the type of an "apply" member method (see "followApply")
ftpe1.isError || {
val specificCount = (if (isAsSpecific(ftpe1, ftpe2)) 1 else 0) -
(if (isAsSpecific(ftpe2, ftpe1) &&
@@ -1536,7 +1538,6 @@ trait Infer {
// (tupling would work)
})
-
def improves(sym1: Symbol, sym2: Symbol) =
sym2 == NoSymbol || sym2.isError ||
isStrictlyMoreSpecific(followApply(pre.memberType(sym1)),
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 20cf790ca8..f8dd35cfdd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -23,7 +23,7 @@ trait NamesDefaults { self: Analyzer =>
val noApplyInfo = NamedApplyInfo(None, Nil, Nil, null)
def nameOf(arg: Tree) = arg match {
- case Assign(Ident(name), rhs) => Some(name)
+ case a @ Assign(Ident(name), rhs) if a.namedArg => Some(name)
case _ => None
}
def isNamed(arg: Tree) = nameOf(arg).isDefined
@@ -327,7 +327,7 @@ trait NamesDefaults { self: Analyzer =>
val default2 = (default1 /: previousArgss)((tree, args) =>
Apply(tree, args.map(_.duplicate)).setPos(pos))
if (positional) default2
- else Assign(Ident(p.name), default2)
+ else atPos(pos) { new AssignOrNamedArg(Ident(p.name), default2) }
})
(givenArgs ::: defaultArgs, Nil)
} else (givenArgs, missing filter (! _.hasFlag(DEFAULTPARAM)))
@@ -348,14 +348,14 @@ trait NamesDefaults { self: Analyzer =>
val argPos = (new Array[Int](args.length)) map (x => -1)
var positionalAllowed = true
val namelessArgs = for ((arg, index) <- (args.zipWithIndex)) yield arg match {
- case Assign(Ident(name), rhs) =>
+ case a @ Assign(Ident(name), rhs) if a.namedArg =>
val pos = params.indexWhere(p => p.name == name && !p.hasFlag(SYNTHETIC))
if (pos == -1) {
if (positionalAllowed) {
argPos(index) = index
// prevent isNamed from being true when calling doTypedApply recursively,
// treat the arg as an assignment of type Unit
- Block(List(), arg)
+ Assign(a.lhs, rhs).setPos(arg.pos)
} else {
errorTree(arg, "unknown parameter name: "+ name)
}
@@ -377,10 +377,7 @@ trait NamesDefaults { self: Analyzer =>
case _: TypeError =>
positionalAllowed = false
argPos(index) = pos
- // if `rhs' has the form `x = ...`, wrap it into a block, prevent
- // treating it as named argument again.
- if (isNamed(rhs)) Block(List(), rhs)
- else rhs
+ rhs
case t: Tree =>
errorTree(arg, "reference to "+ name +" is ambiguous; it is both, a parameter\n"+
"name of the method and the name of a variable currently in scope.")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d82c995e05..d91f680123 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -182,10 +182,11 @@ trait Typers { self: Analyzer =>
case (arg, param) =>
if (arg != SearchFailure) {
if (positional) List(arg.tree)
- else List(atPos(arg.tree.pos)(Assign(Ident(param.name), (arg.tree))))
+ else List(atPos(arg.tree.pos)(new AssignOrNamedArg(Ident(param.name), (arg.tree))))
} else {
if (!param.hasFlag(DEFAULTPARAM))
- context.error(fun.pos, "could not find implicit value for parameter "+ param.name +":"+ param.tpe +".")
+ context.error(fun.pos, "could not find implicit value for parameter "+
+ param.name +":"+ param.tpe +".")
positional = false
Nil
}
@@ -1526,8 +1527,11 @@ trait Typers { self: Analyzer =>
}
}
- if (meth.paramss.exists(_.exists(_.tpe.typeSymbol == RepeatedParamClass)))
- error(meth.pos, "methods with `*'-parameters are not allowed to have default arguments")
+ if (meth.paramss.exists( ps => {
+ ps.exists(_.hasFlag(DEFAULTPARAM)) &&
+ (ps.last.tpe.typeSymbol == RepeatedParamClass)
+ }))
+ error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments")
}
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
@@ -1912,16 +1916,13 @@ trait Typers { self: Analyzer =>
if (fun.hasSymbol && (fun.symbol hasFlag OVERLOADED)) {
// remove alternatives with wrong number of parameters without looking at types.
// less expensive than including them in inferMethodAlternatvie (see below).
- def shapeType(arg: Tree): Type = {
- def shape(arg1: Tree, toplevel: Boolean): Type = arg1 match {
- case Function(vparams, body) =>
- functionType(vparams map (vparam => AnyClass.tpe), shape(body, false))
- case Assign(Ident(name), rhs) if toplevel =>
- NamedType(name, shape(rhs, false))
- case _ =>
- NothingClass.tpe
- }
- shape(arg, true)
+ def shapeType(arg: Tree): Type = arg match {
+ case Function(vparams, body) =>
+ functionType(vparams map (vparam => AnyClass.tpe), shapeType(body))
+ case a @ Assign(Ident(name), rhs) if a.namedArg =>
+ NamedType(name, shapeType(rhs))
+ case _ =>
+ NothingClass.tpe
}
val argtypes = args map shapeType
val pre = fun.symbol.tpe.prefix
@@ -1949,11 +1950,12 @@ trait Typers { self: Analyzer =>
val argtpes = new ListBuffer[Type]
val amode = argMode(fun, mode)
val args1 = args map {
- case Assign(Ident(name), rhs) =>
+ case arg @ Assign(Ident(name), rhs) if arg.namedArg =>
// named args: only type the righthand sides ("unknown identifier" errors otherwise)
val rhs1 = typedArg(rhs, amode, 0, WildcardType)
argtpes += NamedType(name, rhs1.tpe.deconst)
- Assign(Ident(name), rhs1) // untyped; that's ok because we call doTypedApply
+ // the assign is untyped; that's ok because we call doTypedApply
+ atPos(arg.pos) { new AssignOrNamedArg(arg.lhs , rhs1) }
case arg =>
val arg1 = typedArg(arg, amode, 0, WildcardType)
argtpes += arg1.tpe.deconst
@@ -2348,7 +2350,7 @@ trait Typers { self: Analyzer =>
} else {
val args =
if (argss.head.length == 1 && !isNamed(argss.head.head))
- List(Assign(Ident(nme.value), argss.head.head))
+ List(new AssignOrNamedArg(Ident(nme.value), argss.head.head))
else argss.head
val annScope = annType.decls
.filter(sym => sym.isMethod && !sym.isConstructor && sym.hasFlag(JAVA))
@@ -2356,7 +2358,7 @@ trait Typers { self: Analyzer =>
names ++= (if (isJava) annScope.iterator
else typedFun.tpe.params.iterator)
val nvPairs = args map {
- case arg @ Assign(Ident(name), rhs) =>
+ case arg @ Assign(Ident(name), rhs) if arg.namedArg =>
val sym = if (isJava) annScope.lookupWithContext(name)(context.owner)
else typedFun.tpe.params.find(p => p.name == name).getOrElse(NoSymbol)
if (sym == NoSymbol) {