diff options
| author | Taylan Kammer <taylan.kammer@gmail.com> | 2025-03-18 21:39:51 +0100 |
|---|---|---|
| committer | Taylan Kammer <taylan.kammer@gmail.com> | 2025-03-18 21:39:51 +0100 |
| commit | f1c256884b0d59683e8bd43160b048561191a809 (patch) | |
| tree | 804f356fccb0e1a2b77f61e25bc81cbfc2452b03 /src/libzisp/value | |
| parent | c43c3c22e5d0f872168c5b687141c7b08a188c5d (diff) | |
Implement istr.
Diffstat (limited to 'src/libzisp/value')
| -rw-r--r-- | src/libzisp/value/fixnum.zig | 12 | ||||
| -rw-r--r-- | src/libzisp/value/istr.zig | 55 | ||||
| -rw-r--r-- | src/libzisp/value/pair.zig | 1 | ||||
| -rw-r--r-- | src/libzisp/value/ptr.zig | 6 | ||||
| -rw-r--r-- | src/libzisp/value/seq.zig | 56 |
5 files changed, 119 insertions, 11 deletions
diff --git a/src/libzisp/value/fixnum.zig b/src/libzisp/value/fixnum.zig index c705880..80fb4ae 100644 --- a/src/libzisp/value/fixnum.zig +++ b/src/libzisp/value/fixnum.zig @@ -19,19 +19,15 @@ pub fn assert(v: Value) void { } // See detailed NaN packing docs for why the +/- 1. -const fixnum_min = std.math.minInt(i52) + 1; -const fixnum_max = std.math.maxInt(i52) - 1; - -pub fn isValidRange(int: i64) bool { - return fixnum_min < int and int < fixnum_max; -} +pub const min = std.math.minInt(i52) + 1; +pub const max = std.math.maxInt(i52) - 1; fn assertValidRange(int: i64) void { - if (int < fixnum_min) { + if (int < min) { std.debug.print("int too small for fixnum: {}\n", .{int}); @panic("int too small for fixnum"); } - if (int > fixnum_max) { + if (int > max) { std.debug.print("int too large for fixnum: {}\n", .{int}); @panic("int too large for fixnum"); } diff --git a/src/libzisp/value/istr.zig b/src/libzisp/value/istr.zig index 5937531..8056d98 100644 --- a/src/libzisp/value/istr.zig +++ b/src/libzisp/value/istr.zig @@ -1,3 +1,58 @@ const std = @import("std"); const value = @import("../value.zig"); +const gc = @import("../gc.zig"); + +const ptr = @import("ptr.zig"); +const seq = @import("seq.zig"); + +const Value = value.Value; + +// Zig API + +pub fn check(v: Value) bool { + return ptr.checkZispTag(v, .seq); +} + +pub fn assert(v: Value) void { + if (!check(v)) { + v.dump(); + @panic("not istr"); + } +} + +pub fn intern(str: []const u8, quoted: bool) Value { + if (str.len > value.fixnum.max) { + @panic("String length out of fixnum range."); + } + const header: seq.Header = .{ + .type = .string, + .info = .{ .string = .{ + .enc = .utf8, + .quoted = quoted, + .interned = true, + } }, + .size = @intCast(str.len), + }; + const bytes_ptr = gc.intern(header, str); + return ptr.pack(bytes_ptr, .seq); +} + +pub fn getHeader(v: Value) *seq.Header { + assert(v); + return gc.istrHeader(ptr.unpack(v).@"0"); +} + +// Zisp API + +pub fn pred(v: Value) Value { + return value.boole.pack(check(v)); +} + +pub fn len(v: Value) Value { + const l = getHeader(v).size; + if (l > value.fixnum.max) { + @panic("string length out of range"); + } + return value.fixnum.pack(@intCast(l)); +} diff --git a/src/libzisp/value/pair.zig b/src/libzisp/value/pair.zig index 87e18e7..6ea1edf 100644 --- a/src/libzisp/value/pair.zig +++ b/src/libzisp/value/pair.zig @@ -1,4 +1,5 @@ const std = @import("std"); + const value = @import("../value.zig"); const gc = @import("../gc.zig"); diff --git a/src/libzisp/value/ptr.zig b/src/libzisp/value/ptr.zig index 115cc2d..b07acc4 100644 --- a/src/libzisp/value/ptr.zig +++ b/src/libzisp/value/ptr.zig @@ -132,10 +132,10 @@ fn untagPtr(tagged: u48) struct { [*]Hval, Tag } { } pub const Tag = enum(u3) { - /// *[2]Value + /// Pair aka cons cell aka *[2]Value pair, - /// Interned string (symbol) - istr, + /// Sequence of various kinds (16-bit meta, 48-bit length, then data) + seq, /// Procedure proc, }; diff --git a/src/libzisp/value/seq.zig b/src/libzisp/value/seq.zig new file mode 100644 index 0000000..5382a7e --- /dev/null +++ b/src/libzisp/value/seq.zig @@ -0,0 +1,56 @@ +const builtin = @import("builtin"); +const std = @import("std"); + +const value = @import("../value.zig"); +const gc = @import("../gc.zig"); + +const Value = value.Value; + +const Endian = enum(u1) { + little, + big, + + const native: Endian = switch (builtin.target.cpu.arch.endian()) { + .little => .little, + .big => .big, + }; +}; + +pub const Header = packed struct(u64) { + type: enum(u2) { + values, + string, + ints, + floats, + }, + info: packed union { + values: packed struct(u14) { + weak: bool = false, + _: u13 = 0, + }, + string: packed struct(u14) { + enc: enum(u4) { utf8, utf16, utf24, utf32 }, + endian: Endian = .native, + quoted: bool, + interned: bool, + _: u7 = 0, + }, + ints: packed struct(u14) { + signed: bool, + endian: Endian = .native, + size: u12, + }, + floats: packed struct(u14) { + double: bool, + endian: Endian = .native, + _: u12 = 0, + }, + }, + size: u48, + + pub fn bytes(self: *Header) []u8 { + const ptr: [*]u8 = @ptrCast(self); + const end = 8 + self.size; + return ptr[8..end]; + } +}; |
