summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-12-03 05:02:37 +0000
committerPaul Phillips <paulp@improving.org>2010-12-03 05:02:37 +0000
commit715d95479e77b06dd65303886d2e0e70ddcf461f (patch)
tree991f4e4be398f9b32ef6c4df49fbd927ae8dd6d6 /src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
parent31533385b7ac4e1643ad8664141f3d197dc637f1 (diff)
downloadscala-715d95479e77b06dd65303886d2e0e70ddcf461f.tar.gz
scala-715d95479e77b06dd65303886d2e0e70ddcf461f.tar.bz2
scala-715d95479e77b06dd65303886d2e0e70ddcf461f.zip
Generalizes catch blocks to include any Partial...
Generalizes catch blocks to include any PartialFunction[Throwable, T]. Existing catch blocks will compile exactly as before. Anything else (which mean: the token after CATCH is not a left brace, or it is a left brace not immediately followed by CASE) is desugared as follows: try body catch expr // becomes try body catch { case x => val catchFn = expr if (catchFn isDefinedAt x) catchFn(x) else throw x } Review by odersky.
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 01cfc440c5..afb9999db8 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -17,8 +17,10 @@ abstract class TreeBuilder {
val global: Global
import global._
- def freshName(prefix: String): Name
def freshName(): Name = freshName("x$")
+ def freshName(prefix: String): Name
+ def freshTermName(prefix: String): TermName
+ def freshTypeName(prefix: String): TypeName
def o2p(offset: Int): Position
def r2p(start: Int, point: Int, end: Int): Position
@@ -467,6 +469,28 @@ abstract class TreeBuilder {
def makeCaseDef(pat: Tree, guard: Tree, rhs: Tree): CaseDef =
CaseDef(patvarTransformer.transform(pat), guard, rhs)
+ /** Creates tree representing:
+ * { case x: Throwable =>
+ * val catchFn = catchExpr
+ * if (catchFn isDefinedAt x) catchFn(x) else throw x
+ * }
+ */
+ def makeCatchFromExpr(catchExpr: Tree): CaseDef = {
+ val binder = freshTermName("x")
+ val pat = atPos(catchExpr.pos)(Bind(binder, Typed(Ident(nme.WILDCARD), Ident(tpnme.Throwable))))
+ val catchDef = ValDef(NoMods, freshTermName("catchExpr"), TypeTree(), catchExpr)
+ val catchFn = Ident(catchDef.name)
+ val body = Block(
+ List(catchDef),
+ If(
+ Apply(Select(catchFn, nme.isDefinedAt), List(Ident(binder))),
+ Apply(Select(catchFn, nme.apply), List(Ident(binder))),
+ Throw(Ident(binder))
+ )
+ )
+ makeCaseDef(pat, EmptyTree, body)
+ }
+
/** Create tree for pattern definition <val pat0 = rhs> */
def makePatDef(pat: Tree, rhs: Tree): List[Tree] =
makePatDef(Modifiers(0), pat, rhs)