summaryrefslogtreecommitdiff
path: root/src/zisp/io/print.zig
blob: 8ef8b21d76a87d7d327e821bed12802c61ace47e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
const std = @import("std");

const gc = @import("../gc.zig");
const value = @import("../value.zig");

const Value = value.Value;

pub fn toWriter(w: *std.Io.Writer, v: Value) anyerror!void {
    // zig fmt: off
    try if (v.isDouble()) double(w, v)
    else if (v.isFixnum()) fixnum(w, v)
    else if (v.getPtr(.pair)) |p| pair(w, @ptrCast(p))
    else if (v.getPtr(.seq)) |p| seq(w, @ptrCast(p))
    else if (v.isRune()) rune(w, v)
    else if (v.isChar()) char(w, v)
    else if (v.isMisc()) misc(w, v)
    else if (v.isSrat()) srat(w, v)
    else if (v.isSstr()) sstr(w, v)
    ;
    // zig fmt: on
}

pub fn double(w: *std.Io.Writer, v: Value) !void {
    _ = w;
    _ = v;
    @panic("not implemented");
}

pub fn fixnum(w: *std.Io.Writer, v: Value) !void {
    _ = w;
    _ = v;
    @panic("not implemented");
}

pub fn rune(w: *std.Io.Writer, v: Value) !void {
    const name = value.rune.unpack(v);
    try w.writeByte('#');
    try w.writeAll(name.slice());
}

pub fn sstr(w: *std.Io.Writer, v: Value) !void {
    // TODO: Check if pipes/escapes necessary.
    const str = value.sstr.unpack(v);
    try w.writeAll(str.slice());
}

pub fn char(w: *std.Io.Writer, v: Value) !void {
    const uc: u21 = value.char.unpack(v);
    var buf: [4]u8 = undefined;
    const len = try std.unicode.utf8Encode(uc, &buf);
    try w.writeAll(buf[0..len]);
}

pub fn misc(w: *std.Io.Writer, v: Value) !void {
    try switch (v.bits) {
        value.f.bits => w.writeAll("#f"),
        value.t.bits => w.writeAll("#t"),
        value.nil.bits => w.writeAll("()"),
        value.eof.bits => w.writeAll("#EOF"),
        value.none.bits => w.writeAll("#NONE"),
        value.undef.bits => w.writeAll("#UNDEF"),
        else => @panic("not implemented"),
    };
}

pub fn srat(w: *std.Io.Writer, v: Value) !void {
    _ = w;
    _ = v;
    @panic("not implemented");
}

pub fn pair(w: *std.Io.Writer, p: *[2]Value) !void {
    try w.writeByte('(');
    try toWriter(w, p[0]);
    var cdr = p[1];
    while (value.pair.check(cdr)) |p2| : (cdr = value.pair.cdr(cdr)) {
        try w.writeByte(' ');
        try toWriter(w, p2[0]);
    }
    if (!value.nil.eq(cdr)) {
        try w.writeByte(' ');
        try w.writeByte('&');
        try w.writeByte(' ');
        try toWriter(w, cdr);
    }
    try w.writeByte(')');
}

pub fn seq(w: *std.Io.Writer, s: *value.seq.Header) !void {
    switch (s.type) {
        .string => try string(w, s),
        else => @panic("not implemented"),
    }
}

pub fn string(w: *std.Io.Writer, s: *value.seq.Header) !void {
    // TODO: Check if pipes/escapes necessary.
    try w.writeByte('|');
    try w.writeAll(s.bytes());
    try w.writeByte('|');
}