summaryrefslogtreecommitdiff
path: root/Tools/LuaMacro/macro/try.lua
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-11-17 23:03:07 +0800
committerchai <chaifix@163.com>2021-11-17 23:03:07 +0800
commit27d6efb5f5a076f825fe2da1875e0cabaf02b4e7 (patch)
tree44f301110bc2ea742908ed92a78eba0803cd3b60 /Tools/LuaMacro/macro/try.lua
parentb34310c631989551054d456eb47aaab5ded266a4 (diff)
+ LuaMacro
Diffstat (limited to 'Tools/LuaMacro/macro/try.lua')
-rw-r--r--Tools/LuaMacro/macro/try.lua47
1 files changed, 47 insertions, 0 deletions
diff --git a/Tools/LuaMacro/macro/try.lua b/Tools/LuaMacro/macro/try.lua
new file mode 100644
index 0000000..8e49eb0
--- /dev/null
+++ b/Tools/LuaMacro/macro/try.lua
@@ -0,0 +1,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_ '
+