summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-10-07 00:02:05 +0000
committerPaul Phillips <paulp@improving.org>2009-10-07 00:02:05 +0000
commit4a6c3da399756720b124eaa209ed34e36c394600 (patch)
treef6107153edce4ec097353641cd8b20c3188fdcbf
parent9b33c1c5ef386e776e8eed10430aa7f94131fcf1 (diff)
downloadscala-4a6c3da399756720b124eaa209ed34e36c394600.tar.gz
scala-4a6c3da399756720b124eaa209ed34e36c394600.tar.bz2
scala-4a6c3da399756720b124eaa209ed34e36c394600.zip
Getting variable binding bits into appropriate ...
Getting variable binding bits into appropriate places. Waved goodbye to PatternNodes.
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala23
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternBindings.scala73
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternNodes.scala63
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala109
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala3
5 files changed, 124 insertions, 147 deletions
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index a533863b0f..12a3ac99c2 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -23,16 +23,35 @@ trait ParallelMatching extends ast.TreeDSL
with Patterns
with PatternBindings
with PatternOptimizer
- with PatternNodes
{
self: ExplicitOuter =>
import global.{ typer => _, _ }
import definitions.{ AnyRefClass, IntClass, getProductArgs, productProj }
import treeInfo.{ isStar }
- import Types._
import CODE._
+ object Types {
+ import definitions._
+ implicit def enrichType(x: Type): RichType = new RichType(x)
+
+ class RichType(undecodedTpe: Type) {
+ def tpe = decodedEqualsType(undecodedTpe)
+ def isAnyRef = tpe <:< AnyRefClass.tpe
+
+ // These tests for final classes can inspect the typeSymbol
+ private def is(s: Symbol) = tpe.typeSymbol eq s
+ def isByte = is(ByteClass)
+ def isShort = is(ShortClass)
+ def isInt = is(IntClass)
+ def isChar = is(CharClass)
+ def isBoolean = is(BooleanClass)
+ def isNothing = is(NothingClass)
+ def isArray = is(ArrayClass)
+ }
+ }
+ import Types._
+
/** Debugging support: enable with -Ypmat-debug **/
private final def trace = settings.Ypmatdebug.value
diff --git a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
index f791236a10..6450962391 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
@@ -38,12 +38,72 @@ trait PatternBindings extends ast.TreeDSL
case Alternative(ps) => ps map prevBindings
}
}
-
def makeBind(vs: List[Symbol], pat: Tree): Tree = vs match {
case Nil => pat
case x :: xs => Bind(x, makeBind(xs, pat)) setType pat.tpe
}
+ trait PatternBindingLogic {
+ self: Pattern =>
+
+ // This is for traversing the pattern tree - pattern types which might have
+ // bound variables beneath them return a list of said patterns for flatMapping.
+ def subpatternsForVars: List[Pattern] = Nil
+
+ // This is what calls subpatternsForVars.
+ def definedVars: List[Symbol] =
+ (boundVariables ::: (subpatternsForVars flatMap (_.definedVars))).reverse // XXX reverse?
+
+ lazy val boundVariables = strip(boundTree)
+
+ // XXX only a var for short-term experimentation.
+ private var _boundTree: Bind = null
+ def boundTree = if (_boundTree == null) tree else _boundTree
+ def withBoundTree(x: Bind): this.type = {
+ _boundTree = x
+ this
+ }
+
+ // If a tree has bindings, boundTree looks something like
+ // Bind(v3, Bind(v2, Bind(v1, tree)))
+ // This takes the given tree and creates a new pattern
+ // using the same bindings.
+ def rebindTo(t: Tree): Pattern =
+ Pattern(wrapBindings(boundVariables, t))
+
+ // Wrap this pattern's bindings around (_: Type)
+ def rebindToType(tpe: Type, annotatedType: Type = null): Pattern = {
+ val aType = if (annotatedType == null) tpe else annotatedType
+ rebindTo(Typed(WILD(tpe), TypeTree(aType)) setType tpe)
+ }
+
+ // Wrap them around _
+ def rebindToEmpty(tpe: Type): Pattern =
+ rebindTo(Typed(EmptyTree, TypeTree(tpe)) setType tpe)
+
+ // Wrap them around a singleton type for an EqualsPattern check.
+ def rebindToEqualsCheck(): Pattern =
+ rebindToType(equalsCheck)
+
+ // Like rebindToEqualsCheck, but subtly different. Not trying to be
+ // mysterious -- I haven't sorted it all out yet.
+ def rebindToObjectCheck(): Pattern = {
+ val sType = mkSingleton
+ rebindToType(mkEqualsRef(sType), sType)
+ }
+
+ /** Helpers **/
+
+ private def wrapBindings(vs: List[Symbol], pat: Tree): Tree = vs match {
+ case Nil => pat
+ case x :: xs => Bind(x, wrapBindings(xs, pat)) setType pat.tpe
+ }
+ private def strip(t: Tree): List[Symbol] = t match {
+ case b @ Bind(_, pat) => b.symbol :: strip(pat)
+ case _ => Nil
+ }
+ }
+
case class Binding(pvar: Symbol, tvar: Symbol) {
// see bug #1843 for the consequences of not setting info.
// there is surely a better way to do this, especially since
@@ -52,10 +112,8 @@ trait PatternBindings extends ast.TreeDSL
if (tvar.info containsTp WildcardType)
tvar setInfo pvar.info
- def toIdent =
- Ident(tvar) setType pvar.tpe
-
- def castIfNeeded =
+ def toIdent = Ident(tvar) setType pvar.tpe
+ def castIfNeeded =
if (tvar.tpe <:< pvar.tpe) ID(tvar)
else ID(tvar) AS_ANY pvar.tpe
}
@@ -71,8 +129,6 @@ trait PatternBindings extends ast.TreeDSL
}
class Bindings(private val vlist: List[Binding]) extends Function1[Symbol, Option[Ident]] {
- def this() = this(Nil)
-
def vmap(v: Symbol): Option[Binding] = vlist find (_.pvar eq v)
// filters the given list down to those defined in these bindings
@@ -83,11 +139,10 @@ trait PatternBindings extends ast.TreeDSL
val newBindings = vs.toList map (v => Binding(v, tvar))
new Bindings(newBindings ++ vlist)
}
-
def apply(v: Symbol): Option[Ident] = vmap(v) map (_.toIdent)
override def toString() = " Bound(%s)".format(vlist)
}
- val NoBinding: Bindings = new Bindings()
+ val NoBinding: Bindings = new Bindings(Nil)
} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala b/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
deleted file mode 100644
index c28a0790b2..0000000000
--- a/src/compiler/scala/tools/nsc/matching/PatternNodes.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2009 LAMP/EPFL
- * @author Burak Emir
- */
-// $Id$
-
-package scala.tools.nsc
-package matching
-
-import scala.tools.nsc.util.NoPosition
-
-/**
- * @author Burak Emir
- */
-trait PatternNodes extends ast.TreeDSL
-{
- self: transform.ExplicitOuter =>
-
- import global.{ typer => _, _ }
- import CODE._
- import definitions.{ ListClass, ConsClass }
-
- object Types {
- import definitions._
- implicit def enrichType(x: Type): RichType = new RichType(x)
-
- class RichType(undecodedTpe: Type) {
- def tpe = decodedEqualsType(undecodedTpe)
- def isAnyRef = tpe <:< AnyRefClass.tpe
-
- // These tests for final classes can inspect the typeSymbol
- private def is(s: Symbol) = tpe.typeSymbol eq s
- def isByte = is(ByteClass)
- def isShort = is(ShortClass)
- def isInt = is(IntClass)
- def isChar = is(CharClass)
- def isBoolean = is(BooleanClass)
- def isNothing = is(NothingClass)
- def isArray = is(ArrayClass)
- }
- }
-
- /** For folding a list into a well-typed x :: y :: etc :: tree. */
- private def listFolder(tpe: Type) = {
- val MethodType(_, TypeRef(pre, sym, _)) = ConsClass.primaryConstructor.tpe
- val consRef = typeRef(pre, sym, List(tpe))
- val listRef = typeRef(pre, ListClass, List(tpe))
-
- def fold(x: Tree, xs: Tree) = unbind(x) match {
- case _: Star => makeBind(Pattern(x).definedVars, WILD(x.tpe))
- case _ =>
- val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
- val consType = MethodType(dummyMethod newSyntheticValueParams List(tpe, listRef), consRef)
-
- Apply(TypeTree(consType), List(x, xs)) setType consRef
- }
-
- fold _
- }
-
- def normalizedListPattern(pats: List[Tree], tptArg: Type): Tree =
- pats.foldRight(gen.mkNil)(listFolder(tptArg))
-}
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index b1c3726e36..35406d097f 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -7,6 +7,7 @@ package scala.tools.nsc
package matching
import symtab.Flags
+import util.NoPosition
/**
* Simple pattern types:
@@ -66,6 +67,8 @@ trait Patterns extends ast.TreeDSL {
case class TypedPattern(tree: Typed) extends Pattern {
private val Typed(expr, tpt) = tree
+ override def subpatternsForVars: List[Pattern] = List(Pattern(expr))
+
override def irrefutableFor(tpe: Type) = tpe <:< tree.tpe
override def simplify(testVar: Symbol) = Pattern(expr) match {
case ExtractorPattern(ua) if testVar.tpe <:< tpt.tpe => this rebindTo expr
@@ -142,8 +145,8 @@ trait Patterns extends ast.TreeDSL {
}
// 8.1.7
- case class ExtractorPattern(tree: UnApply) extends Pattern {
- private val UnApply(Apply(fn, _), args) = tree
+ case class ExtractorPattern(tree: UnApply) extends UnapplyPattern {
+ private val Apply(fn, _) = unfn
private val MethodType(List(arg, _*), _) = fn.tpe
private def uaTyped = Typed(tree, TypeTree(arg.tpe)) setType arg.tpe
@@ -158,16 +161,35 @@ trait Patterns extends ast.TreeDSL {
}
// 8.1.8 (unapplySeq calls)
- case class SequenceExtractorPattern(tree: UnApply) extends Pattern {
+ case class SequenceExtractorPattern(tree: UnApply) extends UnapplyPattern {
private val UnApply(
Apply(TypeApply(Select(_, nme.unapplySeq), List(tptArg)), _),
List(ArrayValue(_, elems))
) = tree
+ /** For folding a list into a well-typed x :: y :: etc :: tree. */
+ private def listFolder = {
+ val tpe = tptArg.tpe
+ val MethodType(_, TypeRef(pre, sym, _)) = ConsClass.primaryConstructor.tpe
+ val consRef = typeRef(pre, sym, List(tpe))
+ val listRef = typeRef(pre, ListClass, List(tpe))
+
+ def fold(x: Tree, xs: Tree) = unbind(x) match {
+ case _: Star => makeBind(Pattern(x).definedVars, WILD(x.tpe))
+ case _ =>
+ val dummyMethod = new TermSymbol(NoSymbol, NoPosition, "matching$dummy")
+ val consType = MethodType(dummyMethod newSyntheticValueParams List(tpe, listRef), consRef)
+
+ Apply(TypeTree(consType), List(x, xs)) setType consRef
+ }
+
+ fold _
+ }
+
// @pre: is not right-ignoring (no star pattern) ; no exhaustivity check
override def simplify(testVar: Symbol) = {
testVar setFlag Flags.TRANS_FLAG
- this rebindTo normalizedListPattern(elems, tptArg.tpe)
+ this rebindTo elems.foldRight(gen.mkNil)(listFolder)
}
override def toString() = "UnapplySeq(%s)".format(elems)
}
@@ -178,6 +200,8 @@ trait Patterns extends ast.TreeDSL {
lazy val elemPatterns = toPats(elems)
lazy val nonStarPatterns = if (hasStar) elemPatterns.init else elemPatterns
+ override def subpatternsForVars: List[Pattern] = elemPatterns
+
def hasStar = isRightIgnoring(tree)
def nonStarLength = nonStarPatterns.length
def isAllDefaults = nonStarPatterns forall (_.isDefault)
@@ -345,7 +369,7 @@ trait Patterns extends ast.TreeDSL {
/** Some intermediate pattern classes with shared structure **/
- trait SelectPattern extends NamePattern {
+ sealed trait SelectPattern extends NamePattern {
def select: Select
lazy val Select(qualifier, name) = select
def pathSegments = getPathSegments(tree)
@@ -367,7 +391,7 @@ trait Patterns extends ast.TreeDSL {
}
}
- trait NamePattern extends Pattern {
+ sealed trait NamePattern extends Pattern {
def name: Name
override def simplify(testVar: Symbol) = this.rebindToEqualsCheck()
override def matchingType = mkSingleton
@@ -377,8 +401,15 @@ trait Patterns extends ast.TreeDSL {
// def simplify(testVar: Symbol): Pattern = this
// }
- sealed abstract class ApplyPattern extends Pattern {
+ sealed trait UnapplyPattern extends Pattern {
+ lazy val UnApply(unfn, args) = tree
+ override def subpatternsForVars: List[Pattern] = toPats(args)
+ }
+
+ sealed trait ApplyPattern extends Pattern {
protected lazy val Apply(fn, args) = tree
+ override def subpatternsForVars: List[Pattern] = toPats(args)
+
def isConstructorPattern = fn.isType
}
@@ -449,70 +480,6 @@ trait Patterns extends ast.TreeDSL {
override def hashCode() = boundTree.hashCode()
}
- trait PatternBindingLogic {
- self: Pattern =>
-
- // XXX only a var for short-term experimentation.
- private var _boundTree: Bind = null
- def boundTree = if (_boundTree == null) tree else _boundTree
- def withBoundTree(x: Bind): this.type = {
- _boundTree = x
- this
- }
- lazy val boundVariables = strip(boundTree)
-
- def definedVars = definedVarsInternal(boundTree)
- private def definedVarsInternal(x: Tree): List[Symbol] = {
- def vars(x: Tree): List[Symbol] = x match {
- case Apply(_, args) => args flatMap vars
- case b @ Bind(_, p) => b.symbol :: vars(p)
- case Typed(p, _) => vars(p) // otherwise x @ (_:T)
- case UnApply(_, args) => args flatMap vars
- case ArrayValue(_, xs) => xs flatMap vars
- case x => Nil
- }
- vars(x) reverse
- }
-
- private def wrapBindings(vs: List[Symbol], pat: Tree): Tree = vs match {
- case Nil => pat
- case x :: xs => Bind(x, wrapBindings(xs, pat)) setType pat.tpe
- }
-
- // If a tree has bindings, boundTree looks something like
- // Bind(v3, Bind(v2, Bind(v1, tree)))
- // This takes the given tree and creates a new pattern
- // using the same bindings.
- def rebindTo(t: Tree): Pattern =
- Pattern(wrapBindings(boundVariables, t))
-
- // Wrap this pattern's bindings around (_: Type)
- def rebindToType(tpe: Type, annotatedType: Type = null): Pattern = {
- val aType = if (annotatedType == null) tpe else annotatedType
- rebindTo(Typed(WILD(tpe), TypeTree(aType)) setType tpe)
- }
-
- // Wrap them around _
- def rebindToEmpty(tpe: Type): Pattern =
- rebindTo(Typed(EmptyTree, TypeTree(tpe)) setType tpe)
-
- // Wrap them around a singleton type for an EqualsPattern check.
- def rebindToEqualsCheck(): Pattern =
- rebindToType(equalsCheck)
-
- // Like rebindToEqualsCheck, but subtly different. Not trying to be
- // mysterious -- I haven't sorted it all out yet.
- def rebindToObjectCheck(): Pattern = {
- val sType = mkSingleton
- rebindToType(mkEqualsRef(sType), sType)
- }
-
- /** Helpers **/
- private def strip(t: Tree): List[Symbol] = t match {
- case b @ Bind(_, pat) => b.symbol :: strip(pat)
- case _ => Nil
- }
- }
/*** Extractors ***/
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index c5d8e481fe..0118c0f9cc 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -10,7 +10,7 @@ package transform
import symtab._
import Flags.{ CASE => _, _ }
import scala.collection.mutable.ListBuffer
-import matching.{ TransMatcher, Patterns, PatternNodes, ParallelMatching }
+import matching.{ TransMatcher, Patterns, ParallelMatching }
/** This class ...
*
@@ -19,7 +19,6 @@ import matching.{ TransMatcher, Patterns, PatternNodes, ParallelMatching }
*/
abstract class ExplicitOuter extends InfoTransform
with TransMatcher
- with PatternNodes
with Patterns
with ParallelMatching
with TypingTransformers