const builtin = @import("builtin"); const std = @import("std"); const value = @import("value.zig"); const seq = value.seq; const Value = value.Value; /// A "heap value" that could be a Value or object header. pub const Hval = union { value: Value, seq_header: seq.Header, }; var _debugAlloc = switch (builtin.mode) { .Debug => std.heap.DebugAllocator(.{}).init, else => undefined, }; const alloc = switch (builtin.mode) { .Debug => _debugAlloc.allocator(), else => std.heap.smp_allocator, }; // Cons cells var cons_pool = std.heap.MemoryPool([2]Value).init(alloc); pub fn cons(v1: Value, v2: Value) *[2]Value { const mem = cons_pool.create() catch @panic("OOM"); mem[0] = v1; mem[1] = v2; return mem; } // Interned strings var istr_pool = std.hash_map.StringHashMap(void).init(alloc); pub fn intern(header: seq.Header, str: []const u8) *seq.Header { const hs = @sizeOf(seq.Header); const size = str.len + hs; const copy = alloc.alloc(u8, size) catch @panic("OOM"); const header_bytes: [hs]u8 = @bitCast(header); @memcpy(copy[0..hs], &header_bytes); @memcpy(copy[hs..size], str); const entry = istr_pool.getOrPutValue(copy, {}) catch @panic("OOM"); return @ptrCast(entry.key_ptr); } pub fn istrHeader(ptr: *Hval) *seq.Header { const entry_key: *[]u8 = @ptrCast(ptr); return @alignCast(@ptrCast(entry_key.ptr)); }