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) => Ok(b(args.to_vec())),
298 Object::BoundMethod(bound) => {
299 apply_method(&bound.method, &bound.receiver, args, &bound.name)
300 }
301 Object::Class(class) => {
302 Err(format!("class {} must be constructed with new", class.borrow().name))
303 }
304 f => Err(format!("expected {} to be a function", f)),
305 }
306}
307
308fn apply_method(
309 method: &Rc<Object>,
310 receiver: &InstanceRef,
311 args: &[Rc<Object>],
312 display_name: &str,
313) -> Result<Rc<Object>, EvalError> {
314 let Object::Function(params, body, declaration_env) = &**method else {
315 return Err(format!("{} is not a method", display_name));
316 };
317 if params.len() != args.len() {
318 return Err(format!(
319 "wrong number of arguments for {}: want={}, got={}",
320 display_name,
321 params.len(),
322 args.len()
323 ));
324 }
325
326 let mut call_env = Environment::new_enclosed_environment(declaration_env);
327 call_env.set("this".to_string(), Rc::new(Object::Instance(Rc::clone(receiver))));
328 for (parameter, argument) in params.iter().zip(args) {
329 call_env.set(parameter.name.clone(), Rc::clone(argument));
330 }
331 let evaluated = eval_block_statements(&body.body, &Rc::new(RefCell::new(call_env)))?;
332 unwrap_return(evaluated)
333}
334
335fn unwrap_return(obj: Rc<Object>) -> Result<Rc<Object>, EvalError> {
336 if let Object::ReturnValue(val) = &*obj {
337 Ok(Rc::clone(val))
338 } else {
339 Ok(obj)
340 }
341}
342
343fn eval_expressions(exprs: &Vec<Expression>, env: &Env) -> Result<Vec<Rc<Object>>, EvalError> {
344 let mut list = Vec::new();
345 for expr in exprs {
346 let val = eval_expression(expr, &Rc::clone(env))?;
347 list.push(val);
348 }
349
350 Ok(list)
351}
352
353fn eval_identifier(identifier: &str, env: &Env) -> Result<Rc<Object>, EvalError> {
354 match env.borrow().get(identifier) {
355 Some(obj) => Ok(obj.clone()),
356 None => match BuiltIns.iter().find(|builtin| builtin.name == identifier) {
357 Some(obj) => Ok(Rc::new(Object::Builtin(obj.function))),
358 None => Err(format!("unknown identifier {}", identifier)),
359 },
360 }
361}
362
363fn eval_prefix(op: &Token, right: &Object) -> Result<Rc<Object>, EvalError> {
364 match op.kind {
365 TokenKind::BANG => eval_prefix_bang(right),
366 TokenKind::MINUS => eval_prefix_minus(right),
367 _ => Err(format!("unknown prefix operator: {}", op)),
368 }
369}
370
371fn eval_prefix_bang(expr: &Object) -> Result<Rc<Object>, EvalError> {
372 match *expr {
373 Object::Null => Ok(Rc::new(Object::Boolean(true))),
374 Object::Boolean(b) => Ok(Rc::new(Object::Boolean(!b))),
375 _ => Ok(Rc::new(Object::Boolean(false))),
376 }
377}
378
379fn eval_prefix_minus(expr: &Object) -> Result<Rc<Object>, EvalError> {
380 match *expr {
381 Object::Integer(i) => Ok(Rc::from(Object::Integer(-i))),
382 _ => Err(format!("can't apply prefix minus operator: {}", expr)),
383 }
384}
385
386fn eval_infix(op: &Token, left: &Object, right: &Object) -> Result<Rc<Object>, EvalError> {
387 if op.kind == TokenKind::EQ || op.kind == TokenKind::NotEq {
388 let equal = left == right;
389 return Ok(Rc::new(Object::Boolean(if op.kind == TokenKind::EQ { equal } else { !equal })));
390 }
391 match (left, right) {
392 (Object::Integer(left), Object::Integer(right)) => {
393 return eval_integer_infix(op, *left, *right);
394 }
395 (Object::Boolean(left), Object::Boolean(right)) => {
396 return eval_boolean_infix(op, *left, *right);
397 }
398 (Object::String(left), Object::String(right)) => {
399 return eval_string_infix(op, left.to_string(), right.to_string());
400 }
401 _ => Err(format!("eval infix error for op: {}, left: {}, right: {}", op, left, right)),
402 }
403}
404
405fn eval_integer_infix(op: &Token, left: i64, right: i64) -> Result<Rc<Object>, EvalError> {
406 let result = match &op.kind {
407 TokenKind::PLUS => Object::Integer(left + right),
408 TokenKind::MINUS => Object::Integer(left - right),
409 TokenKind::ASTERISK => Object::Integer(left * right),
410 TokenKind::SLASH => Object::Integer(left / right),
411 TokenKind::LT => Object::Boolean(left < right),
412 TokenKind::GT => Object::Boolean(left > right),
413 TokenKind::EQ => Object::Boolean(left == right),
414 TokenKind::NotEq => Object::Boolean(left != right),
415 op => return Err(format!("Invalid infix operator {} for int", op)),
416 };
417
418 Ok(Rc::from(result))
419}
420
421fn eval_boolean_infix(op: &Token, left: bool, right: bool) -> Result<Rc<Object>, EvalError> {
422 let result = match &op.kind {
423 TokenKind::EQ => Object::Boolean(left == right),
424 TokenKind::NotEq => Object::Boolean(left != right),
425 op => return Err(format!("Invalid infix operator for boolean: {}", op)),
426 };
427
428 Ok(Rc::from(result))
429}
430
431fn eval_string_infix(op: &Token, left: String, right: String) -> Result<Rc<Object>, EvalError> {
432 let result = match &op.kind {
433 TokenKind::EQ => Object::Boolean(left == right),
434 TokenKind::NotEq => Object::Boolean(left != right),
435 TokenKind::PLUS => Object::String(format!("{}{}", left, right)),
436 op => return Err(format!("Invalid infix {} operator for string", op)),
437 };
438
439 Ok(Rc::from(result))
440}
441
442fn eval_literal(literal: &Literal, env: &Env) -> Result<Rc<Object>, EvalError> {
443 match literal {
444 Literal::Integer(Integer {
445 raw: i,
446 ..
447 }) => Ok(Rc::from(Object::Integer(*i))),
448 Literal::Boolean(Boolean {
449 raw: b,
450 ..
451 }) => Ok(Rc::from(Object::Boolean(*b))),
452 Literal::String(StringType {
453 raw: s,
454 ..
455 }) => Ok(Rc::from(Object::String(s.clone()))),
456 Literal::Array(Array {
457 elements,
458 ..
459 }) => {
460 let list = eval_expressions(elements, env)?;
461 return Ok(Rc::from(Object::Array(list)));
462 }
463 Literal::Hash(Hash {
464 elements: map,
465 ..
466 }) => {
467 #[allow(clippy::mutable_key_type)]
470 let mut hash_map = HashMap::new();
471
472 for (k, v) in map {
473 let key = eval_expression(k, env)?;
474 if !key.is_hashable() {
475 return Err(format!("key {} is not hashable", key));
476 }
477 let value = eval_expression(v, env)?;
478 hash_map.insert(key, value);
479 }
480
481 return Ok(Rc::new(Object::Hash(hash_map)));
482 } }
484}