1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
--- A try/except block.
-- This generates syntactical sugar around `pcal`l, and correctly
-- distinguishes between the try block finishing naturally and
-- explicitly using 'return' with no value. This is handled by
-- converting any no value `return` to `return nil`.
--
-- Apart from the usual creation of a closure, this uses a table
-- to capture all the results. Not likely to win speed contests,
-- but intended to be correct.
-- @module macro.try
local M = require 'macro'
local function pack (...)
local args = {...}
args.n = select('#',...)
return args
end
function pcall_(fn,...)
return pack(pcall(fn,...))
end
local function check_return_value(get,put)
local t,v = get:next()
put:space()
if t=='keyword' and (v=='end' or v=='else' or v=='until') then
put:keyword 'nil'
end
return put(t,v)
end
M.define('RR_',M.make_scoped_handler('return',check_return_value))
--- A try macro, paired with except.
--
-- try
-- maybe_something_bad()
-- except (e)
-- print(e)
-- end
-- @macro try
M.define 'try do local r_ = pcall_(function() RR_ '
M.define 'except(e) end); if r_[1] then if r_.n > 1 then return unpack(r_,2,r_.n) end else local e = r_[2] _END_END_ '
|