From 27d6efb5f5a076f825fe2da1875e0cabaf02b4e7 Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 17 Nov 2021 23:03:07 +0800 Subject: + LuaMacro --- Tools/LuaMacro/tests/list.lua | 59 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Tools/LuaMacro/tests/list.lua (limited to 'Tools/LuaMacro/tests/list.lua') diff --git a/Tools/LuaMacro/tests/list.lua b/Tools/LuaMacro/tests/list.lua new file mode 100644 index 0000000..274d482 --- /dev/null +++ b/Tools/LuaMacro/tests/list.lua @@ -0,0 +1,59 @@ +local M = require 'macro' +List = require 'pl.List' + +local list_check + +-- list [ = ] +-- acts as a 'macro factory', making locally-scoped macros for the variables, +-- and emitting code to initialize plain variables. +M.define ('list',function(get) + get() -- skip space + -- 'list' acts as a 'type' followed by a variable list, which may be + -- followed by initial values + local values + local vars,endt = get:idens (function(t,v) + return t == '=' or (t == 'space' and v:find '\n') + end) + -- there is an initialization list + if endt[1] == '=' then + values,endt = get:list '\n' + else + values = {} + end + -- build up the initialization list + for i,name in ipairs(vars) do + M.define_scoped(name,list_check) + values[i] = 'List('..tostring(values[i] or '')..')' + end + local lcal = M._interactive and '' or 'local ' + local res = lcal..table.concat(vars,',')..' = '..table.concat(values,',')..tostring(endt) + return res +end) + +function list_check (get,put) + local t,v = get:peek(1) + if t ~= '[' then return nil, true end -- pass-through; plain var reference + get:expecting '[' + local args = get:list(']',':') + -- it's just plain table access + if #args == 1 then return '['..tostring(args[1])..']',true end + + -- two items separated by a colon; use sensible defaults + M.assert(#args == 2, "slice has two arguments!") + local start,finish = tostring(args[1]),tostring(args[2]) + if start == '' then start = '1' end + if finish == '' then finish = '-1' end + + -- look ahead to see if we're on the left hand side of an assignment + if get:peek(1) == '=' then + get:next() -- skip '=' + local rest,eoln = get:upto '\n' + rest,eoln = tostring(rest),tostring(eoln) + return (':slice_assign(%s,%s,%s)%s'):format(start,finish,rest,eoln),true + else + return (':slice(%s,%s)'):format(start,finish),true + end +end + + + -- cgit v1.1-26-g67d0