build: enable lintlua for src/ dir #26395

Problem:
Not all Lua code is checked by stylua. Automating code-style is an
important mechanism for reducing time spent on accidental
(non-essential) complexity.

Solution:
- Enable lintlua for `src/` directory.

followup to 517f0cc634
This commit is contained in:
Justin M. Keyes
2023-12-04 13:31:57 -08:00
committed by GitHub
parent 517f0cc634
commit 45fe4d11ad
20 changed files with 3224 additions and 2978 deletions

View File

@@ -1,6 +1,6 @@
local mpack = vim.mpack
local hashy = require'generators.hashy'
local hashy = require 'generators.hashy'
assert(#arg >= 5)
-- output h file with generated dispatch functions (dispatch_wrappers.generated.h)
@@ -23,16 +23,20 @@ local function_names = {}
local c_grammar = require('generators.c_grammar')
local function startswith(String,Start)
return string.sub(String,1,string.len(Start))==Start
local function startswith(String, Start)
return string.sub(String, 1, string.len(Start)) == Start
end
local function add_function(fn)
local public = startswith(fn.name, "nvim_") or fn.deprecated_since
local public = startswith(fn.name, 'nvim_') or fn.deprecated_since
if public and not fn.noexport then
functions[#functions + 1] = fn
function_names[fn.name] = true
if #fn.parameters >= 2 and fn.parameters[2][1] == 'Array' and fn.parameters[2][2] == 'uidata' then
if
#fn.parameters >= 2
and fn.parameters[2][1] == 'Array'
and fn.parameters[2][2] == 'uidata'
then
-- function receives the "args" as a parameter
fn.receives_array_args = true
-- remove the args parameter
@@ -70,7 +74,7 @@ local function add_keyset(val)
local types = {}
local is_set_name = 'is_set__' .. val.keyset_name .. '_'
local has_optional = false
for i,field in ipairs(val.fields) do
for i, field in ipairs(val.fields) do
if field.type ~= 'Object' then
types[field.name] = field.type
end
@@ -80,14 +84,17 @@ local function add_keyset(val)
if i > 1 then
error("'is_set__{type}_' must be first if present")
elseif field.name ~= is_set_name then
error(val.keyset_name..": name of first key should be "..is_set_name)
error(val.keyset_name .. ': name of first key should be ' .. is_set_name)
elseif field.type ~= 'OptionalKeys' then
error("'"..is_set_name.."' must have type 'OptionalKeys'")
error("'" .. is_set_name .. "' must have type 'OptionalKeys'")
end
has_optional = true
end
end
table.insert(keysets, {name=val.keyset_name, keys=keys, types=types, has_optional=has_optional})
table.insert(
keysets,
{ name = val.keyset_name, keys = keys, types = types, has_optional = has_optional }
)
end
-- read each input file, parse and append to the api metadata
@@ -97,7 +104,7 @@ for i = 6, #arg do
for part in string.gmatch(full_path, '[^/]+') do
parts[#parts + 1] = part
end
headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts]
headers[#headers + 1] = parts[#parts - 1] .. '/' .. parts[#parts]
local input = io.open(full_path, 'rb')
@@ -123,14 +130,14 @@ end
-- Export functions under older deprecated names.
-- These will be removed eventually.
local deprecated_aliases = require("api.dispatch_deprecated")
for _,f in ipairs(shallowcopy(functions)) do
local deprecated_aliases = require('api.dispatch_deprecated')
for _, f in ipairs(shallowcopy(functions)) do
local ismethod = false
if startswith(f.name, "nvim_") then
if startswith(f.name, "nvim__") or f.name == "nvim_error_event" then
if startswith(f.name, 'nvim_') then
if startswith(f.name, 'nvim__') or f.name == 'nvim_error_event' then
f.since = -1
elseif f.since == nil then
print("Function "..f.name.." lacks since field.\n")
print('Function ' .. f.name .. ' lacks since field.\n')
os.exit(1)
end
f.since = tonumber(f.since)
@@ -138,16 +145,16 @@ for _,f in ipairs(shallowcopy(functions)) do
f.deprecated_since = tonumber(f.deprecated_since)
end
if startswith(f.name, "nvim_buf_") then
if startswith(f.name, 'nvim_buf_') then
ismethod = true
elseif startswith(f.name, "nvim_win_") then
elseif startswith(f.name, 'nvim_win_') then
ismethod = true
elseif startswith(f.name, "nvim_tabpage_") then
elseif startswith(f.name, 'nvim_tabpage_') then
ismethod = true
end
f.remote = f.remote_only or not f.lua_only
f.lua = f.lua_only or not f.remote_only
f.eval = (not f.lua_only) and (not f.remote_only)
f.eval = (not f.lua_only) and not f.remote_only
else
f.deprecated_since = tonumber(f.deprecated_since)
assert(f.deprecated_since == 1)
@@ -159,56 +166,59 @@ for _,f in ipairs(shallowcopy(functions)) do
if newname ~= nil then
if function_names[newname] then
-- duplicate
print("Function "..f.name.." has deprecated alias\n"
..newname.." which has a separate implementation.\n"..
"Please remove it from src/nvim/api/dispatch_deprecated.lua")
print(
'Function '
.. f.name
.. ' has deprecated alias\n'
.. newname
.. ' which has a separate implementation.\n'
.. 'Please remove it from src/nvim/api/dispatch_deprecated.lua'
)
os.exit(1)
end
local newf = shallowcopy(f)
newf.name = newname
if newname == "ui_try_resize" then
if newname == 'ui_try_resize' then
-- The return type was incorrectly set to Object in 0.1.5.
-- Keep it that way for clients that rely on this.
newf.return_type = "Object"
newf.return_type = 'Object'
end
newf.impl_name = f.name
newf.lua = false
newf.eval = false
newf.since = 0
newf.deprecated_since = 1
functions[#functions+1] = newf
functions[#functions + 1] = newf
end
end
-- don't expose internal attributes like "impl_name" in public metadata
local exported_attributes = {'name', 'return_type', 'method',
'since', 'deprecated_since'}
local exported_attributes = { 'name', 'return_type', 'method', 'since', 'deprecated_since' }
local exported_functions = {}
for _,f in ipairs(functions) do
if not (startswith(f.name, "nvim__") or f.name == "nvim_error_event" or f.name == "redraw") then
for _, f in ipairs(functions) do
if not (startswith(f.name, 'nvim__') or f.name == 'nvim_error_event' or f.name == 'redraw') then
local f_exported = {}
for _,attr in ipairs(exported_attributes) do
for _, attr in ipairs(exported_attributes) do
f_exported[attr] = f[attr]
end
f_exported.parameters = {}
for i,param in ipairs(f.parameters) do
if param[1] == "DictionaryOf(LuaRef)" then
param = {"Dictionary", param[2]}
elseif startswith(param[1], "Dict(") then
param = {"Dictionary", param[2]}
for i, param in ipairs(f.parameters) do
if param[1] == 'DictionaryOf(LuaRef)' then
param = { 'Dictionary', param[2] }
elseif startswith(param[1], 'Dict(') then
param = { 'Dictionary', param[2] }
end
f_exported.parameters[i] = param
end
exported_functions[#exported_functions+1] = f_exported
exported_functions[#exported_functions + 1] = f_exported
end
end
-- serialize the API metadata using msgpack and embed into the resulting
-- binary for easy querying by clients
local funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb')
local packed = mpack.encode(exported_functions)
local dump_bin_array = require("generators.dump_bin_array")
local dump_bin_array = require('generators.dump_bin_array')
dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed)
funcs_metadata_output:close()
@@ -246,67 +256,81 @@ output:write([[
]])
for _,k in ipairs(keysets) do
for _, k in ipairs(keysets) do
local c_name = {}
for i = 1,#k.keys do
for i = 1, #k.keys do
-- some keys, like "register" are c keywords and get
-- escaped with a trailing _ in the struct.
if vim.endswith(k.keys[i], "_") then
if vim.endswith(k.keys[i], '_') then
local orig = k.keys[i]
k.keys[i] = string.sub(k.keys[i],1, #(k.keys[i]) - 1)
k.keys[i] = string.sub(k.keys[i], 1, #k.keys[i] - 1)
c_name[k.keys[i]] = orig
k.types[k.keys[i]] = k.types[orig]
end
end
local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function (idx)
return k.name.."_table["..idx.."].str"
local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function(idx)
return k.name .. '_table[' .. idx .. '].str'
end)
keysets_defs:write("extern KeySetLink "..k.name.."_table[];\n")
keysets_defs:write('extern KeySetLink ' .. k.name .. '_table[];\n')
local function typename(type)
if type ~= nil then
return "kObjectType"..type
return 'kObjectType' .. type
else
return "kObjectTypeNil"
return 'kObjectTypeNil'
end
end
output:write("KeySetLink "..k.name.."_table[] = {\n")
output:write('KeySetLink ' .. k.name .. '_table[] = {\n')
for i, key in ipairs(neworder) do
local ind = -1
if k.has_optional then
ind = i
keysets_defs:write("#define KEYSET_OPTIDX_"..k.name.."__"..key.." "..ind.."\n")
keysets_defs:write('#define KEYSET_OPTIDX_' .. k.name .. '__' .. key .. ' ' .. ind .. '\n')
end
output:write(' {"'..key..'", offsetof(KeyDict_'..k.name..", "..(c_name[key] or key).."), "..typename(k.types[key])..", "..ind.."},\n")
output:write(
' {"'
.. key
.. '", offsetof(KeyDict_'
.. k.name
.. ', '
.. (c_name[key] or key)
.. '), '
.. typename(k.types[key])
.. ', '
.. ind
.. '},\n'
)
end
output:write(' {NULL, 0, kObjectTypeNil, -1},\n')
output:write("};\n\n")
output:write(' {NULL, 0, kObjectTypeNil, -1},\n')
output:write('};\n\n')
output:write(hashfun)
output:write([[
KeySetLink *KeyDict_]]..k.name..[[_get_field(const char *str, size_t len)
KeySetLink *KeyDict_]] .. k.name .. [[_get_field(const char *str, size_t len)
{
int hash = ]]..k.name..[[_hash(str, len);
int hash = ]] .. k.name .. [[_hash(str, len);
if (hash == -1) {
return NULL;
}
return &]]..k.name..[[_table[hash];
return &]] .. k.name .. [[_table[hash];
}
]])
keysets_defs:write("#define api_free_keydict_"..k.name.."(x) api_free_keydict(x, "..k.name.."_table)\n")
keysets_defs:write(
'#define api_free_keydict_' .. k.name .. '(x) api_free_keydict(x, ' .. k.name .. '_table)\n'
)
end
local function real_type(type)
local rv = type
local rmatch = string.match(type, "Dict%(([_%w]+)%)")
local rmatch = string.match(type, 'Dict%(([_%w]+)%)')
if rmatch then
return "KeyDict_"..rmatch
return 'KeyDict_' .. rmatch
elseif c_grammar.typed_container:match(rv) then
if rv:match('Array') then
rv = 'Array'
@@ -333,24 +357,30 @@ for i = 1, #functions do
if fn.impl_name == nil and fn.remote then
local args = {}
output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)')
output:write(
'Object handle_' .. fn.name .. '(uint64_t channel_id, Array args, Arena* arena, Error *error)'
)
output:write('\n{')
output:write('\n#ifdef NVIM_LOG_DEBUG')
output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke '..fn.name..'", channel_id);')
output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke ' .. fn.name .. '", channel_id);')
output:write('\n#endif')
output:write('\n Object ret = NIL;')
-- Declare/initialize variables that will hold converted arguments
for j = 1, #fn.parameters do
local param = fn.parameters[j]
local rt = real_type(param[1])
local converted = 'arg_'..j
output:write('\n '..rt..' '..converted..';')
local converted = 'arg_' .. j
output:write('\n ' .. rt .. ' ' .. converted .. ';')
end
output:write('\n')
if not fn.receives_array_args then
output:write('\n if (args.size != '..#fn.parameters..') {')
output:write('\n api_set_error(error, kErrorTypeException, \
"Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);')
output:write('\n if (args.size != ' .. #fn.parameters .. ') {')
output:write(
'\n api_set_error(error, kErrorTypeException, \
"Wrong number of arguments: expecting '
.. #fn.parameters
.. ' but got %zu", args.size);'
)
output:write('\n goto cleanup;')
output:write('\n }\n')
end
@@ -359,55 +389,121 @@ for i = 1, #functions do
for j = 1, #fn.parameters do
local converted, param
param = fn.parameters[j]
converted = 'arg_'..j
converted = 'arg_' .. j
local rt = real_type(param[1])
if rt == 'Object' then
output:write('\n '..converted..' = args.items['..(j - 1)..'];\n')
output:write('\n ' .. converted .. ' = args.items[' .. (j - 1) .. '];\n')
elseif rt:match('^KeyDict_') then
converted = '&' .. converted
output:write('\n if (args.items['..(j - 1)..'].type == kObjectTypeDictionary) {') --luacheck: ignore 631
output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));') -- TODO: neeeee
output:write('\n if (!api_dict_to_keydict('..converted..', '..rt..'_get_field, args.items['..(j - 1)..'].data.dictionary, error)) {')
output:write('\n if (args.items[' .. (j - 1) .. '].type == kObjectTypeDictionary) {') --luacheck: ignore 631
output:write('\n memset(' .. converted .. ', 0, sizeof(*' .. converted .. '));') -- TODO: neeeee
output:write(
'\n if (!api_dict_to_keydict('
.. converted
.. ', '
.. rt
.. '_get_field, args.items['
.. (j - 1)
.. '].data.dictionary, error)) {'
)
output:write('\n goto cleanup;')
output:write('\n }')
output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631
output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));')
output:write(
'\n } else if (args.items['
.. (j - 1)
.. '].type == kObjectTypeArray && args.items['
.. (j - 1)
.. '].data.array.size == 0) {'
) --luacheck: ignore 631
output:write('\n memset(' .. converted .. ', 0, sizeof(*' .. converted .. '));')
output:write('\n } else {')
output:write('\n api_set_error(error, kErrorTypeException, \
"Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");')
output:write(
'\n api_set_error(error, kErrorTypeException, \
"Wrong type for argument '
.. j
.. ' when calling '
.. fn.name
.. ', expecting '
.. param[1]
.. '");'
)
output:write('\n goto cleanup;')
output:write('\n }\n')
else
if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then
-- Buffer, Window, and Tabpage have a specific type, but are stored in integer
output:write('\n if (args.items['..
(j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {')
output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;')
output:write(
'\n if (args.items['
.. (j - 1)
.. '].type == kObjectType'
.. rt
.. ' && args.items['
.. (j - 1)
.. '].data.integer >= 0) {'
)
output:write(
'\n ' .. converted .. ' = (handle_T)args.items[' .. (j - 1) .. '].data.integer;'
)
else
output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {')
output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';')
output:write('\n if (args.items[' .. (j - 1) .. '].type == kObjectType' .. rt .. ') {')
output:write(
'\n '
.. converted
.. ' = args.items['
.. (j - 1)
.. '].data.'
.. attr_name(rt)
.. ';'
)
end
if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then
if
rt:match('^Buffer$')
or rt:match('^Window$')
or rt:match('^Tabpage$')
or rt:match('^Boolean$')
then
-- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages
output:write('\n } else if (args.items['..
(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {')
output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;')
output:write(
'\n } else if (args.items['
.. (j - 1)
.. '].type == kObjectTypeInteger && args.items['
.. (j - 1)
.. '].data.integer >= 0) {'
)
output:write(
'\n ' .. converted .. ' = (handle_T)args.items[' .. (j - 1) .. '].data.integer;'
)
end
if rt:match('^Float$') then
-- accept integers for Floats
output:write('\n } else if (args.items['..
(j - 1)..'].type == kObjectTypeInteger) {')
output:write('\n '..converted..' = (Float)args.items['..(j - 1)..'].data.integer;')
output:write('\n } else if (args.items[' .. (j - 1) .. '].type == kObjectTypeInteger) {')
output:write(
'\n ' .. converted .. ' = (Float)args.items[' .. (j - 1) .. '].data.integer;'
)
end
-- accept empty lua tables as empty dictionaries
if rt:match('^Dictionary') then
output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631
output:write('\n '..converted..' = (Dictionary)ARRAY_DICT_INIT;')
output:write(
'\n } else if (args.items['
.. (j - 1)
.. '].type == kObjectTypeArray && args.items['
.. (j - 1)
.. '].data.array.size == 0) {'
) --luacheck: ignore 631
output:write('\n ' .. converted .. ' = (Dictionary)ARRAY_DICT_INIT;')
end
output:write('\n } else {')
output:write('\n api_set_error(error, kErrorTypeException, \
"Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");')
output:write(
'\n api_set_error(error, kErrorTypeException, \
"Wrong type for argument '
.. j
.. ' when calling '
.. fn.name
.. ', expecting '
.. param[1]
.. '");'
)
output:write('\n goto cleanup;')
output:write('\n }\n')
end
@@ -431,11 +527,11 @@ for i = 1, #functions do
output:write('\n ')
if fn.return_type ~= 'void' then
-- has a return value, prefix the call with a declaration
output:write(fn.return_type..' rv = ')
output:write(fn.return_type .. ' rv = ')
end
-- write the function name and the opening parenthesis
output:write(fn.name..'(')
output:write(fn.name .. '(')
if fn.receives_channel_id then
-- if the function receives the channel id, pass it as first argument
@@ -455,7 +551,7 @@ for i = 1, #functions do
else
if fn.receives_array_args then
if #args > 0 or fn.call_fail then
output:write('args, '..call_args)
output:write('args, ' .. call_args)
else
output:write('args')
end
@@ -465,7 +561,7 @@ for i = 1, #functions do
end
if fn.arena_return then
output:write(', arena')
output:write(', arena')
end
if fn.has_lua_imp then
@@ -492,36 +588,45 @@ for i = 1, #functions do
end
if fn.return_type ~= 'void' then
output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);')
output:write('\n ret = ' .. string.upper(real_type(fn.return_type)) .. '_OBJ(rv);')
end
output:write('\n\ncleanup:');
output:write('\n\ncleanup:')
output:write('\n return ret;\n}\n\n');
output:write('\n return ret;\n}\n\n')
end
end
local remote_fns = {}
for _,fn in ipairs(functions) do
for _, fn in ipairs(functions) do
if fn.remote then
remote_fns[fn.name] = fn
end
end
remote_fns.redraw = {impl_name="ui_client_redraw", fast=true}
remote_fns.redraw = { impl_name = 'ui_client_redraw', fast = true }
local names = vim.tbl_keys(remote_fns)
table.sort(names)
local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", names, function (idx)
return "method_handlers["..idx.."].name"
local hashorder, hashfun = hashy.hashy_hash('msgpack_rpc_get_handler_for', names, function(idx)
return 'method_handlers[' .. idx .. '].name'
end)
output:write("const MsgpackRpcRequestHandler method_handlers[] = {\n")
output:write('const MsgpackRpcRequestHandler method_handlers[] = {\n')
for n, name in ipairs(hashorder) do
local fn = remote_fns[name]
fn.handler_id = n-1
output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name)..
', .fast = '..tostring(fn.fast)..', .arena_return = '..tostring(not not fn.arena_return)..'},\n')
fn.handler_id = n - 1
output:write(
' { .name = "'
.. name
.. '", .fn = handle_'
.. (fn.impl_name or fn.name)
.. ', .fast = '
.. tostring(fn.fast)
.. ', .arena_return = '
.. tostring(not not fn.arena_return)
.. '},\n'
)
end
output:write("};\n\n")
output:write('};\n\n')
output:write(hashfun)
output:close()
@@ -534,7 +639,7 @@ mpack_output:close()
local function include_headers(output_handle, headers_to_include)
for i = 1, #headers_to_include do
if headers_to_include[i]:sub(-12) ~= '.generated.h' then
output_handle:write('\n#include "nvim/'..headers_to_include[i]..'"')
output_handle:write('\n#include "nvim/' .. headers_to_include[i] .. '"')
end
end
end
@@ -572,7 +677,10 @@ local lua_c_functions = {}
local function process_function(fn)
local lua_c_function_name = ('nlua_api_%s'):format(fn.name)
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
static int %s(lua_State *lstate)
{
@@ -582,71 +690,108 @@ local function process_function(fn)
api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
goto exit_0;
}
]], lua_c_function_name, #fn.parameters, #fn.parameters,
(#fn.parameters == 1) and '' or 's'))
]],
lua_c_function_name,
#fn.parameters,
#fn.parameters,
(#fn.parameters == 1) and '' or 's'
)
)
lua_c_functions[#lua_c_functions + 1] = {
binding=lua_c_function_name,
api=fn.name
binding = lua_c_function_name,
api = fn.name,
}
if not fn.fast then
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
if (!nlua_is_deferred_safe()) {
return luaL_error(lstate, e_luv_api_disabled, "%s");
}
]], fn.name))
]],
fn.name
)
)
end
if fn.textlock then
write_shifted_output(output, [[
write_shifted_output(
output,
[[
if (text_locked()) {
api_set_error(&err, kErrorTypeException, "%s", get_text_locked_msg());
goto exit_0;
}
]])
]]
)
elseif fn.textlock_allow_cmdwin then
write_shifted_output(output, [[
write_shifted_output(
output,
[[
if (textlock != 0 || expr_map_locked()) {
api_set_error(&err, kErrorTypeException, "%s", e_textlock);
goto exit_0;
}
]])
]]
)
end
local cparams = ''
local free_code = {}
for j = #fn.parameters,1,-1 do
for j = #fn.parameters, 1, -1 do
local param = fn.parameters[j]
local cparam = string.format('arg%u', j)
local param_type = real_type(param[1])
local lc_param_type = real_type(param[1]):lower()
local extra = param_type == "Dictionary" and "false, " or ""
if param[1] == "Object" or param[1] == "DictionaryOf(LuaRef)" then
extra = "true, "
local extra = param_type == 'Dictionary' and 'false, ' or ''
if param[1] == 'Object' or param[1] == 'DictionaryOf(LuaRef)' then
extra = 'true, '
end
local errshift = 0
local seterr = ''
if string.match(param_type, '^KeyDict_') then
write_shifted_output(output, string.format([[
%s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]], param_type, cparam, cparam, param_type))
cparam = '&'..cparam
write_shifted_output(
output,
string.format(
[[
%s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]],
param_type,
cparam,
cparam,
param_type
)
)
cparam = '&' .. cparam
errshift = 1 -- free incomplete dict on error
else
write_shifted_output(output, string.format([[
const %s %s = nlua_pop_%s(lstate, %s&err);]], param[1], cparam, param_type, extra))
write_shifted_output(
output,
string.format(
[[
const %s %s = nlua_pop_%s(lstate, %s&err);]],
param[1],
cparam,
param_type,
extra
)
)
seterr = [[
err_param = "]]..param[2]..[[";]]
err_param = "]] .. param[2] .. [[";]]
end
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format([[
if (ERROR_SET(&err)) {]]..seterr..[[
if (ERROR_SET(&err)) {]] .. seterr .. [[
goto exit_%u;
}
]], #fn.parameters - j + errshift))
free_code[#free_code + 1] = ('api_free_%s(%s);'):format(
lc_param_type, cparam)
]], #fn.parameters - j + errshift)
)
free_code[#free_code + 1] = ('api_free_%s(%s);'):format(lc_param_type, cparam)
cparams = cparam .. ', ' .. cparams
end
if fn.receives_channel_id then
@@ -654,9 +799,12 @@ local function process_function(fn)
end
if fn.arena_return then
cparams = cparams .. '&arena, '
write_shifted_output(output, [[
write_shifted_output(
output,
[[
Arena arena = ARENA_EMPTY;
]])
]]
)
end
if fn.has_lua_imp then
@@ -675,8 +823,7 @@ local function process_function(fn)
if i == 1 and not string.match(real_type(fn.parameters[1][1]), '^KeyDict_') then
free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code)
else
free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format(
rev_i, code)
free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format(rev_i, code)
end
end
local err_throw_code = [[
@@ -704,45 +851,86 @@ local function process_function(fn)
end
local free_retval
if fn.arena_return then
free_retval = "arena_mem_free(arena_finish(&arena));"
free_retval = 'arena_mem_free(arena_finish(&arena));'
else
free_retval = "api_free_"..return_type:lower().."(ret);"
free_retval = 'api_free_' .. return_type:lower() .. '(ret);'
end
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
const %s ret = %s(%s);
]], fn.return_type, fn.name, cparams))
]],
fn.return_type,
fn.name,
cparams
)
)
if fn.has_lua_imp then
-- only push onto the Lua stack if we haven't already
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
if (lua_gettop(lstate) == 0) {
nlua_push_%s(lstate, ret, true);
}
]], return_type))
]],
return_type
)
)
else
local special = (fn.since ~= nil and fn.since < 11)
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
nlua_push_%s(lstate, ret, %s);
]], return_type, tostring(special)))
]],
return_type,
tostring(special)
)
)
end
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
%s
%s
%s
return 1;
]], free_retval, free_at_exit_code, err_throw_code))
]],
free_retval,
free_at_exit_code,
err_throw_code
)
)
else
write_shifted_output(output, string.format([[
write_shifted_output(
output,
string.format(
[[
%s(%s);
%s
%s
return 0;
]], fn.name, cparams, free_at_exit_code, err_throw_code))
]],
fn.name,
cparams,
free_at_exit_code,
err_throw_code
)
)
end
write_shifted_output(output, [[
write_shifted_output(
output,
[[
}
]])
]]
)
end
for _, fn in ipairs(functions) do
@@ -751,18 +939,25 @@ for _, fn in ipairs(functions) do
end
end
output:write(string.format([[
output:write(string.format(
[[
void nlua_add_api_functions(lua_State *lstate)
REAL_FATTR_NONNULL_ALL;
void nlua_add_api_functions(lua_State *lstate)
{
lua_createtable(lstate, 0, %u);
]], #lua_c_functions))
]],
#lua_c_functions
))
for _, func in ipairs(lua_c_functions) do
output:write(string.format([[
output:write(string.format(
[[
lua_pushcfunction(lstate, &%s);
lua_setfield(lstate, -2, "%s");]], func.binding, func.api))
lua_setfield(lstate, -2, "%s");]],
func.binding,
func.api
))
end
output:write([[