]> git.lizzy.rs Git - metalua.git/blob - src/lib/metalua/extension/withdo.mlua
Merge remote branch 'origin/master'
[metalua.git] / src / lib / metalua / extension / withdo.mlua
1 -- RAII in metalua.
2 --
3 -- Write:
4 -- with var_1, var_2... = val_1, val_2... do
5 --    ...
6 -- end
7 --
8 -- will assign val_n to var_n foreach n, and guaranty that var_n:close() will be called,
9 -- no matter what, even if the body causes an error, even if it returns, even
10 -- if another :close() call causes an error, etc. No. Matter. What.
11
12 require 'metalua.extension.trycatch'
13
14 function withdo_builder (x)
15    local names, vals, body = unpack(x)
16    for i = #names, 1, -1 do
17       local name, val = names[i], vals[i]
18       body = trycatch_builder{ { `Set{ {name}, {val} }, body }, -- try-block
19                                { }, -- catch-block
20                                { +{ print ("closing "..-{`String{name[1]}}) },
21                                  `Invoke{ name, `String "close" } } }
22    end
23    table.insert(body, 1, `Local{ names })
24    return body
25 end
26
27 mlp.lexer:add 'with'
28 mlp.stat:add{
29    'with', mlp.id_list, '=', mlp.expr_list, 'do', mlp.block, 'end',
30    builder = withdo_builder }