f9f79ea6853c7a89c3183150e2f9796821f3da3b
[jackhill/mal.git] / rust / src / step3_env.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,Int,Sym,List,Vector,Hash_Map,
10 _int,list,vector,hash_map,func};
11 use env::{Env,env_new,env_set,env_get};
12 mod readline;
13 mod types;
14 mod reader;
15 mod printer;
16 mod env;
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: Env) -> MalRet {
25 let ast2 = ast.clone();
26 match *ast2 {
27 //match *ast {
28 Sym(ref sym) => {
29 env_get(env.clone(), sym.clone())
30 },
31 List(ref a) | Vector(ref a) => {
32 let mut ast_vec : Vec<MalVal> = vec![];
33 for mv in a.iter() {
34 let mv2 = mv.clone();
35 match eval(mv2, env.clone()) {
36 Ok(mv) => { ast_vec.push(mv); },
37 Err(e) => { return Err(e); },
38 }
39 }
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.clone()) {
47 Ok(mv) => { new_hm.insert(key.to_string(), mv); },
48 Err(e) => return Err(e),
49 }
50 }
51 Ok(hash_map(new_hm))
52 },
53 _ => {
54 Ok(ast)
55 }
56 }
57 }
58
59 fn eval(ast: MalVal, env: Env) -> MalRet {
60 //println!("eval: {}, {}", ast, env.borrow());
61 //println!("eval: {}", ast);
62 let ast2 = ast.clone();
63 match *ast2 {
64 List(_) => (), // continue
65 _ => return eval_ast(ast2, env),
66 }
67
68 // apply list
69 match *ast2 {
70 List(ref args) => {
71 if args.len() == 0 {
72 return Ok(ast);
73 }
74 let ref a0 = *args[0];
75 match *a0 {
76 Sym(ref a0sym) => {
77 match a0sym.as_slice() {
78 "def!" => {
79 let a1 = (*args)[1].clone();
80 let a2 = (*args)[2].clone();
81 let res = eval(a2, env.clone());
82 match res {
83 Ok(r) => {
84 match *a1 {
85 Sym(ref s) => {
86 env_set(&env.clone(), s.clone(), r.clone());
87 return Ok(r);
88 },
89 _ => {
90 return Err("def! of non-symbol".to_string())
91 }
92 }
93 },
94 Err(e) => return Err(e),
95 }
96 },
97 "let*" => {
98 let let_env = env_new(Some(env.clone()));
99 let a1 = (*args)[1].clone();
100 let a2 = (*args)[2].clone();
101 match *a1 {
102 List(ref binds) | Vector(ref binds) => {
103 let mut it = binds.iter();
104 while it.len() >= 2 {
105 let b = it.next().unwrap();
106 let exp = it.next().unwrap();
107 match **b {
108 Sym(ref bstr) => {
109 match eval(exp.clone(), let_env.clone()) {
110 Ok(r) => {
111 env_set(&let_env, bstr.clone(), r);
112 },
113 Err(e) => {
114 return Err(e);
115 },
116 }
117 },
118 _ => {
119 return Err("let* with non-symbol binding".to_string());
120 },
121 }
122 }
123 },
124 _ => return Err("let* with non-list bindings".to_string()),
125 }
126 return eval(a2, let_env.clone());
127 },
128 _ => ()
129 }
130 }
131 _ => (),
132 }
133 // function call
134 return match eval_ast(ast, env) {
135 Err(e) => Err(e),
136 Ok(el) => {
137 match *el {
138 List(ref args) => {
139 let ref f = args.clone()[0];
140 f.apply(args.slice(1,args.len()).to_vec())
141 }
142 _ => Err("Invalid apply".to_string()),
143 }
144 }
145 }
146 }
147 _ => Err("Expected list".to_string()),
148 }
149 }
150
151 // print
152 fn print(exp: MalVal) -> String {
153 exp.pr_str(true)
154 }
155
156 fn rep(str: String, env: Env) -> Result<String,String> {
157 match read(str) {
158 Err(e) => Err(e),
159 Ok(ast) => {
160 //println!("read: {}", ast);
161 match eval(ast, env) {
162 Err(e) => Err(e),
163 Ok(exp) => Ok(print(exp)),
164 }
165 }
166 }
167 }
168
169 fn int_op(f: |i:int,j:int|-> int, a:Vec<MalVal>) -> MalRet {
170 match *a[0] {
171 Int(a0) => match *a[1] {
172 Int(a1) => Ok(_int(f(a0,a1))),
173 _ => Err("second arg must be an int".to_string()),
174 },
175 _ => Err("first arg must be an int".to_string()),
176 }
177 }
178 fn add(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i+j }, a) }
179 fn sub(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i-j }, a) }
180 fn mul(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i*j }, a) }
181 fn div(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) }
182
183 fn main() {
184 let repl_env = env_new(None);
185 env_set(&repl_env, "+".to_string(), func(add));
186 env_set(&repl_env, "-".to_string(), func(sub));
187 env_set(&repl_env, "*".to_string(), func(mul));
188 env_set(&repl_env, "/".to_string(), func(div));
189
190 loop {
191 let line = readline::mal_readline("user> ");
192 match line { None => break, _ => () }
193 match rep(line.unwrap(), repl_env.clone()) {
194 Ok(str) => println!("{}", str),
195 Err(str) => println!("Error: {}", str),
196 }
197 }
198 }