Commit | Line | Data |
---|---|---|
bbeb1b87 | 1 | extern crate mal; |
0ab374bc | 2 | |
0ab374bc | 3 | use std::collections::HashMap; |
8f5b0f10 | 4 | |
fb439f3c JM |
5 | use mal::types::{MalVal, MalRet, MalError, err_str, err_string}; |
6 | use mal::types::{list, vector, hash_map, _int, func}; | |
bbeb1b87 | 7 | use mal::types::MalError::{ErrString, ErrMalVal}; |
fb439f3c | 8 | use mal::types::MalType::{Sym, List, Vector, Hash_Map, Int}; |
bbeb1b87 | 9 | use mal::{readline, reader}; |
0ab374bc JM |
10 | |
11 | // read | |
12 | fn read(str: String) -> MalRet { | |
13 | reader::read_str(str) | |
14 | } | |
15 | ||
16 | // eval | |
17 | fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { | |
18 | match *ast { | |
19 | Sym(ref sym) => { | |
bbeb1b87 AC |
20 | match env.get(sym) { |
21 | Some(mv) => Ok(mv.clone()), | |
fb439f3c JM |
22 | //None => Ok(_nil()), |
23 | None => err_string(format!("'{}' not found", sym)), | |
0ab374bc JM |
24 | } |
25 | }, | |
bd306723 | 26 | List(ref a,_) | Vector(ref a,_) => { |
0ab374bc JM |
27 | let mut ast_vec : Vec<MalVal> = vec![]; |
28 | for mv in a.iter() { | |
fb439f3c JM |
29 | let mv2 = mv.clone(); |
30 | ast_vec.push(try!(eval(mv2, env))); | |
0ab374bc | 31 | } |
bd306723 | 32 | Ok(match *ast { List(_,_) => list(ast_vec), |
77b2da6c | 33 | _ => vector(ast_vec) }) |
fb439f3c | 34 | } |
bd306723 | 35 | Hash_Map(ref hm,_) => { |
5939404b JM |
36 | let mut new_hm: HashMap<String,MalVal> = HashMap::new(); |
37 | for (key, value) in hm.iter() { | |
fb439f3c JM |
38 | new_hm.insert(key.to_string(), |
39 | try!(eval(value.clone(), env))); | |
5939404b JM |
40 | } |
41 | Ok(hash_map(new_hm)) | |
0ab374bc | 42 | } |
fb439f3c | 43 | _ => Ok(ast.clone()), |
0ab374bc JM |
44 | } |
45 | } | |
46 | ||
47 | fn eval(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { | |
fb439f3c JM |
48 | //println!("eval: {}", ast); |
49 | match *ast { | |
bd306723 | 50 | List(_,_) => (), // continue |
fb439f3c | 51 | _ => return eval_ast(ast, env), |
0ab374bc JM |
52 | } |
53 | ||
54 | // apply list | |
fb439f3c JM |
55 | match *try!(eval_ast(ast, env)) { |
56 | List(ref args,_) => { | |
57 | let ref f = args.clone()[0]; | |
58 | f.apply(args[1..].to_vec()) | |
59 | }, | |
60 | _ => return err_str("Expected list"), | |
0ab374bc JM |
61 | } |
62 | } | |
63 | ||
64 | ||
65 | fn print(exp: MalVal) -> String { | |
66 | exp.pr_str(true) | |
67 | } | |
68 | ||
3744d566 | 69 | fn rep(str: &str, env: &HashMap<String,MalVal>) -> Result<String,MalError> { |
fb439f3c JM |
70 | let ast = try!(read(str.to_string())); |
71 | //println!("read: {}", ast); | |
72 | let exp = try!(eval(ast, env)); | |
73 | Ok(print(exp)) | |
0ab374bc JM |
74 | } |
75 | ||
bbeb1b87 AC |
76 | fn int_op<F>(f: F, a:Vec<MalVal>) -> MalRet |
77 | where F: FnOnce(isize, isize) -> isize | |
78 | { | |
0ab374bc JM |
79 | match *a[0] { |
80 | Int(a0) => match *a[1] { | |
4ee7c0f2 | 81 | Int(a1) => Ok(_int(f(a0,a1))), |
3744d566 | 82 | _ => err_str("second arg must be an int"), |
0ab374bc | 83 | }, |
3744d566 | 84 | _ => err_str("first arg must be an int"), |
0ab374bc JM |
85 | } |
86 | } | |
87 | fn add(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i+j }, a) } | |
88 | fn sub(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i-j }, a) } | |
89 | fn mul(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i*j }, a) } | |
90 | fn div(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) } | |
91 | ||
92 | fn main() { | |
93 | let mut repl_env : HashMap<String,MalVal> = HashMap::new(); | |
4ee7c0f2 JM |
94 | repl_env.insert("+".to_string(), func(add)); |
95 | repl_env.insert("-".to_string(), func(sub)); | |
96 | repl_env.insert("*".to_string(), func(mul)); | |
97 | repl_env.insert("/".to_string(), func(div)); | |
0ab374bc JM |
98 | |
99 | loop { | |
100 | let line = readline::mal_readline("user> "); | |
101 | match line { None => break, _ => () } | |
bbeb1b87 | 102 | match rep(&line.unwrap(), &repl_env) { |
0ab374bc | 103 | Ok(str) => println!("{}", str), |
3744d566 JM |
104 | Err(ErrMalVal(_)) => (), // Blank line |
105 | Err(ErrString(s)) => println!("Error: {}", s), | |
0ab374bc JM |
106 | } |
107 | } | |
108 | } |