aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-12-20 11:33:05 +0100
committerMartin Odersky <odersky@gmail.com>2013-12-20 11:38:39 +0100
commit146a362bf74418feeb18e12c34178819ecb64942 (patch)
tree2dec7acd61107a673ce859450cccfad9b50dba88 /src/dotty
parentbac6a2081d971c7f5c87b610cfaac7cd39c06713 (diff)
downloaddotty-146a362bf74418feeb18e12c34178819ecb64942.tar.gz
dotty-146a362bf74418feeb18e12c34178819ecb64942.tar.bz2
dotty-146a362bf74418feeb18e12c34178819ecb64942.zip
Handling implicit unapply arguments.
Changed format of UnApply nodes to also take implicit parameters. See doc comment in class Trees.UnApply
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/CheckTrees.scala2
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala30
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala4
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala10
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala20
7 files changed, 48 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala
index 56a8b9a88..6152a2880 100644
--- a/src/dotty/tools/dotc/ast/CheckTrees.scala
+++ b/src/dotty/tools/dotc/ast/CheckTrees.scala
@@ -195,7 +195,7 @@ object CheckTrees {
}
case Alternative(alts) =>
for (alt <- alts) check(alt.isValueOrPattern)
- case UnApply(fun, args) => // todo: review
+ case UnApply(fun, implicits, args) => // todo: review
check(fun.isTerm)
for (arg <- args) check(arg.isValueOrPattern)
val funtpe @ MethodType(_, _) = fun.tpe.widen
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 388cf8579..183e5a2e4 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -640,8 +640,20 @@ object Trees {
type ThisTree[-T >: Untyped] = Alternative[T]
}
- /** fun(args) in a pattern, if fun is an extractor */
- case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], args: List[Tree[T]])
+ /** The typed translation of `extractor(patterns)` in a pattern. The translation has the following
+ * components:
+ *
+ * @param fun is `extractor.unapply` (or, for backwards compatibility, `extractor.unapplySeq`)
+ * possibly with type parameters
+ * @param implicits Any implicit parameters passed to the unapply after the selector
+ * @param patterns The argument patterns in the pattern match.
+ *
+ * Given a match selector `sel` a pattern UnApply(fun, implicits, patterns) is roughly translated as follows
+ *
+ * val result = fun(sel)(implicits)
+ * if (result.isDefined) "match patterns against result"
+ */
+ case class UnApply[-T >: Untyped] private[ast] (fun: Tree[T], implicits: List[Tree[T]], patterns: List[Tree[T]])
extends PatternTree[T] {
type ThisTree[-T >: Untyped] = UnApply[T]
}
@@ -1014,9 +1026,9 @@ object Trees {
case tree: Alternative if (trees eq tree.trees) => tree
case _ => finalize(tree, untpd.Alternative(trees))
}
- def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply = tree match {
- case tree: UnApply if (fun eq tree.fun) && (args eq tree.args) => tree
- case _ => finalize(tree, untpd.UnApply(fun, args))
+ def UnApply(tree: Tree, fun: Tree, implicits: List[Tree], patterns: List[Tree]): UnApply = tree match {
+ case tree: UnApply if (fun eq tree.fun) && (implicits eq tree.implicits) && (patterns eq tree.patterns) => tree
+ case _ => finalize(tree, untpd.UnApply(fun, implicits, patterns))
}
def ValDef(tree: Tree, mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef = tree match {
case tree: ValDef if (mods == tree.mods) && (name == tree.name) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
@@ -1122,8 +1134,8 @@ object Trees {
cpy.Bind(tree, name, transform(body))
case Alternative(trees) =>
cpy.Alternative(tree, transform(trees))
- case UnApply(fun, args) =>
- cpy.UnApply(tree, transform(fun), transform(args))
+ case UnApply(fun, implicits, patterns) =>
+ cpy.UnApply(tree, transform(fun), transform(implicits), transform(patterns))
case ValDef(mods, name, tpt, rhs) =>
cpy.ValDef(tree, mods, name, transform(tpt), transform(rhs))
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
@@ -1227,8 +1239,8 @@ object Trees {
this(x, body)
case Alternative(trees) =>
this(x, trees)
- case UnApply(fun, args) =>
- this(this(x, fun), args)
+ case UnApply(fun, implicits, patterns) =>
+ this(this(this(x, fun), implicits), patterns)
case ValDef(mods, name, tpt, rhs) =>
this(this(x, tpt), rhs)
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 195797b2b..8d079fa72 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -205,12 +205,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def Alternative(trees: List[Tree])(implicit ctx: Context): Alternative =
untpd.Alternative(trees).withType(ctx.typeComparer.lub(trees map (_.tpe))).checked
- def UnApply(fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = {
+ def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree])(implicit ctx: Context): UnApply = {
val owntype = fun.tpe.widen match {
case MethodType(_, paramType :: Nil) => paramType
case _ => check(false); ErrorType
}
- untpd.UnApply(fun, args).withType(owntype).checked
+ untpd.UnApply(fun, implicits, patterns).withType(owntype).checked
}
def ValDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): ValDef =
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index 740e8f110..afb3ba63a 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -82,7 +82,7 @@ object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] {
def TypeBoundsTree(lo: Tree, hi: Tree): TypeBoundsTree = new TypeBoundsTree(lo, hi)
def Bind(name: Name, body: Tree): Bind = new Bind(name, body)
def Alternative(trees: List[Tree]): Alternative = new Alternative(trees)
- def UnApply(fun: Tree, args: List[Tree]): UnApply = new UnApply(fun, args)
+ def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree]): UnApply = new UnApply(fun, implicits, patterns)
def ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef = new ValDef(mods, name, tpt, rhs)
def DefDef(mods: Modifiers, name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef = new DefDef(mods, name, tparams, vparamss, tpt, rhs)
def TypeDef(mods: Modifiers, name: TypeName, rhs: Tree): TypeDef = new TypeDef(mods, name, rhs)
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 88dbca4f7..177a8f21d 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -979,7 +979,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
case UNAPPLYtree =>
val fun = readTreeRef()
val args = until(end, readTreeRef)
- UnApply(fun, args)
+ UnApply(fun, Nil, args) // !!! this is wrong in general
case ARRAYVALUEtree =>
val elemtpt = readTreeRef()
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index b4221d7eb..3636731aa 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -241,8 +241,14 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
changePrec(InfixPrec) { toText(name) ~ " @ " ~ toText(body) }
case Alternative(trees) =>
changePrec(OrPrec) { toText(trees, " | ") }
- case UnApply(fun, args) =>
- toTextLocal(fun) ~ "(" ~ toTextGlobal(args, ", ") ~ ")"
+ case UnApply(fun, implicits, patterns) =>
+ val extractor = fun match {
+ case Select(extractor, nme.unapply) => extractor
+ case _ => fun
+ }
+ toTextLocal(extractor) ~
+ "(" ~ toTextGlobal(patterns, ", ") ~ ")" ~
+ ("(" ~ toTextGlobal(implicits, ", ") ~ ")" provided implicits.nonEmpty)
case ValDef(mods, name, tpt, rhs) =>
modText(mods, if (mods is Mutable) "var" else "val") ~~ toText(name) ~
optAscription(tpt) ~ optText(rhs)(" = " ~ _)
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index ad6bdd787..08987a095 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -629,7 +629,7 @@ trait Applications extends Compatibility { self: Typer =>
}
unapply.tpe.widen match {
- case mt: MethodType if !mt.isDependent =>
+ case mt: MethodType if mt.paramTypes.length == 1 && !mt.isDependent =>
val unapplyArgType = mt.paramTypes.head
println(s"unapp arg tpe = ${unapplyArgType.show}, pt = ${pt.show}")
def wpt = widenForMatchSelector(pt)
@@ -671,7 +671,15 @@ trait Applications extends Compatibility { self: Typer =>
i"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $wpt",
tree.pos)
}
- var argTypes = unapplyArgs(mt.resultType)
+
+ val dummyArg = dummyTreeOfType(unapplyArgType)
+ val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapply, dummyArg :: Nil)))
+ val unapplyImplicits = unapplyApp match {
+ case Apply(Apply(unapply, `dummyArg` :: Nil), args2) => assert(args2.nonEmpty); args2
+ case Apply(unapply, `dummyArg` :: Nil) => Nil
+ }
+
+ var argTypes = unapplyArgs(unapplyApp.tpe)
val bunchedArgs = argTypes match {
case argType :: Nil if argType.isRepeatedParam => untpd.SeqLiteral(args) :: Nil
case _ => args
@@ -681,15 +689,15 @@ trait Applications extends Compatibility { self: Typer =>
argTypes = argTypes.take(args.length) ++
List.fill(argTypes.length - args.length)(WildcardType)
}
- val typedArgs = (bunchedArgs, argTypes).zipped map (typed(_, _))
- val result = cpy.UnApply(tree, unapply, typedArgs) withType ownType
- println(s"typedargs = $typedArgs")
+ val unapplyPatterns = (bunchedArgs, argTypes).zipped map (typed(_, _))
+ val result = cpy.UnApply(tree, unapply, unapplyImplicits, unapplyPatterns) withType ownType
+ println(s"unapply patterns = $unapplyPatterns")
if ((ownType eq pt) || ownType.isError) result
else Typed(result, TypeTree(ownType))
case tp =>
val unapplyErr = if (tp.isError) unapply else notAnExtractor(unapply)
val typedArgsErr = args mapconserve (typed(_, defn.AnyType))
- cpy.UnApply(tree, unapplyErr, typedArgsErr) withType ErrorType
+ cpy.UnApply(tree, unapplyErr, Nil, typedArgsErr) withType ErrorType
}
}