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