rust: Update rust and update/refactor implementation
[jackhill/mal.git] / rust / printer.rs
1 use types::MalVal;
2 use types::MalVal::{Nil,Bool,Int,Str,Sym,List,Vector,Hash,Func,MalFunc,Atom};
3
4 fn escape_str(s: &str) -> String {
5 s.chars().map(|c| {
6 match c {
7 '"' => "\\\"".to_string(),
8 '\n' => "\\n".to_string(),
9 '\\' => "\\\\".to_string(),
10 _ => c.to_string(),
11 }
12 }).collect::<Vec<String>>().join("")
13 }
14
15 impl MalVal {
16 pub fn pr_str(&self, print_readably: bool) -> String {
17 match self {
18 Nil => String::from("nil"),
19 Bool(true) => String::from("true"),
20 Bool(false) => String::from("false"),
21 Int(i) => format!("{}", i),
22 //Float(f) => format!("{}", f),
23 Str(s) => {
24 if s.starts_with("\u{29e}") {
25 format!(":{}", &s[2..])
26 } else if print_readably {
27 format!("\"{}\"", escape_str(s))
28 } else {
29 s.clone()
30 }
31 }
32 Sym(s) => s.clone(),
33 List(l,_) => pr_seq(&**l, print_readably, "(", ")", " "),
34 Vector(l,_) => pr_seq(&**l, print_readably, "[", "]", " "),
35 Hash(hm,_) => {
36 let l: Vec<MalVal> = hm
37 .iter()
38 .flat_map(|(k, v)| { vec![Str(k.to_string()), v.clone()] })
39 .collect();
40 pr_seq(&l, print_readably, "{", "}", " ")
41 },
42 Func(f,_) => format!("#<fn {:?}>", f),
43 MalFunc{ast: a, params: p, ..} => {
44 format!("(fn* {} {})", p.pr_str(true), a.pr_str(true))
45 },
46 Atom(a) => format!("(atom {})", a.borrow().pr_str(true)),
47 }
48 }
49 }
50
51 pub fn pr_seq(seq: &Vec<MalVal>, print_readably: bool,
52 start: &str, end: &str, join: &str) -> String {
53 let strs: Vec<String> = seq
54 .iter()
55 .map(|x| x.pr_str(print_readably))
56 .collect();
57 format!("{}{}{}", start, strs.join(join), end)
58 }
59
60 // vim: ts=2:sw=2:expandtab