quotationBuilder.zig
· 3.0 KiB · Zig
Неформатований
Playground
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);
}
};
| 1 | const QuotationBuilder = struct { |
| 2 | symbols: std.ArrayList(vm.Symbol), |
| 3 | ops: std.ArrayList(vm.Op), |
| 4 | literals: std.ArrayList(vm.Value), |
| 5 | alloc: std.mem.Allocator, |
| 6 | postQuoteSymbol: ?vm.Symbol, |
| 7 | |
| 8 | fn idxForLiteral(self: *QuotationBuilder, toFind: struct {vm.Value, *bool }) !u16 { |
| 9 | const literal, const found = toFind; |
| 10 | for (self.literals.items, 0..) |i,idx| { |
| 11 | if (i.equal(literal)) { |
| 12 | found.* = true; |
| 13 | return @intCast(idx); |
| 14 | } |
| 15 | } |
| 16 | found.* = false; |
| 17 | if (self.literals.items.len >= 65535) { |
| 18 | return ParseError.TooManyLiteralsInQuotation; |
| 19 | } |
| 20 | const slot: u16 = @intCast(self.literals.items.len); |
| 21 | try self.literals.append(self.alloc, literal); |
| 22 | return slot; |
| 23 | } |
| 24 | |
| 25 | pub fn compile(self: *QuotationBuilder, toCompile: Compilation) !void { |
| 26 | switch(toCompile) { |
| 27 | .op => try self.ops.append(self.alloc, toCompile.op), |
| 28 | .lit => try self.ops.appendSlice(self.alloc, &.{ |
| 29 | .LIT, @enumFromInt(try self.idxForLiteral(toCompile.lit)), |
| 30 | }), |
| 31 | .immediate => try self.ops.append(self.alloc, |
| 32 | @enumFromInt(try self.idxForLiteral(toCompile.immediate))), |
| 33 | } |
| 34 | } |
| 35 | pub fn comp(self: *QuotationBuilder, toCompile: []const Compilation) !void { |
| 36 | for (toCompile) |c| { try self.compile(c); } |
| 37 | } |
| 38 | |
| 39 | pub fn addSymbolFrom(self: *QuotationBuilder, name: []const u8, location: source.Location) !void { |
| 40 | try self.addSymbol(.{ .name=name, .location=location }); |
| 41 | } |
| 42 | |
| 43 | pub fn addSymbol(self: *QuotationBuilder, s: vm.Symbol) !void { |
| 44 | try self.symbols.append(self.alloc, s); |
| 45 | } |
| 46 | |
| 47 | pub fn toCodeObj(self: *QuotationBuilder) !vm.Value { |
| 48 | return .{ .quotation = try self.toQuotation() }; |
| 49 | } |
| 50 | |
| 51 | pub fn toQuotation(self: *QuotationBuilder) !*vm.Quotation { |
| 52 | const ret = try self.alloc.create(vm.Quotation); |
| 53 | ret.* = .{ |
| 54 | .refcount = 0, |
| 55 | .symbols = try self.symbols.toOwnedSlice(self.alloc), |
| 56 | .ops = try self.ops.toOwnedSlice(self.alloc), |
| 57 | .literals = try self.literals.toOwnedSlice(self.alloc), |
| 58 | .alloc = self.alloc, |
| 59 | }; |
| 60 | return ret; |
| 61 | } |
| 62 | |
| 63 | pub fn init(gpa: std.mem.Allocator) !*QuotationBuilder { |
| 64 | const me = try gpa.create(QuotationBuilder); |
| 65 | me.* = .{ |
| 66 | .symbols = try std.ArrayList(vm.Symbol).initCapacity(gpa, 32), |
| 67 | .ops = try std.ArrayList(vm.Op).initCapacity(gpa, 128), |
| 68 | .literals = try std.ArrayList(vm.Value).initCapacity(gpa, 16), |
| 69 | .postQuoteSymbol = null, |
| 70 | .alloc = gpa, |
| 71 | }; |
| 72 | return me; |
| 73 | } |
| 74 | |
| 75 | pub fn deinit(self: *QuotationBuilder) void { |
| 76 | self.symbols.deinit(self.alloc); |
| 77 | self.ops.deinit(self.alloc); |
| 78 | // for (self.literals.items) |i| { i.deref(); } |
| 79 | self.literals.deinit(self.alloc); |
| 80 | if (self.postQuoteSymbol) |s| { s.deinit(self.alloc); } |
| 81 | self.alloc.destroy(self); |
| 82 | } |
| 83 | |
| 84 | }; |
| 85 |