aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/transform/PatternMatcher.scala
diff options
context:
space:
mode:
authorDmitry Petrashko <dmitry.petrashko@gmail.com>2014-09-09 15:24:59 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-09-17 18:07:16 +0200
commit4c62011df6584e4ebe98a012a3b1a438679f8735 (patch)
treefaa11b3b6c67d3e9443562f140a5b6ea576a530e /src/dotty/tools/dotc/transform/PatternMatcher.scala
parentfa5212f8e3fb3be08a92b921b87553b5827b1417 (diff)
downloaddotty-4c62011df6584e4ebe98a012a3b1a438679f8735.tar.gz
dotty-4c62011df6584e4ebe98a012a3b1a438679f8735.tar.bz2
dotty-4c62011df6584e4ebe98a012a3b1a438679f8735.zip
CommonCodegen for patMat
Diffstat (limited to 'src/dotty/tools/dotc/transform/PatternMatcher.scala')
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala144
1 files changed, 140 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index a6846a405..32655da21 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -9,17 +9,153 @@ import core.Symbols._
import core.Types._
import core.Constants._
import core.StdNames._
+import core.transform.Erasure.isUnboundedGeneric
import typer.ErrorReporting._
import ast.Trees._
+import dotty.tools.dotc.util.Positions.Position
+import dotty.tools.dotc.core.Decorators._
+import dotty.tools.dotc.core.Flags
+
/** This transform eliminates patterns. Right now it's a dummy.
* Awaiting the real pattern matcher.
*/
class PatternMatcher extends MiniPhaseTransform {
- import ast.tpd._
+ import dotty.tools.dotc.ast.tpd._
+
+ implicit val ctx: Context = ???
+
+ def name: String = "patternMatcher"
+
+ /*override def transformCaseDef(tree: CaseDef)(implicit ctx: Context, info: TransformerInfo): Tree =
+ cpy.CaseDef(tree, Literal(Constant("<eliminated pattern>")), tree.guard, tree.body)*/
+
+
+ /*case Try(block, catches, finalizer) =>
+ treeCopy.Try(tree, transform(block), translator.translateTry(transformTrees(catches).asInstanceOf[List[CaseDef]], tree.tpe, tree.pos), transform(finalizer))
+ case _ => super.transform(tree)*/
+ /*override def transformMatch(tree: tpd.Match)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = {
+ case Match(sel, cases) =>
+ val origTp = tree.tpe
+ // setType origTp intended for CPS -- TODO: is it necessary?
+ val translated = translator.translateMatch(treeCopy.Match(tree, transform(sel), transformTrees(cases).asInstanceOf[List[CaseDef]]))
+ try {
+ localTyper.typed(translated) setType origTp
+ } catch {
+ case x: (Types#TypeError) =>
+ // TODO: this should never happen; error should've been reported during type checking
+ unit.error(tree.pos, "error during expansion of this match (this is a scalac bug).\nThe underlying error was: "+ x.msg)
+ translated
+ }
+ }*/
+
+
+ def translator = {
+ new OptimizingMatchTranslator/*(localTyper)*/
+ }
+
+ class OptimizingMatchTranslator/*(val typer: analyzer.Typer)*/ /*extends MatchTranslator
+ with MatchOptimizer*/
+
+ trait Debugging {
+
+ // 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
+ final def patmat(s: => String) = /*if (printPatmat) Console.err.*/
+ println(s)
+ final def patmatResult[T](s: => String)(result: T): T = {
+ /*if (printPatmat) Console.err.*/
+ println(s + ": " + result)
+ result
+ }
+ }
+ }
+
+ trait MatchMonadInterface {
+ // val typer: Typer
+ def matchOwner(implicit ctx: Context) = ctx.owner
+ def pureType(tp: Type): Type = tp
+
+ def reportUnreachable(pos: Position) = {
+ ctx.warning("unreachable code", pos)
+ }
+ def reportMissingCases(pos: Position, counterExamples: List[String]) = {
+ val ceString =
+ if (counterExamples.tail.isEmpty) "input: " + counterExamples.head
+ else "inputs: " + counterExamples.mkString(", ")
+
+ ctx.warning("match may not be exhaustive.\nIt would fail on the following "+ ceString, pos)
+ }
+ }
+
+ trait CodegenCore extends MatchMonadInterface {
+ private var ctr = 0
+ def freshName(prefix: String) = ctx.freshName(prefix).toTermName
+
+ // assert(owner ne null); assert(owner ne NoSymbol)
+ def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x") =
+ ctx.newSymbol(ctx.owner, freshName(prefix) ,Flags.Synthetic, tp, coord = pos)
+
+ def newSynthCaseLabel(name: String) = ???
+ //NoSymbol.newLabel(freshName(name), NoPosition) setFlag treeInfo.SYNTH_CASE_FLAGS
+
+ // codegen relevant to the structure of the translation (how extractors are combined)
+ trait AbsCodegen {
+ def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree
+
+ // local / context-free
+ def _asInstanceOf(b: Symbol, tp: Type): Tree
+ def _equals(checker: Tree, binder: Symbol): Tree
+ def _isInstanceOf(b: Symbol, tp: Type): Tree
+ def drop(tgt: Tree)(n: Int): Tree
+ def index(tgt: Tree)(i: Int): Tree
+ def mkZero(tp: Type): Tree
+ def tupleSel(binder: Symbol)(i: Int): Tree
+ }
+
+ // structure
+ trait Casegen extends AbsCodegen {
+ def one(res: Tree): Tree
+
+ def flatMap(prev: Tree, b: Symbol, next: Tree): Tree
+ def flatMapCond(cond: Tree, res: Tree, nextBinder: Symbol, next: Tree): Tree
+ def flatMapGuard(cond: Tree, next: Tree): Tree
+ def ifThenElseZero(c: Tree, thenp: Tree): Tree =
+ If(c, thenp, zero)
+ protected def zero: Tree
+ }
+
+ def codegen: AbsCodegen
+
+ abstract class CommonCodegen extends AbsCodegen {
+ def fun(arg: TermSymbol, body: Tree): Tree =
+ DefDef(arg, body)
+
+ def tupleSel(binder: Symbol)(i: Int): Tree = ref(binder).select(nme.productAccessorName(i)) // make tree that accesses the i'th component of the tuple referenced by binder
+ def index(tgt: Tree)(i: Int): Tree = tgt.appliedTo(Literal(Constant(i)))
+
+ // Right now this blindly calls drop on the result of the unapplySeq
+ // unless it verifiably has no drop method (this is the case in particular
+ // with Array.) You should not actually have to write a method called drop
+ // for name-based matching, but this was an expedient route for the basics.
+ def drop(tgt: Tree)(n: Int): Tree = {
+ def callDirect = tgt.select(nme.drop).appliedTo(Literal(Constant(n)))
+ def callRuntime = ref(ctx.definitions.traversableDropMethod).appliedTo(tgt, Literal(Constant(n)))
+
+ def needsRuntime = (tgt.tpe ne null) && tgt.tpe.baseTypeRef(ctx.definitions.SeqType.classSymbol).member(nme.drop).exists /*typeOfMemberNamedDrop(tgt.tpe) == NoType*/
+
+ if (needsRuntime) callRuntime else callDirect
+ }
+
+ // NOTE: checker must be the target of the ==, that's the patmat semantics for ya
+ def _equals(checker: Tree, binder: Symbol): Tree = checker.select(defn.Any_equals).appliedTo(ref(binder))
- override def phaseName: String = "patternMatcher"
+ // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
+ def _asInstanceOf(b: Symbol, tp: Type): Tree = if (b.info <:< tp) ref(b) else ref(b).select(defn.Any_asInstanceOf).appliedToType(tp)
+ def _isInstanceOf(b: Symbol, tp: Type): Tree = ref(b).select(defn.Any_isInstanceOf).appliedToType(tp)
- override def transformCaseDef(tree: CaseDef)(implicit ctx: Context, info: TransformerInfo): Tree =
- cpy.CaseDef(tree)(Literal(Constant("<eliminated pattern>")), tree.guard, tree.body)
+ def mkZero(tp: Type): Tree = initValue(tp)
+ }
+ }
} \ No newline at end of file