summaryrefslogtreecommitdiffstatshomepage
path: root/src/nlua0.zig
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2025-03-11 14:01:55 +0100
committerbfredl <bjorn.linse@gmail.com>2025-05-02 09:28:50 +0200
commit1f004970f00bd8ef7ad955b52857df136f82185b (patch)
treef3714cf7fcb3e8cd9ec20249c2d3ee9aef5b78c6 /src/nlua0.zig
parent0ab0cdb2dabc551f836851aa85d06e927c42d92a (diff)
feat(build): build.zig MVP: build and run functionaltests on linux
NEW BUILD SYSTEM! This is a MVP implementation which supports building the "nvim" binary, including cross-compilation for some targets. As an example, you can build a aarch64-macos binary from an x86-64-linux-gnu host, or vice versa Add CI target for build.zig currently for functionaltests on linux x86_64 only Follow up items: - praxis for version and dependency bumping - windows 💀 - full integration of libintl and gettext (or a desicion not to) - update help and API metadata files - installation into a $PREFIX - more tests and linters
Diffstat (limited to 'src/nlua0.zig')
-rw-r--r--src/nlua0.zig120
1 files changed, 120 insertions, 0 deletions
diff --git a/src/nlua0.zig b/src/nlua0.zig
new file mode 100644
index 0000000000..042ff01609
--- /dev/null
+++ b/src/nlua0.zig
@@ -0,0 +1,120 @@
+//! "nlua" is an abbreviation for nvim flavored lua, i e lua with the
+//! extended standard library functionality added by nvim such as json, mpack
+//! and libuv and a range of vim.* utility functions.
+//!
+//! nlua0 is an interpreter for the "bootstrap" lua code we need to run before
+//! nvim can be built, in order to run lua scripts which process and generate
+//! more .c code, which still need these extensions.
+const std = @import("std");
+const ziglua = @import("ziglua");
+const options = @import("options");
+
+const embedded_data = @import("embedded_data");
+
+// these are common dependencies used by many generators
+const hashy = @embedFile("gen/hashy.lua");
+const c_grammar = @embedFile("gen/c_grammar.lua");
+
+const Lua = ziglua.Lua;
+
+extern "c" fn luaopen_mpack(ptr: *anyopaque) c_int;
+extern "c" fn luaopen_lpeg(ptr: *anyopaque) c_int;
+extern "c" fn luaopen_bit(ptr: *anyopaque) c_int;
+
+fn init() !*Lua {
+ // Initialize the Lua vm
+ var lua = try Lua.init(std.heap.c_allocator);
+ lua.openLibs();
+
+ // this sets _G.vim by itself, so we don't need to
+ try lua.loadBuffer(embedded_data.shared_module, "shared.lua");
+ lua.call(.{ .results = 1 });
+
+ try lua.loadBuffer(embedded_data.inspect_module, "inspect.lua");
+ lua.call(.{ .results = 1 });
+ lua.setField(-2, "inspect");
+
+ try lua.loadBuffer(embedded_data.iter_module, "iter.lua");
+ lua.call(.{ .results = 1 });
+ lua.setField(-2, "iter");
+
+ _ = try lua.getGlobal("package");
+ _ = lua.getField(-1, "preload");
+ try lua.loadBuffer(hashy, "hashy.lua"); // [package, preload, hashy]
+ lua.setField(-2, "gen.hashy");
+ try lua.loadBuffer(c_grammar, "c_grammar.lua"); // [package, preload, c_grammar]
+ lua.setField(-2, "gen.c_grammar");
+ lua.pop(2);
+
+ const retval = luaopen_mpack(lua);
+ if (retval != 1) return error.LoadError;
+ _ = lua.getField(-1, "NIL"); // [vim, mpack, NIL]
+ lua.setField(-3, "NIL"); // vim.NIL = mpack.NIL (wow BOB wow)
+ lua.setField(-2, "mpack");
+
+ const retval2 = luaopen_lpeg(lua);
+ if (retval2 != 1) return error.LoadError;
+ lua.setField(-3, "lpeg");
+
+ lua.pop(2);
+
+ if (!options.use_luajit) {
+ lua.pop(luaopen_bit(lua));
+ }
+ return lua;
+}
+
+pub fn main() !void {
+ const argv = std.os.argv;
+
+ const lua = try init();
+ defer lua.deinit();
+
+ if (argv.len < 2) {
+ std.debug.print("USAGE: nlua0 script.lua args...\n\n", .{});
+ return;
+ }
+ lua.createTable(@intCast(argv.len - 2), 1);
+ for (0.., argv[1..]) |i, arg| {
+ _ = lua.pushString(std.mem.span(arg));
+ lua.rawSetIndex(-2, @intCast(i));
+ }
+ lua.setGlobal("arg");
+
+ _ = try lua.getGlobal("debug");
+ _ = lua.getField(-1, "traceback");
+ try lua.loadFile(std.mem.span(argv[1]));
+ lua.protectedCall(.{ .msg_handler = -2 }) catch |e| {
+ if (e == error.LuaRuntime) {
+ const msg = try lua.toString(-1);
+ std.debug.print("{s}\n", .{msg});
+ }
+ return e;
+ };
+}
+
+fn do_ret1(lua: *Lua, str: [:0]const u8) !void {
+ try lua.loadString(str);
+ try lua.protectedCall(.{ .results = 1 });
+}
+
+test "simple test" {
+ const lua = try init();
+ defer lua.deinit();
+
+ try do_ret1(lua, "return vim.isarray({2,3})");
+ try std.testing.expectEqual(true, lua.toBoolean(-1));
+ lua.pop(1);
+
+ try do_ret1(lua, "return vim.isarray({a=2,b=3})");
+ try std.testing.expectEqual(false, lua.toBoolean(-1));
+ lua.pop(1);
+
+ try do_ret1(lua, "return vim.inspect(vim.mpack.decode('\\146\\42\\69'))");
+ try std.testing.expectEqualStrings("{ 42, 69 }", try lua.toString(-1));
+ lua.pop(1);
+
+ try do_ret1(lua, "return require'bit'.band(7,12)");
+ try std.testing.expectEqualStrings("4", try lua.toString(-1));
+ lua.pop(1);
+}