1
0
mirror of https://github.com/g012/l65.git synced 2024-09-29 01:57:03 +00:00
l65/macro/builtin.lua

162 lines
4.3 KiB
Lua

-------
-- 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)