]> git.lizzy.rs Git - metalua.git/commitdiff
introduce RAII extension
authorFabien Fleutot <fabien@macfabien.local>
Thu, 31 Jan 2008 08:24:30 +0000 (09:24 +0100)
committerFabien Fleutot <fabien@macfabien.local>
Thu, 31 Jan 2008 08:24:30 +0000 (09:24 +0100)
src/lib/extension/withdo.mlua [new file with mode: 0644]
src/samples/withdo_test.mlua [new file with mode: 0644]

diff --git a/src/lib/extension/withdo.mlua b/src/lib/extension/withdo.mlua
new file mode 100644 (file)
index 0000000..c5db100
--- /dev/null
@@ -0,0 +1,30 @@
+-- RAII in metalua.
+--
+-- Write:
+-- with var_1, var_2... = val_1, val_2... do
+--    ...
+-- end
+--
+-- will assign val_n to var_n foreach n, and guaranty that var_n:close() will be called,
+-- no matter what, even if the body causes an error, even if it returns, even
+-- if another :close() call causes an error, etc. No. Matter. What.
+
+require 'extension.trycatch'
+
+function withdo_builder (x)
+   local names, vals, body = unpack(x)
+   for i = #names, 1, -1 do
+      local name, val = names[i], vals[i]
+      body = trycatch_builder{
+         { `Set{ {name}, {val} }, body }, -- try-block
+         { }, -- catch-block
+         {  +{ print ("closing "..-{`String{name[1]}}) },
+            `Invoke{ name, `String "close" } } }
+   end
+   return body
+end
+
+mlp.lexer:add 'with'
+mlp.stat:add{
+   'with', mlp.id_list, '=', mlp.expr_list, 'do', mlp.block, 'end',
+   builder = withdo_builder }
\ No newline at end of file
diff --git a/src/samples/withdo_test.mlua b/src/samples/withdo_test.mlua
new file mode 100644 (file)
index 0000000..3d68db9
--- /dev/null
@@ -0,0 +1,19 @@
+-{ extension 'withdo' }
+
+local original_close = io.close
+function io:close()
+   original_close(self)
+   print "closed a file"
+end
+
+function x()
+   --with f = io.open 'withdo_test.mlua' do
+   with f = io.open 'withdo_test.mlua' do
+      for l in f:lines() do
+         printf("[%s]", l)
+      end
+      return '123'
+   end
+end
+
+print(x())
\ No newline at end of file