const std = @import("std"); const testing = std.testing; pub const io = @import("../zisp/io.zig"); pub const value = @import("../zisp/value.zig"); pub const Value = value.Value; fn parseString(str: []const u8) Value { var fbs = std.io.fixedBufferStream(str); return io.parser.parse(fbs.reader().any()); } test "parse" { const val = parseString("\"foo\""); try testing.expect(value.sstr.check(val)); const s = value.sstr.unpack(val); try testing.expectEqualStrings("foo", s.slice()); } test "parse2" { const val = parseString( \\ ;; Testing some crazy datum comments \\ ;~"bar"([x #"y"]{##`,'z}) #"foo" \\ ;; end ); const r = value.rune.unpack(value.pair.car(val)); try testing.expectEqualStrings("HASH", r.slice()); const s = value.pair.cdr(val); try testing.expect(value.sstr.check(s)); const f = value.sstr.unpack(s); try testing.expectEqualStrings("foo", f.slice()); } test "parse3" { const val = parseString( \\(foo ;~x ;~(x y) ;~x #bar [#x #"baz"] 'bat) ); const car = value.pair.car; const cdr = value.pair.cdr; const e1 = car(val); const e2 = car(cdr(val)); const e3 = car(cdr(cdr(val))); const e4 = car(cdr(cdr(cdr(val)))); try testing.expect(value.sstr.check(e1)); try testing.expect(value.rune.check(e2)); try testing.expect(value.pair.check(e3)); try testing.expect(value.pair.check(e4)); } test "parse4" { const val = parseString("(foo . ;~x bar ;~y)"); const s = value.sstr.unpack(value.pair.car(val)); try testing.expectEqualStrings("foo", s.slice()); const f = value.sstr.unpack(value.pair.cdr(val)); try testing.expectEqualStrings("bar", f.slice()); } test "unparse" { var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; var out: std.ArrayList(u8) = .init(gpa.allocator()); const w = out.writer(); const v = parseString("#foo"); try io.unparser.unparse(w, v); try testing.expectEqualStrings("#foo", try out.toOwnedSlice()); } test "unparse2" { var gpa: std.heap.GeneralPurposeAllocator(.{}) = .init; var out: std.ArrayList(u8) = .init(gpa.allocator()); const w = out.writer(); const v = parseString("#{foo bar['x]}"); try io.unparser.unparse(w, v); try testing.expectEqualStrings( "(#HASH #BRACE foo (#JOIN bar #SQUARE (#QUOTE . x)))", try out.toOwnedSlice(), ); } fn writeParseResult(str: []const u8) !void { const w = std.io.getStdErr().writer(); const v = parseString(str); try io.unparser.unparse(w, v); try w.writeByte('\n'); } test "unparse3" { try writeParseResult("#{foo bar['x](y)(z)}"); } test "unparse4" { try writeParseResult("(foo ;~bar)"); } test "unparse5" { try writeParseResult("(;~foo foo ;~bar . ;~bar bar ;~bar)"); } test "unparse6" { try writeParseResult("(foo bar ... baz bat.(qux))"); } test "unparse7" { try writeParseResult("#`(#,(->keyword (syntax->datum #'sym)) . in)"); } fn parseBench(path: []const u8, iters: usize) !void { const file = try std.fs.cwd().openFile(path, .{}); defer file.close(); var sfa = io.parser.DefaultSfa.init(std.heap.smp_allocator); var parser = try io.parser.initSfa(&sfa); defer parser.deinit(); var timer = try std.time.Timer.start(); for (0..iters) |i| { _ = i; var br = std.io.bufferedReader(file.reader()); const reader = br.reader().any(); // const reader = file.reader().any(); var v: Value = undefined; while (true) { // std.debug.print("hihi {s}\n", .{path}); v = parser.run(reader) catch |e| { std.debug.print("\nfile pos: {}\n", .{ try file.getPos(), }); return e; }; // try io.unparser.unparse(std.io.getStdOut().writer().any(), v); if (value.eof.eq(v)) { break; } } try file.seekTo(0); } const ns: f64 = @floatFromInt(timer.lap()); const secs = ns / 1_000_000_000; std.debug.print( "parse {s} x {}: {d:.3}s\n", .{ path, iters, secs }, ); } test "parse bench" { try parseBench("src/test/data/parser-test-1.scm", 200); try parseBench("src/test/data/parser-test-2.scm", 800); try parseBench("src/test/data/parser-torture.scm", 1); }