main.zig (3954B)
1 const std = @import("std"); 2 const Int = std.math.big.int; 3 const value = @import("value.zig"); 4 const chunk = @import("chunk.zig"); 5 const vm = @import("vm.zig"); 6 const cl = @cImport(@cInclude("crossline.h")); 7 const s = @import("scan.zig"); 8 const comp = @import("compile.zig"); 9 const symintern = @import("symintern.zig"); 10 const builtin = @import("builtin"); 11 const core = @import("core.zig"); 12 13 const GPAll = std.heap.GeneralPurposeAllocator(.{}); 14 15 pub const std_options = .{ 16 .log_level = if (builtin.mode == .Debug) std.log.Level.debug else .info, 17 .log_scope_levels = &.{.{ .scope = .read, .level = .err }}, 18 .logFn = myLogFn, 19 }; 20 21 pub fn myLogFn( 22 comptime level: std.log.Level, 23 comptime scope: @TypeOf(.EnumLiteral), 24 comptime format: []const u8, 25 args: anytype, 26 ) void { 27 const scope_prefix = "(" ++ @tagName(scope) ++ "): "; 28 29 std.debug.lockStdErr(); 30 defer std.debug.unlockStdErr(); 31 const stderrf = std.io.getStdErr(); 32 const stderr = stderrf.writer(); 33 34 const config = std.io.tty.detectConfig(stderrf); 35 36 config.setColor(stderr, switch (level) { 37 .debug => .blue, 38 .info => .green, 39 .warn => .orange, 40 .err => .red, 41 }) catch return; 42 stderr.writeAll(comptime level.asText()) catch return; 43 config.setColor(stderr, .reset) catch return; 44 stderr.print(scope_prefix ++ format ++ "\n", args) catch return; 45 } 46 47 fn runContent(content: []const u8, v: *vm.VM, all: std.mem.Allocator) !void { 48 var offset: ?usize = null; 49 var reader = try s.Reader.init(content, all, &offset); 50 51 while (reader.readValue(&offset)) |val| { 52 defer val.unref(); 53 54 var compiler = try comp.Compiler.init(all, val); 55 defer compiler.deinit(); 56 57 var c = try compiler.compile(); 58 defer c.deinit(); 59 60 const result = try v.interpret(&c); 61 defer result.unref(); 62 std.debug.assert(v.stack.items.len == 0); 63 64 const stdout = std.io.getStdOut(); 65 try std.fmt.format(stdout.writer(), "=> {}\n", .{result.formatter()}); 66 } else |err| { 67 if (err != error.Eof) { 68 std.log.err("Parse error {} at {}, char '{c}' ({})", .{err, offset.?, content[offset.?], content[offset.?]}); 69 return err; 70 } 71 } 72 } 73 74 fn runFile(path: []const u8, v: *vm.VM, all: std.mem.Allocator) !void { 75 // TODO: file parsing stuff 76 var file = try std.fs.cwd().openFile(path, .{}); 77 defer file.close(); 78 79 const content = try file.readToEndAlloc(all, 10 * 1024 * 1024); 80 defer all.free(content); 81 try runContent(content, v, all); 82 } 83 84 pub fn main() !void { 85 var gp = GPAll{}; 86 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 87 88 const all = if (builtin.mode == .Debug) gp.allocator() else arena.allocator(); 89 90 defer if (builtin.mode == .Debug) std.debug.assert(gp.deinit() == .ok); 91 92 symintern.init(all); 93 defer symintern.deinit(); 94 95 try value.init(all); 96 defer value.deinit(); 97 98 var v = try vm.VM.init(all); 99 defer v.deinit(); 100 101 try v.setupCore(core.funcs); 102 103 var args = std.process.args(); 104 _ = args.next(); 105 106 if (args.next()) |path| { 107 try runFile(path, &v, all); 108 } else { 109 var buf: [1024:0]u8 = undefined; 110 111 _ = cl.crossline_history_load(".zahl_history"); 112 defer _ = cl.crossline_history_save(".zahl_history"); 113 114 while (cl.crossline_readline("> ", &buf, buf.len)) |obuf| { 115 const input = obuf[0..std.mem.len(obuf)]; 116 117 if (input.len == 0) { 118 continue; 119 } 120 121 if (input[0] == '.') { 122 var tokens = std.mem.tokenizeScalar(u8, input, ' '); 123 if (tokens.next()) |fst| { 124 if (std.mem.eql(u8, fst, ".read")) { 125 try runFile(tokens.next().?, &v, all); 126 } 127 } 128 } else { 129 try runContent(input, &v, all); 130 } 131 } 132 } 133 }