diff options
author | Martin Odersky <odersky@gmail.com> | 2007-01-16 20:33:20 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2007-01-16 20:33:20 +0000 |
commit | 6093bbedc0c0cf39650c4cd931afb18feb1bcda8 (patch) | |
tree | 3c812fab17a33c73b6ce03bb9129d0674dd1b6bf | |
parent | 96376cd15412c66bcd30e9b397f211eec4e7bf35 (diff) | |
download | scala-6093bbedc0c0cf39650c4cd931afb18feb1bcda8.tar.gz scala-6093bbedc0c0cf39650c4cd931afb18feb1bcda8.tar.bz2 scala-6093bbedc0c0cf39650c4cd931afb18feb1bcda8.zip |
enabled -Xunapply.
fixed bug contrib 291.
Added Map/Set types to Predef.
Option no longer inherits from Iterable, but there's an implicit conversion.
various other small things.
-rw-r--r-- | src/actors/scala/actors/Channel.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Settings.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/UnCurry.scala | 10 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 19 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 49 | ||||
-rw-r--r-- | src/library/scala/Option.scala | 20 | ||||
-rw-r--r-- | src/library/scala/Predef.scala | 4 | ||||
-rw-r--r-- | src/library/scala/collection/Set.scala | 2 | ||||
-rw-r--r-- | test/files/pos/channels.scala | 30 | ||||
-rw-r--r-- | test/pending/pos/unapplyComplex.scala | 2 | ||||
-rw-r--r-- | test/pending/run/unapply.scala | 2 |
11 files changed, 94 insertions, 47 deletions
diff --git a/src/actors/scala/actors/Channel.scala b/src/actors/scala/actors/Channel.scala index 89ee7e9473..29293b3286 100644 --- a/src/actors/scala/actors/Channel.scala +++ b/src/actors/scala/actors/Channel.scala @@ -81,7 +81,7 @@ class Channel[Msg] extends InputChannel[Msg] with OutputChannel[Msg] { def ? : Msg = receive { case any => any } - def poll = { + def poll: Option[Msg] = { Some(?) } orElse { None.asInstanceOf[Option[Msg]] diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 4ee1ec82d0..129d0dcfaf 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -129,6 +129,7 @@ class Settings(error: String => unit) { val Xscript = new BooleanSetting("-Xscript", "compile script file") { override def hiddenToIDE = true } val Xexperimental = BooleanSetting("-Xexperimental", "enable experimental extensions") val Xunapply = BooleanSetting("-Xunapply", "enable unapply pattern matching") + Xunapply.value = true val Xplugtypes = BooleanSetting("-Xplugtypes", "parse but ignore annotations in more locations") val Xkilloption = BooleanSetting("-Xkilloption", "optimizes option types") val XprintOuterMatches = BooleanSetting("-XprintOuterMatches", "prints outer-checks caused by pattern matching ") diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 352dc3b75c..b3feb1ed7f 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -424,9 +424,13 @@ abstract class UnCurry extends InfoTransform with TypingTransformers { case _ => val tree1 = super.transform(tree) if (isByNameRef(tree1)) - localTyper.typed(atPos(tree1.pos)( - Apply(Select(tree1 setType functionType(List(), tree1.tpe), nme.apply), List()))) - else tree1; + return localTyper.typed { + atPos(tree1.pos) { + Apply(Select(tree1 setType functionType(List(), tree1.tpe), nme.apply), + List()) + } + } + tree1 } } setType uncurryTreeType(tree.tpe) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 35954ca8a7..63b59f01cb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -843,30 +843,29 @@ trait Infer requires Analyzer { } } - def inferTypedPattern(tpt: Tree, pt: Type): Type = { - //Console.println("infer typed pattern: "+tpt+" wrt "+pt)//debug - checkCheckable(tpt.pos, tpt.tpe) - if (!(tpt.tpe <:< pt)) { - val tpparams = freeTypeParamsOfTerms.collect(tpt.tpe) + def inferTypedPattern(pos: PositionType, pattp: Type, pt: Type): Type = { + checkCheckable(pos, pattp) + if (!(pattp <:< pt)) { + val tpparams = freeTypeParamsOfTerms.collect(pattp) if (settings.debug.value) log("free type params (1) = " + tpparams) var tvars = tpparams map freshVar - var tp = tpt.tpe.subst(tpparams, tvars) + var tp = pattp.subst(tpparams, tvars) if (!(tp <:< pt)) { tvars = tpparams map freshVar - tp = tpt.tpe.subst(tpparams, tvars) + tp = pattp.subst(tpparams, tvars) val ptparams = freeTypeParamsOfTerms.collect(pt) if (settings.debug.value) log("free type params (2) = " + ptparams) val ptvars = ptparams map freshVar val pt1 = pt.subst(ptparams, ptvars) if (!isPopulated(tp, pt1)) { - error(tpt.pos, "pattern type is incompatibe with expected type"+foundReqMsg(tpt.tpe, pt)) - return tpt.tpe + error(pos, "pattern type is incompatibe with expected type"+foundReqMsg(pattp, pt)) + return pattp } ptvars foreach instantiateTypeVar } tvars foreach instantiateTypeVar } - intersect(pt, tpt.tpe) + intersect(pt, pattp) } def inferModulePattern(pat: Tree, pt: Type) = diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 7d361a1800..2bea199dbc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1417,6 +1417,7 @@ trait Typers requires Analyzer { // !!! this is fragile, maybe needs to be revised when unapply patterns become terms val unapp = definitions.unapplyMember(otpe) assert(unapp.exists, tree) + val unappType = otpe.memberType(unapp) // this is no longer needed! @@ -1427,11 +1428,12 @@ trait Typers requires Analyzer { if (args.length > MaxTupleArity) error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity) val arg = Ident(argDummy) setType argDummyType +/* var funPt: Type = null try { funPt = unapp.name match { case nme.unapply => unapplyReturnTypeExpected(args.length) - case nme.unapplySeq => unapplyTypeListFromReturnTypeSeq(unapp.tpe) match { + case nme.unapplySeq => unapplyTypeListFromReturnTypeSeq(unappType) match { case List() => null //fail case List(TypeRef(pre,repeatedParam, tpe)) => optionType(seqType(WildcardType)) //succeed case xs => optionType(productType((xs.tail map {x => WildcardType}) ::: List(seqType(WildcardType))))// succeed @@ -1444,31 +1446,30 @@ trait Typers requires Analyzer { error(fun.pos, " unapplySeq should return Option[T] for T<:Product?[...Seq[?]]") return setError(tree) } - val fun0 = Ident(fun.symbol) setPos fun.pos setType otpe // would this change when patterns are terms??? - val fun1untyped = atPos(fun.pos) { - Apply(Select(gen.mkAttributedRef(fun.tpe.prefix,fun.symbol), unapp), List(arg)) - } - - // bq: find out if argument requires instanceOf check, if yes then lie about the type +*/ val oldArgType = arg.tpe - unapp.tpe match { - case MethodType(formals, restpe) => - if(!isSubType(arg.tpe, formals(0))) { - //Console.println(" -- apply mono hack") - arg.tpe = AllClass.tpe // deceive typechecker, we'll insert an instanceOf check later - } - case PolyType(tparams,MethodType(fmls, res)) => - try { - methTypeArgs(tparams, fmls, res, List(arg.tpe.deconst), WildcardType, new ListBuffer[Symbol]()) - } catch { - case e => //Console.println(e.getMessage()) - //Console.println(" -- apply poly hack") - arg.tpe = AllClass.tpe // deceive typechecker, we'll insert an instanceOf check later - } + if (!isApplicable(List(), unappType, List(arg.tpe), WildcardType)) { + //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType) + def freshArgType(tp: Type): {Type, List[Symbol]} = tp match { + case MethodType(formals, restpe) => + {formals(0), List()} + case PolyType(tparams, restype) => + val tparams1 = cloneSymbols(tparams) + {freshArgType(restype)._1.substSym(tparams, tparams1), tparams1} + } + val {unappFormal, freeVars} = freshArgType(unappType) + val context1 = context.makeNewScope(context.tree, context.owner) + freeVars foreach context1.scope.enter + val typer1 = new Typer(context1) + arg.tpe = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe) + //todo: replace arg with arg.asInstanceOf[inferTypedPattern(unappFormal, arg.tpe)] instead. } - //Console.println("UNAPPLY2 "+fun+"/"+fun.tpe+" "+fun1untyped+", funPt = "+funPt) - val fun1 = typed(fun1untyped, EXPRmode, funPt) + val fun1untyped = atPos(fun.pos) { + Apply(Select(gen.mkAttributedRef(fun.tpe.prefix,fun.symbol), unapp), List(arg)) + } + //Console.println("UNAPPLY2 "+fun+"/"+fun.tpe+" "+fun1untyped) + val fun1 = typed(fun1untyped) if (fun1.tpe.isErroneous) setError(tree) else { val formals0 = unapplyTypeList(fun1.symbol, fun1.tpe) @@ -2021,7 +2022,7 @@ trait Typers requires Analyzer { case Typed(expr, tpt) => val tpt1 = typedType(tpt) val expr1 = typed(expr, mode & stickyModes, tpt1.tpe) - val owntype = if ((mode & PATTERNmode) != 0) inferTypedPattern(tpt1, widen(pt)) else tpt1.tpe + val owntype = if ((mode & PATTERNmode) != 0) inferTypedPattern(tpt1.pos, tpt1.tpe, widen(pt)) else tpt1.tpe //Console.println(typed pattern: "+tree+":"+", tp = "+tpt1.tpe+", pt = "+pt+" ==> "+owntype)//DEBUG copy.Typed(tree, expr1, tpt1) setType owntype diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala index 78f501fa9f..96d9fb2457 100644 --- a/src/library/scala/Option.scala +++ b/src/library/scala/Option.scala @@ -14,6 +14,14 @@ package scala; import Predef._ +object Option { + implicit def option2Iterable[a](xo: Option[a]): Iterable[a] = xo match { + case Some(x) => List(x) + case None => Nil + } +} + + /** This class represents optional values. Instances of <code>Option</code> * are either instances of case class <code>Some</code> or it is case * object <code>None</code>. @@ -22,7 +30,7 @@ import Predef._ * @author Matthias Zenger * @version 1.0, 16/07/2003 */ -sealed abstract class Option[+A] extends Iterable[A] with Product { +sealed abstract class Option[+A] extends Product { def isEmpty: Boolean = this match { case None => true @@ -42,22 +50,22 @@ sealed abstract class Option[+A] extends Iterable[A] with Product { case Some(x) => x } - override def map[B](f: A => B): Option[B] = this match { + def map[B](f: A => B): Option[B] = this match { case None => None case Some(x) => Some(f(x)) } - override def flatMap[B](f: A => Iterable[B]): Iterable[B] = this match { + def flatMap[B](f: A => Option[B]): Option[B] = this match { case None => None case Some(x) => f(x) } - override def filter(p: A => Boolean): Option[A] = this match { + def filter(p: A => Boolean): Option[A] = this match { case None => None case Some(x) => if (p(x)) Some(x) else None } - override def foreach(f: A => Unit): Unit = this match { + def foreach(f: A => Unit): Unit = this match { case None => () case Some(x) => f(x) } @@ -67,7 +75,7 @@ sealed abstract class Option[+A] extends Iterable[A] with Product { case Some(x) => Iterator.fromValues(x) } - override def toList: List[A] = this match { + def toList: List[A] = this match { case None => List() case Some(x) => List(x) } diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index 8178d1d5d0..05f38e8688 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -61,9 +61,13 @@ object Predef { type Function[-a,+b] = Function1[a,b] + type Map[a, b] = collection.mutable.Map[a, b] + type Set[a] = collection.mutable.Set[a] + val Map = collection.mutable.Map val Set = collection.mutable.Set + // errors and asserts ------------------------------------------------- def error(message: String): Nothing = throw new Error(message) diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala index 66e9b3b4a4..2de995df25 100644 --- a/src/library/scala/collection/Set.scala +++ b/src/library/scala/collection/Set.scala @@ -98,6 +98,6 @@ trait Set[A] extends (A => Boolean) with Iterable[A] { * * @return a string showing all elements of this set. */ - override def toString(): String = mkString("{", ", ", "}") + override def toString(): String = mkString("Set(", ", ", ")") } diff --git a/test/files/pos/channels.scala b/test/files/pos/channels.scala new file mode 100644 index 0000000000..6513f3a5f0 --- /dev/null +++ b/test/files/pos/channels.scala @@ -0,0 +1,30 @@ +class Channel[a] + +import collection.mutable.Set + +case class ![a](chan: Channel[a], data: a) + +/* +object Bang { + def unapply[a](x: ![a]): Option[{Channel[a], a}] = + Some(x.chan, x.data) +} + +*/ +object Test extends Application { + object IC extends Channel[int] + def f[b](x: ![b]): int = x match { + case send: ![c] => + send.chan match { + case IC => send.data + } + } +} + +object Test2 extends Application { + object IC extends Channel[Set[int]] + def f[b](s: ![b]): Set[int] = s match { + case IC ! x => x + } +} + diff --git a/test/pending/pos/unapplyComplex.scala b/test/pending/pos/unapplyComplex.scala index 0d5700a3be..54080eb86f 100644 --- a/test/pending/pos/unapplyComplex.scala +++ b/test/pending/pos/unapplyComplex.scala @@ -29,7 +29,7 @@ object Test { Console.println("mod"+mod+"arg"+arg) } val Komplex = ComplexRect - new ComplexPolar(Math.sqrt(2),Math.PI / 4.0) match { + new ComplexPolar(Math.sqrt(2),Math.Pi / 4.0) match { case Komplex(re,im) => // z @ ??? Console.println("re"+re+" im"+im) } diff --git a/test/pending/run/unapply.scala b/test/pending/run/unapply.scala index e00a1e63a0..d84711519f 100644 --- a/test/pending/run/unapply.scala +++ b/test/pending/run/unapply.scala @@ -79,7 +79,7 @@ object Mas extends Assert { object Lis extends Assert { def run { - assertEquals(List(1,2,3) match { case List(x,y,_*) => {x,y}}, {1,2}) + assertEquals((List(1,2,3): Any) match { case List(x,y,_*) => {x,y}}, {1,2}) } } |