function trycatch_builder(x)\r
--$log ("trycatch_builder", x, 'nohash', 60)\r
local try_code, catch_cases, finally_code = unpack(x)\r
- local insert_return_catcher = false\r
+ local insert_return_catcher = false \r
\r
-- Can't be hygienize automatically by the current version of H, as\r
-- it must bridge from inside user code (hacjed return statements)\r
-- to outside macro code.\r
local caught_return = !mlp.gensym 'caught_return'\r
+ local saved_args\r
\r
!try_code; !(finally_code or { })\r
-- FIXME: Am I sure there's no need to hygienize inside?\r
-- allows to avoid inserting return-handling code in the result\r
-- when not needed.\r
----------------------------------------------------------------\r
- local replace_returns do\r
+ local replace_returns_and_dots do\r
local function f(x)\r
match x with \r
| `Return{...} -> \r
return 'break'\r
| `Function{...} -> return 'break' \r
-- inside this, returns would be the nested function's, not ours.\r
+ | `Dots ->\r
+ if not saved_args then saved_args = mlp.gensym 'args' end\r
+ x <- `Call{ `Id 'unpack', saved_args } \r
| _ -> -- pass\r
end\r
end\r
local cfg = { stat = {down=f}, expr = {down=f} }\r
- replace_returns = |x| walk.block(cfg, x)\r
+ replace_returns_and_dots = |x| walk.block(cfg, x)\r
end\r
\r
-- parse returns in the try-block:\r
- replace_returns (try_code)\r
+ replace_returns_and_dots (try_code)\r
\r
-- code handling the error catching process:\r
local catch_result do\r
for x in ivalues (catch_cases) do\r
local case_code = x[3]\r
-- handle rogue returns:\r
- replace_returns (case_code)\r
+ replace_returns_and_dots (case_code)\r
-- in case of error in the catch, we still need to run "finally":\r
x[3] = +{block: catch_success, catch_error = -{mkpcall(case_code)}}\r
end\r
caught_return_init, caught_return_rethrow = { }, { }\r
end\r
end\r
+ \r
+ local saved_args_init =\r
+ saved_args and `Local{ {saved_args}, { `Table{`Dots} } } or { }\r
\r
-- The finally code, to execute no matter what:\r
local finally_result = finally_code or { }\r
-- And the whole statement, gluing all taht together:\r
local result = +{stat: \r
do\r
+ -{ saved_args_init }\r
-{ caught_return_init }\r
local user_success, user_error = -{mkpcall(try_code)}\r
local catch_success, catch_error = false, user_error\r
local names, vals, body = unpack(x)
for i = #names, 1, -1 do
local name, val = names[i], vals[i]
- body = trycatch_builder{
- { `Set{ {name}, {val} }, body }, -- try-block
- { }, -- catch-block
- { +{ print ("closing "..-{`String{name[1]}}) },
- `Invoke{ name, `String "close" } } }
+ body = trycatch_builder{ { `Set{ {name}, {val} }, body }, -- try-block
+ { }, -- catch-block
+ { +{ print ("closing "..-{`String{name[1]}}) },
+ `Invoke{ name, `String "close" } } } }
end
+ table.insert(body, 1, `Local{ names })
return body
end