aboutsummaryrefslogtreecommitdiff
path: root/src/compile.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/compile.zig')
-rw-r--r--src/compile.zig88
1 files changed, 88 insertions, 0 deletions
diff --git a/src/compile.zig b/src/compile.zig
new file mode 100644
index 0000000..b9e1a86
--- /dev/null
+++ b/src/compile.zig
@@ -0,0 +1,88 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const root = @import("root");
+const Token = root.Lexer.Token;
+const Expr = root.Expr;
+const Location = root.Lexer.Location;
+
+pub const Reg = enum(u32) { _ };
+
+pub const Instr = union(enum) {
+ constant: Constant,
+ bin_op: BinOp,
+
+ const Constant = struct {
+ dest: Reg,
+ value: Location,
+ };
+
+ const BinOp = struct {
+ dest: Reg,
+ lhs: Reg,
+ rhs: Reg,
+ op: Op,
+
+ const Op = enum {
+ add,
+ };
+ };
+};
+
+pub const Block = struct {
+ // arguments: []Reg,
+ instrs: []Instr,
+};
+
+pub fn compile(allocator: Allocator, expr: *const Expr) !Block {
+ const instrs: std.ArrayListUnmanaged(Instr) = try .initCapacity(allocator, 0);
+ var ctx: CompileContext = .{
+ .allocator = allocator,
+ .register_counter = 0,
+ .instrs = instrs,
+ };
+ _ = try ctx.compileExpr(expr);
+ return .{ .instrs = ctx.instrs.items };
+}
+
+const CompileContext = struct {
+ allocator: Allocator,
+ register_counter: u32,
+ instrs: std.ArrayListUnmanaged(Instr),
+
+ const Self = @This();
+
+ fn addInstr(self: *Self, instr: Instr) !void {
+ try self.instrs.append(self.allocator, instr);
+ }
+
+ fn compileExpr(self: *Self, expr: *const Expr) !Reg {
+ const dest = self.register();
+ switch (expr.type) {
+ .integer_literal => try addInstr(self, .{
+ .constant = .{ .dest = dest, .value = expr.loc },
+ }),
+ .bin_op => |binop| {
+ const lhs = try self.compileExpr(binop.lhs);
+ const rhs = try self.compileExpr(binop.rhs);
+ try addInstr(self, .{
+ .bin_op = .{
+ .dest = dest,
+ .lhs = lhs,
+ .rhs = rhs,
+ .op = switch (binop.op) {
+ .plus => .add,
+ },
+ },
+ });
+ },
+ .invalid => return error.CantCompileInvalidExpr,
+ }
+ return dest;
+ }
+
+ fn register(self: *Self) Reg {
+ const reg: Reg = @enumFromInt(self.register_counter);
+ self.register_counter += 1;
+ return reg;
+ }
+};