summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-12-12 11:27:07 +0000
committerMartin Odersky <odersky@gmail.com>2006-12-12 11:27:07 +0000
commit8de712dd91a63ae056628c459035a458b315503e (patch)
treee36e5a3ea3c4eb3ef9bc609b52caec506f021150 /src/compiler
parent9551ed8f5854ddad14a759ae7c5268b2883155b8 (diff)
downloadscala-8de712dd91a63ae056628c459035a458b315503e.tar.gz
scala-8de712dd91a63ae056628c459035a458b315503e.tar.bz2
scala-8de712dd91a63ae056628c459035a458b315503e.zip
1. allow trailing commas in tuples; fix of bug 857
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala42
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala19
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala2
5 files changed, 43 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 4e1d73b53f..4b85bd2b6d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -575,7 +575,7 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
*/
def xScalaPatterns: List[Tree] = {
sync;
- val b = p.patterns(true);
+ val b = p.patterns(true, false);
if (/*s.*/token != RBRACE) {
reportSyntaxError(" expected end of Scala patterns");
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 9fd03dedc0..70bc199c31 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -615,13 +615,13 @@ trait Parsers requires SyntaxAnalyzer {
* | StableId
* | Path `.' type
* | `(' Type `)'
- * | `{' [Type `,' Types] `}'
+ * | `{' [Type `,' [Types [`,']]] `}'
* | AttributeClauses SimpleType // if Xplugtypes enabled
* SimpleTypePattern ::= SimpleTypePattern1 [TypePatternArgs]
* SimpleTypePattern1 ::= SimpleTypePattern1 "#" Id
* | StableId
* | Path `.' type
- * | `{' [ArgTypePattern `,' ArgTypePatterns] `}'
+ * | `{' [ArgTypePattern `,' [ArgTypePatterns [`,']]] `}'
*/
def simpleType(isPattern: boolean): Tree = {
if(settings.Xplugtypes.value)
@@ -640,11 +640,11 @@ trait Parsers requires SyntaxAnalyzer {
else {
val t1 = argType(isPattern)
accept(COMMA)
- t1 :: argTypes(isPattern)
+ t1 :: (if (in.token == RBRACE) List() else argTypes(isPattern, true))
}
checkSize("tuple elements", ts.length, definitions.MaxTupleArity)
accept(RBRACE)
- makeTupleType(ts)
+ makeTupleType(ts, false)
} else {
val r = path(false, true)
val x = r match {
@@ -673,7 +673,7 @@ trait Parsers requires SyntaxAnalyzer {
*/
def typeArgs(isPattern: boolean): List[Tree] = {
accept(LBRACKET)
- val ts = argTypes(isPattern)
+ val ts = argTypes(isPattern, false)
accept(RBRACKET)
ts
}
@@ -681,11 +681,12 @@ trait Parsers requires SyntaxAnalyzer {
/** ArgTypes ::= ArgType {`,' ArgType}
* ArgTypePatterns ::= ArgTypePattern {`,' ArgTypePattern}
*/
- def argTypes(isPattern: boolean): List[Tree] = {
+ def argTypes(isPattern: boolean, trailingComma: boolean): List[Tree] = {
val ts = new ListBuffer[Tree] + argType(isPattern)
while (in.token == COMMA) {
in.nextToken()
- ts += argType(isPattern)
+ if (!trailingComma || in.token != RBRACE)
+ ts += argType(isPattern)
}
ts.toList
}
@@ -1098,7 +1099,7 @@ trait Parsers requires SyntaxAnalyzer {
}
/** Block ::= BlockStatSeq
- * Tuple ::= [Expr1 {`,' Expr1}]
+ * Tuple ::= [Expr1 `,' {Expr1 `,'} [Expr1]]
*/
def block(): Tree = blockOrTuple(false)
def blockOrTuple(tupleOK: boolean): Tree =
@@ -1153,11 +1154,12 @@ trait Parsers requires SyntaxAnalyzer {
/** Patterns ::= Pattern { `,' Pattern } */
/** SeqPatterns ::= SeqPattern { `,' SeqPattern } */
- def patterns(seqOK: boolean): List[Tree] = {
+ def patterns(seqOK: boolean, trailingComma: boolean): List[Tree] = {
val ts = new ListBuffer[Tree]
ts += pattern(seqOK)
while (in.token == COMMA) {
- in.nextToken(); ts += pattern(seqOK)
+ in.nextToken();
+ if (!trailingComma || in.token != RBRACE) ts += pattern(seqOK)
}
ts.toList
}
@@ -1255,13 +1257,13 @@ trait Parsers requires SyntaxAnalyzer {
* | XmlPattern
* | StableId [ `(' SeqPatterns `)' ]
* | `(' [Pattern] `)'
- * | `{' [Pattern `,' Patterns] `}'
+ * | `{' [Pattern `,' [Patterns [`,']]] `}'
* SimpleSeqPattern ::= varid
* | `_'
* | literal
* | `<' xLiteralPattern
* | StableId [TypePatternArgs] `(' SeqPatterns `)' ]
- * | `{' [Pattern `,' Patterns] `}'
+ * | `{' [Pattern `,' [Patterns [`,']]] `}'
* | `(' SeqPatterns `)'
*/
def simplePattern(seqOK: boolean): Tree = in.token match {
@@ -1281,14 +1283,14 @@ trait Parsers requires SyntaxAnalyzer {
atPos(in.currentPos) {
val ts = typeArgs(true)
accept(LPAREN)
- val ps = if (in.token == RPAREN) List() else patterns(true)
+ val ps = if (in.token == RPAREN) List() else patterns(true, false)
accept(RPAREN)
Apply(TypeApply(convertToTypeId(t), ts), ps)
}
else */
if (in.token == LPAREN) {
atPos(in.skipToken()) {
- val ps = if (in.token == RPAREN) List() else patterns(true)
+ val ps = if (in.token == RPAREN) List() else patterns(true, false)
accept(RPAREN)
Apply(convertToTypeId(t), ps)
}
@@ -1298,11 +1300,11 @@ trait Parsers requires SyntaxAnalyzer {
else {
val p1 = pattern()
accept(COMMA)
- p1 :: patterns(false)
+ p1 :: (if (in.token == RBRACE) List() else patterns(false, true))
}
checkSize("tuple elements", ts.length, definitions.MaxTupleArity)
accept(RBRACE)
- makeTupleTerm(ts)
+ makeTupleTerm(ts, false)
} else t
case USCORE =>
atPos(in.skipToken()) { Ident(nme.WILDCARD) }
@@ -1311,7 +1313,7 @@ trait Parsers requires SyntaxAnalyzer {
case LPAREN =>
val pos = in.skipToken()
val p =
- //if (false /*disabled, no regexp matching*/ && seqOK) atPos(pos) { makeSequence(patterns(true)) }
+ //if (false /*disabled, no regexp matching*/ && seqOK) atPos(pos) { makeSequence(patterns(true, false)) }
//else
if (in.token != RPAREN) pattern(false)
else Literal(()).setPos(pos)
@@ -2103,7 +2105,7 @@ trait Parsers requires SyntaxAnalyzer {
* | LocalModifiers TmplDef
* | Expr1
* |
- * TupleExprs ::= ResultExpr "," ResultExprs
+ * Tuple ::= [Expr1 `,' {Expr1 `,'} [Expr1]]
*/
def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] =
blockStatSeqOrTuple(false, stats)
@@ -2129,14 +2131,14 @@ trait Parsers requires SyntaxAnalyzer {
val exprs = new ListBuffer[Tree] + expr
while (in.token == COMMA) {
in.nextToken()
- exprs += expr1()
+ if (in.token != RBRACE) exprs += expr1()
}
if (in.token == ARROW) {
val vdefs = exprs.toList flatMap convertToParams
checkSize("function arguments", vdefs.length, definitions.MaxFunctionArity)
stats += atPos(in.skipToken()) { Function(vdefs, block()) }
} else {
- stats += makeTupleTerm(exprs.toList)
+ stats += makeTupleTerm(exprs.toList, false)
}
} else stats += expr
if (in.token != RBRACE && in.token != CASE) acceptStatSep()
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 4060d8f619..0aec97dcdd 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -94,15 +94,15 @@ abstract class TreeBuilder {
Apply(scalaDot(if (isType) newTypeName(tupString) else newTermName(tupString)), trees)
}
- def makeTupleTerm(trees: List[Tree]): Tree = trees match {
+ def makeTupleTerm(trees: List[Tree], flattenUnary: boolean): Tree = trees match {
case List() => Literal(())
- case List(tree) => tree
+ case List(tree) if flattenUnary => tree
case _ => makeTuple(trees, false)
}
- def makeTupleType(trees: List[Tree]): Tree = trees match {
+ def makeTupleType(trees: List[Tree], flattenUnary: boolean): Tree = trees match {
case List() => scalaUnitConstr
- case List(tree) => tree
+ case List(tree) if flattenUnary => tree
case _ => AppliedTypeTree(scalaDot(newTypeName("Tuple" + trees.length)), trees)
}
@@ -300,7 +300,7 @@ abstract class TreeBuilder {
val ids = (patX1 :: defpats) map makeValue
val rhs1 = makeForYield(
List(ValFrom(pos, patX1, rhs)),
- Block(pdefs, makeTupleTerm(ids)))
+ Block(pdefs, makeTupleTerm(ids, true)))
makeFor(mapName, flatMapName, ValFrom(pos, makeTuple(pat :: pats, true), rhs1) :: rest1, body)
case _ =>
EmptyTree //may happen for erroneous input
@@ -391,7 +391,7 @@ abstract class TreeBuilder {
val pat1 = patvarTransformer.transform(pat)
val vars = getVariables(pat1)
val matchExpr = atPos(pat1.pos){
- Match(rhs, List(CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (._1) map Ident))))
+ Match(rhs, List(CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (._1) map Ident, true))))
}
vars match {
case List() =>
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 6a4b598827..5b264a33e8 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -31,6 +31,11 @@ abstract class AddInterfaces extends InfoTransform {
*/
def erasedTypeRef(sym: Symbol): Type
+ /** Erasure type-map; to be defined in subclass
+ * <code>Erasure</code>.
+ */
+ def erasure: TypeMap
+
/** A lazily constructed map that associates every non-interface trait with
* its implementation class.
*/
@@ -169,12 +174,14 @@ abstract class AddInterfaces extends InfoTransform {
* @param tp ...
* @return ...
*/
- private def mixinToImplClass(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) if (sym.needsImplClass) =>
- typeRef(pre, implClass(sym), args)
- case _ =>
- tp
- }
+ private def mixinToImplClass(tp: Type): Type =
+ erasure(
+ tp match {
+ case TypeRef(pre, sym, args) if (sym.needsImplClass) =>
+ typeRef(pre, implClass(sym), args)
+ case _ =>
+ tp
+ })
def transformMixinInfo(tp: Type): Type = tp match {
case ClassInfoType(parents, decls, clazz) =>
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 17b3798e34..fc4e9a1769 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -57,7 +57,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
* </li>
* </ul>
*/
- private val erasure = new TypeMap {
+ val erasure = new TypeMap {
def apply(tp: Type): Type = tp match {
case ConstantType(_) =>
tp