summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/test/strings.zig6
-rw-r--r--src/zisp/gc/IstrSet.zig2
-rw-r--r--src/zisp/io/Parser.zig25
-rw-r--r--src/zisp/value/fixnum.zig2
-rw-r--r--src/zisp/value/istr.zig25
5 files changed, 32 insertions, 28 deletions
diff --git a/src/test/strings.zig b/src/test/strings.zig
index f0cdde9..1cffa39 100644
--- a/src/test/strings.zig
+++ b/src/test/strings.zig
@@ -11,13 +11,13 @@ const fx = value.fixnum;
test "istr" {
const s1 = "foo bar baz";
- const v1 = try istr.getOrNew(s1);
+ const v1 = istr.pack(try istr.getOrNew(s1));
const v1_len: usize = @intCast(fx.unpack(istr.getLen(v1)));
try testing.expectEqualStrings(s1, istr.getBytes(v1));
try testing.expectEqual(s1.len, v1_len);
const s2 = @embedFile("data/string.txt");
- const v2 = try istr.getOrNew(s2);
+ const v2 = istr.pack(try istr.getOrNew(s2));
const v2_len: usize = @intCast(fx.unpack(istr.getLen(v2)));
try testing.expectEqualStrings(s2, istr.getBytes(v2));
try testing.expectEqual(s2.len, v2_len);
@@ -25,7 +25,7 @@ test "istr" {
// Check that modifying a slice doesn't affect the string.
var s3 = "test".*;
- const v3 = try istr.getOrNew(&s3);
+ const v3 = istr.pack(try istr.getOrNew(&s3));
s3[0] = 'x';
try testing.expectEqualStrings("test", istr.getBytes(v3));
}
diff --git a/src/zisp/gc/IstrSet.zig b/src/zisp/gc/IstrSet.zig
index bf0db47..900caa7 100644
--- a/src/zisp/gc/IstrSet.zig
+++ b/src/zisp/gc/IstrSet.zig
@@ -65,10 +65,10 @@ pub fn deinit(self: *Set) void {
/// Get the istr with the given string contents, or alloc and store a new one.
pub fn getOrNew(self: *Set, s: []const u8) !IstrPtr {
+ std.debug.assert(s.len <= value.istr.max_len);
if (test_stdlib_impl) {
return self.addStdlib(s);
}
- std.debug.assert(s.len < 256);
return self.getOrPutOrNew(s, null);
}
diff --git a/src/zisp/io/Parser.zig b/src/zisp/io/Parser.zig
index 29b8590..6dcfe42 100644
--- a/src/zisp/io/Parser.zig
+++ b/src/zisp/io/Parser.zig
@@ -48,6 +48,7 @@ const ListPool = gc.ListPool;
const IstrSet = gc.IstrSet;
const Decoder = io.Decoder;
const Value = value.Value;
+const IstrPtr = value.istr.IstrPtr;
const Parser = @This();
@@ -115,7 +116,7 @@ pub fn init() !Parser {
const istr_set = gc.mainIstrSet();
const alloc = gc.mainAlloc();
const decoder = io.mainDecoder();
- return initCustom(list_pool, istr_set, alloc, 32, 2048, 32, decoder);
+ return initCustom(list_pool, istr_set, alloc, 16, 512, 32, decoder);
}
pub fn initCustom(
@@ -127,13 +128,17 @@ pub fn initCustom(
init_list_elts_cap: usize,
decoder: ?*Decoder,
) !Parser {
+ // Force some sane minimum values.
+ const ctx_cap = @max(1, init_ctx_stack_cap);
+ const str_cap = @max(8, init_str_chars_cap);
+ const lst_cap = @max(2, init_list_elts_cap);
return .{
.list_pool = list_pool,
.istr_set = istr_set,
.alloc = alloc,
- .ctx_stack = try .initCapacity(alloc, init_ctx_stack_cap),
- .str_chars = try .initCapacity(alloc, init_str_chars_cap),
- .list_elts = try .initCapacity(alloc, init_list_elts_cap),
+ .ctx_stack = try .initCapacity(alloc, ctx_cap),
+ .str_chars = try .initCapacity(alloc, str_cap),
+ .list_elts = try .initCapacity(alloc, lst_cap),
.decoder = decoder,
};
}
@@ -218,17 +223,17 @@ fn getCharsAsString(p: *Parser) !Value {
if (value.sstr.isValidSstr(s)) {
return value.sstr.pack(s);
} else if (value.istr.isValidIstr(s)) {
- return p.getIstr(s);
+ return value.istr.pack(try p.getIstr(s));
} else {
- return value.array.newString(p.alloc, s);
+ return try value.array.newString(p.alloc, s);
}
}
-fn getIstr(p: *Parser, s: []const u8) !Value {
+fn getIstr(p: *Parser, s: []const u8) !IstrPtr {
if (p.istr_set) |set| {
- return value.istr.getOrNewInSet(set, s);
+ return try value.istr.getOrNewInSet(set, s);
} else {
- return value.istr.pack(try value.istr.new(p.alloc, s));
+ return try value.istr.new(p.alloc, s);
}
}
@@ -249,7 +254,7 @@ fn addListElt(p: *Parser, elt: Value) !void {
fn getList(p: *Parser) !Value {
if (p.context.comment) return value.nil;
if (p.list_elts.items.len == p.context.list_start) return value.nil;
- defer p.list_elts.items.len = p.context.list_start;
+ defer p.list_elts.shrinkRetainingCapacity(p.context.list_start);
const vals = p.list_elts.items[p.context.list_start..];
return value.list.new(p.alloc, p.list_pool, vals);
}
diff --git a/src/zisp/value/fixnum.zig b/src/zisp/value/fixnum.zig
index 1929ba2..3bd6112 100644
--- a/src/zisp/value/fixnum.zig
+++ b/src/zisp/value/fixnum.zig
@@ -54,8 +54,6 @@ fn unpackPositive(v: Value) i64 {
return @bitCast(uint ^ positive_mask);
}
-// Although we use if, these should compile to branchless code using cmov.
-
pub fn pack(int: i64) Value {
assertValidRange(int);
if (int < 0) {
diff --git a/src/zisp/value/istr.zig b/src/zisp/value/istr.zig
index dfe4614..a581289 100644
--- a/src/zisp/value/istr.zig
+++ b/src/zisp/value/istr.zig
@@ -12,6 +12,8 @@ const value = @import("../value.zig");
const IstrSet = gc.IstrSet;
const Value = value.Value;
+pub const max_len = 255;
+
// Zig API
/// Pointer to an interned string. First byte is length.
@@ -49,7 +51,7 @@ pub fn assert(v: Value) void {
}
pub fn isValidIstr(s: []const u8) bool {
- return s.len <= 255;
+ return s.len <= max_len;
}
fn assertValidIstr(s: []const u8) void {
@@ -67,6 +69,15 @@ pub fn new(alloc: Alloc, s: []const u8) !IstrPtr {
return istr;
}
+pub fn getOrNew(s: []const u8) !IstrPtr {
+ return getOrNewInSet(gc.mainIstrSet(), s);
+}
+
+pub fn getOrNewInSet(set: *IstrSet, s: []const u8) !IstrPtr {
+ assertValidIstr(s);
+ return try set.getOrNew(s);
+}
+
pub fn pack(istr: IstrPtr) Value {
const ptr = @intFromPtr(istr);
return .{ .istr = .{ .ptr = @intCast(ptr) } };
@@ -76,19 +87,9 @@ pub fn unpack(v: Value) IstrPtr {
return @ptrFromInt(v.istr.ptr);
}
-pub fn getOrNew(s: []const u8) !Value {
- return getOrNewInSet(gc.mainIstrSet(), s);
-}
-
-pub fn getOrNewInSet(set: *IstrSet, s: []const u8) !Value {
- assertValidIstr(s);
- return pack(try set.getOrNew(s));
-}
-
pub fn getBytes(v: Value) []const u8 {
assert(v);
- const istr: IstrPtr = @ptrFromInt(v.istr.ptr);
- return istr.bytes();
+ return unpack(v).bytes();
}
// Zisp API