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/builtin.lua | |
parent | b34310c631989551054d456eb47aaab5ded266a4 (diff) |
+ LuaMacro
Diffstat (limited to 'Tools/LuaMacro/macro/builtin.lua')
-rw-r--r-- | Tools/LuaMacro/macro/builtin.lua | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/Tools/LuaMacro/macro/builtin.lua b/Tools/LuaMacro/macro/builtin.lua new file mode 100644 index 0000000..12c8b38 --- /dev/null +++ b/Tools/LuaMacro/macro/builtin.lua @@ -0,0 +1,161 @@ +------- +-- LuaMacro built-in macros. +-- @module macro.builtin + +local M = require 'macro' + +local function macro_def (scoped) + return function (get) + local t,name,parms,openp + local t,name = get:next() + local upto,ret + if t == '(' then + t,name = get:next() + upto = function(t,v) return t == ')' end + else + upto = function(t,v) + return t == 'space' and v:find '\n' + end + -- return space following (returned by copy_tokens) + ret = true + end + -- might be immediately followed by a parm list + t,openp = get() + if openp == '(' then + parms = get:names() + end + -- the actual substitution is up to the end of the line + local args, space = M.copy_tokens(get,upto) + if scoped then + M.define_scoped(name,args,parms) + else + M.set_macro(name,args,parms) + end + return ret and space[2] + end +end + +--- a macro for defining lexically scoped simple macros. +-- def_ may be followed by an arglist, and the substitution is the +-- rest of the line. +-- @usage def_ block (function() _END_CLOSE_ +-- @usage def_ sqr(x) ((x)*(x)) +-- @macro def_ +M.define ('def_',macro_def(true)) + +--- a global version of `def_`. +-- @see def_ +-- @macro define_ +M.define ('define_',macro_def(false)) + +--- set the value of an existing macro. +-- the name and value follows immediately, and the value must be +-- a single token +-- @usage set_ T 'string' +-- @usage set_ F function +-- @macro set_ +M.define('set_',function(get) + local name = get:name() + local t,v = get:next() + M.set_macro(name,{{t,v}}) +end) + +--- undefining identifier macros. +-- @macro undef_ +M.define('undef_',function(get) + M.set_macro(get:name()) +end) + +--- Insert text after current block end. `_END_` is followed by a quoted string +-- and is used to insert that string after the current block closes. +-- @macro _END_ +M.define ('_END_',function(get) + local str = get:string() + M.block_handler(-1,function(get,word) + if word ~= 'end' then return nil,true end + return str + end) +end) + +--- insert an end after the next closing block. +-- @macro _END_END_ +-- @see _END_ +M.define '_END_END_ _END_ " end"' + +--- insert a closing parens after next closing block. +-- @usage def_ begin (function() _END_CLOSE_ +-- fun begin ... end --> fun (function() ... end) +-- @macro _END_CLOSE_ +-- @see _END_ +M.define '_END_CLOSE_ _END_ ")"' + +--- 'stringizing' macro. +-- Will convert its argument into a string. +-- @usage def_ _assert(x) assert(x,_STR_(x)) +-- @macro _STR_ +M.define('_STR_(x)',function(x) + x = tostring(x) + local put = M.Putter() + return put '"':name(x) '"' +end) + +-- macro stack manipulation + + +--- push a value onto a given macro' stack. +-- @macro _PUSH_ +-- @param mac existing macro name +-- @param V a string +M.define('_PUSH_(mac,V)',function(mac,V) + M.push_macro_stack(mac:get_string(),V:get_string()) +end) + +--- pop a value from a macro's stack. +-- @macro _POP_ +-- @param mac existing macro name +-- @return a string +-- @see _PUSH_ +M.define('_POP_',function(get,put) + local val = M.pop_macro_stack(get:string()) + if val then + return put(val) + end +end) + +--- drop the top of a macro's stack. +-- Like `_POP_`, except that it does not return the value +-- @macro _DROP_ +-- @return existing macro name +-- @see _POP_ +M.define('_DROP_',function(get) + M.pop_macro_stack(get:string()) +end) + +--- Load a Lua module immediately. This allows macro definitions to +-- to be loaded before the rest of the file is parsed. +-- If the module returns a function, then this is assumed to be a +-- substitution function, allowing macro modules to insert code +-- at this point. +-- @macro require_ +M.define('require_',function(get,put) + local name = get:string() + local ok,fn = pcall(require,name) + if not ok then + fn = require('macro.'..name) + end + if type(fn) == 'function' then + return fn(get,put) + end +end) + +--- Include the contents of a file. This inserts the file directly +-- into the token stream, and is equivalent to cpp's `#include` directive. +-- @macro include_ +M.define('include_',function(get) + local str = get:string() + local f = M.assert(io.open(str)) + local txt = f:read '*a' + f:close() + M.push_substitution(txt) +end) + |