diff options
author | chai <chaifix@163.com> | 2021-11-17 23:03:07 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-11-17 23:03:07 +0800 |
commit | 27d6efb5f5a076f825fe2da1875e0cabaf02b4e7 (patch) | |
tree | 44f301110bc2ea742908ed92a78eba0803cd3b60 /Tools/LuaMacro/macro/forall.lua | |
parent | b34310c631989551054d456eb47aaab5ded266a4 (diff) |
+ LuaMacro
Diffstat (limited to 'Tools/LuaMacro/macro/forall.lua')
-rw-r--r-- | Tools/LuaMacro/macro/forall.lua | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/Tools/LuaMacro/macro/forall.lua b/Tools/LuaMacro/macro/forall.lua new file mode 100644 index 0000000..8ec5c68 --- /dev/null +++ b/Tools/LuaMacro/macro/forall.lua @@ -0,0 +1,70 @@ +-------------------- +-- `forall` statement. +-- The syntax is `forall VAR SELECT [if CONDN] do` where +-- `SELECT` is either `in TBL` or `= START,FINISH` +-- +-- For example, +-- +-- forall name in {'one','two'} do print(name) end +-- +-- forall obj in get_objects() if obj:alive() then +-- obj:action() +-- end +-- +-- Using `forall`, we also define _list comprehensions_ like +-- `L{s:upper() | s in names if s:match '%S+'}` +-- +-- @module macro.forall + +local M = require 'macro' + +--- extended for statement. +-- @macro forall +M.define('forall',function(get,put) + local var = get:iden() + local t,v = get:next() + local rest,endt = get:list(M.upto_keywords('do','if')) + put:keyword 'for' + if v == 'in' then + put:iden '_' ',' :iden(var):keyword 'in' + put:iden 'ipairs' '(' :list(rest) ')' + elseif v == '=' then + put:iden(var) '=' :list(rest) + else + M.error("expecting in or =") + end + put:keyword 'do' + if endt[2] == 'if' then + rest,endt = get:list(M.upto_keywords('do')) + put:keyword 'if':list(rest):keyword 'then':iden '_END_END_' + end + return put +end) + +--- list comprehension. +-- Syntax is `L{expr | select}` where `select` is as in `forall`, +-- or `L{expr for select}` where `select` is as in the regular `for` statement. +-- @macro L +-- @return a list of values +-- @usage L{2*x | x in {1,2,3}} == {1,4,9} +-- @usage L{2*x|x = 1,3} == {1,4,9} +-- @usage L{{k,v} for k,v in pairs(t)} +-- @see forall +M.define('L',function(get,put) + local t,v = get:next() -- must be '{' + local expr,endt = get:list(function(t,v) + return t == '|' or t == 'keyword' and v == 'for' + end,'') + local select = get:list('}','') + put '(' : keyword 'function' '(' ')' :keyword 'local':iden 'res' '=' '{' '}' + if endt[2] == '|' then + put:iden'forall' + else + put:keyword 'for' + end + put:list(select):space():keyword'do' + put:iden'res' '[' '#' :iden'res' '+' :number(1) ']' '=' :list(expr):space() + put:keyword 'end' :keyword 'return' : iden 'res' :keyword 'end' ')' '(' ')' + put:iden '_POP_':string'L' + return put +end) |