]> git.lizzy.rs Git - metalua.git/blob - src/lib/ext-syntax/exceptions.lua
springs minor refactoring
[metalua.git] / src / lib / ext-syntax / exceptions.lua
1 require "std"
2
3 function try_with_builder(x)
4    local block, handlers = x[1], x[3]
5    local result, exn, endmark = 
6       mlp.gensym "_result", mlp.gensym "_exn", mlp.gensym "_endmark"
7    local function parse_exn_handler (x)
8       local exn_test, block = x[1], x[2]
9        return { +{ -{exn_test} <= -{exn} }, block }
10     end
11    local catchers = table.flatten (table.map(parse_exn_handler, handlers))   
12    catchers.tag = "If"
13    table.insert (catchers, { `Call{ `Id "error", exn } } )
14    table.insert (block, `Return{ endmark })
15    return +{ block:
16       local -{endmark} = { }
17       local -{result}  = { pcall (function() -{block} end) }
18       if -{result}[1] then -- no exception raised
19          if -{result}[2] ~= -{endmark} then -- user-caused return: propagate it
20             table.remove( -{result}, 1)
21             return unpack( -{result})
22          end
23       else -- an error/exception occured
24          local -{exn} = -{result}[2]
25          -{catchers} 
26       end }
27 end
28
29 mlp.block.terminators:add{ "|", "with" }
30 mlp.lexer:add{ "try", "with", "->" }
31 mlp.stat:add{ name="try block",
32    "try", mlp.block, "with", 
33    gg.optkeyword "|",
34    gg.list{ name="exception catchers list",
35       gg.sequence{ name="exception catching case",
36          mlp.expr, "->", mlp.block },
37       separators = "|", terminators = "end" },
38    "end",
39    builder = try_with_builder }