summaryrefslogtreecommitdiff
path: root/src/libzisp/io/unparser.zig
blob: d7031820b483d0ed997585f254d5197b5e3bcbc4 (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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
const std = @import("std");

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

const istr = value.istr;
const seq = value.seq;

const ShortString = value.ShortString;
const OtherTag = value.OtherTag;
const Value = value.Value;

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, @ptrCast(p)),
        .seq => unparseSeq(w, @ptrCast(p)),
        else => @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());
}

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: *[2]Value) !void {
    try w.writeByte('(');
    try unparse(w, p[0]);
    var cdr = p[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);
    }
    try w.writeByte(')');
}

fn unparseSeq(w: anytype, p: *seq.Header) !void {
    const h = istr.getHeaderFromPtr(@ptrCast(p));
    switch (h.type) {
        .string => try unparseString(w, h),
        else => @panic("not implemented"),
    }
}

fn unparseString(w: anytype, h: *seq.Header) !void {
    const info = h.info.string;
    if (info.quoted) {
        try w.writeByte('"');
    }
    try w.writeAll(h.bytes());
    if (info.quoted) {
        try w.writeByte('"');
    }
}