1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
use std::collections::HashMap; use types::*; use types::RispType::*; use environment::*; use core::create_core_environment; pub fn eval(ast: RispType, env: &mut Environment) -> RispResult { match ast { List(list) => { let first_element = list.first().ok_or_else(|| error("Empty List"))?; match *first_element { Symbol(ref symbol) => { match symbol.as_ref() { "def" => { let var = list.get(1).ok_or_else(|| error("Missing variable in def"))?; match *var { Symbol(ref sym_var) => { let value_ast = list.get(2).ok_or_else(|| error("Missing value in def"))?; let value = eval(value_ast.clone(), env)?; env.set(sym_var, value.clone()); Ok(value) } _ => error_result(format!("Expected symbol in def but got {:?}", var)) } }, "do" => { if let Some((last, elements)) = (&list[1..]).split_last() { for child_ast in elements.iter() { eval(child_ast.clone(), env)?; } eval(last.clone(), env) } else { error_result("Empty do block") } } _ => { let evaluated_tail = list[1..].iter() .map(|el| eval(el.clone(), env)) .collect::<Result<Vec<_>, _>>()?; let env_value = env.get(symbol).ok_or_else(|| error(format!("Undefined symbol{:?}", symbol)))?; match env_value { Function(function) => function(evaluated_tail.to_vec()), _ => error_result(format!("Expected function but got {:?}", env_value)) } } } } _ => error_result(format!("Expected symbol but got {:?}", first_element)) } } Vector(vector) => { let evaluated_vector = vector.iter() .map(|el| eval(el.clone(), env)) .collect::<Result<Vec<_>, _>>()?; Ok(Vector(evaluated_vector)) } Map(map_value) => { let evaluated_map = map_value.iter() .map(|(key, val)| eval(val.clone(), env).map(|evaluated_value| (key.to_string(), evaluated_value))) .collect::<Result<HashMap<String, RispType>, _>>()?; Ok(Map(evaluated_map)) } Symbol(symbol) => { env.get(&symbol).ok_or_else(|| error(format!("symbol '{:?}' is undefined", symbol))) } other => Ok(other) } } #[allow(dead_code)] fn eval_test(ast: RispType) -> RispResult { eval(ast, &mut create_core_environment()) } #[test] fn test_eval_number() { assert_eq!(eval_test(Int(23)), Ok(Int(23))); } #[test] fn test_eval_math() { assert_eq!(eval_test(List(vec![Symbol("+".to_string()), Int(1), Int(2)])), Ok(Int(3))); } #[test] fn test_nested_math() { assert_eq!(eval_test(List(vec![ Symbol("+".to_string()), Int(1), List(vec![Symbol("+".to_string()), Int(10), Int(100)]) ])), Ok(Int(111))); } #[test] fn test_mul() { assert_eq!(eval_test(List(vec![ Symbol("+".to_string()), Int(1), List(vec![Symbol("*".to_string()), Int(10), Int(23)]) ])), Ok(Int(231))); } #[test] fn test_def() { let variable = "variable"; let variable_value = Int(23); let mut env = create_core_environment(); assert_eq!(eval(List(vec![ symbol("def"), symbol(variable), variable_value.clone() ]), &mut env), Ok(variable_value.clone())); assert_eq!(env.get(variable), Some(variable_value)); } #[test] fn test_def_evaluated() { let variable = "variable"; let mut env = create_core_environment(); assert_eq!(eval(List(vec![ symbol("def"), symbol(variable), List(vec![symbol("+"), Int(1), Int(2)]) ]), &mut env), Ok(Int(3))); assert_eq!(env.get(variable), Some(Int(3))); } #[test] fn test_eval_simple_vector() { let simple_vector = Vector(vec![Int(1), Int(2)]); assert_eq!(eval_test(simple_vector.clone()), Ok(simple_vector)); } #[test] fn test_eval_nested_vector() { let simple_vector = Vector(vec![Int(1), List(vec![symbol("+"), Int(1), Int(2)])]); assert_eq!(eval_test(simple_vector.clone()), Ok(Vector(vec![Int(1), Int(3)]))); } #[test] fn test_eval_simple_map() { let simple_map = map(vec![ ("key1", Int(1)), ("key2", Int(2)) ]); assert_eq!(eval_test(simple_map.clone()), Ok(simple_map)); } #[test] fn test_eval_nested_map() { let input_map = map(vec![ ("key", List(vec![symbol("+"), Int(1), Int(2)])) ]); let expected_output_map = map(vec![ ("key", Int(3)) ]); assert_eq!(eval_test(input_map.clone()), Ok(expected_output_map)); }