zahl

Log | Files | Refs | README

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 }