summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-01-16 20:33:20 +0000
committerMartin Odersky <odersky@gmail.com>2007-01-16 20:33:20 +0000
commit6093bbedc0c0cf39650c4cd931afb18feb1bcda8 (patch)
tree3c812fab17a33c73b6ce03bb9129d0674dd1b6bf
parent96376cd15412c66bcd30e9b397f211eec4e7bf35 (diff)
downloadscala-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.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala19
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala49
-rw-r--r--src/library/scala/Option.scala20
-rw-r--r--src/library/scala/Predef.scala4
-rw-r--r--src/library/scala/collection/Set.scala2
-rw-r--r--test/files/pos/channels.scala30
-rw-r--r--test/pending/pos/unapplyComplex.scala2
-rw-r--r--test/pending/run/unapply.scala2
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})
}
}