1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::rc::Rc;
4
5use object::builtins::*;
6use object::environment::*;
7use object::{BoundMethodObject, ClassObject, EvalError, InstanceObject, InstanceRef, Object};
8use parser::ast::*;
9use parser::lexer::token::{Token, TokenKind};
10use parser::validation::validate_program;
11
12mod interpreter_test;
13
14pub fn eval(node: Node, env: &Env) -> Result<Rc<Object>, EvalError> {
15 match node {
16 Node::Program(p) => {
17 let mut predefined_names = env.borrow().visible_names();
18 predefined_names.extend(BuiltIns.iter().map(|builtin| builtin.name.to_string()));
19 let predefined_names = predefined_names
20 .iter()
21 .map(String::as_str)
22 .collect::<Vec<_>>();
23 validate_program(&p, &predefined_names).map_err(|error| error.message)?;
24 eval_block_statements(&p.body, env)
25 }
26 Node::Statement(statements) => eval_statement(&statements, env),
27 Node::Expression(expression) => eval_expression(&expression, env),
28 }
29}
30
31fn eval_block_statements(statements: &Vec<Statement>, env: &Env) -> Result<Rc<Object>, EvalError> {
32 let mut result = Rc::new(Object::Null);
33 for statement in statements {
34 let val = eval_statement(statement, &Rc::clone(env))?;
35 match *val {
36 Object::ReturnValue(_) => return Ok(val),
37 _ => {
38 result = val;
39 }
40 }
41 }
42
43 return Ok(result);
44}
45
46fn eval_statement(statement: &Statement, env: &Env) -> Result<Rc<Object>, EvalError> {
47 match statement {
48 Statement::Expr(expr) => eval_expression(expr, env),
49 Statement::Return(ReturnStatement {
50 argument,
51 ..
52 }) => {
53 let val = eval_expression(argument, env)?;
54 return Ok(Rc::new(Object::ReturnValue(val)));
55 }
56 Statement::Let(Let {
57 identifier: id,
58 expr,
59 ..
60 }) => {
61 let val = eval_expression(expr, &Rc::clone(env))?;
62 let obj: Rc<Object> = Rc::clone(&val);
63 if let TokenKind::IDENTIFIER {
64 name,
65 } = &id.kind
66 {
67 env.borrow_mut().set(name.clone(), obj);
68 }
69 return Ok(Rc::new(Object::Null));
70 }
71 Statement::Class(class) => eval_class_declaration(class, env),
72 Statement::SetProperty(statement) => {
73 let receiver = eval_expression(&statement.object, env)?;
74 let value = eval_expression(&statement.value, env)?;
75 set_property(&receiver, statement.property.name.clone(), value)?;
76 Ok(Rc::new(Object::Null))
77 }
78 }
79}
80
81fn eval_class_declaration(
82 declaration: &ClassDeclaration,
83 env: &Env,
84) -> Result<Rc<Object>, EvalError> {
85 let mut constructor = None;
86 let mut methods = HashMap::new();
87 for method in &declaration.methods {
88 let function =
89 Rc::new(Object::Function(method.params.clone(), method.body.clone(), Rc::clone(env)));
90 match method.kind {
91 MethodKind::Constructor => constructor = Some(function),
92 MethodKind::Method => {
93 methods.insert(method.name.name.clone(), function);
94 }
95 }
96 }
97
98 let class = Rc::new(RefCell::new(ClassObject {
99 name: declaration.name.name.clone(),
100 constructor,
101 methods,
102 }));
103 env.borrow_mut()
104 .set(declaration.name.name.clone(), Rc::new(Object::Class(class)));
105 Ok(Rc::new(Object::Null))
106}
107
108fn is_truthy(obj: &Object) -> bool {
109 match obj {
110 Object::Null => return false,
111 Object::Boolean(false) => return false,
112 _ => true,
113 }
114}
115
116fn eval_expression(expression: &Expression, env: &Env) -> Result<Rc<Object>, EvalError> {
117 match expression {
118 Expression::LITERAL(literal) => eval_literal(literal, env),
119 Expression::PREFIX(UnaryExpression {
120 op,
121 operand: expr,
122 ..
123 }) => {
124 let right = eval_expression(expr, &Rc::clone(env))?;
125 return eval_prefix(op, &right);
126 }
127 Expression::INFIX(BinaryExpression {
128 op,
129 left,
130 right,
131 ..
132 }) => {
133 let left = eval_expression(left, &Rc::clone(env))?;
134 let right = eval_expression(right, &Rc::clone(env))?;
135 return eval_infix(op, &left, &right);
136 }
137 Expression::IF(IF {
138 condition,
139 consequent,
140 alternate,
141 ..
142 }) => {
143 let condition = eval_expression(condition, &Rc::clone(env))?;
144 if is_truthy(&condition) {
145 eval_block_statements(&(consequent.body), env)
146 } else {
147 match alternate {
148 Some(alt) => eval_block_statements(&(alt.body), env),
149 None => Ok(Rc::new(Object::Null)),
150 }
151 }
152 }
153 Expression::IDENTIFIER(IDENTIFIER {
154 name: id,
155 ..
156 }) => eval_identifier(id, env),
157 Expression::FUNCTION(FunctionDeclaration {
158 params,
159 body,
160 ..
161 }) => {
162 return Ok(Rc::new(Object::Function(params.clone(), body.clone(), Rc::clone(env))));
163 }
164 Expression::FunctionCall(FunctionCall {
165 callee,
166 arguments,
167 ..
168 }) => {
169 let func = eval_expression(callee, &Rc::clone(env))?;
170 let args = eval_expressions(arguments, env)?;
171 apply_function(&func, &args)
172 }
173 Expression::Index(Index {
174 object: left,
175 index,
176 ..
177 }) => {
178 let literal = eval_expression(left, &Rc::clone(env))?;
179 let index = eval_expression(index, env)?;
180 eval_index_expression(&literal, &index)
181 }
182 Expression::This(_) => eval_identifier("this", env),
183 Expression::Property(property) => {
184 let receiver = eval_expression(&property.object, env)?;
185 get_property(&receiver, &property.property.name)
186 }
187 Expression::New(new_expression) => {
188 let class = eval_identifier(&new_expression.callee.name, env)?;
189 let arguments = eval_expressions(&new_expression.arguments, env)?;
190 construct_instance(&class, &arguments)
191 }
192 }
193}
194
195fn get_property(receiver: &Rc<Object>, name: &str) -> Result<Rc<Object>, EvalError> {
196 let Object::Instance(instance) = &**receiver else {
197 return Err(format!("cannot read property '{}' of {}", name, receiver));
198 };
199
200 if let Some(value) = instance.borrow().fields.get(name).cloned() {
201 return Ok(value);
202 }
203
204 let (class_name, method) = {
205 let instance = instance.borrow();
206 let class = instance.class.borrow();
207 (class.name.clone(), class.methods.get(name).cloned())
208 };
209 if let Some(method) = method {
210 return Ok(Rc::new(Object::BoundMethod(Rc::new(BoundMethodObject {
211 receiver: Rc::clone(instance),
212 method,
213 name: name.to_string(),
214 }))));
215 }
216
217 Err(format!("property '{}' does not exist on {}", name, class_name))
218}
219
220fn set_property(receiver: &Rc<Object>, name: String, value: Rc<Object>) -> Result<(), EvalError> {
221 let Object::Instance(instance) = &**receiver else {
222 return Err(format!("cannot set property '{}' of {}", name, receiver));
223 };
224 instance.borrow_mut().fields.insert(name, value);
225 Ok(())
226}
227
228fn construct_instance(
229 class_value: &Rc<Object>,
230 args: &[Rc<Object>],
231) -> Result<Rc<Object>, EvalError> {
232 let Object::Class(class) = &**class_value else {
233 return Err(format!("cannot construct {}", class_value));
234 };
235 let instance = Rc::new(RefCell::new(InstanceObject {
236 class: Rc::clone(class),
237 fields: HashMap::new(),
238 }));
239 let instance_value = Rc::new(Object::Instance(Rc::clone(&instance)));
240 let constructor = class.borrow().constructor.clone();
241 if let Some(constructor) = constructor {
242 apply_method(
243 &constructor,
244 &instance,
245 args,
246 &format!("{}.constructor", class.borrow().name),
247 )?;
248 } else if !args.is_empty() {
249 return Err(format!(
250 "wrong number of arguments for {}.constructor: want=0, got={}",
251 class.borrow().name,
252 args.len()
253 ));
254 }
255 Ok(instance_value)
256}
257
258fn eval_index_expression(left: &Rc<Object>, index: &Rc<Object>) -> Result<Rc<Object>, EvalError> {
259 match (&**left, &**index) {
260 (Object::Array(arr), Object::Integer(idx)) => match arr.get(*idx as usize) {
261 Some(obj) => return Ok(Rc::clone(obj)),
262 None => return Ok(Rc::new(Object::Null)),
263 },
264 (Object::Hash(map), key) => {
265 if !(key.is_hashable()) {
266 return Err("not a valid hash key".to_string());
267 }
268
269 match map.get(key) {
270 Some(obj) => return Ok(Rc::clone(obj)),
271 None => return Ok(Rc::new(Object::Null)),
272 }
273 }
274 _ => return Err(format!("index operator not supported for {}", left)),
275 }
276}
277
278fn apply_function(function: &Rc<Object>, args: &[Rc<Object>]) -> Result<Rc<Object>, EvalError> {
279 match &**function {
280 Object::Function(params, body, env) => {
281 if params.len() != args.len() {
282 return Err(format!(
283 "wrong number of arguments: want={}, got={}",
284 params.len(),
285 args.len()
286 ));
287 }
288 let mut env = Environment::new_enclosed_environment(env);
289
290 params.iter().enumerate().for_each(|(i, param)| {
291 env.set(param.name.clone(), args[i].clone());
292 });
293
294 let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(env)))?;
295 return unwrap_return(evaluated);
296 }
297 Object::Builtin(b) => {
298 let result = b(args.to_vec());
299 match &*result {
303 Object::Error(message) => Err(message.clone()),
304 _ => Ok(result),
305 }
306 }
307 Object::BoundMethod(bound) => {
308 apply_method(&bound.method, &bound.receiver, args, &bound.name)
309 }
310 Object::Class(class) => {
311 Err(format!("class {} must be constructed with new", class.borrow().name))
312 }
313 f => Err(format!("expected {} to be a function", f)),
314 }
315}
316
317fn apply_method(
318 method: &Rc<Object>,
319 receiver: &InstanceRef,
320 args: &[Rc<Object>],
321 display_name: &str,
322) -> Result<Rc<Object>, EvalError> {
323 let Object::Function(params, body, declaration_env) = &**method else {
324 return Err(format!("{} is not a method", display_name));
325 };
326 if params.len() != args.len() {
327 return Err(format!(
328 "wrong number of arguments for {}: want={}, got={}",
329 display_name,
330 params.len(),
331 args.len()
332 ));
333 }
334
335 let mut call_env = Environment::new_enclosed_environment(declaration_env);
336 call_env.set("this".to_string(), Rc::new(Object::Instance(Rc::clone(receiver))));
337 for (parameter, argument) in params.iter().zip(args) {
338 call_env.set(parameter.name.clone(), Rc::clone(argument));
339 }
340 let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(call_env)))?;
341 unwrap_return(evaluated)
342}
343
344fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
345 if let Object::ReturnValue(val) = &*obj {
346 Ok(Rc::clone(val))
347 } else {
348 Ok(obj)
349 }
350}
351
352fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
353 let mut list = Vec::new();
354 for expr in exprs {
355 let val = eval_expression(expr, &Rc::clone(env))?;
356 list.push(val);
357 }
358
359 Ok(list)
360}
361
362fn eval_identifier(identifier: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
363 match env.borrow().get(identifier) {
364 Some(obj) => Ok(obj.clone()),
365 None => match BuiltIns.iter().find(|builtin| builtin.name == identifier) {
366 Some(obj) => Ok(Rc::new(Object::Builtin(obj.function))),
367 None => Err(format!("unknown identifier {}", identifier)),
368 },
369 }
370}
371
372fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
373 match op.kind {
374 TokenKind::BANG => eval_prefix_bang(right),
375 TokenKind::MINUS => eval_prefix_minus(right),
376 _ => Err(format!("unknown prefix operator: {}", op)),
377 }
378}
379
380fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
381 match *expr {
382 Object::Null => Ok(Rc::new(Object::Boolean(true))),
383 Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
384 _ => Ok(Rc::new(Object::Boolean(false))),
385 }
386}
387
388fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
389 match *expr {
390 Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
391 _ => Err(format!("can't apply prefix minus operator: {}", expr)),
392 }
393}
394
395fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
396 if op.kind == TokenKind::EQ || op.kind == TokenKind::NotEq {
397 let equal = left == right;
398 return Ok(Rc::new(Object::Boolean(if op.kind == TokenKind::EQ { equal } else { !equal })));
399 }
400 match (left, right) {
401 (Object::Integer(left), Object::Integer(right)) => {
402 return eval_integer_infix(op, *left, *right);
403 }
404 (Object::Boolean(left), Object::Boolean(right)) => {
405 return eval_boolean_infix(op, *left, *right);
406 }
407 (Object::String(left), Object::String(right)) => {
408 return eval_string_infix(op, left.to_string(), right.to_string());
409 }
410 _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right)),
411 }
412}
413
414fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
415 let result = match &op.kind {
416 TokenKind::PLUS => Object::Integer(left + right),
417 TokenKind::MINUS => Object::Integer(left - right),
418 TokenKind::ASTERISK => Object::Integer(left * right),
419 TokenKind::SLASH => Object::Integer(left / right),
420 TokenKind::LT => Object::Boolean(left < right),
421 TokenKind::GT => Object::Boolean(left > right),
422 TokenKind::EQ => Object::Boolean(left == right),
423 TokenKind::NotEq => Object::Boolean(left != right),
424 op => return Err(format!("Invalid infix operator {} for int", op)),
425 };
426
427 Ok(Rc::from(result))
428}
429
430fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
431 let result = match &op.kind {
432 TokenKind::EQ => Object::Boolean(left == right),
433 TokenKind::NotEq => Object::Boolean(left != right),
434 op => return Err(format!("Invalid infix operator for boolean: {}", op)),
435 };
436
437 Ok(Rc::from(result))
438}
439
440fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
441 let result = match &op.kind {
442 TokenKind::EQ => Object::Boolean(left == right),
443 TokenKind::NotEq => Object::Boolean(left != right),
444 TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
445 op => return Err(format!("Invalid infix {} operator for string", op)),
446 };
447
448 Ok(Rc::from(result))
449}
450
451fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
452 match literal {
453 Literal::Integer(Integer {
454 raw: i,
455 ..
456 }) => Ok(Rc::from(Object::Integer(*i))),
457 Literal::Boolean(Boolean {
458 raw: b,
459 ..
460 }) => Ok(Rc::from(Object::Boolean(*b))),
461 Literal::String(StringType {
462 raw: s,
463 ..
464 }) => Ok(Rc::from(Object::String(s.clone()))),
465 Literal::Array(Array {
466 elements,
467 ..
468 }) => {
469 let list = eval_expressions(elements, env)?;
470 return Ok(Rc::from(Object::Array(list)));
471 }
472 Literal::Hash(Hash {
473 elements: map,
474 ..
475 }) => {
476 #[allow(clippy::mutable_key_type)]
479 let mut hash_map = HashMap::new();
480
481 for (k, v) in map {
482 let key = eval_expression(k, env)?;
483 if !key.is_hashable() {
484 return Err(format!("key {} is not hashable", key));
485 }
486 let value = eval_expression(v, env)?;
487 hash_map.insert(key, value);
488 }
489
490 return Ok(Rc::new(Object::Hash(hash_map)));
491 } }
493}