Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
reimplement try/catch/finally entirely.
  • Loading branch information
diakopter committed Nov 8, 2011
1 parent ea903a6 commit c14bd69
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 109 deletions.
12 changes: 6 additions & 6 deletions lua/compiler/LST2Lua.pm
Expand Up @@ -125,13 +125,13 @@ our multi sub cs_for(LST::Stmts $stmts) {
our multi sub cs_for(LST::TryFinally $tf) {
unless +@($tf) == 2 { pir::die('LST::TryFinally nodes must have 2 children') }
my $try_result := get_unique_id('try_result');
my $code := " try\{\n" ~
my $code := " try_catch_finally(\n" ~
" function ()\n" ~
cs_for((@($tf))[0]);
$code := $code ~
" $try_result = $*LAST_TEMP;\n" ~
" end\n" ~
" }.finally(\"\",\n" ~
" end,\n" ~
" \"\",nil,\n" ~
" function (catchClass, exceptions, exc)\n" ~
cs_for((@($tf))[1]) ~
" end\n" ~
Expand All @@ -143,13 +143,13 @@ our multi sub cs_for(LST::TryFinally $tf) {
our multi sub cs_for(LST::TryCatch $tc) {
unless +@($tc) == 2 { pir::die('LST::TryCatch nodes must have 2 children') }
my $try_result := get_unique_id('try_result');
my $code := " try\{\n" ~
my $code := " try_catch_finally(\n" ~
" function ()\n" ~
cs_for((@($tc))[0]);
$code := $code ~
" $try_result = $*LAST_TEMP;\n" ~
" end\n" ~
" }.except(\"" ~ $tc.exception_type ~ "\",\n" ~
" end,\n" ~
" \"" ~ $tc.exception_type ~ "\",\n" ~
" function (catchClass, exceptions, exc)\n" ~
cs_for((@($tc))[1]) ~
" $try_result = $*LAST_TEMP;\n" ~
Expand Down
110 changes: 7 additions & 103 deletions lua/runtime/Try.lua
Expand Up @@ -22,118 +22,22 @@ E.resolve = function(exception)
return exceptions
end

local getlocals = function(func)
local n = 1
local locals = {}
func = (type(func) == "number") and func + 1 or func
while true do
local lname, lvalue = debug.getlocal(func, n)
if lname == nil then break end
if lvalue == nil then lvalue = mynil end
locals[lname] = lvalue
n = n + 1
end
return locals
end

function try_catch_finally(try, exception_class, catch, finally)
local ok = {pcall(fn)}
local exception = nil
if not ok[1] then
exception = ok[2]
end
local ok, exception = pcall(try)
local caught = false
if catch ~= nil and exception ~= nil then
local exps = E.resolve(exception)
if exps[exception_class] then
caught = true
catch(exception_class, exps, exception)
else
error(exception)
end
end
end
if finally ~= nil then
finally()
end
end

function try(fn, ...)
local real_args = {...}
fn = fn[1]
--if type(fn) == "table" then fn = fn[1] end
--if type(fn) == "string" then fn = loadstring(fn) end
--if type(fn) ~= "function" then return nil end
--local locals = getlocals(2)

--for _,obj in pairs(locals) do rawset(_G,_.."___macro",obj) end
--setmetatable(_G,_mtg)

--local ok = {pcall(function() return fn(unpack(real_args)) end)}
local ok = {pcall(fn)}
--local ok = {true, fn(unpack(real_args))}

--setmetatable(_G,_orig)
--for k,__ in pairs(locals) do rawset(_G,k.."___macro",nil) end

local returns = {}
local exception = nil
if ok[1] then
table.remove(ok, 1)
returns.values = ok
else
exception = ok[2]
end
returns.except = function(catch, _fn)
if not catch then return returns.except("GenericError") end
if type(catch) == "string" and not _fn then return function(fn) return returns.except(catch, fn) end end
if type(catch) == "table" then _fn = catch[1]; catch = "GenericError" end
if type(catch) == "function" then _fn = catch end
if type(_fn) == "table" then _fn = _fn[1] end
if not (_fn and type(_fn) == "function") then return end
local exps = E.resolve(exception)
--setmetatable(exps, {__tostring = function(self)
-- local _r = "{";
-- for k,_ in pairs(exps) do
-- _r = _r .. k .. ", "
-- end;
-- return _r:sub(0,#_r-2).."}";
-- end})
if exps[catch] or (type(catch) ~= "string" and exception) then
return _fn(catch, exps, exception)
elseif exception then
error(exception)
else
return unpack(returns.values)
end
if returns.values then
return unpack(returns.values)
end
end
returns.finally = function(catch, _fn)
if not catch then return returns.finally("GenericError") end
if type(catch) == "string" and not _fn then return function(fn) return returns.finally(catch, fn) end end
if type(catch) == "table" then _fn = catch[1]; catch = "GenericError" end
if type(catch) == "function" then _fn = catch end
if type(_fn) == "table" then _fn = _fn[1] end
if not (_fn and type(_fn) == "function") then return end
local exps = E.resolve(exception)
--setmetatable(exps, {__tostring = function(self)
-- local _r = "{";
-- for k,_ in pairs(exps) do
-- _r = _r .. k .. ", "
-- end;
-- return _r:sub(0,#_r-2).."}";
-- end})
_fn(catch, exps, exception)
if exception then
error(exception)
else
return unpack(returns.values)
end
if returns.values then
return unpack(returns.values)
end
end
setmetatable(returns, {__call = function(self) return self.values end})
return returns
if exception ~= nil and not caught then
error(exception)
end
end

__exceptions = {
Expand Down

0 comments on commit c14bd69

Please sign in to comment.