forked from natecraddock/ziglua
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterpreter.zig
More file actions
86 lines (71 loc) · 2.77 KB
/
interpreter.zig
File metadata and controls
86 lines (71 loc) · 2.77 KB
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
//! Simple Lua interpreter
//! This is a modified program from Programming in Lua 4th Edition
const std = @import("std");
// The zlua module is made available in build.zig
const zlua = @import("zlua");
const ReadError = error{BufferTooSmall};
fn readlineStdin(io: std.Io, out_buf: []u8) anyerror!usize {
var in_buf: [4096]u8 = undefined;
var stdin_file = std.Io.File.stdin().reader(io, &in_buf);
const stdin = &stdin_file.interface;
const s = try stdin.takeDelimiterExclusive('\n');
if (s.len < out_buf.len) {
@memcpy(out_buf[0..s.len], s);
return s.len;
}
return error.BufferTooSmall;
}
fn flushedStdoutPrint(io: std.Io, comptime fmt: []const u8, args: anytype) !void {
var out_buf: [4096]u8 = undefined;
var w = std.Io.File.stdout().writer(io, &out_buf);
const stdout = &w.interface;
try stdout.print(fmt, args);
try stdout.flush();
}
pub fn main() anyerror!void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer _ = gpa.deinit();
var threaded: std.Io.Threaded = .init_single_threaded;
defer threaded.deinit();
const io = threaded.io();
// Initialize The Lua vm and get a reference to the main thread
//
// Passing a Zig allocator to the Lua state requires a stable pointer
var lua = try zlua.Lua.init(allocator);
defer lua.deinit();
// Open all Lua standard libraries
lua.openLibs();
while (true) {
try flushedStdoutPrint(io, "> ", .{});
// Read a line of input
var buffer: [256]u8 = undefined;
const len = readlineStdin(io, buffer[0 .. buffer.len - 1]) catch |err| {
switch (err) {
error.BufferTooSmall => {
try flushedStdoutPrint(io, "error: line too long!\n", .{});
continue;
},
error.EndOfStream => break,
else => return err,
}
};
// Ensure the buffer is null-terminated so the Lua API can read the length
buffer[len] = 0;
// Compile a line of Lua code
lua.loadString(buffer[0..len :0]) catch {
// If there was an error, Lua will place an error string on the top of the stack.
// Here we print out the string to inform the user of the issue.
try flushedStdoutPrint(io, "{s}\n", .{lua.toString(-1) catch unreachable});
// Remove the error from the stack and go back to the prompt
lua.pop(1);
continue;
};
// Execute a line of Lua code
lua.protectedCall(.{}) catch {
// Error handling here is the same as above.
try flushedStdoutPrint(io, "{s}\n", .{lua.toString(-1) catch unreachable});
lua.pop(1);
};
}
}