diff options
author | Paul Phillips <paulp@improving.org> | 2010-12-03 05:02:37 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-12-03 05:02:37 +0000 |
commit | 715d95479e77b06dd65303886d2e0e70ddcf461f (patch) | |
tree | 991f4e4be398f9b32ef6c4df49fbd927ae8dd6d6 /src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala | |
parent | 31533385b7ac4e1643ad8664141f3d197dc637f1 (diff) | |
download | scala-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.scala | 26 |
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) |