diff options
| author | Taylan Kammer <taylan.kammer@gmail.com> | 2025-02-28 14:38:57 +0100 |
|---|---|---|
| committer | Taylan Kammer <taylan.kammer@gmail.com> | 2025-02-28 14:38:57 +0100 |
| commit | 472f3e89a61ec51218cefe65305ec6f0a0d95fbf (patch) | |
| tree | a64ef16a6b23a822ab09e02b9d967f3b8bb3d17e /src | |
| parent | 34de389fe744018e808f2c8b301648d504ab610d (diff) | |
update
Diffstat (limited to 'src')
| -rw-r--r-- | src/libzisp.zig | 30 | ||||
| -rw-r--r-- | src/libzisp/gc.zig | 13 | ||||
| -rw-r--r-- | src/libzisp/io/parser.zig | 199 | ||||
| -rw-r--r-- | src/libzisp/io/unparser.zig | 101 | ||||
| -rw-r--r-- | src/libzisp/value.zig | 43 | ||||
| -rw-r--r-- | src/libzisp/value/boole.zig | 5 | ||||
| -rw-r--r-- | src/libzisp/value/char.zig | 2 | ||||
| -rw-r--r-- | src/libzisp/value/eof.zig | 2 | ||||
| -rw-r--r-- | src/libzisp/value/istr.zig | 3 | ||||
| -rw-r--r-- | src/libzisp/value/misc.zig | 8 | ||||
| -rw-r--r-- | src/libzisp/value/nil.zig | 2 | ||||
| -rw-r--r-- | src/libzisp/value/pair.zig | 2 | ||||
| -rw-r--r-- | src/libzisp/value/ptr.zig | 54 | ||||
| -rw-r--r-- | src/libzisp/value/rune.zig | 13 | ||||
| -rw-r--r-- | src/libzisp/value/sstr.zig | 10 |
15 files changed, 281 insertions, 206 deletions
diff --git a/src/libzisp.zig b/src/libzisp.zig index 79a54b4..b2c8283 100644 --- a/src/libzisp.zig +++ b/src/libzisp.zig @@ -5,13 +5,13 @@ const std = @import("std"); const builtin = @import("builtin"); const testing = std.testing; -pub const gc = @import("libzisp/gc.zig"); pub const io = @import("libzisp/io.zig"); pub const lib = @import("libzisp/lib.zig"); pub const value = @import("libzisp/value.zig"); pub const ShortString = value.ShortString; pub const Value = value.Value; +pub const Hval = value.Hval; test "double" { const d1: f64 = 0.123456789; @@ -46,12 +46,12 @@ test "fixnum" { test "ptr" { const ptr = value.ptr; - const val: [*]gc.Bucket = @ptrFromInt(256); - const tag = ptr.Tag.string; + const val: [*]Hval = @ptrFromInt(256); + const tag = ptr.Tag.istr; const p = ptr.pack(val, tag); try std.testing.expect(ptr.check(p)); - try std.testing.expect(ptr.checkZisp(p, tag)); + try std.testing.expect(ptr.checkZispTag(p, tag)); try std.testing.expect(ptr.checkStrong(p)); const pv, const pt = ptr.unpack(p); @@ -60,7 +60,7 @@ test "ptr" { var w = ptr.makeWeak(p); try std.testing.expect(ptr.check(w)); - try std.testing.expect(ptr.checkZisp(w, tag)); + try std.testing.expect(ptr.checkZispTag(w, tag)); try std.testing.expect(ptr.checkWeak(w)); try std.testing.expectEqual(true, value.boole.unpack(ptr.predWeak(w))); try std.testing.expectEqual(false, value.boole.unpack(ptr.predWeakNull(w))); @@ -258,7 +258,7 @@ test "parse" { test "parse2" { const val = io.parser.parse( \\ ;; Testing some crazy datum comments - \\ ##;"bar"#;([x #"y"]{##`,'z})"foo" + \\ #;"bar"#;([x #"y"]{##`,'z}) #"foo" \\ ;; end ); @@ -299,8 +299,20 @@ test "parse4" { } test "unparse" { - try std.testing.expectEqualStrings( - "#foo", - io.unparser.unparse(io.parser.parse("#foo")), + const unparse = io.unparser.unparse; + + var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; + var out: std.ArrayList(u8) = .init(gpa.allocator()); + + const w = out.writer(); + const v = io.parser.parse("#foo"); + try unparse(w, v); + try std.testing.expectEqualStrings("#foo", try out.toOwnedSlice()); +} + +test "unparse2" { + try io.unparser.unparse( + std.io.getStdErr().writer(), + io.parser.parse("#{foo bar['x]}"), ); } diff --git a/src/libzisp/gc.zig b/src/libzisp/gc.zig index 819fa0b..6704102 100644 --- a/src/libzisp/gc.zig +++ b/src/libzisp/gc.zig @@ -1,15 +1,12 @@ const std = @import("std"); -const Value = @import("value.zig").Value; +const value = @import("value.zig"); + +const Hval = value.Hval; var _gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; const gpa = _gpa.allocator(); -pub const Bucket = packed union { - bits: u64, - value: Value, -}; - -pub fn alloc(count: usize) []Bucket { - return gpa.alloc(Bucket, count) catch @panic("OOM"); +pub fn alloc(count: usize) []Hval { + return gpa.alloc(Hval, count) catch @panic("OOM"); } diff --git a/src/libzisp/io/parser.zig b/src/libzisp/io/parser.zig index 1e61385..6449431 100644 --- a/src/libzisp/io/parser.zig +++ b/src/libzisp/io/parser.zig @@ -25,17 +25,19 @@ // // The following table summarizes the other supported transformations: // -// [...] -> (#SQUARE ...) #datum -> (#HASH . datum) +// #datum -> (#HASH . datum) #rune(...) -> (#rune ...) // -// {...} -> (#BRACE ...) #rune(...) -> (#rune ...) +// [...] -> (#SQUARE ...) dat1dat2 -> (#JOIN dat1 . dat2) // -// #<...> -> (#ANGLE ...) dat1dat2 -> (#JOIN dat1 . dat2) +// {...} -> (#BRACE ...) dat1.dat2 -> (#DOT dat1 . dat2) // -// 'datum -> (#QUOTE . datum) dat1.dat2 -> (#DOT dat1 . dat2) +// 'datum -> (#QUOTE . datum) dat1:dat2 -> (#COLON dat1 . dat2) // -// `datum -> (#GRAVE . datum) #n#=datum -> (#LABEL n . datum) +// `datum -> (#GRAVE . datum) dat1|dat2 -> (#PIPE dat1 . dat2) // -// ,datum -> (#COMMA . datum) #n# -> (#LABEL . n) +// ,datum -> (#COMMA . datum) #n#=datum -> (#LABEL n . datum) +// +// #n# -> (#LABEL . n) // // Notes: // @@ -64,10 +66,6 @@ // The parser will see this as an attempt to use an 8-letter rune name, and // raise an error, since rune names are limited to 6 characters. // -// * The #<...> form is a special case; the less-than and greater-than symbols -// are not otherwise treated as brackets; e.g., <a b c d> is actually four -// strings: "<a", "b", "c", "d>". -// // Syntax sugar can combine arbitrarily; some examples follow: // // #{...} -> (#HASH #BRACE ...) @@ -105,7 +103,7 @@ // // #{x} -> (#HASH (#BRACE (x))) #{x} -> (#HASH #BRACE x) // -// foo(x y) -> (#JOIN foo (x y)) foo(bar) -> (#JOIN foo x y) +// foo(x y) -> (#JOIN foo (x y)) foo(x y) -> (#JOIN foo x y) // // // === Decoder === @@ -249,11 +247,11 @@ const State = struct { parent: ?*State = null, retval: Value = undefined, - // To store accumulated context, such as list elements. + // To store a value for context, such as a list of accumulated elements. context: Value = undefined, - // To remember what kind of list we're in: () [] {} - opening_bracket: u8 = undefined, + // To store a character for context, such as the type of opening bracket. + char_context: u8 = undefined, fn eof(s: *State) bool { return s.top.pos >= s.top.input.len; @@ -264,6 +262,7 @@ const State = struct { } fn skip(s: *State) void { + // std.debug.print("{c}\n", .{s.top.input[s.top.pos]}); s.top.pos += 1; } @@ -284,13 +283,10 @@ const State = struct { // Consumes whitespace and line comments. fn consumeBlanks(s: *State) void { while (!s.eof()) { - if (s.isWhitespace()) { - s.skip(); - } else if (s.peek() == ';') { - s.skip(); - s.consumeLineComment(); - } else { - return; + switch (s.peek()) { + '\t', '\n', ' ' => s.skip(), + ';' => s.consumeLineComment(), + else => return, } } } @@ -360,11 +356,10 @@ fn readShortString( const Fn = enum { start_parse, start_datum, - end_dotted_datum, - end_joined_datum, - end_datum_label, + end_join_datum, + end_label_datum, end_hash_datum, - end_quote, + end_quote_datum, continue_list, finish_improper_list, end_improper_list, @@ -380,19 +375,21 @@ pub fn parse(input: []const u8) Value { var top = TopState{ .alloc = alloc, .input = input }; var s0 = State{ .top = &top }; var s = &s0; - while (true) s = switch (s.next) { - .start_parse => startParse(s), - .start_datum => startDatum(s), - .end_dotted_datum => endDottedDatum(s), - .end_joined_datum => endJoinedDatum(s), - .end_datum_label => endDatumLabel(s), - .end_hash_datum => endHashDatum(s), - .end_quote => endQuote(s), - .continue_list => continueList(s), - .finish_improper_list => finishImproperList(s), - .end_improper_list => endImproperList(s), - .perform_return => s.performReturn() orelse return s.retval, - }; + while (true) { + // std.debug.print("{}\n", .{s.next}); + s = switch (s.next) { + .start_parse => startParse(s), + .start_datum => startDatum(s), + .end_join_datum => endJoinedDatum(s), + .end_label_datum => endLabelDatum(s), + .end_hash_datum => endHashDatum(s), + .end_quote_datum => endQuoteDatum(s), + .continue_list => continueList(s), + .finish_improper_list => finishImproperList(s), + .end_improper_list => endImproperList(s), + .perform_return => s.performReturn() orelse return s.retval, + }; + } } fn startParse(s: *State) *State { @@ -441,11 +438,8 @@ fn startDatum(s: *State) *State { fn endDatum(s: *State, d: Value) *State { // - // We're at the end of a datum; check for dot and join notations: - // - // DATUM|.DATUM2 - // - // DATUM|DATUM2 + // We're at the end of a datum; check for the various ways data can be + // joined together, like DATUM|DATUM or DATUM|.DATUM etc. // if (isEndOfDatum(s)) { @@ -453,28 +447,32 @@ fn endDatum(s: *State, d: Value) *State { return s.returnDatum(d); } - s.context = d; + // There's a stupid special-case we have to handle here, where a datum + // comment may fool us into thinking there's something to join: foo|#;bar - if (s.peek() == '.') { - s.skip(); - return s.recurParse(.start_datum, .end_dotted_datum); + const c = s.peek(); + switch (c) { + '.', ':', '|' => s.skip(), + '#' => if (checkTrailingDatumComment(s)) { + return s.returnDatum(d); + }, + else => {}, } - - return s.recurParse(.start_datum, .end_joined_datum); -} - -fn endDottedDatum(s: *State) *State { - const rune = value.rune.pack("DOT"); - const first = s.context; - const second = s.retval; - return endDatum(s, value.pair.cons(rune, value.pair.cons(first, second))); + s.context = d; + s.char_context = c; + return s.recurParse(.start_datum, .end_join_datum); } -fn endJoinedDatum(s: *State) *State { - const rune = value.rune.pack("JOIN"); - const first = s.context; - const second = s.retval; - return endDatum(s, value.pair.cons(rune, value.pair.cons(first, second))); +fn checkTrailingDatumComment(s: *State) bool { + const pos = s.pos(); + s.skip(); + if (s.eof()) { + // Error, but let it be handled later. + return false; + } + const c = s.peek(); + s.resetPos(pos); + return c == ';'; } fn isEndOfDatum(s: *State) bool { @@ -484,20 +482,29 @@ fn isEndOfDatum(s: *State) bool { }; } +fn endJoinedDatum(s: *State) *State { + const rune = value.rune.pack(switch (s.char_context) { + '.' => "DOT", + ':' => "COLON", + '|' => "PIPE", + else => "JOIN", + }); + const joined = value.pair.cons(s.context, s.retval); + return endDatum(s, value.pair.cons(rune, joined)); +} + fn handleHash(s: *State) *State { s.skip(); // // We just consumed a hash. Possibilities include: // - // #|foo ;rune - // - // #n#=DATUM ;datum with numeric label + // #|foo ;rune // - // #n# ;reference to datum label + // #|n#[=DATUM] ;datum label, with or without datum // - // #|;DATUM ;datum comment + // #|;DATUM ;datum comment // - // #|DATUM ;hash-datum + // #|DATUM ;hash-datum // if (s.eof()) { @@ -507,29 +514,17 @@ fn handleHash(s: *State) *State { return err(s, "whitespace after hash"); } - // Is it a rune? #foo switch (s.peek()) { 'a'...'z', 'A'...'Z' => return handleRune(s), - else => {}, - } - - // Is it a datum label / reference? - switch (s.peek()) { '0'...'9' => return handleDatumLabel(s), - else => {}, - } - - // Is it a datum comment? #;DATUM - if (s.peek() == ';') { - s.skip(); - // Don't change s.next in this case. Just let the parser try to redo - // what it was doing as soon as the commented-out datum has been read. - return s.recurParse(.start_datum, s.next); + ';' => { + s.skip(); + // Don't change s.next in this case. Just let the parser redo what + // it was doing as soon as the commented-out datum has been read. + return s.recurParse(.start_datum, s.next); + }, + else => return s.recurParse(.start_datum, .end_hash_datum), } - - // Otherwise, it must be a hash-datum. #DATUM - - return s.recurParse(.start_datum, .end_hash_datum); } fn handleRune(s: *State) *State { @@ -560,7 +555,7 @@ fn handleDatumLabel(s: *State) *State { if (s.eof() or s.isWhitespace()) { const rune = value.rune.pack("LABEL"); - return s.returnDatum(value.pair.cons(rune, n)); + return endDatum(s, value.pair.cons(rune, n)); } if (s.getc() != '=') { @@ -568,22 +563,22 @@ fn handleDatumLabel(s: *State) *State { } s.context = n; - return s.recurParse(.start_datum, .end_datum_label); + return s.recurParse(.start_datum, .end_label_datum); } fn readDatumLabel(s: *State) ?Value { return readShortString(s, std.ascii.isDigit, value.sstr.pack); } -fn endDatumLabel(s: *State) *State { +fn endLabelDatum(s: *State) *State { const rune = value.rune.pack("LABEL"); const payload = value.pair.cons(s.context, s.retval); - return s.returnDatum(value.pair.cons(rune, payload)); + return endDatum(s, value.pair.cons(rune, payload)); } fn endHashDatum(s: *State) *State { const rune = value.rune.pack("HASH"); - return s.returnDatum(value.pair.cons(rune, s.retval)); + return endDatum(s, value.pair.cons(rune, s.retval)); } fn startQuotedString(s: *State) *State { @@ -591,7 +586,7 @@ fn startQuotedString(s: *State) *State { s.skip(); const str = readQuotedString(s) catch return err(s, "unclosed string"); - return s.returnDatum(str); + return endDatum(s, str); } // RQS = Read Quoted String @@ -611,7 +606,7 @@ fn readQuotedSstr(s: *State) !?Value { const c = s.getc(); if (c == '"') { // ok, return what we accumulated - return value.sstr.packLiteral(buf[0..i]); + return value.sstr.packQuoted(buf[0..i]); } if (i == 6) { // failed; reset and bail out @@ -637,7 +632,7 @@ fn startBareString(s: *State) *State { fn readBareSstr(s: *State) ?*State { const sp = s.pos(); if (readShortString(s, isSstrChar, value.sstr.pack)) |sstr| { - return s.returnDatum(sstr); + return endDatum(s, sstr); } else { s.resetPos(sp); return null; @@ -666,11 +661,11 @@ fn startQuote(s: *State) *State { ',' => "COMMA", else => unreachable, }); - return s.recurParse(.start_datum, .end_quote); + return s.recurParse(.start_datum, .end_quote_datum); } -fn endQuote(s: *State) *State { - return s.returnDatum(value.pair.cons(s.context, s.retval)); +fn endQuoteDatum(s: *State) *State { + return endDatum(s, value.pair.cons(s.context, s.retval)); } // List processing is, unsurprisingly, the most complicated, and it's made even @@ -689,7 +684,7 @@ fn startList(s: *State) *State { } s.context = value.nil.nil; - s.opening_bracket = open; + s.char_context = open; return if (isEndOfList(s)) endList(s) else @@ -704,19 +699,19 @@ fn isEndOfList(s: *State) bool { } fn endList(s: *State) *State { - const open = s.opening_bracket; + const open = s.char_context; const char = s.getc(); if (open == '(' and char == ')') { - return s.returnDatum(s.context); + return endDatum(s, s.context); } if (open == '[' and char == ']') { const rune = value.rune.pack("SQUARE"); - return s.returnDatum(value.pair.cons(rune, s.context)); + return endDatum(s, value.pair.cons(rune, s.context)); } if (open == '{' and char == '}') { const rune = value.rune.pack("BRACE"); - return s.returnDatum(value.pair.cons(rune, s.context)); + return endDatum(s, value.pair.cons(rune, s.context)); } return err(s, "wrong closing bracket for list"); diff --git a/src/libzisp/io/unparser.zig b/src/libzisp/io/unparser.zig index d835924..c25e918 100644 --- a/src/libzisp/io/unparser.zig +++ b/src/libzisp/io/unparser.zig @@ -3,19 +3,100 @@ const std = @import("std"); const value = @import("../value.zig"); const ShortString = value.ShortString; +const OtherTag = value.OtherTag; const Value = value.Value; +const Hval = value.Hval; -// const State = struct { +pub fn unparse(w: anytype, v: Value) anyerror!void { + try if (value.double.check(v)) + unparseDouble(w, v) + else if (value.fixnum.check(v)) + unparseFixnum(w, v) + else if (value.ptr.checkZisp(v)) + unparseHeap(w, v) + else + unparseOther(w, v); +} + +fn unparseDouble(w: anytype, v: Value) !void { + _ = w; + _ = v; + @panic("not implemented"); +} + +fn unparseFixnum(w: anytype, v: Value) !void { + _ = w; + _ = v; + @panic("not implemented"); +} -// } +fn unparseHeap(w: anytype, v: Value) !void { + const p, const t = value.ptr.unpack(v); + try switch (t) { + .pair => unparsePair(w, p), + .istr => @panic("not implemented"), + .proc => @panic("not implemented"), + }; +} + +fn unparseOther(w: anytype, v: Value) !void { + try switch (v.other.tag) { + .rune => unparseRune(w, v), + .sstr => unparseSstr(w, v), + .qstr => unparseQstr(w, v), + .char => unparseChar(w, v), + .misc => unparseMisc(w, v), + }; +} + +fn unparseRune(w: anytype, v: Value) !void { + const name = value.rune.unpack(v); + try w.writeByte('#'); + try w.writeAll(name.constSlice()); +} -pub fn unparse(v: Value) []u8 { - var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; - var out: std.ArrayList(u8) = .init(gpa.allocator()); - if (value.rune.check(v)) { - const name = value.rune.unpack(v); - out.append('#') catch @panic(""); - out.appendSlice(name.slice()) catch @panic(""); +fn unparseSstr(w: anytype, v: Value) !void { + const str = value.sstr.unpack(v); + try w.writeAll(str.constSlice()); +} + +fn unparseQstr(w: anytype, v: Value) !void { + const str = value.sstr.unpack(v); + try w.writeByte('"'); + try w.writeAll(str.constSlice()); + try w.writeByte('"'); +} + +fn unparseChar(w: anytype, v: Value) !void { + var buf: [4]u8 = undefined; + const len = try std.unicode.utf8Encode(v.char.value, &buf); + try w.writeAll(buf[0..len]); +} + +fn unparseMisc(w: anytype, v: Value) !void { + try switch (v.misc.value) { + .f => w.writeAll("#f"), + .t => w.writeAll("#t"), + .nil => w.writeAll("()"), + .eof => w.writeAll("#eof"), + .undef => w.writeAll("#undef"), + }; +} + +fn unparsePair(w: anytype, p: [*]Hval) !void { + const vs: *[2]Value = @ptrCast(p); + try w.writeByte('('); + try unparse(w, vs[0]); + var cdr = vs[1]; + while (value.pair.check(cdr)) : (cdr = value.pair.cdr(cdr)) { + try w.writeByte(' '); + try unparse(w, value.pair.car(cdr)); + } + if (!value.nil.check(cdr)) { + try w.writeByte(' '); + try w.writeByte('.'); + try w.writeByte(' '); + try unparse(w, cdr); } - return out.toOwnedSlice() catch @panic(""); + try w.writeByte(')'); } diff --git a/src/libzisp/value.zig b/src/libzisp/value.zig index 273c659..fbe7dbe 100644 --- a/src/libzisp/value.zig +++ b/src/libzisp/value.zig @@ -165,7 +165,9 @@ const FILL = 0x7ff; // Used when dealing with runes and short strings. pub const ShortString = std.BoundedArray(u8, 6); -pub const OtherTag = enum(u3) { rune, sstr, sstr_lit, char, misc }; +pub const OtherTag = enum(u3) { rune, sstr, qstr, char, misc }; + +pub const MiscValue = enum(u8) { f, t, nil, eof, undef = 255 }; /// Represents a Zisp value/object. pub const Value = packed union { @@ -266,7 +268,7 @@ pub const Value = packed union { /// For initializing and reading misc values aka singletons. misc: packed struct { - value: u8, + value: MiscValue, _reserved: u40 = 0, _tag: OtherTag = .misc, _is_ptr: bool = false, @@ -274,11 +276,9 @@ pub const Value = packed union { _is_fixnum: bool = false, }, - const Self = @This(); - /// Hexdumps the value. - pub fn dump(self: Self) void { - std.debug.dumpHex(std.mem.asBytes(&self)); + pub inline fn dump(v: Value) void { + std.debug.dumpHex(std.mem.asBytes(&v)); } // The following aren't type predicates per se, but rather determine which @@ -286,32 +286,37 @@ pub const Value = packed union { // since those aren't sub-categorized into further types. /// Checks for a Zisp double, including: +nan.0, -nan.0, +inf.0, -inf.0 - pub fn isDouble(self: Self) bool { - return self.ieee.exp != FILL or self.ieee.rest == 0; + pub inline fn isDouble(v: Value) bool { + return v.ieee.exp != FILL or v.ieee.rest == 0; } /// Checks for a non-double Zisp value packed into a NaN. - pub fn isPacked(self: Self) bool { - return !self.isDouble(); + pub inline fn isPacked(v: Value) bool { + return !v.isDouble(); } /// Checks for a fixnum. - pub fn isFixnum(self: Self) bool { - return self.isPacked() and self.ieee.sign; + pub inline fn isFixnum(v: Value) bool { + return v.isPacked() and v.ieee.sign; } /// Checks for any kind of pointer. - pub fn isPtr(self: Self) bool { - return self.isPacked() and !self.ieee.sign and self.ieee.quiet; + pub inline fn isPtr(v: Value) bool { + return v.isPacked() and !v.ieee.sign and v.ieee.quiet; } /// Checks for a non-double, non-fixnum, non-pointer Zisp value. - fn _isOther(self: Self) bool { - return self.isPacked() and !self.ieee.sign and !self.ieee.quiet; + pub inline fn isOther(v: Value) bool { + return v.isPacked() and !v.ieee.sign and !v.ieee.quiet; } - /// Checks for any "other" type of value. - pub fn isOther(self: Self, tag: OtherTag) bool { - return self._isOther() and self.other.tag == tag; + /// Checks for an other type of value based on tag. + pub inline fn isOtherTag(v: Value, tag: OtherTag) bool { + return v.isOther() and v.other.tag == tag; } }; + +/// A "heap value" that could be a Value or object header. +pub const Hval = packed union { + value: Value, +}; diff --git a/src/libzisp/value/boole.zig b/src/libzisp/value/boole.zig index 623dbc2..2e94e4d 100644 --- a/src/libzisp/value/boole.zig +++ b/src/libzisp/value/boole.zig @@ -1,8 +1,7 @@ const Value = @import("../value.zig").Value; -const misc = @import("misc.zig"); -pub const f = misc.f; -pub const t = misc.t; +pub const f = Value{ .misc = .{ .value = .f } }; +pub const t = Value{ .misc = .{ .value = .t } }; // Zig API diff --git a/src/libzisp/value/char.zig b/src/libzisp/value/char.zig index eb4bbc9..09a3034 100644 --- a/src/libzisp/value/char.zig +++ b/src/libzisp/value/char.zig @@ -5,7 +5,7 @@ const Value = value.Value; // Zig API pub fn check(v: Value) bool { - return v.isOther(.char); + return v.isOtherTag(.char); } pub fn assert(v: Value) void { diff --git a/src/libzisp/value/eof.zig b/src/libzisp/value/eof.zig index 367a86c..4b16669 100644 --- a/src/libzisp/value/eof.zig +++ b/src/libzisp/value/eof.zig @@ -2,7 +2,7 @@ const value = @import("../value.zig"); const Value = value.Value; -pub const eof = @import("misc.zig").eof; +pub const eof = Value{ .misc = .{ .value = .eof } }; // Zig API diff --git a/src/libzisp/value/istr.zig b/src/libzisp/value/istr.zig new file mode 100644 index 0000000..5937531 --- /dev/null +++ b/src/libzisp/value/istr.zig @@ -0,0 +1,3 @@ +const std = @import("std"); + +const value = @import("../value.zig"); diff --git a/src/libzisp/value/misc.zig b/src/libzisp/value/misc.zig deleted file mode 100644 index 30cbf84..0000000 --- a/src/libzisp/value/misc.zig +++ /dev/null @@ -1,8 +0,0 @@ -const Value = @import("../value.zig").Value; - -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 } }; - -pub const undef = Value{ .misc = .{ .value = 255 } }; diff --git a/src/libzisp/value/nil.zig b/src/libzisp/value/nil.zig index 14bd800..f95ecad 100644 --- a/src/libzisp/value/nil.zig +++ b/src/libzisp/value/nil.zig @@ -2,7 +2,7 @@ const value = @import("../value.zig"); const Value = value.Value; -pub const nil = @import("misc.zig").nil; +pub const nil = Value{ .misc = .{ .value = .nil } }; // Zig API diff --git a/src/libzisp/value/pair.zig b/src/libzisp/value/pair.zig index 541a5f5..1c34096 100644 --- a/src/libzisp/value/pair.zig +++ b/src/libzisp/value/pair.zig @@ -9,7 +9,7 @@ const Value = value.Value; // Zig API pub fn check(v: Value) bool { - return ptr.checkZisp(v, .pair); + return ptr.checkZispTag(v, .pair); } pub fn assert(v: Value) void { diff --git a/src/libzisp/value/ptr.zig b/src/libzisp/value/ptr.zig index e1fadf2..115cc2d 100644 --- a/src/libzisp/value/ptr.zig +++ b/src/libzisp/value/ptr.zig @@ -2,8 +2,8 @@ const std = @import("std"); const value = @import("../value.zig"); const gc = @import("../gc.zig"); -const Bucket = gc.Bucket; const Value = value.Value; +const Hval = value.Hval; // Zig API @@ -42,19 +42,19 @@ pub fn unpackForeign(v: Value) u50 { // Zisp Pointers -fn _checkZisp(v: Value) bool { +pub fn checkZisp(v: Value) bool { return check(v) and !v.ptr.is_foreign; } -fn _assertZisp(v: Value) void { - if (!_checkZisp(v)) { +pub fn assertZisp(v: Value) void { + if (!checkZisp(v)) { v.dump(); @panic("not zisp pointer"); } } pub fn checkWeak(v: Value) bool { - return _checkZisp(v) and v.zptr.is_weak; + return checkZisp(v) and v.zptr.is_weak; } pub fn assertWeak(v: Value) void { @@ -64,19 +64,19 @@ pub fn assertWeak(v: Value) void { } } -pub fn checkZisp(v: Value, tag: Tag) bool { - return _checkZisp(v) and unpack(v).@"1" == tag; +pub fn checkZispTag(v: Value, tag: Tag) bool { + return checkZisp(v) and unpack(v).@"1" == tag; } -pub fn assertZisp(v: Value, tag: Tag) void { - if (!checkZisp(v, tag)) { +pub fn assertZispTag(v: Value, tag: Tag) void { + if (!checkZispTag(v, tag)) { v.dump(); @panic("not zisp pointer or wrong tag"); } } pub fn checkStrong(v: Value) bool { - return _checkZisp(v) and !v.zptr.is_weak; + return checkZisp(v) and !v.zptr.is_weak; } pub fn assertStrong(v: Value) void { @@ -86,24 +86,24 @@ pub fn assertStrong(v: Value) void { } } -pub fn packZisp(ptr: [*]Bucket, tag: Tag, is_weak: bool) Value { +pub fn packZisp(ptr: [*]Hval, tag: Tag, is_weak: bool) Value { return .{ .zptr = .{ .tagged_value = tagPtr(ptr, tag), .is_weak = is_weak, } }; } -pub fn pack(ptr: [*]Bucket, tag: Tag) Value { +pub fn pack(ptr: [*]Hval, tag: Tag) Value { return packZisp(ptr, tag, false); } -pub fn packWeak(ptr: [*]Bucket, tag: Tag) Value { +pub fn packWeak(ptr: [*]Hval, tag: Tag) Value { return packZisp(ptr, tag, true); } // Unpacks weak as well; no need for a separate fn. -pub fn unpack(v: Value) struct { [*]Bucket, Tag } { - _assertZisp(v); +pub fn unpack(v: Value) struct { [*]Hval, Tag } { + assertZisp(v); return untagPtr(v.zptr.tagged_value); } @@ -117,37 +117,27 @@ pub fn isWeakNull(v: Value) bool { return v.zptr.tagged_value == 0; } -fn tagPtr(ptr: [*]Bucket, tag: Tag) u48 { +fn tagPtr(ptr: [*]Hval, tag: Tag) u48 { const int: usize = @intFromPtr(ptr); const untagged: u48 = @intCast(int); return untagged | @intFromEnum(tag); } -fn untagPtr(tagged: u48) struct { [*]Bucket, Tag } { +fn untagPtr(tagged: u48) struct { [*]Hval, Tag } { const untagged: u48 = tagged & 0xfffffffffff8; - const ptr: [*]Bucket = @ptrFromInt(untagged); + const ptr: [*]Hval = @ptrFromInt(untagged); const int: u3 = @truncate(tagged); const tag: Tag = @enumFromInt(int); return .{ ptr, tag }; } pub const Tag = enum(u3) { - /// 0. Strings / Symbols - string, - /// 1. Bignums / Ratnums - number, - /// 2. Pairs ([2]Value) + /// *[2]Value pair, - /// 3. Collections: Vector, table, etc. - coll, - /// 4. OOP: Classes, instances, etc. - oop, - /// 5. String buffers - text, - /// 6. Procedures + /// Interned string (symbol) + istr, + /// Procedure proc, - /// 7. Others - other, }; // Zisp API diff --git a/src/libzisp/value/rune.zig b/src/libzisp/value/rune.zig index 3a4dc61..a6152b1 100644 --- a/src/libzisp/value/rune.zig +++ b/src/libzisp/value/rune.zig @@ -8,7 +8,7 @@ const Value = value.Value; // Zig API pub fn check(v: Value) bool { - return v.isOther(.rune); + return v.isOtherTag(.rune); } pub fn assert(v: Value) void { @@ -50,15 +50,12 @@ pub fn pack(s: []const u8) Value { } pub fn unpack(v: Value) ShortString { - var s = ShortString{ .buffer = @bitCast(v.sstr.string) }; + assert(v); + const s: [6]u8 = @bitCast(v.rune.name); inline for (0..6) |i| { - if (s.buffer[i] == 0) { - s.len = i; - return s; - } + if (s[i] == 0) return .{ .buffer = s, .len = i }; } - s.len = 6; - return s; + return .{ .buffer = s, .len = 6 }; } // Zisp API diff --git a/src/libzisp/value/sstr.zig b/src/libzisp/value/sstr.zig index 1c9812e..b02fd3d 100644 --- a/src/libzisp/value/sstr.zig +++ b/src/libzisp/value/sstr.zig @@ -9,7 +9,7 @@ const Value = value.Value; // Zig API pub fn check(v: Value) bool { - return v.isOther(.sstr) or v.isOther(.sstr_lit); + return v.isOtherTag(.sstr) or v.isOtherTag(.qstr); } pub fn assert(v: Value) void { @@ -19,6 +19,10 @@ pub fn assert(v: Value) void { } } +pub fn checkQuoted(v: Value) bool { + return v.isOtherTag(.qstr); +} + // For now, ignore encoding, just treat it as []u8. pub fn isValidSstr(s: []const u8) bool { @@ -50,8 +54,8 @@ pub fn pack(s: []const u8) Value { return _pack(s, .sstr); } -pub fn packLiteral(s: []const u8) Value { - return _pack(s, .sstr_lit); +pub fn packQuoted(s: []const u8) Value { + return _pack(s, .qstr); } fn _pack(s: []const u8, tag: OtherTag) Value { |
