Commit | Line | Data |
---|---|---|
0ab374bc JM |
1 | // support precompiled regexes in reader.rs |
2 | #![feature(phase)] | |
3 | #[phase(plugin)] | |
4 | extern crate regex_macros; | |
5 | extern crate regex; | |
6 | ||
0ab374bc | 7 | use std::collections::HashMap; |
8f5b0f10 | 8 | |
3744d566 JM |
9 | use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, |
10 | Int,Sym,List,Vector,Hash_Map, | |
5939404b | 11 | _nil,_int,list,vector,hash_map,func}; |
0ab374bc JM |
12 | mod readline; |
13 | mod types; | |
14 | mod reader; | |
15 | mod printer; | |
3744d566 | 16 | mod env; // because types uses env |
0ab374bc JM |
17 | |
18 | // read | |
19 | fn read(str: String) -> MalRet { | |
20 | reader::read_str(str) | |
21 | } | |
22 | ||
23 | // eval | |
24 | fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { | |
25 | match *ast { | |
26 | Sym(ref sym) => { | |
8f5b0f10 | 27 | match env.find_copy(sym) { |
0ab374bc | 28 | Some(mv) => Ok(mv), |
4ee7c0f2 | 29 | None => Ok(_nil()), |
0ab374bc JM |
30 | } |
31 | }, | |
5939404b | 32 | List(ref a) | Vector(ref a) => { |
0ab374bc JM |
33 | let mut ast_vec : Vec<MalVal> = vec![]; |
34 | for mv in a.iter() { | |
5939404b JM |
35 | match eval(mv.clone(), env) { |
36 | Ok(mv) => ast_vec.push(mv), | |
37 | Err(e) => return Err(e), | |
0ab374bc JM |
38 | } |
39 | } | |
5939404b JM |
40 | Ok(match *ast { List(_) => list(ast_vec), |
41 | _ => vector(ast_vec) }) | |
42 | }, | |
43 | Hash_Map(ref hm) => { | |
44 | let mut new_hm: HashMap<String,MalVal> = HashMap::new(); | |
45 | for (key, value) in hm.iter() { | |
46 | match eval(value.clone(), env) { | |
47 | Ok(mv) => { new_hm.insert(key.to_string(), mv); }, | |
48 | Err(e) => return Err(e), | |
49 | } | |
50 | } | |
51 | Ok(hash_map(new_hm)) | |
0ab374bc JM |
52 | }, |
53 | _ => { | |
54 | Ok(ast.clone()) | |
55 | } | |
56 | } | |
57 | } | |
58 | ||
59 | fn eval(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { | |
60 | let ast2 = ast.clone(); | |
61 | match *ast2 { | |
62 | List(_) => (), // continue | |
63 | _ => return eval_ast(ast2, env), | |
64 | } | |
65 | ||
66 | // apply list | |
67 | match eval_ast(ast, env) { | |
68 | Err(e) => Err(e), | |
69 | Ok(el) => { | |
70 | match *el { | |
71 | List(ref args) => { | |
a77e2b31 JM |
72 | let ref f = args.clone()[0]; |
73 | f.apply(args.slice(1,args.len()).to_vec()) | |
0ab374bc | 74 | } |
3744d566 | 75 | _ => err_str("Invalid apply"), |
0ab374bc JM |
76 | } |
77 | } | |
78 | } | |
79 | } | |
80 | ||
81 | ||
82 | fn print(exp: MalVal) -> String { | |
83 | exp.pr_str(true) | |
84 | } | |
85 | ||
3744d566 JM |
86 | fn rep(str: &str, env: &HashMap<String,MalVal>) -> Result<String,MalError> { |
87 | match read(str.to_string()) { | |
0ab374bc JM |
88 | Err(e) => Err(e), |
89 | Ok(ast) => { | |
90 | //println!("read: {}", ast); | |
91 | match eval(ast, env) { | |
92 | Err(e) => Err(e), | |
93 | Ok(exp) => Ok(print(exp)), | |
94 | } | |
95 | } | |
96 | } | |
97 | } | |
98 | ||
99 | fn int_op(f: |i:int,j:int|-> int, a:Vec<MalVal>) -> MalRet { | |
100 | match *a[0] { | |
101 | Int(a0) => match *a[1] { | |
4ee7c0f2 | 102 | Int(a1) => Ok(_int(f(a0,a1))), |
3744d566 | 103 | _ => err_str("second arg must be an int"), |
0ab374bc | 104 | }, |
3744d566 | 105 | _ => err_str("first arg must be an int"), |
0ab374bc JM |
106 | } |
107 | } | |
108 | fn add(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i+j }, a) } | |
109 | fn sub(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i-j }, a) } | |
110 | fn mul(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i*j }, a) } | |
111 | fn div(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) } | |
112 | ||
113 | fn main() { | |
114 | let mut repl_env : HashMap<String,MalVal> = HashMap::new(); | |
4ee7c0f2 JM |
115 | repl_env.insert("+".to_string(), func(add)); |
116 | repl_env.insert("-".to_string(), func(sub)); | |
117 | repl_env.insert("*".to_string(), func(mul)); | |
118 | repl_env.insert("/".to_string(), func(div)); | |
0ab374bc JM |
119 | |
120 | loop { | |
121 | let line = readline::mal_readline("user> "); | |
122 | match line { None => break, _ => () } | |
3744d566 | 123 | match rep(line.unwrap().as_slice(), &repl_env) { |
0ab374bc | 124 | Ok(str) => println!("{}", str), |
3744d566 JM |
125 | Err(ErrMalVal(_)) => (), // Blank line |
126 | Err(ErrString(s)) => println!("Error: {}", s), | |
0ab374bc JM |
127 | } |
128 | } | |
129 | } |