1use builtins::*;
21use data_structures::{Boolean, Commands, Env, Program, Sourcedata, Coredata, Macro, Function};
22use super::VEC_CAPACITY;
23use utilities::*;
24
25use num::BigInt;
26
27pub fn eval(mut program: Program, mut env: Env) -> Env {
52 macro_rules! ppush {
53 ($source:expr, $data:expr,) => { ppush![$source, $data] };
54 ($source:expr, $data:expr) => {
55 program.push(rc(Sourcedata($source.clone(), $data)))
56 };
57 }
58 while let Some(top) = program.pop() {
59 match *top {
60 Sourcedata(ref source, Coredata::Internal(Commands::Call(ref statement))) => {
62 match **statement {
63 Sourcedata(_, Coredata::Function(Function::Builtin(ref transfer, ..))) => {
64 let error = transfer(&mut program, &mut env);
65 env.params.pop();
66 err(source, &error, &mut program, &mut env);
67 }
68 Sourcedata(_,
69 Coredata::Function(Function::Library(ref parameters,
70 ref transfer))) => {
71 if let Some(arguments) = env.params.pop() {
72 if arguments.len() != parameters.len() {
73 err(
74 source,
75 &Some(format![
76 "expected {} but got {} arguments",
77 parameters.len(),
78 arguments.len(),
79 ]),
80 &mut program,
81 &mut env,
82 );
83 } else {
84 let cmd = Commands::Deparameterize(
85 optimize_tail_call(&mut program, &mut env, parameters),
86 );
87 ppush![source, Coredata::Internal(cmd)];
88 for (counter, parameter) in parameters.iter().enumerate() {
89 if env.store.contains_key(parameter) {
90 env.store.get_mut(parameter).unwrap().push(
91 arguments[counter]
92 .clone(),
93 );
94 } else {
95 env.store.insert(
96 parameter.clone(),
97 vec![arguments[counter].clone()],
98 );
99 }
100 }
101 program.extend(transfer.iter().cloned());
102 }
103 }
104 }
105 _ => {
106 err(
107 source,
108 &Some("element not callable".into()),
109 &mut program,
110 &mut env,
111 );
112 }
113 }
114 }
115 Sourcedata(_, Coredata::Internal(Commands::Deparameterize(ref arguments))) => {
116 pop_parameters(&mut program, &mut env, arguments);
117 }
118 Sourcedata(_, Coredata::Internal(Commands::Evaluate)) => {
119 program.push(env.result.clone());
120 }
121 Sourcedata(_, Coredata::Internal(Commands::If(ref first, ref second))) => {
122 if let Coredata::Boolean(Boolean::False) = env.result.1 {
123 program.push(second.clone());
124 } else {
125 program.push(first.clone());
126 }
127 }
128 Sourcedata(_, Coredata::Internal(Commands::Parameterize)) => {
129 let condition = if let Some(ref mut last) = env.params.last_mut() {
130 last.push(env.result.clone());
131 None
132 } else {
133 Some("parameter stack nonexistent".into())
134 };
135 err(&None, &condition, &mut program, &mut env);
136 }
137 Sourcedata(ref source, Coredata::Internal(Commands::Prepare(ref arguments))) => {
140 match *env.result.clone() {
141 Sourcedata(_, Coredata::Function(..)) => {
142 env.params.push(vec![]);
143 ppush![
144 source,
145 Coredata::Internal(Commands::Call(env.result.clone())),
146 ];
147 for argument in collect_pair_into_vec(arguments) {
148 ppush![None, Coredata::Internal(Commands::Parameterize)];
149 program.push(argument.clone());
150 }
151 }
152 Sourcedata(_, Coredata::Macro(Macro::Builtin(ref transfer, ..))) => {
153 env.result = arguments.clone();
154 let error = transfer(&mut program, &mut env);
155 err(source, &error, &mut program, &mut env);
156 }
157 Sourcedata(_, Coredata::Macro(Macro::Library(ref bound, ref code))) => {
158 ppush![None, Coredata::Internal(Commands::Evaluate)];
159 let command = optimize_tail_call(&mut program, &mut env, &[bound.clone()]);
160 if env.store.contains_key(bound) {
161 env.store.get_mut(bound).unwrap().push(arguments.clone());
162 } else {
163 env.store.insert(bound.clone(), vec![arguments.clone()]);
164 }
165 ppush![
166 source,
167 Coredata::Internal(Commands::Deparameterize(command)),
168 ];
169 program.extend(code.iter().cloned());
170 }
171 _ => {
172 err(
173 source,
174 &Some("element not callable".into()),
175 &mut program,
176 &mut env,
177 );
178 }
179 }
180 }
181 Sourcedata(_, Coredata::Internal(Commands::Wind)) => {}
182 Sourcedata(_, Coredata::Pair(ref head, ref tail)) => {
183 ppush![head.0, Coredata::Internal(Commands::Prepare(tail.clone()))];
184 program.push(head.clone());
185 }
186 Sourcedata(ref source, Coredata::Symbol(ref string)) => {
187 if let Some(number) = BigInt::parse_bytes(string.as_bytes(), 10) {
188 env.result = rc(Sourcedata(source.clone(), Coredata::Integer(number)));
189 } else {
190 let error = if let Some(value) = env.store.get(string) {
191 if let Some(value) = value.last() {
192 env.result = value.clone();
193 None
194 } else {
195 Some(format!["variable not found: {}", string])
196 }
197 } else {
198 Some(format!["variable not found: {}", string])
199 };
200 err(source, &error, &mut program, &mut env);
201 }
202 }
203 _ => {
204 env.result = top.clone();
205 }
206 }
207 }
208 env
209}
210
211pub fn initialize_environment_with_standard_library() -> Env {
219 Env {
220 store: create_builtin_library_table(),
221 params: Vec::with_capacity(VEC_CAPACITY),
222 result: rc(Sourcedata(None, Coredata::Null)),
223 }
224}
225
226pub fn interpret(program: Program) -> Env {
248 let env = initialize_environment_with_standard_library();
249 eval(program, env)
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255 use parse::parse_file;
256 #[test]
257 fn test_interpreter() {
258 let p = parse_file("examples/basic.tko").ok().unwrap();
259 interpret(p);
260 }
261}