From 979180ca5f30752d94d64b083b6dbca57dab0c4b Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 Feb 2007 13:37:19 +0000 Subject: more changes to make tuples (...) --- src/compiler/scala/tools/nsc/ast/TreeGen.scala | 4 +- .../scala/tools/nsc/ast/parser/Parsers.scala | 22 +++++------ src/compiler/scala/tools/nsc/symtab/Symbols.scala | 2 +- .../scala/tools/nsc/typechecker/Infer.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 44 ++++++++++++---------- test/files/neg/bug835.check | 4 +- test/files/neg/bug876.check | 2 +- test/files/neg/patmatexhaust.check | 4 +- test/files/neg/patmatexhaust.scala | 6 +-- test/files/pos/unapplySeq.scala | 2 +- test/files/run/patmatnew.scala | 4 +- test/files/run/runtime.scala | 4 +- test/files/run/tuples.check | 3 ++ test/files/run/tuples.scala | 28 ++++++++++++-- test/files/run/unapply.scala | 14 +++---- 15 files changed, 87 insertions(+), 58 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index f639fc3c44..28a7fd10b0 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -163,10 +163,10 @@ abstract class TreeGen { def mkNil: Tree = mkAttributedRef(definitions.NilModule) - /** Builds a pair */ + /** Builds a tuple */ def mkTuple(elems: List[Tree]): Tree = if (elems.isEmpty) Literal(()) - else New(TypeTree(definitions.TupleClass(elems.length).tpe), List(elems)) + else Apply(mkAttributedRef(definitions.TupleClass(elems.length).caseFactory), elems) def mkCached(cvar: Symbol, expr: Tree): Tree = { val cvarRef = if (cvar.owner.isClass) Select(This(cvar.owner), cvar) else Ident(cvar) diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index dfbc330145..18980a9437 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -801,7 +801,7 @@ trait Parsers requires SyntaxAnalyzer { * | throw Expr * | return [Expr] * | [SimpleExpr `.'] Id `=' Expr - * | SimpleExpr ArgumentExprs `=' Expr + * | SimpleExpr1 ArgumentExprs `=' Expr * | `.' SimpleExpr * | PostfixExpr [`:' (CompoundType | `_' `*')] * | PostfixExpr match [`!'] `{' CaseClauses `}' @@ -1006,21 +1006,20 @@ trait Parsers requires SyntaxAnalyzer { } /* SimpleExpr ::= new SimpleType {`(' [Exprs] `)'} {`with' SimpleType} [TemplateBody] + * | BlockExpr * | SimpleExpr1 * SimpleExpr1 ::= literal * | xLiteral * | Path * | StableId `.' class * | `(' [Expr] `)' - * | BlockExpr - * | new Template * | SimpleExpr `.' Id * | SimpleExpr TypeArgs * | SimpleExpr1 ArgumentExprs */ def simpleExpr(): Tree = { var t: Tree = null - var isNew = false + var canApply = true in.token match { case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL => @@ -1036,6 +1035,7 @@ trait Parsers requires SyntaxAnalyzer { t = Parens(ts) case LBRACE => t = blockExpr() + canApply = false case NEW => t = atPos(in.skipToken()) { val parents = new ListBuffer[Tree] + simpleType(false) @@ -1050,7 +1050,7 @@ trait Parsers requires SyntaxAnalyzer { val stats = if (in.token == LBRACE) templateBody() else List() makeNew(parents.toList, stats, argss.toList) } - isNew = true + canApply = false case _ => if (settings.migrate.value) { if (in.token == MATCH) @@ -1061,21 +1061,21 @@ trait Parsers requires SyntaxAnalyzer { syntaxErrorOrIncomplete("illegal start of simple expression", true) t = errorTermTree } - simpleExprRest(t, isNew) + simpleExprRest(t, canApply) } - def simpleExprRest(t: Tree, isNew: boolean): Tree = in.token match { + def simpleExprRest(t: Tree, canApply: boolean): Tree = in.token match { case DOT => - simpleExprRest(atPos(in.skipToken()) { selector(stripParens(t)) }, false) + simpleExprRest(atPos(in.skipToken()) { selector(stripParens(t)) }, true) case LBRACKET => t match { case Ident(_) | Select(_, _) => - simpleExprRest(atPos(in.currentPos) { TypeApply(t, typeArgs(false)) }, false) + simpleExprRest(atPos(in.currentPos) { TypeApply(t, typeArgs(false)) }, true) case _ => t } - case LPAREN | LBRACE if (!isNew) => - simpleExprRest(atPos(in.currentPos) { Apply(stripParens(t), argumentExprs()) }, false) + case LPAREN | LBRACE if (canApply) => + simpleExprRest(atPos(in.currentPos) { Apply(stripParens(t), argumentExprs()) }, true) case _ => t } diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 2db48eaa41..5d2e5220d4 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -825,7 +825,7 @@ trait Symbols requires SymbolTable { * @pre case class is a member of some other class or package */ final def caseFactory: Symbol = - owner.info.decl(name.toTermName).suchThat(.isCaseFactory) + initialize.owner.info.decl(name.toTermName).suchThat(.isCaseFactory) /** If this symbol is a skolem, its corresponding type parameter, otherwise this */ def deSkolemize: Symbol = this diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 91ff898450..52672ed014 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -56,7 +56,7 @@ trait Infer requires Analyzer { else actuals def actualArgs(pos: PositionType, actuals: List[Tree], nformals: int): List[Tree] = - if (nformals == 1 && actuals.length != 1) List(gen.mkTuple(actuals) setPos pos) else actuals + if (nformals == 1 && actuals.length != 1) List(atPos(pos)(gen.mkTuple(actuals))) else actuals /** A fresh type varable with given type parameter as origin. * diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1e645f3baa..c05c17a0a2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -545,13 +545,9 @@ trait Typers requires Analyzer { } else if (!meth.isConstructor && mt.paramTypes.isEmpty) { // (4.3) adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt) } else if (context.implicitsEnabled) { - if (settings.migrate.value && !meth.isConstructor && - isCompatible(tparamsToWildcards(mt, context.undetparams), pt)) - errorTree(tree, migrateMsg + " method can be converted to function only if an expected function type is given"); - else - errorTree(tree, "missing arguments for "+meth+meth.locationString+ - (if (meth.isConstructor) "" - else ";\nprefix this method with `&' if you want to treat it as a partially applied function")) + errorTree(tree, "missing arguments for "+meth+meth.locationString+ + (if (meth.isConstructor) "" + else ";\nprefix this method with `&' if you want to treat it as a partially applied function")) } else { setError(tree) } @@ -1382,8 +1378,14 @@ trait Typers requires Analyzer { case MethodType(formals0, restpe) => val formals = formalTypes(formals0, args.length) var args1 = actualArgs(tree.pos, args, formals.length) - if (formals.length != args1.length) { - Console.println(formals+" "+args1);//DEBUG + if (args1.length != args.length) { + try { + silentTypedApply(tree, fun, args1, mode, pt) + } catch { + case ex: TypeError => + errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) + } + } else if (formals.length != args1.length) { errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) } else { val tparams = context.undetparams @@ -1537,6 +1539,18 @@ trait Typers requires Analyzer { } } + def silentTypedApply(tree: Tree, fun: Tree, args: List[Tree], mode: int, pt: Type): Tree = + if (context.reportGeneralErrors) { + val context1 = context.makeSilent(context.reportAmbiguousErrors) + context1.undetparams = context.undetparams + val typer1 = newTyper(context1) + val result = typer1.typedApply(tree, fun, args, mode, pt) + context.undetparams = context1.undetparams + result + } else { + typedApply(tree, fun, args, mode, pt) + } + def typedAnnotation(constr: Tree, elements: List[Tree]): AttrInfo = { var attrError: Boolean = false; def error(pos: PositionType, msg: String): Null = { @@ -1643,17 +1657,7 @@ trait Typers requires Analyzer { * @return ... */ def tryTypedApply(fun: Tree, args: List[Tree]): Tree = try { - if (context.reportGeneralErrors) { - val context1 = context.makeSilent(context.reportAmbiguousErrors) - context1.undetparams = context.undetparams - val typer1 = newTyper(context1) - val result = - typer1.typedApply(tree, fun, args, mode, pt) - context.undetparams = context1.undetparams - result - } else { - typedApply(tree, fun, args, mode, pt) - } + silentTypedApply(tree, fun, args, mode, pt) } catch { case ex: CyclicReference => throw ex diff --git a/test/files/neg/bug835.check b/test/files/neg/bug835.check index 16b311ff4c..83db589280 100644 --- a/test/files/neg/bug835.check +++ b/test/files/neg/bug835.check @@ -1,4 +1,4 @@ -bug835.scala:2: error: `)' expected +bug835.scala:2: error: _*-argument may not appear after other arguments matching a *-parameter Console.println(List(List(1, 2, 3) : _*, List(4, 5, 6) : _*)) - ^ + ^ one error found diff --git a/test/files/neg/bug876.check b/test/files/neg/bug876.check index 54c27fc96a..e7d5d5d78f 100644 --- a/test/files/neg/bug876.check +++ b/test/files/neg/bug876.check @@ -1,4 +1,4 @@ -bug876.scala:25: error: wrong number of arguments for method apply: (AssertionError.this.A)manager.B +bug876.scala:25: error: wrong number of arguments for method apply: (AssertionError.this.A)manager.B in trait Map assert(manager.map(A2) == List(manager.map(A2, A1))) ^ one error found diff --git a/test/files/neg/patmatexhaust.check b/test/files/neg/patmatexhaust.check index 6a0eda5861..19e79b2928 100644 --- a/test/files/neg/patmatexhaust.check +++ b/test/files/neg/patmatexhaust.check @@ -5,10 +5,10 @@ patmatexhaust.scala:12: warning: does not cover case {class Bar} def ma2(x:Foo) = x match { ^ patmatexhaust.scala:24: warning: does not cover case {class Kult} - case {Kult(_), Qult()} => // Kult missing + case (Kult(_), Qult()) => // Kult missing ^ patmatexhaust.scala:26: warning: does not cover case {class Qult} - case {Qult(), Kult(_)} => // Qult missing + case (Qult(), Kult(_)) => // Qult missing ^ patmatexhaust.scala:44: warning: does not cover cases {object Gu,class Gp} def ma4(x:Deep) = x match { // missing cases: Gu, Gp diff --git a/test/files/neg/patmatexhaust.scala b/test/files/neg/patmatexhaust.scala index e1b52a61ef..204bf2f170 100644 --- a/test/files/neg/patmatexhaust.scala +++ b/test/files/neg/patmatexhaust.scala @@ -20,10 +20,10 @@ class TestSealedExhaustive { // compile only def ma33(x:Kult) = x match { // exhaustive case Kult(_) => // exhaustive } - def ma3(x:Mult) = {x,x} match { // not exhaustive - case Pair(Kult(_), Qult()) => // Kult missing + def ma3(x:Mult) = (x,x) match { // not exhaustive + case (Kult(_), Qult()) => // Kult missing //case Pair(Kult(_), Kult(_)) => - case Pair(Qult(), Kult(_)) => // Qult missing + case (Qult(), Kult(_)) => // Qult missing //case Pair(Qult(), Qult()) => } diff --git a/test/files/pos/unapplySeq.scala b/test/files/pos/unapplySeq.scala index aac211de5a..6d13cc8b52 100644 --- a/test/files/pos/unapplySeq.scala +++ b/test/files/pos/unapplySeq.scala @@ -2,7 +2,7 @@ object FooSeq { def unapplySeq(x:Any): Option[Product2[Int,Seq[String]]] = { if(x.isInstanceOf[Bar]) { val y = x.asInstanceOf[Bar] - Some({y.size, y.name}) + Some(y.size, y.name) } else None } diff --git a/test/files/run/patmatnew.scala b/test/files/run/patmatnew.scala index e77e10abeb..daa1f9898a 100644 --- a/test/files/run/patmatnew.scala +++ b/test/files/run/patmatnew.scala @@ -99,7 +99,7 @@ object Test { // these are exhaustive matches // should not generate any warnings - def f[A](z:{Option[A],Option[A]}) = z match { + def f[A](z:(Option[A],Option[A])) = z match { case Pair(None,Some(x)) => 1 case Pair(Some(x),None ) => 2 case Pair(Some(x),Some(y)) => 3 @@ -118,7 +118,7 @@ object Test { case _ => true } - def h[A](x:{Option[A],Option[A]}) = x match { + def h[A](x: (Option[A],Option[A])) = x match { case Pair(None,_:Some[_]) => 1 case Pair(_:Some[_],None ) => 2 case Pair(_:Some[_],_:Some[_]) => 3 diff --git a/test/files/run/runtime.scala b/test/files/run/runtime.scala index 192d405eba..45fdf91c95 100644 --- a/test/files/run/runtime.scala +++ b/test/files/run/runtime.scala @@ -66,7 +66,7 @@ object Test1Test { // {System.out.print(12); java.lang}.System.out.println(); // {System.out.print(13); java.lang.System}.out.println(); {Console.print(14); Console}.println; - {Console.print(15); (() => Console.println):(() => Unit)}(); + {Console.print(15); (() => Console.println):(() => Unit)} apply (); {Console.print(16); Console.println}; {Console.print(20)}; test1.bar.System.out.println(); @@ -74,7 +74,7 @@ object Test1Test { // {System.out.print(22); test1.bar}.System.out.println(); {Console.print(23); test1.bar.System}.out.println(); {Console.print(24); test1.bar.System.out}.println(); - {Console.print(25); test1.bar.System.out.println:(() => Unit)}(); + {Console.print(25); test1.bar.System.out.println:(() => Unit)} apply (); {Console.print(26); test1.bar.System.out.println()}; } diff --git a/test/files/run/tuples.check b/test/files/run/tuples.check index 731f2746c9..ff7fb4fe7a 100644 --- a/test/files/run/tuples.check +++ b/test/files/run/tuples.check @@ -1,2 +1,5 @@ {1,abc,true} OK +x = 2; y = xxx; z = 3.14159 +x = 2; y = xxx; z = 3.14159 +x = 2; y = xxx; z = 3.14159 diff --git a/test/files/run/tuples.scala b/test/files/run/tuples.scala index 3d0dcf7ac0..857b166917 100644 --- a/test/files/run/tuples.scala +++ b/test/files/run/tuples.scala @@ -1,8 +1,30 @@ +import Function._ + object Test extends Application { - var xyz: Triple(int, String, boolean) = _ - xyz = Triple(1, "abc", true) + var xyz: (int, String, boolean) = _ + xyz = (1, "abc", true) Console.println(xyz) xyz match { - case Triple(1, "abc", true) => Console.println("OK") + case (1, "abc", true) => Console.println("OK") } + def func(x : int, y : String, z : double) : unit = { + Console.println("x = " + x + "; y = " + y + "; z = " + z); + } + + def params = (2, "xxx", 3.14159) // (*****) + + tupled(&func)(params) // call the function with all the params at once + func(2, "xxx", 3.14159) // the same call + (&func).apply(2, "xxx", 3.14159) // the same call + + // Composing a tuple + def t = (1, "Hello", false) + + // Decomposing a tuple + val (i, s, b) = t + + // all the assertions are passed + assert(i == 1) + assert(s == "Hello") + assert(b == false) } diff --git a/test/files/run/unapply.scala b/test/files/run/unapply.scala index 8b913ee593..fb154cf192 100644 --- a/test/files/run/unapply.scala +++ b/test/files/run/unapply.scala @@ -34,7 +34,7 @@ object Foo extends Assert { case _ => None } def doMatch1(b:Bar) = b match { - case Foo(s:Int, n:String) => {s,n} + case Foo(s:Int, n:String) => (s,n) } def doMatch2(b:Bar) = b match { case Fii() => null @@ -50,7 +50,7 @@ object Foo extends Assert { } def run { val b = new Bar - assertEquals(doMatch1(b),{50,"medium"}) + assertEquals(doMatch1(b),(50,"medium")) assertEquals(doMatch2(b),null) assertEquals(doMatch3(b),"medium") assertEquals(doMatch4(b),"medium") @@ -73,16 +73,16 @@ object Mas extends Assert { def run { val b = new Baz assertEquals(b match { - case Gaz(s:Int, n:String) => {s,n} - }, {60,"too large"}) + case Gaz(s:Int, n:String) => (s,n) + }, (60,"too large")) } } object LisSeqArr extends Assert { def run { - assertEquals((List(1,2,3): Any) match { case List(x,y,_*) => {x,y}}, {1,2}) - assertEquals((List(1,2,3): Any) match { case Seq(x,y,_*) => {x,y}}, {1,2}) - assertEquals((Array(1,2,3): Any) match { case Seq(x,y,_*) => {x,y}}, {1,2}) + assertEquals((List(1,2,3): Any) match { case List(x,y,_*) => (x,y)}, (1,2)) + assertEquals((List(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}, (1,2)) + assertEquals((Array(1,2,3): Any) match { case Seq(x,y,_*) => (x,y)}, (1,2)) //assertEquals((Array(1,2,3): Any) match { case Array(x,y,_*) => {x,y}}, {1,2}) } } -- cgit v1.2.3