summaryrefslogtreecommitdiff
path: root/Tools/LuaMacro/macro/ifelse.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/ifelse.lua
parentb34310c631989551054d456eb47aaab5ded266a4 (diff)
+ LuaMacro
Diffstat (limited to 'Tools/LuaMacro/macro/ifelse.lua')
-rw-r--r--Tools/LuaMacro/macro/ifelse.lua90
1 files changed, 90 insertions, 0 deletions
diff --git a/Tools/LuaMacro/macro/ifelse.lua b/Tools/LuaMacro/macro/ifelse.lua
new file mode 100644
index 0000000..3d5a0df
--- /dev/null
+++ b/Tools/LuaMacro/macro/ifelse.lua
@@ -0,0 +1,90 @@
+local M = require 'macro'
+
+local function eval (expr,was_expr)
+ expr = tostring(expr)
+ if was_expr then expr = "return "..expr end
+ local chunk = M.assert(loadstring(expr))
+ local ok, res = pcall(chunk)
+ if not ok then M.error("error evaluating "..res) end
+ return res
+end
+
+local function eval_line (get,was_expr)
+ local args = get:line()
+ return eval(args,was_expr)
+end
+
+local function grab (get)
+ local ilevel = 0
+ while true do
+ local t,v = get()
+ while t ~= '@' do t = get() end
+ t,v = get()
+ if v == 'if' then
+ ilevel = ilevel + 1
+ else -- 'end','elseif','else'
+ if ilevel > 0 and v == 'end' then
+ ilevel = ilevel - 1
+ elseif ilevel == 0 then return '@'..v end
+ end
+ end
+end
+
+M.define('@',function(get,put)
+ local t,v = get()
+--~ print('got',t,v)
+ return put:iden(v..'_')
+end)
+
+local ifstack,push,pop = {},table.insert,table.remove
+
+local function push_if (res)
+--~ print 'push'
+ push(ifstack, not (res==false or res==nil))
+end
+
+local function pop_if ()
+--~ print 'pop'
+ pop(ifstack)
+end
+
+M.define('if_',function(get)
+ local res = eval_line(get,true)
+ push_if(res)
+ if not res then
+ return grab(get)
+ end
+end)
+
+M.define('elseif_',function(get)
+ local res
+ if ifstack[#ifstack] then
+ res = false
+ else
+ res = eval_line(get,true)
+ pop_if()
+ push_if(res)
+ end
+ if not res then
+ return grab(get)
+ end
+end)
+
+M.define('else_',function(get)
+ if #ifstack == 0 then M.error("mismatched else") end
+ if ifstack[#ifstack] then
+ return grab(get)
+ end
+end)
+
+M.define('end_',function(get)
+ pop_if()
+end)
+
+M.define('let_',function(get)
+ eval_line(get)
+end)
+
+M.define('eval_(X)',function(X)
+ return tostring(eval(X,true))
+end)