aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitry Petrashko <dmitry.petrashko@gmail.com>2014-10-28 21:02:42 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-10-30 17:22:14 +0100
commite07e9a3986ec59cab1f0ec2b9b4458fd6a64d8c8 (patch)
tree051fd810ac9f1b690c7e7f1cb56508a2d903ebfd /src
parent6dcd16ab2040a5a337e78bc77e40228dc9944662 (diff)
downloaddotty-e07e9a3986ec59cab1f0ec2b9b4458fd6a64d8c8.tar.gz
dotty-e07e9a3986ec59cab1f0ec2b9b4458fd6a64d8c8.tar.bz2
dotty-e07e9a3986ec59cab1f0ec2b9b4458fd6a64d8c8.zip
Restructure Try node.
Now Try node always has cases as handlers. In case handler is an Ident of type Throwable => T than it's desugared to a CaseDef during parsing.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala16
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala16
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala2
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala10
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala13
-rw-r--r--src/dotty/tools/dotc/transform/LazyVals.scala15
-rw-r--r--src/dotty/tools/dotc/transform/PatternMatcher.scala2
-rw-r--r--src/dotty/tools/dotc/transform/TailRec.scala9
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala4
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala9
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala15
13 files changed, 55 insertions, 59 deletions
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index d7dcff992..4cd41cc2e 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -611,7 +611,7 @@ object Trees {
*
* Match(EmptyTree, <case x: Throwable => $anonfun(x)>)
*/
- case class Try[-T >: Untyped] private[ast] (expr: Tree[T], handler: Tree[T], finalizer: Tree[T])
+ case class Try[-T >: Untyped] private[ast] (expr: Tree[T], cases: List[CaseDef[T]], finalizer: Tree[T])
extends TermTree[T] {
type ThisTree[-T >: Untyped] = Try[T]
}
@@ -1027,9 +1027,9 @@ object Trees {
case tree: Return if (expr eq tree.expr) && (from eq tree.from) => tree
case _ => finalize(tree, untpd.Return(expr, from))
}
- def Try(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try = tree match {
- case tree: Try if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree
- case _ => finalize(tree, untpd.Try(expr, handler, finalizer))
+ def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = tree match {
+ case tree: Try if (expr eq tree.expr) && (cases eq tree.cases) && (finalizer eq tree.finalizer) => tree
+ case _ => finalize(tree, untpd.Try(expr, cases, finalizer))
}
def Throw(tree: Tree)(expr: Tree)(implicit ctx: Context): Throw = tree match {
case tree: Throw if (expr eq tree.expr) => tree
@@ -1131,8 +1131,8 @@ object Trees {
Closure(tree: Tree)(env, meth, tpt)
def CaseDef(tree: CaseDef)(pat: Tree = tree.pat, guard: Tree = tree.guard, body: Tree = tree.body)(implicit ctx: Context): CaseDef =
CaseDef(tree: Tree)(pat, guard, body)
- def Try(tree: Try)(expr: Tree = tree.expr, handler: Tree = tree.handler, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
- Try(tree: Tree)(expr, handler, finalizer)
+ def Try(tree: Try)(expr: Tree = tree.expr, cases: List[CaseDef] = tree.cases, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
+ Try(tree: Tree)(expr, cases, finalizer)
def UnApply(tree: UnApply)(fun: Tree = tree.fun, implicits: List[Tree] = tree.implicits, patterns: List[Tree] = tree.patterns): UnApply =
UnApply(tree: Tree)(fun, implicits, patterns)
def ValDef(tree: ValDef)(mods: Modifiers = tree.mods, name: TermName = tree.name, tpt: Tree = tree.tpt, rhs: Tree = tree.rhs): ValDef =
@@ -1184,8 +1184,8 @@ object Trees {
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
case Return(expr, from) =>
cpy.Return(tree)(transform(expr), transformSub(from))
- case Try(block, handler, finalizer) =>
- cpy.Try(tree)(transform(block), transform(handler), transform(finalizer))
+ case Try(block, cases, finalizer) =>
+ cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
case Throw(expr) =>
cpy.Throw(tree)(transform(expr))
case SeqLiteral(elems) =>
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 4c21fcf49..d0f64f5a7 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -113,8 +113,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def Return(expr: Tree, from: Tree)(implicit ctx: Context): Return =
ta.assignType(untpd.Return(expr, from))
- def Try(block: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try =
- ta.assignType(untpd.Try(block, handler, finalizer), block, handler)
+ def Try(block: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try =
+ ta.assignType(untpd.Try(block, cases, finalizer), block, cases)
def Throw(expr: Tree)(implicit ctx: Context): Throw =
ta.assignType(untpd.Throw(expr))
@@ -457,11 +457,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
override def Return(tree: Tree)(expr: Tree, from: Tree)(implicit ctx: Context): Return =
ta.assignType(untpd.cpy.Return(tree)(expr, from))
- override def Try(tree: Tree)(expr: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try = {
- val tree1 = untpd.cpy.Try(tree)(expr, handler, finalizer)
+ override def Try(tree: Tree)(expr: Tree, cases: List[CaseDef], finalizer: Tree)(implicit ctx: Context): Try = {
+ val tree1 = untpd.cpy.Try(tree)(expr, cases, finalizer)
tree match {
- case tree: Try if (expr.tpe eq tree.expr.tpe) && (handler.tpe eq tree.handler.tpe) => tree1.withTypeUnchecked(tree.tpe)
- case _ => ta.assignType(tree1, expr, handler)
+ case tree: Try if (expr.tpe eq tree.expr.tpe) && (sameTypes(cases, tree.cases)) => tree1.withTypeUnchecked(tree.tpe)
+ case _ => ta.assignType(tree1, expr, cases)
}
}
@@ -490,8 +490,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Closure(tree: Tree)(env, meth, tpt)
override def CaseDef(tree: CaseDef)(pat: Tree = tree.pat, guard: Tree = tree.guard, body: Tree = tree.body)(implicit ctx: Context): CaseDef =
CaseDef(tree: Tree)(pat, guard, body)
- override def Try(tree: Try)(expr: Tree = tree.expr, handler: Tree = tree.handler, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
- Try(tree: Tree)(expr, handler, finalizer)
+ override def Try(tree: Try)(expr: Tree = tree.expr, cases: List[CaseDef] = tree.cases, finalizer: Tree = tree.finalizer)(implicit ctx: Context): Try =
+ Try(tree: Tree)(expr, cases, finalizer)
}
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index 5a6c9fa89..a5072bc96 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -123,7 +123,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def Match(selector: Tree, cases: List[CaseDef]): Match = new Match(selector, cases)
def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body)
def Return(expr: Tree, from: Tree): Return = new Return(expr, from)
- def Try(expr: Tree, handler: Tree, finalizer: Tree): Try = new Try(expr, handler, finalizer)
+ def Try(expr: Tree, cases: List[CaseDef], finalizer: Tree): Try = new Try(expr, cases, finalizer)
def Throw(expr: Tree): Throw = new Throw(expr)
def SeqLiteral(elems: List[Tree]): SeqLiteral = new SeqLiteral(elems)
def JavaSeqLiteral(elems: List[Tree]): JavaSeqLiteral = new JavaSeqLiteral(elems)
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index f7354a8b4..99290f084 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -121,6 +121,7 @@ object StdNames {
val SUPER_PREFIX: N = "super$"
val TRAIT_SETTER_PREFIX: N = "_setter_$"
val WHILE_PREFIX: N = "while$"
+ val DEFAULT_EXCEPTION_NAME: N = "ex$"
// value types (and AnyRef) are all used as terms as well
// as (at least) arguments to the @specialize annotation.
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 3510462cc..60000441c 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -1035,7 +1035,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
val block = readTreeRef()
val finalizer = readTreeRef()
val catches = until(end, readCaseDefRef)
- Try(block, Match(EmptyTree, catches), finalizer)
+ Try(block, catches, finalizer)
case THROWtree =>
Throw(readTreeRef())
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 1efc2d31c..a787f9712 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -914,7 +914,15 @@ object Parsers {
val finalizer =
if (handler.isEmpty || in.token == FINALLY) { accept(FINALLY); expr() }
else EmptyTree
- Try(body, handler, finalizer)
+ handler match {
+ case Match(sel, cases) => Try(body, cases, finalizer)
+ case EmptyTree => Try(body, Nil, finalizer)
+ case _ =>
+ Try(body,
+ List(CaseDef(Ident(nme.DEFAULT_EXCEPTION_NAME), EmptyTree, Apply(handler, Ident(nme.DEFAULT_EXCEPTION_NAME)))),
+ finalizer)
+ }
+
}
case THROW =>
atPos(in.skipToken()) { Throw(expr()) }
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index d9e248e40..f0d558824 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -141,6 +141,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
super.toText(tp)
}
+ def blockText[T >: Untyped](trees: List[Tree[T]]): Text =
+ "{" ~ toText(trees, "\n") ~ "}"
+
override def toText[T >: Untyped](tree: Tree[T]): Text = controlled {
def optDotPrefix(name: Name) = optText(name)(_ ~ ".")
@@ -155,8 +158,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def addVparamssText(txt: Text, vparamss: List[List[ValDef[T]]]): Text =
(txt /: vparamss)((txt, vparams) => txt ~ "(" ~ toText(vparams, ", ") ~ ")")
- def blockText(trees: List[Tree[T]]): Text =
- "{" ~ toText(trees, "\n") ~ "}"
+
def caseBlockText(tree: Tree[T]): Text = tree match {
case Block(stats, expr) => toText(stats :+ expr, "\n")
@@ -261,9 +263,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
"case " ~ toText(pat) ~ optText(guard)(" if " ~ _) ~ " => " ~ caseBlockText(body)
case Return(expr, from) =>
changePrec(GlobalPrec) { "return" ~ optText(expr)(" " ~ _) }
- case Try(expr, handler, finalizer) =>
+ case Try(expr, cases, finalizer) =>
changePrec(GlobalPrec) {
- "try " ~ toText(expr) ~ optText(handler)(" catch " ~ _) ~ optText(finalizer)(" finally " ~ _)
+ "try " ~ toText(expr) ~ optText(cases)(" catch " ~ _) ~ optText(finalizer)(" finally " ~ _)
}
case Throw(expr) =>
changePrec(GlobalPrec) {
@@ -461,6 +463,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def optText[T >: Untyped](tree: Tree[T])(encl: Text => Text): Text =
if (tree.isEmpty) "" else encl(toText(tree))
+ def optText[T >: Untyped](tree: List[Tree[T]])(encl: Text => Text): Text =
+ if (tree.exists(!_.isEmpty)) "" else encl(blockText(tree))
+
override protected def polyParamName(name: TypeName): TypeName =
name.unexpandedName()
diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala
index cc9aac366..9c47ce628 100644
--- a/src/dotty/tools/dotc/transform/LazyVals.scala
+++ b/src/dotty/tools/dotc/transform/LazyVals.scala
@@ -217,18 +217,15 @@ class LazyValsTransform extends MiniPhaseTransform with IdentityDenotTransformer
val compute = {
val handlerSymbol = ctx.newSymbol(methodSymbol, "$anonfun".toTermName, Flags.Synthetic,
MethodType(List("x$1".toTermName), List(defn.ThrowableType), defn.IntType))
-
- val handler = Closure(handlerSymbol, {
- args =>
- val exception = args.head.head
- val complete = setFlagState.appliedTo(thiz, offset, initState, Literal(Constant(ord)))
- Block(List(complete), Throw(exception))
- })
+ val caseSymbol = ctx.newSymbol(methodSymbol, nme.DEFAULT_EXCEPTION_NAME, Flags.Synthetic, defn.ThrowableType)
+ val complete = setFlagState.appliedTo(thiz, offset, initState, Literal(Constant(ord)))
+ val handler = CaseDef(Bind(caseSymbol, ref(caseSymbol)), EmptyTree,
+ Block(List(complete), Throw(ref(caseSymbol))
+ ))
val compute = Assign(ref(resultSymbol), rhs)
- val tr = Try(compute, handler, EmptyTree)
+ val tr = Try(compute, List(handler), EmptyTree)
val assign = Assign(ref(target), ref(resultSymbol))
- val complete = setFlagState.appliedTo(thiz, offset, computedState, Literal(Constant(ord)))
val noRetry = Assign(ref(retrySymbol), Literal(Constants.Constant(false)))
val body = If(casFlag.appliedTo(thiz, offset, ref(flagSymbol), computeState, Literal(Constant(ord))),
Block(tr :: assign :: complete :: noRetry :: Nil, Literal(Constant(()))),
diff --git a/src/dotty/tools/dotc/transform/PatternMatcher.scala b/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 9ba8d54c7..842582592 100644
--- a/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -51,7 +51,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
override def transformMatch(tree: Match)(implicit ctx: Context, info: TransformerInfo): Tree = {
val translated = new Translator()(ctx).translator.translateMatch(tree)
- Typed(translated.ensureConforms(tree.tpe), TypeTree(tree.tpe))
+ translated.ensureConforms(tree.tpe)
}
class Translator(implicit ctx: Context) {
diff --git a/src/dotty/tools/dotc/transform/TailRec.scala b/src/dotty/tools/dotc/transform/TailRec.scala
index b3f63bcaf..46028e0fc 100644
--- a/src/dotty/tools/dotc/transform/TailRec.scala
+++ b/src/dotty/tools/dotc/transform/TailRec.scala
@@ -156,9 +156,8 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
def noTailTransform(tree: Tree)(implicit c: Context): Tree =
transform(tree, noTailContext)
-
- def noTailTransforms(trees: List[Tree])(implicit c: Context) =
- trees map (noTailTransform)
+ def noTailTransforms[Tr <: Tree](trees: List[Tr])(implicit c: Context): List[Tr] =
+ trees.map(noTailTransform).asInstanceOf[List[Tr]]
override def transform(tree: Tree)(implicit c: Context): Tree = {
/* A possibly polymorphic apply to be considered for tail call transformation. */
@@ -247,14 +246,14 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete
// SI-1672 Catches are in tail position when there is no finalizer
tpd.cpy.Try(tree)(
noTailTransform(tree.expr),
- transformHandlers(tree.handler),
+ transformSub(tree.cases),
EmptyTree
)
}
else {
tpd.cpy.Try(tree)(
noTailTransform(tree.expr),
- noTailTransform(tree.handler),
+ noTailTransforms(tree.cases),
noTailTransform(tree.finalizer)
)
}
diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala
index 9e04d03b9..588a13fc9 100644
--- a/src/dotty/tools/dotc/transform/TreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/TreeTransform.scala
@@ -1104,9 +1104,9 @@ object TreeTransforms {
if (mutatedInfo eq null) tree
else {
val block = transform(tree.expr, mutatedInfo, cur)
- val handler = transform(tree.handler, mutatedInfo, cur)
+ val cases1 = tree.cases.mapConserve(transform(_, mutatedInfo, cur)).asInstanceOf[List[CaseDef]]
val finalizer = transform(tree.finalizer, mutatedInfo, cur)
- goTry(cpy.Try(tree)(block, handler, finalizer), mutatedInfo.nx.nxTransTry(cur))
+ goTry(cpy.Try(tree)(block, cases1, finalizer), mutatedInfo.nx.nxTransTry(cur))
}
case tree: Throw =>
implicit val mutatedInfo: TransformerInfo = mutateTransformers(info, prepForThrow, info.nx.nxPrepThrow, tree, cur)
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 193af8f0e..bb488bdc5 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -313,12 +313,9 @@ trait TypeAssigner {
def assignType(tree: untpd.Return)(implicit ctx: Context) =
tree.withType(defn.NothingType)
- def assignType(tree: untpd.Try, expr: Tree, handler: Tree)(implicit ctx: Context) = {
- if(handler.isEmpty) tree.withType(expr.tpe)
- else if(handler.tpe.derivesFrom(defn.FunctionClass(1))) {
- val handlerTypeArgs = handler.tpe.baseArgTypesHi(defn.FunctionClass(1))
- tree.withType(if (handlerTypeArgs.nonEmpty) expr.tpe | handlerTypeArgs(1) else expr.tpe /*| Object, as function returns boxed value ??? */)
- } else tree.withType(expr.tpe | handler.tpe)
+ def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) = {
+ if (cases.isEmpty) tree.withType(expr.tpe)
+ else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes))
}
def assignType(tree: untpd.Throw)(implicit ctx: Context) =
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 355b9f263..4b49d2669 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -666,20 +666,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedTry(tree: untpd.Try, pt: Type)(implicit ctx: Context): Try = track("typedTry") {
val expr1 = typed(tree.expr, pt)
- val handler1: Tree = tree.handler match {
- case h: untpd.Match if ((h.selector eq EmptyTree) // comes from parser
- || (h.selector eq ExceptionHandlerSel)) => // during retyping
- val cases1 = typedCases(h.cases, defn.ThrowableType, pt)
- assignType(untpd.Match(Typed(ExceptionHandlerSel, TypeTree(defn.ThrowableType)), cases1), cases1)
- case Typed(handler, tpe) if ctx.phaseId > ctx.patmatPhase.id => // we are retyping an expanded pattern
- typed(tree.handler, pt)
- case Apply(bx, List(Typed(handler, tpe))) if ctx.erasedTypes && Boxing.isBox(bx.symbol) =>
- typed(tree.handler, pt)
- case _ => typed(tree.handler, defn.FunctionType(defn.ThrowableType :: Nil, pt))
-
- }
+ val cases1 = typedCases(tree.cases, defn.ThrowableType, pt)
val finalizer1 = typed(tree.finalizer, defn.UnitType)
- assignType(cpy.Try(tree)(expr1, handler1, finalizer1), expr1, handler1)
+ assignType(cpy.Try(tree)(expr1, cases1, finalizer1), expr1, cases1)
}
def typedThrow(tree: untpd.Throw)(implicit ctx: Context): Throw = track("typedThrow") {