1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
//! "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;
extern "c" fn luaopen_luv(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");
const retval3 = luaopen_luv(lua);
if (retval3 != 1) return error.LoadError;
lua.setField(-3, "uv");
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);
}
|