From 8de712dd91a63ae056628c459035a458b315503e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 12 Dec 2006 11:27:07 +0000 Subject: 1. allow trailing commas in tuples; fix of bug 857 --- .../scala/tools/nsc/ast/parser/MarkupParsers.scala | 2 +- .../scala/tools/nsc/ast/parser/Parsers.scala | 42 +++++++++++----------- .../scala/tools/nsc/ast/parser/TreeBuilder.scala | 12 +++---- .../scala/tools/nsc/transform/AddInterfaces.scala | 19 ++++++---- .../scala/tools/nsc/transform/Erasure.scala | 2 +- 5 files changed, 43 insertions(+), 34 deletions(-) (limited to 'src') 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 + * Erasure. + */ + 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 { * * */ - private val erasure = new TypeMap { + val erasure = new TypeMap { def apply(tp: Type): Type = tp match { case ConstantType(_) => tp -- cgit v1.2.3