9c826c77b481100b57e365789c85696f8d4252ef
[jackhill/mal.git] / rust / src / step5_tco.rs
1 // support precompiled regexes in reader.rs
2 #![feature(phase)]
3 #[phase(plugin)]
4 extern crate regex_macros;
5 extern crate regex;
6
7 use std::collections::HashMap;
8
9 use types::{MalVal,MalRet,MalFunc,Nil,False,Sym,List,Vector,Hash_Map,Func,
10 _nil,list,vector,hash_map,malfunc};
11 use env::{Env,env_new,env_bind,env_set,env_get};
12 mod readline;
13 mod types;
14 mod reader;
15 mod printer;
16 mod env;
17 mod core;
18
19 // read
20 fn read(str: String) -> MalRet {
21 reader::read_str(str)
22 }
23
24 // eval
25 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
26 let ast2 = ast.clone();
27 match *ast2 {
28 //match *ast {
29 Sym(ref sym) => {
30 env_get(env.clone(), sym.clone())
31 },
32 List(ref a) | Vector(ref a) => {
33 let mut ast_vec : Vec<MalVal> = vec![];
34 for mv in a.iter() {
35 let mv2 = mv.clone();
36 match eval(mv2, env.clone()) {
37 Ok(mv) => { ast_vec.push(mv); },
38 Err(e) => { return Err(e); },
39 }
40 }
41 Ok(match *ast { List(_) => list(ast_vec),
42 _ => vector(ast_vec) })
43 },
44 Hash_Map(ref hm) => {
45 let mut new_hm: HashMap<String,MalVal> = HashMap::new();
46 for (key, value) in hm.iter() {
47 match eval(value.clone(), env.clone()) {
48 Ok(mv) => { new_hm.insert(key.to_string(), mv); },
49 Err(e) => return Err(e),
50 }
51 }
52 Ok(hash_map(new_hm))
53 },
54 _ => {
55 Ok(ast)
56 }
57 }
58 }
59
60 fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
61 'tco: loop {
62
63 //println!("eval: {}, {}", ast, env.borrow());
64 //println!("eval: {}", ast);
65 let ast2 = ast.clone();
66 match *ast2 {
67 List(_) => (), // continue
68 _ => return eval_ast(ast2, env),
69 }
70
71 // apply list
72 let ast3 = ast2.clone();
73 match *ast2 {
74 List(ref args) => {
75 if args.len() == 0 {
76 return Ok(ast3);
77 }
78 let ref a0 = *args[0];
79 match *a0 {
80 Sym(ref a0sym) => {
81 match a0sym.as_slice() {
82 "def!" => {
83 let a1 = (*args)[1].clone();
84 let a2 = (*args)[2].clone();
85 let res = eval(a2, env.clone());
86 match res {
87 Ok(r) => {
88 match *a1 {
89 Sym(ref s) => {
90 env_set(&env.clone(), s.clone(), r.clone());
91 return Ok(r);
92 },
93 _ => {
94 return Err("def! of non-symbol".to_string())
95 }
96 }
97 },
98 Err(e) => return Err(e),
99 }
100 },
101 "let*" => {
102 let let_env = env_new(Some(env.clone()));
103 let a1 = (*args)[1].clone();
104 let a2 = (*args)[2].clone();
105 match *a1 {
106 List(ref binds) | Vector(ref binds) => {
107 let mut it = binds.iter();
108 while it.len() >= 2 {
109 let b = it.next().unwrap();
110 let exp = it.next().unwrap();
111 match **b {
112 Sym(ref bstr) => {
113 match eval(exp.clone(), let_env.clone()) {
114 Ok(r) => {
115 env_set(&let_env, bstr.clone(), r);
116 },
117 Err(e) => {
118 return Err(e);
119 },
120 }
121 },
122 _ => {
123 return Err("let* with non-symbol binding".to_string());
124 },
125 }
126 }
127 },
128 _ => return Err("let* with non-list bindings".to_string()),
129 }
130 ast = a2;
131 env = let_env.clone();
132 continue 'tco;
133 },
134 "do" => {
135 let el = list(args.slice(1,args.len()-1).to_vec());
136 match eval_ast(el, env.clone()) {
137 Err(e) => return Err(e),
138 Ok(_) => {
139 let ref last = args[args.len()-1];
140 ast = last.clone();
141 continue 'tco;
142 },
143 }
144 },
145 "if" => {
146 let a1 = (*args)[1].clone();
147 let cond = eval(a1, env.clone());
148 if cond.is_err() { return cond; }
149 match *cond.unwrap() {
150 False | Nil => {
151 if args.len() >= 4 {
152 let a3 = (*args)[3].clone();
153 ast = a3;
154 env = env.clone();
155 continue 'tco;
156 } else {
157 return Ok(_nil());
158 }
159 },
160 _ => {
161 let a2 = (*args)[2].clone();
162 ast = a2;
163 env = env.clone();
164 continue 'tco;
165 },
166 }
167 },
168 "fn*" => {
169 let a1 = (*args)[1].clone();
170 let a2 = (*args)[2].clone();
171 return Ok(malfunc(eval, a2, env.clone(), a1));
172 },
173 _ => ()
174 }
175 }
176 _ => (),
177 }
178 // function call
179 return match eval_ast(ast3, env.clone()) {
180 Err(e) => Err(e),
181 Ok(el) => {
182 match *el {
183 List(ref args) => {
184 let args2 = args.clone();
185 match *args2[0] {
186 Func(f) => f(args.slice(1,args.len()).to_vec()),
187 MalFunc(ref mf) => {
188 let mfc = mf.clone();
189 let alst = list(args.slice(1,args.len()).to_vec());
190 let new_env = env_new(Some(mfc.env.clone()));
191 match env_bind(&new_env, mfc.params, alst) {
192 Ok(_) => {
193 ast = mfc.exp;
194 env = new_env;
195 continue 'tco;
196 },
197 Err(e) => Err(e),
198 }
199 },
200 _ => Err("attempt to call non-function".to_string()),
201 }
202 }
203 _ => Err("Invalid apply".to_string()),
204 }
205 }
206 }
207 }
208 _ => return Err("Expected list".to_string()),
209 }
210
211 }
212 }
213
214 // print
215 fn print(exp: MalVal) -> String {
216 exp.pr_str(true)
217 }
218
219 fn rep(str: String, env: Env) -> Result<String,String> {
220 match read(str) {
221 Err(e) => Err(e),
222 Ok(ast) => {
223 //println!("read: {}", ast);
224 match eval(ast, env) {
225 Err(e) => Err(e),
226 Ok(exp) => Ok(print(exp)),
227 }
228 }
229 }
230 }
231
232 fn main() {
233 // core.rs: defined using rust
234 let repl_env = env_new(None);
235 for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
236
237 // core.mal: defined using the language itself
238 let _ = rep("(def! not (fn* (a) (if a false true)))".to_string(),
239 repl_env.clone());
240
241 loop {
242 let line = readline::mal_readline("user> ");
243 match line { None => break, _ => () }
244 match rep(line.unwrap(), repl_env.clone()) {
245 Ok(str) => println!("{}", str),
246 Err(str) => println!("Error: {}", str),
247 }
248 }
249 }