Skip to content

Commit 945252b

Browse files
committed
Desugaring of try-catch-else-finally
1 parent 99d49a5 commit 945252b

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

src/desugaring.jl

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,84 @@ function expand_for(ctx, ex)
258258
]
259259
end
260260

261+
function match_try(ex)
262+
@chk numchildren(ex) > 1 "Invalid `try` form"
263+
try_ = ex[1]
264+
catch_and_exc = nothing
265+
exc_var = nothing
266+
catch_ = nothing
267+
finally_ = nothing
268+
else_ = nothing
269+
for e in ex[2:end]
270+
k = kind(e)
271+
if k == K"catch" && isnothing(catch_)
272+
@chk numchildren(e) == 2 "Invalid `catch` form"
273+
if !(kind(e[1]) == K"Bool" && e[1].value === false)
274+
# TODO: Fix this strange AST wart upstream?
275+
exc_var = e[1]
276+
end
277+
catch_ = e[2]
278+
catch_and_exc = e
279+
elseif k == K"else" && isnothing(else_)
280+
@chk numchildren(e) == 1
281+
else_ = e[1]
282+
elseif k == K"finally" && isnothing(finally_)
283+
@chk numchildren(e) == 1
284+
finally_ = e[1]
285+
else
286+
throw(LoweringError(ex, "Invalid clause in `try` form"))
287+
end
288+
end
289+
(try_, catch_and_exc, exc_var, catch_, else_, finally_)
290+
end
291+
292+
function expand_try(ctx, ex)
293+
(try_, catch_and_exc, exc_var, catch_, else_, finally_) = match_try(ex)
294+
295+
if !isnothing(finally_)
296+
# TODO: check unmatched symbolic gotos in try.
297+
end
298+
299+
try_body = @ast ctx try_ [K"scope_block"(scope_type=:neutral) try_]
300+
301+
if isnothing(catch_)
302+
try_block = try_body
303+
else
304+
if !isnothing(exc_var) && !is_identifier_like(exc_var)
305+
throw(LoweringError(exc_var, "Expected an identifier as exception variable"))
306+
end
307+
try_block = @ast ctx ex [K"trycatchelse"
308+
try_body
309+
[K"scope_block"(catch_and_exc, scope_type=:neutral)
310+
if !isnothing(exc_var)
311+
if !is_identifier_like(exc_var)
312+
throw(LoweringError(exc_var, "Expected an identifier as exception variable"))
313+
end
314+
[K"block"
315+
[K"="(exc_var) exc_var [K"the_exception"]]
316+
catch_
317+
]
318+
else
319+
catch_
320+
end
321+
]
322+
if !isnothing(else_)
323+
[K"scope_block"(else_, scope_type=:neutral) else_]
324+
end
325+
]
326+
end
327+
328+
# Add finally block
329+
if isnothing(finally_)
330+
try_block
331+
else
332+
@ast ctx ex [K"tryfinally"
333+
try_block
334+
[K"scope_block"(finally_, scope_type=:neutral) finally_]
335+
]
336+
end
337+
end
338+
261339
# Strip variable type declarations from within a `local` or `global`, returning
262340
# the stripped expression. Works recursively with complex left hand side
263341
# assignments containing tuple destructuring. Eg, given
@@ -750,6 +828,8 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing)
750828
expand_forms_2(ctx, children(ex))...
751829
]
752830
end
831+
elseif k == K"try"
832+
expand_try(ctx, ex)
753833
elseif k == K"tuple"
754834
# TODO: named tuples
755835
expand_forms_2(ctx, @ast ctx ex [K"call"

0 commit comments

Comments
 (0)