]> git.lizzy.rs Git - metalua.git/commitdiff
updated trycatch to work with new match, new catch...then syntax
authorFabien Fleutot <fabien@macfabien.local>
Mon, 18 Feb 2008 18:48:34 +0000 (19:48 +0100)
committerFabien Fleutot <fabien@macfabien.local>
Mon, 18 Feb 2008 18:48:34 +0000 (19:48 +0100)
src/lib/extension/trycatch.mlua

index 979992f5ca0c361daba5e6dc67633648547f6b73..2dc0015e2c6631c6c02690aaa3655771163a2ec9 100644 (file)
@@ -4,30 +4,15 @@
 --\r
 -- TODO:\r
 --\r
--- * Hygiene! this stuff is absolutely not hygienic, and lexically nested\r
---   try...with \r
---\r
--- * give a more lua-like syntax:\r
---   > try ... (catch expr then block)* (finally block)? end\r
---\r
--- * create an RAII-like feature, possibly in a separate extension:\r
---   > with v1, v2, ... = rsc1, rsc2, ... do block end ==>\r
---   > try local v1 = rsc1\r
---   >    try v2 = rsc2\r
---   >       ...\r
---   >    finally v2:close()\r
---   > finally v1:close() end\r
---\r
--- * match.mlua refactoring: there are many other places where it\r
---   should be usable (fancy assignments...), if it were cut in\r
---   smaller, more usable functions. They should probably go in a\r
---   separate module.\r
+-- * Hygienize calls to pcall()\r
 --\r
 --------------------------------------------------------------------------------\r
 \r
 -{ extension 'H' }\r
 -{ extension 'log' }\r
 \r
+require 'extension.match'\r
+\r
 -- Get match parsers and builder, for catch cases handling:\r
 local match_alpha = require 'extension.match' \r
 local H = H:new{side='inside', alpha = match_alpha }\r
@@ -40,6 +25,7 @@ local mkpcall = |block| +{pcall(function() -{block} end)}
 \r
 -- The statement builder:\r
 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
 \r
@@ -48,9 +34,16 @@ function trycatch_builder(x)
    -- to outside macro code.\r
    local caught_return = !mlp.gensym 'caught_return'\r
 \r
-   !try_code; !(catch_code or { }); !(finally_code or { })\r
+   !try_code; !(finally_code or { })\r
+   -- FIXME: Am I sure there's no need to hygienize inside?\r
+   --[[if catch_cases then\r
+      for case in ivalues(catch_cases) do\r
+         --$log(case,'nohash')\r
+         local patterns, guard, block = unpack(case)\r
+         ! block\r
+      end\r
+   end]]\r
 \r
-   --$log(try_code, catch_cases, finally_code)\r
 \r
    ----------------------------------------------------------------\r
    -- Returns in the try-block must be transformed:\r
@@ -83,7 +76,7 @@ function trycatch_builder(x)
             -- Setvar's 'caught_return' code can't be hygienize by H currently.\r
             local setvar = `Set{ {caught_return}, { `Table{ unpack(x) } } }\r
             x <- { setvar; `Return }; x.tag = nil;\r
-            $log('transformed return stat:', x, 60)\r
+            --$log('transformed return stat:', x, 60)\r
             return 'break'\r
          | `Function{...} -> return 'break' \r
             -- inside this, returns would be the nested function's, not ours.\r
@@ -117,7 +110,7 @@ function trycatch_builder(x)
          -- so we introduce a catch-all do-nothing last case:\r
          ----------------------------------------------------------\r
          table.insert (catch_cases, { { { `Id '_' } }, false, { } }) \r
-         catch_result = match_builder{ {+{user_error}}, catch_cases }\r
+         catch_result = spmatch.match_builder{ {+{user_error}}, catch_cases }\r
       else\r
          catch_result = { }\r
       end\r
@@ -157,14 +150,30 @@ function trycatch_builder(x)
    return result\r
 end\r
 \r
+function catch_case_builder(x)\r
+   --$log ("catch_case_builder", x, 'nohash', 60)\r
+   local patterns, guard, _, code = unpack(x)\r
+   -- patterns ought to be a pattern_group, but each expression must\r
+   -- be converted into a single-element pattern_seq.\r
+   for i = 1, #patterns do patterns[i] = {patterns[i]} end\r
+   return { patterns, guard, code }\r
+end\r
+\r
 mlp.lexer:add{ 'try', 'catch', 'finally', '->' }\r
 mlp.block.terminators:add{ 'catch', 'finally' }\r
-table.insert(match_cases_list_parser.terminators, 'finally')\r
 \r
 mlp.stat:add{\r
    'try', \r
    mlp.block, \r
-   gg.onkeyword{ 'catch', match_cases_list_parser },\r
+   gg.onkeyword{ 'catch', \r
+      gg.list{\r
+         gg.sequence{ \r
+            mlp.expr_list,\r
+            gg.onkeyword{ 'if', mlp.expr },\r
+            gg.optkeyword 'then', \r
+            mlp.block,\r
+            builder = catch_case_builder },\r
+         separators = 'catch' } },\r
    gg.onkeyword{ 'finally', mlp.block },\r
    'end',\r
    builder = trycatch_builder }\r