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