summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorBurak Emir <emir@epfl.ch>2007-01-02 16:51:29 +0000
committerBurak Emir <emir@epfl.ch>2007-01-02 16:51:29 +0000
commitbfea9f20d231bc6b7fb75edbce277d883265b89d (patch)
tree97d1ad6e319e2dbc96edde4c906ae9668f82c7cb /src/compiler
parent9e3b5c094b4e8b96d418d7498deab78dcb8bf150 (diff)
downloadscala-bfea9f20d231bc6b7fb75edbce277d883265b89d.tar.gz
scala-bfea9f20d231bc6b7fb75edbce277d883265b89d.tar.bz2
scala-bfea9f20d231bc6b7fb75edbce277d883265b89d.zip
* TupleN extends ProductN, again (genprod updated)
* better comments and parameter names in scala.xml.MetaData typechecker * now handles special cases (n=0, n=1) for unapply correctly * * even if one returns a Option[Product1[T]] * typechecker now handles unapply return types correctly * * e.g. when returning Option[{A,B}] instead of Option[Product2[A,B]]
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternMatchers.scala48
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala12
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
4 files changed, 68 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
index b627a7027f..ecead9e7d2 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternMatchers.scala
@@ -146,6 +146,7 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
val node = new UnapplyPat(newVar(pos, tpe), fn)
node.pos = pos
node.setType(tpe)
+ //Console.println("!build unapply, fn.tpe="+fn.tpe+", casted =" + node.casted+" tpe = "+tpe)
node
}
@@ -230,6 +231,11 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
newVar(pos, cunit.fresh.newName("temp"), tpe).setFlag(Flags.SYNTHETIC)
// ---
+/* //debug
+ def squeezedBlock(vds:List[Tree], exp:Tree): Tree = {
+ Block(vds, exp)
+ }
+*/
def squeezedBlock(vds:List[Tree], exp:Tree): Tree = {
val tpe = exp.tpe
class RefTraverser(sym:Symbol) extends Traverser {
@@ -550,24 +556,32 @@ trait PatternMatchers requires (transform.ExplicitOuter with PatternNodes) {
List(Literal(Constant(index)))))
val seqType = t.tpe
pHeader( pos, seqType, t )
- } else if (defs.isProductType(casted.tpe)) {
- val acc = defs.productProj(casted.tpe.typeArgs.length, index+1)
- val accTree = typed(Apply(Select(ident, acc), List())) // nsc !
- pHeader(pos, accTree.tpe, accTree)
} else {
//Console.println("NOT FIRSTPOS");
//Console.println("newHeader :: ");
-
if(!casted.tpe.symbol.hasFlag(Flags.CASE)) {
-/* Console.println(" newHeader :: casted="+casted);
+
+ //Console.println("NOT CASE");
+
+ if (defs.isProductType(casted.tpe)) {
+ val acc = defs.productProj(casted.tpe.typeArgs.length, index+1)
+ val accTree = typed(Apply(Select(ident, acc), List())) // nsc !
+ return pHeader(pos, accTree.tpe, accTree)
+ }
+
+ /*
+ Console.println(" newHeader :: casted="+casted);
Console.println(" newHeader :: casted.pos="+casted.pos);
Console.println(" newHeader :: casted.pos==Position.FIRSTPOS"+(casted.pos == Position.FIRSTPOS));
Console.println(" newHeader :: casted.tpe="+casted.tpe);
Console.println(" newHeader :: casted.tpe.symbol="+casted.tpe.symbol);
print()
-*/ throw new Error("internal problem, trying casefield access for no case class") //DBG
+*/
+ throw new Error("internal problem, trying casefield access for no case class") //DBG
}
+ //Console.println("CASE");
+
val caseAccs = casted.tpe.symbol.caseFieldAccessors;
if (caseAccs.length <= index) Console.println("selecting " + index + " in case fields of " + casted.tpe.symbol + "=" + casted.tpe.symbol.caseFieldAccessors);//debug
val ts = caseAccs(index);
@@ -617,6 +631,7 @@ print()
target match {
case u @ UnapplyPat(_,_) if u.returnsOne =>
+ //Console.println("u.returnsOne!"+u+ " casted:"+casted+" u.casted"+u.casted)
assert(index==0)
curHeader = pHeader(pat.pos, casted.tpe, Ident(casted) setType casted.tpe)
target.and = curHeader
@@ -627,6 +642,8 @@ print()
curHeader = newHeader(pat.pos, casted, index)
target.and = curHeader; // (*)
+ //Console.println("curHeader : "+curHeader)
+
if (bodycond ne null) target.and = bodycond(target.and) // restores body with the guards
curHeader.or = patternNode(pat, curHeader, env)
@@ -1176,11 +1193,22 @@ print()
Or(And(cond, thenp), elsep)
protected def toTree(node: PatternNode, selector:Tree): Tree = {
- toTree_refined(node, selector, false)
+ val t = toTree_refined(node, selector, false)
+ try {
+ //Console.println("type-checking "+t)
+ typed { t } // DEBUG
+ } catch {
+ case e =>
+
+ Console.println("failed with "+e.getMessage()+" on: "+t)
+ System.exit(-1)
+ //null
+ t
+ }
}
protected def toTree_refined(node: PatternNode, selector:Tree, ignoreSelectorType: Boolean): Tree = {
- //Konsole.println("pm.toTree("+node+","+selector+") selector.tpe = "+selector.tpe+")")
+ //Console.println("pm.toTree("+node+","+selector+") selector.tpe = "+selector.tpe+")")
if (selector.tpe eq null)
scala.Predef.error("cannot go on")
if (node eq null)
@@ -1207,7 +1235,7 @@ print()
),
toTree(node.or, selector.duplicate))
- case UnapplyPat(casted, fn @ Apply(fn1, _)) =>
+ case UnapplyPat(casted, fn @ Apply(fn1, _)) =>
var useSelector = selector
val checkType = fn1.tpe match {
case MethodType(List(argtpe),_) =>
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
index 11cf8f88fa..e31c8d18a0 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
@@ -274,7 +274,17 @@ trait PatternNodes requires transform.ExplicitOuter {
case class DefaultPat()extends PatternNode
case class ConstrPat(casted:Symbol) extends PatternNode
case class UnapplyPat(casted:Symbol, fn:Tree) extends PatternNode {
- def returnsOne = !definitions.isProductType(casted.tpe)
+ def returnsOne = {
+ /*val res =*/ definitions.getProductArgs(casted.tpe) match {
+ case Some(Nil) => true // n = 0
+ case Some(x::Nil) => true // n = 1
+ case Some(_) => false
+ case _ => true
+ }
+ //Console.println("returns one? "+casted.tpe)
+ //Console.println(" I say: "+res)
+ //res
+ }
}
case class ConstantPat(value: Any /*AConstant*/) extends PatternNode
case class VariablePat(tree: Tree) extends PatternNode
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 9103b7a69f..676d2e5530 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -131,9 +131,19 @@ trait Definitions requires SymbolTable {
typeRef(sym.typeConstructor.prefix, sym, elems)
} else NoType
+ /** if tpe <: ProductN[T1,...,TN], returns Some(T1,...,TN) else None */
+ def getProductArgs(tpe: Type): Option[List[Type]] =
+ tpe.baseClasses.find { x => definitions.isProductType(x.tpe) } match {
+ case Some(p) => Some(tpe.baseType(p).typeArgs)
+ case _ => None
+ }
+
var OptionClass: Symbol = _
- def SomeClass: Symbol = getClass("scala.Some")
- def NoneClass: Symbol = getModule("scala.None")
+
+ private var SomeClass_ : Symbol = null
+ def SomeClass: Symbol = { if(SomeClass_ eq null) SomeClass_ = getClass("scala.Some"); SomeClass_ }
+ private var NoneClass_ : Symbol = null
+ def NoneClass: Symbol = { if(NoneClass_ eq null) SomeClass_ = getModule("scala.None"); NoneClass_ }
def isOptionType(tp: Type) = tp match {
case TypeRef(_, sym, List(_)) if sym == OptionClass => true
@@ -158,7 +168,6 @@ trait Definitions requires SymbolTable {
case _ => false
}
-
def unapplyUnwrap(tpe:Type) = tpe match {
case PolyType(_,MethodType(_, res)) => res
case MethodType(_, res) => res
@@ -188,10 +197,10 @@ trait Definitions requires SymbolTable {
case B => Nil
case O | S =>
val prod = tp.typeArgs.head
- prod.baseClasses.find { x => isProductType(x.tpe) } match {
- case Some(p) => prod.baseType(p).typeArgs
- case _ => prod::Nil // special case n = 0
- }
+ getProductArgs(prod) match {
+ case Some(all @ (x1::x2::xs)) => all // n >= 2
+ case _ => prod::Nil // special n == 0 || n == 1
+ }
case _ => throw new IllegalArgumentException(tp.symbol + " in not in {boolean, option, some}")
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d262ad4855..26799b4fd9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1391,6 +1391,9 @@ trait Typers requires Analyzer {
case ErrorType =>
setError(copy.Apply(tree, fun, args))
/* --- begin unapply --- */
+
+ // bq: this is so wrong -- why use WildcardTypes to check patterns arguments?
+ // only because of generics?
case otpe if definitions.unapplyMember(otpe).exists && settings.Xunapply.value =>
// !!! this is fragile, maybe needs to be revised when unapply patterns become terms
val unapp = definitions.unapplyMember(otpe)