diff options
| author | Taylan Kammer <taylan.kammer@gmail.com> | 2025-02-17 22:31:16 +0100 |
|---|---|---|
| committer | Taylan Kammer <taylan.kammer@gmail.com> | 2025-02-17 22:31:16 +0100 |
| commit | a81412ea9d85dd1d5d4a065cbf61c1080420860e (patch) | |
| tree | e04f53d434f554c6cb7c6ce7cea9ef99167a039f /src/libzisp/value | |
| parent | 704411d750dd07da5d2c710807a4dceb671ec8e2 (diff) | |
update
Diffstat (limited to 'src/libzisp/value')
| -rw-r--r-- | src/libzisp/value/boole.zig | 28 | ||||
| -rw-r--r-- | src/libzisp/value/char.zig | 4 | ||||
| -rw-r--r-- | src/libzisp/value/eof.zig | 27 | ||||
| -rw-r--r-- | src/libzisp/value/fixnum.zig | 2 | ||||
| -rw-r--r-- | src/libzisp/value/misc.zig | 8 | ||||
| -rw-r--r-- | src/libzisp/value/nil.zig | 27 | ||||
| -rw-r--r-- | src/libzisp/value/ptr.zig | 34 | ||||
| -rw-r--r-- | src/libzisp/value/sstr.zig | 64 |
8 files changed, 168 insertions, 26 deletions
diff --git a/src/libzisp/value/boole.zig b/src/libzisp/value/boole.zig index d4fbd28..0af7e22 100644 --- a/src/libzisp/value/boole.zig +++ b/src/libzisp/value/boole.zig @@ -1,10 +1,34 @@ const Value = @import("../value.zig").Value; const misc = @import("misc.zig"); -// These can be accessed from either namespace. pub const f = misc.f; pub const t = misc.t; +// Zig API + +/// Checks if the value is a boole. +pub fn check(v: Value) bool { + return v.bits == f.bits or v.bits == t.bits; +} + +pub fn assert(v: Value) void { + if (!check(v)) { + v.dump(); + @panic("not bool"); + } +} + pub fn pack(b: bool) Value { - return if (b) f else t; + return if (b) t else f; +} + +pub fn unpack(v: Value) bool { + assert(v); + return v.bits == t.bits; +} + +// Zisp API + +pub fn pred(v: Value) Value { + return if (check(v)) t else f; } diff --git a/src/libzisp/value/char.zig b/src/libzisp/value/char.zig index 7034128..6a38f0d 100644 --- a/src/libzisp/value/char.zig +++ b/src/libzisp/value/char.zig @@ -15,10 +15,10 @@ pub fn assert(v: Value) void { } pub fn pack(c: u21) Value { - return .{ .char = .{c} }; + return .{ .char = .{ .value = c } }; } pub fn unpack(v: Value) u21 { assert(v); - return v.char.value; + return @truncate(v.char.value); } diff --git a/src/libzisp/value/eof.zig b/src/libzisp/value/eof.zig new file mode 100644 index 0000000..34ab35d --- /dev/null +++ b/src/libzisp/value/eof.zig @@ -0,0 +1,27 @@ +const Value = @import("../value.zig").Value; +const misc = @import("misc.zig"); + +pub const eof = misc.eof; + +// Zig API + +pub fn check(v: Value) bool { + return v.bits == eof.bits; +} + +pub fn assert(v: Value) void { + if (!check(v)) { + v.dump(); + @panic("not bool"); + } +} + +// Zisp API + +pub fn get() Value { + return eof; +} + +pub fn pred(v: Value) Value { + return if (check(v)) misc.t else misc.f; +} diff --git a/src/libzisp/value/fixnum.zig b/src/libzisp/value/fixnum.zig index 60b4239..6d26a9c 100644 --- a/src/libzisp/value/fixnum.zig +++ b/src/libzisp/value/fixnum.zig @@ -21,7 +21,7 @@ pub fn assert(v: Value) void { const fixnum_min = std.math.minInt(i52) + 1; const fixnum_max = std.math.maxInt(i52) - 1; -fn isValidRange(int: i64) bool { +pub fn isValidRange(int: i64) bool { return fixnum_min < int and int < fixnum_max; } diff --git a/src/libzisp/value/misc.zig b/src/libzisp/value/misc.zig index 2570644..793c60e 100644 --- a/src/libzisp/value/misc.zig +++ b/src/libzisp/value/misc.zig @@ -1,6 +1,6 @@ const Value = @import("../value.zig").Value; -pub const f = Value{ .misc = .{0} }; -pub const t = Value{ .misc = .{1} }; -pub const nil = Value{ .misc = .{2} }; -pub const eof = Value{ .misc = .{3} }; +pub const f = Value{ .misc = .{ .value = 0 } }; +pub const t = Value{ .misc = .{ .value = 1 } }; +pub const nil = Value{ .misc = .{ .value = 2 } }; +pub const eof = Value{ .misc = .{ .value = 3 } }; diff --git a/src/libzisp/value/nil.zig b/src/libzisp/value/nil.zig new file mode 100644 index 0000000..1b1a51e --- /dev/null +++ b/src/libzisp/value/nil.zig @@ -0,0 +1,27 @@ +const Value = @import("../value.zig").Value; +const misc = @import("misc.zig"); + +pub const nil = misc.nil; + +// Zig API + +pub fn check(v: Value) bool { + return v.bits == nil.bits; +} + +pub fn assert(v: Value) void { + if (!check(v)) { + v.dump(); + @panic("not bool"); + } +} + +// Zisp API + +pub fn get() Value { + return nil; +} + +pub fn pred(v: Value) Value { + return if (check(v)) misc.t else misc.f; +} diff --git a/src/libzisp/value/ptr.zig b/src/libzisp/value/ptr.zig index 4bf92b6..6a3a6c4 100644 --- a/src/libzisp/value/ptr.zig +++ b/src/libzisp/value/ptr.zig @@ -88,15 +88,15 @@ pub fn packWeak(ptr: *anyopaque, tag: Tag) Value { } // Unpacks weak as well; no need for a separate fn. -pub fn unpack(v: Value) struct { ptr: *anyopaque, tag: Tag } { +pub fn unpack(v: Value) PtrAndTag { assertZisp(v); - return untagPtr(v.ptr.value.tagged); + return untagPtr(v.ptr.value); } // Weak pointers may be null. pub fn isNull(v: Value) bool { assertWeak(v); - const ptr, _ = untagPtr(v.ptr.value.tagged); + const ptr, _ = untagPtr(v.ptr.value); return @intFromPtr(ptr) == 0; } @@ -106,36 +106,38 @@ pub fn tagPtr(ptr: *anyopaque, tag: Tag) u49 { return untagged << 1 | @intFromEnum(tag); } -pub fn untagPtr(tagged: 49) struct { ptr: *anyopaque, tag: Tag } { +pub const PtrAndTag = struct { *anyopaque, Tag }; + +pub fn untagPtr(tagged: u49) PtrAndTag { const untagged: u49 = tagged >> 1 & 0xfffffffffff0; const ptr: *anyopaque = @ptrFromInt(untagged); const int: u4 = @truncate(tagged); const tag: Tag = @enumFromInt(int); - return .{ .ptr = ptr, .tag = tag }; + return .{ ptr, tag }; } pub const Tag = enum(u4) { - /// 1. Strings / Symbols + /// 0. Strings / Symbols string, - /// 2. Bignums / Ratnums + /// 1. Bignums / Ratnums number, - /// 3. Pairs ([2]Value) + /// 2. Pairs ([2]Value) pair, - /// 4. Vector, bytevector, etc. + /// 3. Vector, bytevector, etc. array, - /// 5. Ordered hash table + /// 4. Ordered hash table table, - /// 6. String buffer + /// 5. String buffer text, - /// 7. Class, interface, etc. + /// 6. Class, interface, etc. role, - /// 8. Instance, basically + /// 7. Instance, basically actor, - /// 9. I/O Port + /// 8. I/O Port port, - /// 10. Procedure + /// 9. Procedure proc, - /// 11. Continuation + /// 10. Continuation cont, /// Other other = 15, diff --git a/src/libzisp/value/sstr.zig b/src/libzisp/value/sstr.zig index 3c0755d..c2b2859 100644 --- a/src/libzisp/value/sstr.zig +++ b/src/libzisp/value/sstr.zig @@ -1,3 +1,65 @@ +const std = @import("std"); + const Value = @import("../value.zig").Value; -// stub +// Zig API + +pub fn check(v: Value) bool { + return v.isPacked() and + !v.sstr.fixnum and + !v.sstr.ptr and + v.sstr.tag == .sstr; +} + +pub fn assert(v: Value) void { + if (!check(v)) { + v.dump(); + @panic("not sstr"); + } +} + +// For now, ignore encoding, just treat it as []u8. + +pub fn isValidSstr(s: []const u8) bool { + if (s.len > 6) { + return false; + } + for (s) |c| { + if (c == 0) { + return false; + } + } + return true; +} + +fn assertValidSstr(s: []const u8) void { + if (!isValidSstr(s)) { + std.debug.print("invalid sstr: {s}", .{s}); + @panic("invalid sstr"); + } +} + +// Different ways of doing the following have been tested, including manual +// shifting and bit masking, but memcpy always wins easily according to our +// micro-benchmarks, both under ReleaseSafe and under ReleaseFast. + +pub fn pack(s: []const u8) Value { + assertValidSstr(s); + var v = Value{ .sstr = .{ .value = 0 } }; + const dest: [*]u8 = @ptrCast(&v.sstr.value); + @memcpy(dest, s); + return v; +} + +// It's tempting to inline for here to eliminate the if statement or prevent +// need of @truncate but all alternatives were a little slower. + +pub fn unpack(v: Value) struct { [6]u8, u3 } { + var s: [6]u8 = undefined; + const src: *const [6]u8 = @ptrCast(&v.sstr.value); + @memcpy(&s, src); + for (0..6) |i| { + if (s[i] == 0) return .{ s, @truncate(i) }; + } + return .{ s, 6 }; +} |
