diff options
| author | Taylan Kammer <taylan.kammer@gmail.com> | 2026-06-04 16:37:16 +0200 |
|---|---|---|
| committer | Taylan Kammer <taylan.kammer@gmail.com> | 2026-06-04 16:37:16 +0200 |
| commit | 8de05de165cc7e7f900fb2320a58262ac8d0be5f (patch) | |
| tree | 7c914020c41dd56953a5407989c0373a2883af9b /src | |
| parent | 1a0a55692988fe8e22ebb397a70b60424d653a5e (diff) | |
We can read and print back various strings now.
Diffstat (limited to 'src')
| -rw-r--r-- | src/zisp/io/Parser.zig | 17 | ||||
| -rw-r--r-- | src/zisp/io/print.zig | 79 | ||||
| -rw-r--r-- | src/zisp/value.zig | 5 | ||||
| -rw-r--r-- | src/zisp/value/array.zig | 32 | ||||
| -rw-r--r-- | src/zisp/value/istr.zig | 15 | ||||
| -rw-r--r-- | src/zisp/value/sstr.zig | 8 |
6 files changed, 112 insertions, 44 deletions
diff --git a/src/zisp/io/Parser.zig b/src/zisp/io/Parser.zig index a56a61b..73c0187 100644 --- a/src/zisp/io/Parser.zig +++ b/src/zisp/io/Parser.zig @@ -181,11 +181,11 @@ fn addChar(p: *Parser, c: u8) !void { fn addUnicode(p: *Parser, uc: u21) !void { const n = std.unicode.utf8CodepointSequenceLength(uc) catch { - return p.err(.UnicodeLengthError, "UTF-8 injection"); + return p.err(.UnicodeLengthError, "Unicode/UTF-8 escape"); }; const buf = try p.chars.addManyAsSlice(p.alloc, n); const n2 = std.unicode.utf8Encode(uc, buf) catch { - return p.err(.UnicodeEncodeError, "UTF-8 injection"); + return p.err(.UnicodeEncodeError, "Unicode/UTF-8 escape"); }; std.debug.assert(n == n2); } @@ -193,13 +193,12 @@ fn addUnicode(p: *Parser, uc: u21) !void { fn getCharsAsString(p: *Parser) !Value { defer p.chars.clearRetainingCapacity(); const s = p.chars.items; - if (value.sstr.isValidSstr(s)) { - return value.sstr.pack(s); - } else if (value.istr.isValidIstr(s)) { - return value.istr.intern(s); - } else { - @panic("not implemented"); // TODO - } + return if (value.sstr.isValidSstr(s)) + value.sstr.pack(s) + else if (value.istr.isValidIstr(s)) + value.istr.intern(s) + else + value.array.newString(p.alloc, s); } fn getCharsAsRune(p: *Parser) Value { diff --git a/src/zisp/io/print.zig b/src/zisp/io/print.zig index 0873767..b1647cc 100644 --- a/src/zisp/io/print.zig +++ b/src/zisp/io/print.zig @@ -48,8 +48,7 @@ pub fn rune(w: Writer, v: Value) !void { pub fn sstr(w: Writer, v: Value) !void { // TODO: Check if pipes/escapes necessary. - const str = value.sstr.unpack(v); - try w.writeAll(str.slice()); + try w.writeAll(value.sstr.unpack(&v)); } pub fn char(w: Writer, v: Value) !void { @@ -78,26 +77,68 @@ pub fn srat(w: Writer, v: Value) !void { } pub fn pair(w: Writer, p: PairPtr) !void { - const car = p.car; - //const cdr = p.cdr; - if (car.eq(Parser.PQSTR)) { - //try pipeString(w, cdr); - @panic(""); - } else if (car.eq(Parser.DQSTR)) { - //try quotString(w, cdr); - @panic(""); - } else if (car.eq(Parser.ATSTR)) { - //try atString(w, cdr); - @panic(""); - } else if (car.eq(Parser.LABEL)) { - //try label(w, cdr); - @panic(""); - } else { - try list(w, p); - } + try switch (p.car.bits) { + Parser.PQSTR.bits => quotString(w, p.cdr, '|'), + Parser.DQSTR.bits => quotString(w, p.cdr, '"'), + Parser.ATSTR.bits => atString(w, p.cdr), + Parser.LABEL.bits => label(w, p.cdr), + else => list(w, p), + }; +} + +fn quotString(w: Writer, s: Value, comptime qchar: u8) !void { + try w.writeByte(qchar); + // TODO: use string.zig (when it exists) to get []u8 generically + const str = try getStr(&s); + for (str) |c| switch (c) { + qchar => { + try w.writeByte('\\'); + try w.writeByte(qchar); + }, + '\\' => { + try w.writeByte('\\'); + try w.writeByte('\\'); + }, + else => { + try w.writeByte(c); + }, + }; + try w.writeByte(qchar); +} + +pub fn atString(w: Writer, at_str_pair: Value) !void { + const p = value.pair.assert(at_str_pair); + const b = value.fixnum.unpack(p.car); + std.debug.assert(b <= 255); + const str = try getStr(&p.cdr); + try w.writeByte('@'); + try w.writeByte(@intCast(b)); + try w.writeAll(str); + try w.writeByte(@intCast(b)); +} + +// TODO: belongs in string.zig +fn getStr(s: *const Value) ![]const u8 { + return if (value.sstr.check(s.*)) + value.sstr.unpack(s) + else if (value.istr.check(s.*)) |istr_ptr| + istr_ptr.str() + else if (value.array.check(s.*)) |array_ptr| + array_ptr.str() + else { + s.dump(); + @panic("This is not a string."); + }; +} + +pub fn label(w: Writer, v: Value) !void { + _ = w; + _ = v; + @panic("not implemented"); } pub fn istr(w: Writer, p: IstrPtr) !void { + // TODO: This assumes it needs no quoting try w.writeAll(p.str()); } diff --git a/src/zisp/value.zig b/src/zisp/value.zig index 1a32dc5..5bfeb37 100644 --- a/src/zisp/value.zig +++ b/src/zisp/value.zig @@ -338,6 +338,11 @@ pub const Value = packed union { , .{ v.bits, sign, exp, quiet, rest }); } + /// To treat the 64-bit value as an 8-byte array. + pub fn bytes(v: *const Value) *const [8]u8 { + return @ptrCast(&v); + } + /// Checks for bit-equality i.e. == comprison. pub fn eq(v1: Value, v2: Value) bool { return v1.bits == v2.bits; diff --git a/src/zisp/value/array.zig b/src/zisp/value/array.zig index ef2bcd6..67a5f37 100644 --- a/src/zisp/value/array.zig +++ b/src/zisp/value/array.zig @@ -4,6 +4,8 @@ const std = @import("std"); const gc = @import("../gc.zig"); const value = @import("../value.zig"); +const Alloc = std.mem.Allocator; + const Value = value.Value; /// Pointer to header for an array of various element types and sizes. @@ -46,12 +48,12 @@ const Value = value.Value; /// another array with the same buffer pointer and different type info. /// /// Other remaining bits provide information about element type and size. -pub const ArrayPtr = *align(8) ArrayHeader; +pub const ArrayPtr = *align(@alignOf(value.Zptr)) ArrayHeader; pub const ArrayHeader = packed struct(u64) { len_or_ptr: u48, - is_slice: bool, - is_ptr: bool, + is_slice: bool = false, + is_ptr: bool = false, type: enum(u2) { int, float, value, string }, info: packed union { int: packed struct(u12) { @@ -69,13 +71,12 @@ pub const ArrayHeader = packed struct(u64) { _: u11, }, string: packed struct(u12) { - encoding: enum(u10) { + encoding: enum(u11) { utf8, utf16, utf24, utf32, } = .utf8, - interned: bool = false, endian: Endian = .native, }, }, @@ -97,7 +98,10 @@ pub const ArrayHeader = packed struct(u64) { fn eltSize(self: *@This()) u16 { std.debug.assert(!self.is_ptr); - @panic(""); + return switch (self.type) { + .string => 1, + else => @panic("not implemented"), + }; } fn size(self: *@This()) usize { @@ -160,6 +164,22 @@ const Endian = enum(u1) { }; }; +pub fn newString(alloc: Alloc, s: []const u8) !Value { + std.debug.assert(s.len <= std.math.maxInt(u48)); + const algn = std.mem.Alignment.of(ArrayPtr); + const size = @sizeOf(ArrayHeader) + s.len; + const ptr = try alloc.alignedAlloc(u8, algn, size); + const arr: ArrayPtr = @ptrCast(ptr); + arr.* = .{ + .len_or_ptr = @intCast(s.len), + .type = .string, + .info = .{ .string = .{} }, + }; + const buf = arr.bufContent(); + @memcpy(buf[0..s.len], s); + return value.ptr.pack(arr, .array); +} + pub fn check(v: Value) ?ArrayPtr { if (v.getPtr(.array)) |p| { return @ptrCast(p); diff --git a/src/zisp/value/istr.zig b/src/zisp/value/istr.zig index cadf849..504ffe7 100644 --- a/src/zisp/value/istr.zig +++ b/src/zisp/value/istr.zig @@ -13,7 +13,7 @@ const Value = value.Value; /// /// First 64 bits are a cached hash, of which the lowest 8 bits are actually the /// length of the string: u64hash = (real_u64hash << 8) | u8length -pub const IstrPtr = *align(8) IstrHeader; +pub const IstrPtr = *align(@alignOf(value.Zptr)) IstrHeader; const IstrHeader = packed union { hash: u64, @@ -29,20 +29,23 @@ const IstrHeader = packed union { pub fn putStr(self: *@This(), s: []const u8) void { std.debug.assert(s.len <= 255); const buf = self.bufU8(); - @memcpy(buf[8 .. 8 + s.len], s); + const start = @sizeOf(IstrHeader); + @memcpy(buf[start .. start + s.len], s); } pub fn str(self: *@This()) []const u8 { const buf = self.bufU8(); - return buf[8 .. 8 + self.meta.len]; + const start = @sizeOf(IstrHeader); + return buf[start .. start + self.meta.len]; } }; pub fn new(alloc: Alloc, hash: u64, s: []const u8) !IstrPtr { - const aln = std.mem.Alignment.of(IstrPtr); - const ptr = try alloc.alignedAlloc(u8, aln, 8 + s.len); + const algn = std.mem.Alignment.of(IstrPtr); + const size = @sizeOf(IstrHeader) + s.len; + const ptr = try alloc.alignedAlloc(u8, algn, size); const istr: IstrPtr = @ptrCast(ptr); - istr.hash = hash; + istr.* = .{ .hash = hash }; istr.putStr(s); return istr; } diff --git a/src/zisp/value/sstr.zig b/src/zisp/value/sstr.zig index a91bfa2..8435800 100644 --- a/src/zisp/value/sstr.zig +++ b/src/zisp/value/sstr.zig @@ -38,11 +38,11 @@ pub fn pack(s: []const u8) Value { return .{ .sstr = .{ .string = @bitCast(buf) } }; } -pub fn unpack(v: Value) ShortString { - assert(v); - const buf: [6]u8 = @bitCast(v.sstr.string); +pub fn unpack(v: *const Value) []const u8 { + assert(v.*); + const buf = v.bytes(); const len = value.sstrLen(v.bits); - return .{ .buf = buf, .len = len }; + return buf[0..len]; } // No Zisp API for sstr specifically, since it's a string. See string.zig. |
