aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/generators/gen_api_dispatch.lua
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-08-07 14:42:25 +0200
committerGitHub <noreply@github.com>2023-08-07 14:42:25 +0200
commit3a21c3afe61e5bb76f4b81c1a961b2558e2c8f0a (patch)
tree02d894cf470742f02a1d69e05078562abd7f4762 /src/nvim/generators/gen_api_dispatch.lua
parentef44e597294e4d0d9128ef69b6aa7481a54e17cb (diff)
parent51c754b62e795c49cfcf9df3ab492bdd53c61482 (diff)
downloadrneovim-3a21c3afe61e5bb76f4b81c1a961b2558e2c8f0a.tar.gz
rneovim-3a21c3afe61e5bb76f4b81c1a961b2558e2c8f0a.tar.bz2
rneovim-3a21c3afe61e5bb76f4b81c1a961b2558e2c8f0a.zip
Merge pull request #24524 from bfredl/typed_keys
refactor(api): use typed keysets
Diffstat (limited to 'src/nvim/generators/gen_api_dispatch.lua')
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua100
1 files changed, 65 insertions, 35 deletions
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 1b0565d9b6..02648e6c99 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -67,13 +67,27 @@ local keysets = {}
local function add_keyset(val)
local keys = {}
- for _,field in ipairs(val.fields) do
+ local types = {}
+ local is_set_name = 'is_set__' .. val.keyset_name .. '_'
+ local has_optional = false
+ for i,field in ipairs(val.fields) do
if field.type ~= 'Object' then
- error 'not yet implemented: types other than Object'
+ types[field.name] = field.type
+ end
+ if field.name ~= is_set_name and field.type ~= 'OptionalKeys' then
+ table.insert(keys, field.name)
+ else
+ 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)
+ elseif field.type ~= 'OptionalKeys' then
+ error("'"..is_set_name.."' must have type 'OptionalKeys'")
+ end
+ has_optional = true
end
- table.insert(keys, {field.name, field.type})
end
- table.insert(keysets, {val.keyset_name, keys})
+ 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
@@ -232,53 +246,60 @@ output:write([[
]])
-for _,keyset in ipairs(keysets) do
- local name, keys = unpack(keyset)
- local special = {}
- local function sanitize(key)
- if special[key] then
- return key .. "_"
- end
- return key
- end
+for _,k in ipairs(keysets) do
+ local c_name = {}
- local key_names = {}
- for i = 1,#keys do
- local kname = keys[i][1]
- if vim.endswith(kname, "_") then
- kname = string.sub(kname,1, #kname - 1)
- special[kname] = true
+ 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
+ local orig = k.keys[i]
+ 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
- key_names[i] = kname
end
- local neworder, hashfun = hashy.hashy_hash(name, key_names, function (idx)
- return 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 "..name.."_table[];\n")
+ keysets_defs:write("extern KeySetLink "..k.name.."_table[];\n")
- output:write("KeySetLink "..name.."_table[] = {\n")
- for _, key in ipairs(neworder) do
- output:write(' {"'..key..'", offsetof(KeyDict_'..name..", "..sanitize(key)..")},\n")
+ local function typename(type)
+ if type ~= nil then
+ return "kObjectType"..type
+ else
+ return "kObjectTypeNil"
+ end
+ end
+
+ 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")
+ end
+ output:write(' {"'..key..'", offsetof(KeyDict_'..k.name..", "..(c_name[key] or key).."), "..typename(k.types[key])..", "..ind.."},\n")
end
- output:write(' {NULL, 0},\n')
+ output:write(' {NULL, 0, kObjectTypeNil, -1},\n')
output:write("};\n\n")
output:write(hashfun)
output:write([[
-Object *KeyDict_]]..name..[[_get_field(void *retval, const char *str, size_t len)
+KeySetLink *KeyDict_]]..k.name..[[_get_field(const char *str, size_t len)
{
- int hash = ]]..name..[[_hash(str, len);
+ int hash = ]]..k.name..[[_hash(str, len);
if (hash == -1) {
return NULL;
}
-
- return (Object *)((char *)retval + ]]..name..[[_table[hash].ptr_off);
+ return &]]..k.name..[[_table[hash];
}
]])
- keysets_defs:write("#define api_free_keydict_"..name.."(x) api_free_keydict(x, "..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)
@@ -558,6 +579,7 @@ local function process_function(fn)
static int %s(lua_State *lstate)
{
Error err = ERROR_INIT;
+ char *err_param = 0;
if (lua_gettop(lstate) != %i) {
api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
goto exit_0;
@@ -605,19 +627,22 @@ local function process_function(fn)
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, %s&err);]], param_type, cparam, cparam, param_type, extra))
+ %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))
+ seterr = [[
+ err_param = "]]..param[2]..[[";]]
end
write_shifted_output(output, string.format([[
- if (ERROR_SET(&err)) {
+ if (ERROR_SET(&err)) {]]..seterr..[[
goto exit_%u;
}
@@ -661,9 +686,14 @@ local function process_function(fn)
exit_0:
if (ERROR_SET(&err)) {
luaL_where(lstate, 1);
+ if (err_param) {
+ lua_pushstring(lstate, "Invalid '");
+ lua_pushstring(lstate, err_param);
+ lua_pushstring(lstate, "': ");
+ }
lua_pushstring(lstate, err.msg);
api_clear_error(&err);
- lua_concat(lstate, 2);
+ lua_concat(lstate, err_param ? 5 : 2);
return lua_error(lstate);
}
]]