diff options
author | Burak Emir <emir@epfl.ch> | 2007-01-02 16:51:29 +0000 |
---|---|---|
committer | Burak Emir <emir@epfl.ch> | 2007-01-02 16:51:29 +0000 |
commit | bfea9f20d231bc6b7fb75edbce277d883265b89d (patch) | |
tree | 97d1ad6e319e2dbc96edde4c906ae9668f82c7cb /src/compiler | |
parent | 9e3b5c094b4e8b96d418d7498deab78dcb8bf150 (diff) | |
download | scala-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')
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) |