Permalink
Browse files

simplify dependencies between patmat components, remove self types

  • Loading branch information...
adriaanm committed Feb 23, 2013
1 parent 5d54cf9 commit ebaa34e84dbefd2fa60f3efd09484ce6c8d0faac
@@ -287,7 +287,11 @@ trait Logic extends Debugging {
def findModelFor(f: Formula): Model
def findAllModelsFor(f: Formula): List[Model]
}
+}
+// naive CNF translation and simple DPLL solver
+trait SimpleSolver extends Logic {
+ import PatternMatchingStats._
trait CNF extends PropositionalLogic {
/** Override Array creation for efficiency (to not go through reflection). */
@@ -397,7 +401,8 @@ trait Logic extends Debugging {
}
}
- trait DPLLSolver extends CNF {
+ // simple solver using DPLL
+ trait Solver extends CNF {
// a literal is a (possibly negated) variable
def Lit(sym: Sym, pos: Boolean = true) = new Lit(sym, pos)
class Lit(val sym: Sym, val pos: Boolean) {
@@ -516,7 +521,7 @@ trait Logic extends Debugging {
}
}
-trait ScalaLogic extends Logic { self: PatternMatching =>
+trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis {
type Type = global.Type
type Tree = global.Tree
@@ -125,7 +125,7 @@ trait TreeAndTypeAnalysis extends Debugging {
}
}
-trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
+trait MatchAnalysis extends TreeAndTypeAnalysis with ScalaLogic with MatchTreeMaking {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, CaseDef, atPos,
Select, Block, ThisType, SingleType, NoPrefix, NoType, definitions, needsOuterTest,
@@ -141,7 +141,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
* Represent a match as a formula in propositional logic that encodes whether the match matches (abstractly: we only consider types)
*
*/
- trait TreeMakerApproximation extends TreeMakers with PropositionalLogic with TreesAndTypesDomain with CheckableTreeAndTypeAnalysis { self: CodegenCore =>
+ trait TreeMakerApproximation extends TreeMakers with TreesAndTypesDomain {
object Test {
var currId = 0
}
@@ -348,7 +348,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
}
}
- trait SymbolicMatchAnalysis extends TreeMakerApproximation { self: CodegenCore =>
+ trait MatchAnalyses extends TreeMakerApproximation {
def uncheckedWarning(pos: Position, msg: String) = global.currentUnit.uncheckedWarning(pos, msg)
def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}")
@@ -498,7 +498,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// a way to construct a value that will make the match fail: a constructor invocation, a constant, an object of some type)
class CounterExample {
- protected[SymbolicMatchAnalysis] def flattenConsArgs: List[CounterExample] = Nil
+ protected[MatchAnalyses] def flattenConsArgs: List[CounterExample] = Nil
def coveredBy(other: CounterExample): Boolean = this == other || other == WildcardExample
}
case class ValueExample(c: ValueConst) extends CounterExample { override def toString = c.toString }
@@ -513,11 +513,11 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
}
}
case class ListExample(ctorArgs: List[CounterExample]) extends CounterExample {
- protected[SymbolicMatchAnalysis] override def flattenConsArgs: List[CounterExample] = ctorArgs match {
+ protected[MatchAnalyses] override def flattenConsArgs: List[CounterExample] = ctorArgs match {
case hd :: tl :: Nil => hd :: tl.flattenConsArgs
case _ => Nil
}
- protected[SymbolicMatchAnalysis] lazy val elems = flattenConsArgs
+ protected[MatchAnalyses] lazy val elems = flattenConsArgs
override def coveredBy(other: CounterExample): Boolean =
other match {
@@ -691,5 +691,16 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// this is the variable we want a counter example for
VariableAssignment(scrutVar).toCounterExample()
}
+
+ def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): Unit = {
+ unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
+ reportUnreachable(cases(caseIndex).last.pos)
+ }
+ if (!unchecked) {
+ val counterExamples = exhaustive(prevBinder, cases, pt)
+ if (counterExamples.nonEmpty)
+ reportMissingCases(prevBinder.pos, counterExamples)
+ }
+ }
}
}
@@ -17,7 +17,7 @@ import scala.reflect.internal.util.NoPosition
* We have two modes in which to emit trees: optimized (the default)
* and pure (aka "virtualized": match is parametric in its monad).
*/
-trait MatchCodeGen { self: PatternMatching =>
+trait MatchCodeGen extends Interface {
import PatternMatchingStats._
import global.{nme, treeInfo, definitions, gen, Tree, Type, Symbol, NoSymbol,
appliedType, NoType, MethodType, newTermName, Name,
@@ -19,7 +19,7 @@ import scala.reflect.internal.util.NoPosition
*
* TODO: split out match analysis
*/
-trait MatchOptimization { self: PatternMatching =>
+trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, NoSymbol, CaseDef, atPos,
ConstantType, Literal, Constant, gen, EmptyTree,
@@ -205,7 +205,7 @@ trait MatchOptimization { self: PatternMatching =>
//// DCE
- trait DeadCodeElimination extends TreeMakers { self: CodegenCore =>
+ trait DeadCodeElimination extends TreeMakers {
// TODO: non-trivial dead-code elimination
// e.g., the following match should compile to a simple instanceof:
// case class Ident(name: String)
@@ -217,7 +217,7 @@ trait MatchOptimization { self: PatternMatching =>
}
//// SWITCHES -- TODO: operate on Tests rather than TreeMakers
- trait SwitchEmission extends TreeMakers with OptimizedMatchMonadInterface { self: CodegenCore =>
+ trait SwitchEmission extends TreeMakers with OptimizedMatchMonadInterface {
import treeInfo.isGuardedCase
abstract class SwitchMaker {
@@ -589,25 +589,11 @@ trait MatchOptimization { self: PatternMatching =>
}
}
-
-
-
trait MatchOptimizations extends CommonSubconditionElimination
with DeadCodeElimination
with SwitchEmission
- with OptimizedCodegen
- with SymbolicMatchAnalysis
- with DPLLSolver { self: TreeMakers =>
- override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) = {
- unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
- reportUnreachable(cases(caseIndex).last.pos)
- }
- if (!unchecked) {
- val counterExamples = exhaustive(prevBinder, cases, pt)
- if (counterExamples.nonEmpty)
- reportMissingCases(prevBinder.pos, counterExamples)
- }
-
+ with OptimizedCodegen {
+ override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): (List[List[TreeMaker]], List[Tree]) = {
val optCases = doCSE(prevBinder, doDCE(prevBinder, cases, pt), pt)
val toHoist = (
for (treeMakers <- optCases)
@@ -24,7 +24,7 @@ trait MatchTranslation { self: PatternMatching =>
repeatedToSeq, isRepeatedParamType, getProductArgs}
import global.analyzer.{ErrorUtils, formalTypes}
- trait MatchTranslator extends MatchMonadInterface { self: TreeMakers with CodegenCore =>
+ trait MatchTranslator extends TreeMakers {
import typer.context
// Why is it so difficult to say "here's a name and a context, give me any
@@ -18,7 +18,7 @@ import scala.reflect.internal.util.NoPosition
* The IR is mostly concerned with sequencing, substitution, and rendering all necessary conditions,
* mostly agnostic to whether we're in optimized/pure (virtualized) mode.
*/
-trait MatchTreeMaking { self: PatternMatching =>
+trait MatchTreeMaking extends MatchCodeGen with Debugging {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, CaseDef, atPos, settings,
Select, Block, ThisType, SingleType, NoPrefix, NoType, needsOuterTest,
@@ -30,9 +30,9 @@ trait MatchTreeMaking { self: PatternMatching =>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the making of the trees
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- trait TreeMakers extends TypedSubstitution { self: CodegenCore =>
- def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) =
- (cases, Nil)
+ trait TreeMakers extends TypedSubstitution with CodegenCore {
+ def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): (List[List[TreeMaker]], List[Tree])
+ def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): Unit
def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type, matchFailGenOverride: Option[Tree => Tree], unchecked: Boolean): Option[Tree] =
None
@@ -550,7 +550,9 @@ trait MatchTreeMaking { self: PatternMatching =>
}) None
else matchFailGen
- val (cases, toHoist) = optimizeCases(scrutSym, casesNoSubstOnly, pt, unchecked)
+ analyzeCases(scrutSym, casesNoSubstOnly, pt, unchecked)
+
+ val (cases, toHoist) = optimizeCases(scrutSym, casesNoSubstOnly, pt)
val matchRes = codegen.matcher(scrut, scrutSym, pt)(cases map combineExtractors, synthCatchAll)
@@ -34,13 +34,14 @@ import scala.reflect.internal.util.Position
* - recover GADT typing by locally inserting implicit witnesses to type equalities derived from the current case, and considering these witnesses during subtyping (?)
* - recover exhaustivity/unreachability of user-defined extractors by partitioning the types they match on using an HList or similar type-level structure
*/
-trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
+trait PatternMatching extends Transform with TypingTransformers
with Debugging
with Interface
with MatchTranslation
with MatchTreeMaking
with MatchCodeGen
with ScalaLogic
+ with SimpleSolver
with MatchAnalysis
with MatchOptimization {
import global._
@@ -78,23 +79,28 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- class PureMatchTranslator(val typer: analyzer.Typer, val matchStrategy: Tree) extends MatchTranslator with TreeMakers with PureCodegen
- class OptimizingMatchTranslator(val typer: analyzer.Typer) extends MatchTranslator with TreeMakers with MatchOptimizations
+ class PureMatchTranslator(val typer: analyzer.Typer, val matchStrategy: Tree) extends MatchTranslator with PureCodegen {
+ def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type) = (cases, Nil)
+ def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): Unit = {}
+ }
+
+ class OptimizingMatchTranslator(val typer: analyzer.Typer) extends MatchTranslator
+ with MatchOptimizations
+ with MatchAnalyses
+ with Solver
}
-trait HasGlobal {
+trait Debugging {
val global: Global
-}
-trait Debugging extends HasGlobal {
// TODO: the inliner fails to inline the closures to debug.patmat unless the method is nested in an object
object debug {
val printPatmat = global.settings.Ypatmatdebug.value
@inline final def patmat(s: => String) = if (printPatmat) println(s)
}
}
-trait Interface { self: ast.TreeDSL with HasGlobal =>
+trait Interface extends ast.TreeDSL {
import global.{newTermName, analyzer, Type, ErrorType, Symbol, Tree}
import analyzer.Typer

0 comments on commit ebaa34e

Please sign in to comment.