feat(lua): low-level interpreter mode (nvim -ll)

This commit is contained in:
bfredl
2022-02-26 15:19:10 +01:00
parent facbb11e05
commit d6d6ab3f8e
4 changed files with 77 additions and 23 deletions

View File

@@ -64,6 +64,7 @@
#include "nvim/window.h"
static int in_fast_callback = 0;
static bool in_script = false;
// Initialized in nlua_init().
static lua_State *global_lstate = NULL;
@@ -133,8 +134,13 @@ static void nlua_error(lua_State *const lstate, const char *const msg)
str = lua_tolstring(lstate, -1, &len);
}
msg_ext_set_kind("lua_error");
semsg_multiline(msg, (int)len, str);
if (in_script) {
os_errmsg(str);
os_errmsg("\n");
} else {
msg_ext_set_kind("lua_error");
semsg_multiline(msg, (int)len, str);
}
lua_pop(lstate, 1);
}
@@ -534,7 +540,7 @@ int nlua_get_global_ref_count(void)
return nlua_global_refs->ref_count;
}
static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
static void nlua_common_vim_init(lua_State *lstate, bool is_thread, bool is_standalone)
FUNC_ATTR_NONNULL_ARG(1)
{
nlua_ref_state_t *ref_state = nlua_new_ref_state(lstate, is_thread);
@@ -567,7 +573,9 @@ static void nlua_common_vim_init(lua_State *lstate, bool is_thread)
lua_setfield(lstate, -2, "_empty_dict_mt");
// vim.loop
if (is_thread) {
if (is_standalone) {
// do nothing, use libluv like in a standalone interpreter
} else if (is_thread) {
luv_set_callback(lstate, nlua_luv_thread_cb_cfpcall);
luv_set_thread(lstate, nlua_luv_thread_cfpcall);
luv_set_cthread(lstate, nlua_luv_thread_cfcpcall);
@@ -606,7 +614,7 @@ static int nlua_module_preloader(lua_State *lstate)
return 1;
}
static bool nlua_init_packages(lua_State *lstate)
static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
FUNC_ATTR_NONNULL_ALL
{
// put builtin packages in preload
@@ -618,7 +626,7 @@ static bool nlua_init_packages(lua_State *lstate)
lua_pushcclosure(lstate, nlua_module_preloader, 1); // [package, preload, cclosure]
lua_setfield(lstate, -2, def.name); // [package, preload]
if (nlua_disable_preload && strequal(def.name, "vim.inspect")) {
if ((nlua_disable_preload && !is_standalone) && strequal(def.name, "vim.inspect")) {
break;
}
}
@@ -769,7 +777,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_pushcfunction(lstate, &nlua_ui_detach);
lua_setfield(lstate, -2, "ui_detach");
nlua_common_vim_init(lstate, false);
nlua_common_vim_init(lstate, false, false);
// patch require() (only for --startuptime)
if (time_fd != NULL) {
@@ -788,7 +796,7 @@ static bool nlua_state_init(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
lua_setglobal(lstate, "vim");
if (!nlua_init_packages(lstate)) {
if (!nlua_init_packages(lstate, false)) {
return false;
}
@@ -823,10 +831,29 @@ void nlua_init(char **argv, int argc, int lua_arg0)
}
static lua_State *nlua_thread_acquire_vm(void)
{
return nlua_init_state(true);
}
void nlua_run_script(char **argv, int argc, int lua_arg0)
FUNC_ATTR_NORETURN
{
in_script = true;
global_lstate = nlua_init_state(false);
luv_set_thread_cb(nlua_thread_acquire_vm, nlua_common_free_all_mem);
nlua_init_argv(global_lstate, argv, argc, lua_arg0);
bool lua_ok = nlua_exec_file(argv[lua_arg0 - 1]);
#ifdef EXITFREE
nlua_free_all_mem();
#endif
exit(lua_ok ? 0 : 1);
}
lua_State *nlua_init_state(bool thread)
{
// If it is called from the main thread, it will attempt to rebuild the cache.
const uv_thread_t self = uv_thread_self();
if (uv_thread_equal(&main_thread, &self)) {
if (!in_script && uv_thread_equal(&main_thread, &self)) {
runtime_search_path_validate();
}
@@ -835,9 +862,11 @@ static lua_State *nlua_thread_acquire_vm(void)
// Add in the lua standard libraries
luaL_openlibs(lstate);
// print
lua_pushcfunction(lstate, &nlua_print);
lua_setglobal(lstate, "print");
if (!in_script) {
// print
lua_pushcfunction(lstate, &nlua_print);
lua_setglobal(lstate, "print");
}
lua_pushinteger(lstate, 0);
lua_setfield(lstate, LUA_REGISTRYINDEX, "nlua.refcount");
@@ -845,18 +874,20 @@ static lua_State *nlua_thread_acquire_vm(void)
// vim
lua_newtable(lstate);
nlua_common_vim_init(lstate, true);
nlua_common_vim_init(lstate, thread, in_script);
nlua_state_add_stdlib(lstate, true);
lua_createtable(lstate, 0, 0);
lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
lua_setfield(lstate, -2, "nvim__get_runtime");
lua_setfield(lstate, -2, "api");
if (!in_script) {
lua_createtable(lstate, 0, 0);
lua_pushcfunction(lstate, nlua_thr_api_nvim__get_runtime);
lua_setfield(lstate, -2, "nvim__get_runtime");
lua_setfield(lstate, -2, "api");
}
lua_setglobal(lstate, "vim");
nlua_init_packages(lstate);
nlua_init_packages(lstate, in_script);
lua_getglobal(lstate, "package");
lua_getfield(lstate, -1, "loaded");