aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.zig28
-rw-r--r--src/parse.zig45
2 files changed, 57 insertions, 16 deletions
diff --git a/src/main.zig b/src/main.zig
index d4951e6..dd34c53 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,5 +1,6 @@
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");
@@ -12,7 +13,16 @@ pub fn main() !void {
var args = std.process.args();
_ = args.next();
- const out_file = if (args.next()) |path| try std.fs.cwd().createFile(path, .{ .mode = 0o777 }) else std.io.getStdOut();
+ 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());
@@ -28,7 +38,6 @@ pub fn main() !void {
// try stdout.print("{s}\n", .{line.items});
// }
- // const source = "17216961135462248174 + 4095 - 4294967295 + 2147483647";
const source =
\\print 18446744073709551615;
\\print (0 - 1);
@@ -45,7 +54,7 @@ pub fn main() !void {
const stmts = try parse.statements(allocator, &lexer);
std.debug.print("Statements:\n", .{});
for (stmts) |stmt| {
- std.debug.print(" {}\n", .{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()});
@@ -57,7 +66,18 @@ pub fn main() !void {
}
const elf = try codegen.create_elf(allocator, block);
try output.writeAll(elf);
- // try stdout.print("{x}\n", .{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 {
diff --git a/src/parse.zig b/src/parse.zig
index 1dda517..cadc489 100644
--- a/src/parse.zig
+++ b/src/parse.zig
@@ -12,6 +12,21 @@ pub const Stmt = struct {
pub const Type = union(enum) {
expr: *const Expr,
};
+
+ pub fn fmt(self: Stmt, file_source: []const u8) Format {
+ return .{ .data = .{ self, file_source } };
+ }
+
+ const Format = std.fmt.Formatter(struct {
+ fn format(data: struct { Stmt, []const u8 }, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
+ const self, const file_source = data;
+ _ = f;
+ _ = options;
+ return switch (self.type) {
+ .expr => |expr| writer.print("{};", .{expr.fmt(file_source)}),
+ };
+ }
+ }.format);
};
pub const Expr = struct {
@@ -33,8 +48,8 @@ pub const Expr = struct {
plus,
minus,
- pub fn format(self: Op, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
- _ = fmt;
+ pub fn format(self: Op, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
+ _ = f;
_ = options;
try writer.writeByte(switch (self) {
.plus => '+',
@@ -50,16 +65,23 @@ pub const Expr = struct {
};
};
- pub fn format(self: Expr, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
- _ = fmt;
- _ = options;
- switch (self.type) {
- .integer_literal => try writer.print("<int>", .{}),
- .bin_op => |bin_op| try writer.print("({} {} {})", .{ bin_op.lhs, bin_op.op, bin_op.rhs }),
- .call => |call| try writer.print("({} {})", .{ call.proc, call.arg }),
- .identifier => try writer.print("<identifier>", .{}),
- }
+ pub fn fmt(self: Expr, file_source: []const u8) Format {
+ return .{ .data = .{ self, file_source } };
}
+
+ const Format = std.fmt.Formatter(struct {
+ fn format(data: struct { Expr, []const u8 }, comptime f: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
+ const self, const file_source = data;
+ _ = f;
+ _ = options;
+ switch (self.type) {
+ .integer_literal => try writer.print("{}", .{self.loc.getInt(file_source)}),
+ .bin_op => |bin_op| try writer.print("({} {} {})", .{ bin_op.lhs.fmt(file_source), bin_op.op, bin_op.rhs.fmt(file_source) }),
+ .call => |call| try writer.print("({} {})", .{ call.proc.fmt(file_source), call.arg.fmt(file_source) }),
+ .identifier => try writer.print("{s}", .{self.loc.getIdent(file_source)}),
+ }
+ }
+ }.format);
};
pub fn statements(allocator: Allocator, lexer: *Lexer) ![]Stmt {
@@ -120,7 +142,6 @@ pub fn callExpr(allocator: Allocator, lexer: *Lexer) !*Expr {
pub fn primaryExpr(allocator: Allocator, lexer: *Lexer) !*Expr {
const token = lexer.next();
- // std.debug.print("term {}\n", .{token});
return allocate(Expr, allocator, switch (token.type) {
.left_paren => {
const res = expression(allocator, lexer);