///|
pub(open) trait ToSexp {
#as_free_fn
fn to_sexp(Self) -> Value
}
///|
pub(all) suberror FromSexpError {
FromSexpError(Value)
} derive(Debug)
///|
pub(open) trait FromSexp {
#as_free_fn
fn from_sexp(Value) -> Self raise FromSexpError
}
///|
pub impl ToSexp for Value with fn to_sexp(self) {
self
}
///|
pub impl ToSexp for Int with fn to_sexp(self) {
Int(self)
}
///|
pub impl ToSexp for Double with fn to_sexp(self) {
Double(self)
}
///|
pub impl ToSexp for Bool with fn to_sexp(self) {
Value::bool(self)
}
///|
pub impl ToSexp for Symbol with fn to_sexp(self) {
Symbol(self)
}
///|
pub impl ToSexp for String with fn to_sexp(self) {
String(self)
}
///|
pub impl[A : ToSexp] ToSexp for Array[A] with fn to_sexp(self) {
self.rev_fold(init=Nil, (acc, x) => Pair(x.to_sexp(), acc))
}
///|
pub impl[A : ToSexp] ToSexp for FixedArray[A] with fn to_sexp(self) {
self.rev_fold(init=Nil, (acc, x) => Pair(x.to_sexp(), acc))
}
///|
pub impl[A : ToSexp, B : ToSexp] ToSexp for (A, B) with fn to_sexp(self) {
Pair(self.0.to_sexp(), self.1.to_sexp())
}
///|
pub impl[A : ToSexp, B : ToSexp] ToSexp for Iter2[A, B] with fn to_sexp(self) {
to_sexp(self.to_array())
}
///|
pub impl ToSexp for Json with fn to_sexp(self) {
match self {
Null => Nil
True => True
False => False
Number(x, ..) => Int(x.to_int())
String(x) => Value::symbol(x)
Array(xs) => to_sexp(xs)
Object({ "type": "inproper list", "ls": Array(xs), "r": r, .. }) =>
xs.rev_fold(init=to_sexp(r), (acc, x) => Pair(to_sexp(x), acc))
Object({ "type": "string", "value": String(s), .. }) => String(s)
Object({ "type": "double", "value": Number(d, ..), .. }) => Double(d)
Object({ "type": "vector", "value": Array(arr), .. }) =>
FixedArray::makei(arr.length(), i => to_sexp(arr[i])) |> Vector
Object(m) => Pair(Value::symbol("object"), Pair(to_sexp(m.iter2()), Nil))
}
}
///|
pub impl FromSexp for Json with fn from_sexp(self) {
match self {
Nil => []
True => true
False => false
Int(x) => Json::number(x.to_double())
Symbol(s) => Json::string(s.to_string())
Pair(l, r) => {
let res = [from_sexp(l)]
for r = r {
match r {
Nil => break Json::array(res)
Pair(l, r) => {
res.push(from_sexp(l))
continue r
}
r =>
break {
"type": "inproper list",
"ls": Json::array(res),
"r": (from_sexp(r) : Json),
}
}
}
}
Double(d) => { "type": "double", "value": Json::number(d) }
String(s) => { "type": "string", "value": Json::string(s) }
Vector(arr) => {
let res = []
for v in arr {
res.push(from_sexp(v))
}
{ "type": "vector", "value": Json::array(res) }
}
Closure(_) | Primitive(_) | Continuation(_) => raise FromSexpError(self)
}
}
///|
test "json" {
let j0 : Json = [
"define",
["fact", "x"],
["if", ["=", "x", 0], 1, ["*", "x", ["fact", ["-", "x", 1]]]],
]
@debug.assert_eq(j0, j0 |> to_sexp |> from_sexp)
let s0 : Value = Vector([
Double(1),
Int(2),
String("str"),
Value::symbol("sym"),
Pair(Pair(Value::symbol("a1"), Value::symbol("a2")), Value::symbol("b")),
Pair(Int(1), Pair(Int(2), Nil)),
])
assert_eq(s0, (from_sexp(s0) : Json) |> to_sexp)
json_inspect((from_sexp(s0) : Json), content={
"type": "vector",
"value": [
{ "type": "double", "value": 1 },
2,
{ "type": "string", "value": "str" },
"sym",
{
"type": "inproper list",
"ls": [{ "type": "inproper list", "ls": ["a1"], "r": "a2" }],
"r": "b",
},
[1, 2],
],
})
}