const std = @import("std"); const codegen = @import("./codegen.zig"); const target = @import("builtin").target; pub const parse = @import("./parse.zig"); pub const Lexer = @import("./Lexer.zig"); pub const compile = @import("./compile.zig"); pub fn main() !void { var arena: std.heap.ArenaAllocator = .init(std.heap.smp_allocator); defer arena.deinit(); const allocator = arena.allocator(); var args = std.process.args(); _ = args.next(); const arg = args.next() orelse ""; const run_path, const out_file = if (std.mem.eql(u8, arg, "run")) blk: { const path = try std.fmt.allocPrint(allocator, "/tmp/{}.elf", .{std.crypto.random.int(u32)}); break :blk .{ path, try std.fs.createFileAbsolute(path, .{ .mode = 0o777 }) }; } else if (arg.len > 0) .{ null, try std.fs.cwd().createFile(arg, .{ .mode = 0o777 }) } else .{ null, std.io.getStdOut() }; defer if (run_path) |path| allocator.free(path); const output = out_file.writer(); // var br = std.io.bufferedReader(std.io.getStdIn().reader()); // const stdin = br.reader(); // // var line: std.ArrayList(u8) = .init(alloc); // defer line.deinit(); // while (true) { // try stdin.streamUntilDelimiter(line.writer(), '\n', null); // // const lexer = Lexer{.source = line}; // // try stdout.print("{s}\n", .{line.items}); // } const source = \\print 18446744073709551615; \\print (0 - 1); \\print 69; ; var lexer: Lexer = .{ .source = source }; std.debug.print("Tokens:\n", .{}); while (true) { const token = lexer.next(); std.debug.print(" {}\n", .{token}); if (token.type == .eof) break; } lexer = .{ .source = source }; const stmts = try parse.statements(allocator, &lexer); std.debug.print("Statements:\n", .{}); for (stmts) |stmt| { std.debug.print(" {}\n", .{stmt.fmt(source)}); } if (lexer.peek().type != .eof) { std.debug.print("Unexpected token {}, expected end of file\n", .{lexer.next()}); } const block = try compile.compile(allocator, source, stmts); std.debug.print("Bytecode instructions:\n", .{}); for (block.instrs) |instr| { std.debug.print(" {}\n", .{instr}); } const elf = try codegen.create_elf(allocator, block); try output.writeAll(elf); std.debug.print("Run output:\n", .{}); if (run_path) |path| { out_file.close(); std.debug.print("{}\n", .{std.process.execv( allocator, if (target.cpu.arch == .riscv64 and target.os.tag == .linux) &.{path} else &.{ "qemu-riscv64", path }, )}); } } fn HashMapFormatter(HashMap: type) type { return std.fmt.Formatter(struct { fn formatHashMap( hash_map: HashMap, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype, ) !void { _ = fmt; _ = options; try writer.writeAll("{"); var it = hash_map.iterator(); var first = true; while (it.next()) |kv| { try writer.print("{s} {any}: {any}", .{ if (first) "" else ",", kv.key_ptr.*, kv.value_ptr.* }); first = false; } try writer.writeAll(if (first) "}" else " }"); } }.formatHashMap); } pub fn fmtHashMap(hash_map: anytype) HashMapFormatter(@TypeOf(hash_map)) { return .{ .data = hash_map }; }