diff options
Diffstat (limited to 'src/compile.zig')
-rw-r--r-- | src/compile.zig | 88 |
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; + } +}; |