const QuotationBuilder = struct { symbols: std.ArrayList(vm.Symbol), ops: std.ArrayList(vm.Op), literals: std.ArrayList(vm.Value), alloc: std.mem.Allocator, postQuoteSymbol: ?vm.Symbol, fn idxForLiteral(self: *QuotationBuilder, toFind: struct {vm.Value, *bool }) !u16 { const literal, const found = toFind; for (self.literals.items, 0..) |i,idx| { if (i.equal(literal)) { found.* = true; return @intCast(idx); } } found.* = false; if (self.literals.items.len >= 65535) { return ParseError.TooManyLiteralsInQuotation; } const slot: u16 = @intCast(self.literals.items.len); try self.literals.append(self.alloc, literal); return slot; } pub fn compile(self: *QuotationBuilder, toCompile: Compilation) !void { switch(toCompile) { .op => try self.ops.append(self.alloc, toCompile.op), .lit => try self.ops.appendSlice(self.alloc, &.{ .LIT, @enumFromInt(try self.idxForLiteral(toCompile.lit)), }), .immediate => try self.ops.append(self.alloc, @enumFromInt(try self.idxForLiteral(toCompile.immediate))), } } pub fn comp(self: *QuotationBuilder, toCompile: []const Compilation) !void { for (toCompile) |c| { try self.compile(c); } } pub fn addSymbolFrom(self: *QuotationBuilder, name: []const u8, location: source.Location) !void { try self.addSymbol(.{ .name=name, .location=location }); } pub fn addSymbol(self: *QuotationBuilder, s: vm.Symbol) !void { try self.symbols.append(self.alloc, s); } pub fn toCodeObj(self: *QuotationBuilder) !vm.Value { return .{ .quotation = try self.toQuotation() }; } pub fn toQuotation(self: *QuotationBuilder) !*vm.Quotation { const ret = try self.alloc.create(vm.Quotation); ret.* = .{ .refcount = 0, .symbols = try self.symbols.toOwnedSlice(self.alloc), .ops = try self.ops.toOwnedSlice(self.alloc), .literals = try self.literals.toOwnedSlice(self.alloc), .alloc = self.alloc, }; return ret; } pub fn init(gpa: std.mem.Allocator) !*QuotationBuilder { const me = try gpa.create(QuotationBuilder); me.* = .{ .symbols = try std.ArrayList(vm.Symbol).initCapacity(gpa, 32), .ops = try std.ArrayList(vm.Op).initCapacity(gpa, 128), .literals = try std.ArrayList(vm.Value).initCapacity(gpa, 16), .postQuoteSymbol = null, .alloc = gpa, }; return me; } pub fn deinit(self: *QuotationBuilder) void { self.symbols.deinit(self.alloc); self.ops.deinit(self.alloc); // for (self.literals.items) |i| { i.deref(); } self.literals.deinit(self.alloc); if (self.postQuoteSymbol) |s| { s.deinit(self.alloc); } self.alloc.destroy(self); } };