1use std::cmp::Ordering;
2use std::collections::HashMap;
3use std::rc::Rc;
4use std::cell::RefCell;
5
6use crate::class::Class;
7use crate::environment::Environment;
8use crate::error::{self, Error, ReturnType, RuntimeError, ReturnError, BreakError};
9use crate::expr::{Expr, ExprVisitor};
10use crate::function::{NativeFunction, Function};
11use crate::object::{Object, Callable};
12use crate::stmt::{Stmt, StmtVisitor};
13use crate::token::{Type, Token};
14use crate::literal::Literal;
15
16pub struct Interpreter<'w> {
17 environment: Rc<RefCell<Environment>>,
19 globals: Rc<RefCell<Environment>>,
20 locals: HashMap<Token, usize>,
21 writer: Box<dyn std::io::Write + 'w>,
22}
23
24impl<'w> Interpreter<'w> {
25 pub fn new<W: std::io::Write>(writer: &'w mut W) -> Self {
26 let globals = Rc::new(RefCell::new(Environment::default()));
27
28 NativeFunction::get_globals().iter().for_each(|native| {
29 globals.borrow_mut().define(&native.name.lexeme, Object::from(native.clone()));
30 });
31
32 Interpreter {
33 environment: Rc::clone(&globals),
34 globals: Rc::clone(&globals),
35 locals: HashMap::new(),
36 writer: Box::new(writer),
37 }
38 }
39
40 pub fn interpret(&mut self, statements: &Vec<Stmt>) {
41 for statement in statements {
42 self.execute(statement).unwrap_or_else(|error| {
43 if let ReturnType::Error(error) = error {
44 error.throw();
45 }
46 });
47 }
48 }
49
50 fn execute(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
51 stmt.accept(self)
52 }
53
54 pub fn resolve(&mut self, name: &Token, depth: usize) {
55 self.locals.insert(name.clone(), depth);
56 }
57
58 fn lookup_variable(&mut self, name: &Token) -> Result<Object, ReturnType> {
59 let variable = match self.locals.get(name) {
60 Some(distance) => self.environment.borrow().get_at(*distance, name),
61 None => self.globals.borrow().get(name),
62 };
63
64 return match variable {
65 Ok(value) => Ok(value),
66 Err(error) => Err(ReturnType::Error(error)),
67 };
68 }
69
70 pub fn execute_block(
71 &mut self,
72 statements: &Vec<Stmt>,
73 environment: Rc<RefCell<Environment>>
74 ) -> Result<(), ReturnType> {
75 let previous = self.environment.clone();
76 self.environment = environment;
77
78 for statement in statements {
79 if let Err(return_type) = self.execute(statement) {
80 self.environment = previous;
81 return Err(return_type);
82 }
83 }
84
85 self.environment = previous;
86
87 Ok(())
88 }
89
90 fn evaluate(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
91 expr.accept(self)
92 }
93}
94
95impl<'w> Default for Interpreter<'w> {
96 fn default() -> Self {
97 Self::new(Box::leak(Box::new(std::io::stdout())))
98 }
99}
100
101impl<'w> ExprVisitor<Result<Object, ReturnType>> for Interpreter<'w> {
102 fn visit_literal_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
103 let Expr::Literal(literal) = expr else { unreachable!() };
104 Ok(Object::Literal(literal.clone()))
105 }
106
107 fn visit_logical_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
108 let Expr::Logical(logical) = expr else { unreachable!() };
109 let left = self.evaluate(&logical.left)?;
110
111 match logical.operator.r#type {
112 Type::Or => if left.as_bool().is_some_and(|x| x) { return Ok(left) },
113 Type::And => if !left.as_bool().is_some_and(|x| x) { return Ok(left) },
114 _ => unreachable!(),
115 };
116
117 self.evaluate(&logical.right)
118 }
119
120 fn visit_unary_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
121 let Expr::Unary(unary) = expr else { unreachable!() };
122 let right = self.evaluate(&unary.expr)?;
123
124 let error_message = format!(
125 "Unary operation '{}' is not supported for {} type",
126 unary.operator.lexeme.clone(),
127 right.type_str()
128 );
129
130 let result = match unary.operator.r#type {
131 Type::Minus => -right,
132 Type::Bang => !right,
133 _ => unreachable!(),
134 };
135
136 if let Some(result) = result {
137 Ok(result)
138 } else {
139 return Err(ReturnType::Error(RuntimeError {
140 token: unary.operator.clone(),
141 message: error_message,
142 }));
143 }
144 }
145
146 fn visit_binary_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
147 let Expr::Binary(binary) = expr else { unreachable!() };
148 let left = self.evaluate(&binary.left)?;
149 let right = self.evaluate(&binary.right)?;
150
151 let error_message = format!(
152 "Binary operation '{}' is not supported between {} type and {} type",
153 binary.operator.lexeme.clone(),
154 left.type_str(),
155 right.type_str()
156 );
157
158 let result = match binary.operator.r#type {
159 Type::Plus => left + right,
160 Type::Minus => left - right,
161 Type::Slash => left / right,
162 Type::Star => left * right,
163
164 Type::EqualEqual => Some(Object::Literal(Literal::Bool(left == right))),
165 Type::BangEqual => Some(Object::Literal(Literal::Bool(left != right))),
166
167 Type::Greater => left.partial_cmp(&right)
168 .map(|x| Object::Literal(Literal::Bool(x == Ordering::Greater))),
169 Type::Less => left.partial_cmp(&right)
170 .map(|x| Object::Literal(Literal::Bool(x == Ordering::Less))),
171 Type::GreaterEqual => left.partial_cmp(&right)
172 .map(|x| Object::Literal(Literal::Bool(x == Ordering::Greater || x == Ordering::Equal))),
173 Type::LessEqual => left.partial_cmp(&right)
174 .map(|x| Object::Literal(Literal::Bool(x == Ordering::Less || x == Ordering::Equal))),
175
176 _ => { unreachable!() }
177 };
178
179 if let Some(result) = result {
180 return Ok(result);
181 } else {
182 return Err(ReturnType::Error(RuntimeError {
183 token: binary.operator.clone(),
184 message: error_message,
185 }));
186 }
187 }
188
189 fn visit_call_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
190 let Expr::Call(call) = expr else { unreachable!() };
191 let callee = self.evaluate(call.callee.as_ref())?;
192
193 if let Object::Literal(Literal::Null) = callee {
196 return Ok(Object::from(Literal::Null));
197 }
198
199 let arguments = call.arguments
201 .iter()
202 .map(|expr| self.evaluate(expr))
203 .collect::<Result<Vec<Object>, ReturnType>>()?;
204
205 match callee {
206 Object::Function(function) => {
207 if arguments.len() != function.arity() {
208 return Err(ReturnType::Error(RuntimeError {
209 token: call.paren.clone(),
210 message: format!("Expected {} arguments but got {}", function.arity(), arguments.len()),
211 }));
212 }
213
214 return match function.call(self, arguments) {
215 Ok(value) => Ok(value),
216 Err(error) => {
217 return Err(ReturnType::Error(error));
220 }
221 };
222 },
223 Object::NativeFunction(function) => {
224 if arguments.len() != function.arity() {
225 return Err(ReturnType::Error(RuntimeError {
226 token: call.paren.clone(),
227 message: format!("Expected {} arguments but got {}", function.arity(), arguments.len()),
228 }));
229 }
230
231 return match function.call(self, arguments) {
232 Ok(result) => Ok(result),
233 Err(error) => {
234 return Err(ReturnType::Error(error));
236 }
237 };
238 },
239 Object::Class(class) => {
240 if arguments.len() != class.borrow().arity() {
241 return Err(ReturnType::Error(RuntimeError {
242 token: call.paren.clone(),
243 message: format!("Expected {} arguments but got {}", class.borrow().arity(), arguments.len()),
244 }));
245 }
246
247 return match class.borrow().call(self, arguments) {
248 Ok(result) => Ok(result),
249 Err(error) => {
250 return Err(ReturnType::Error(error));
252 }
253 };
254 },
255 _ => {
256 return Err(ReturnType::Error(RuntimeError {
257 token: call.paren.clone(),
258 message: "Can only call functions and classes".to_string(),
259 }));
260 }
261 }
262 }
263
264 fn visit_grouping_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
265 let Expr::Grouping(grouping) = expr else { unreachable!() };
266 self.evaluate(&grouping.expr)
267 }
268
269 fn visit_variable_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
270 let Expr::Variable(variable) = expr else { unreachable!() };
271 self.lookup_variable(&variable.name)
272 }
273
274 fn visit_assign_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
275 let Expr::Assign(assign) = expr else { unreachable!() };
276 let value = self.evaluate(&assign.value)?;
277
278 if let Some(distance) = self.locals.get(&assign.name) {
279 self.environment.borrow_mut().assign_at(*distance, &assign.name, value.clone());
280 } else {
281 self.globals.borrow_mut().assign(&assign.name, value.clone());
282 }
283
284 Ok(value)
285 }
286
287 fn visit_get_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
288 let Expr::Get(get) = expr else { unreachable!() };
289 let object = self.evaluate(&get.object)?;
290
291 if let Object::Instance(ref instance) = object {
292 return match instance.borrow().get(&get.name, &object) {
293 Ok(value) => Ok(value),
294 Err(error) => Err(ReturnType::Error(error)),
295 }
296 }
297
298 return Err(ReturnType::Error(RuntimeError {
299 token: get.name.clone(),
300 message: "Only instances have properties".to_owned(),
301 }));
302 }
303
304 fn visit_set_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
305 let Expr::Set(set) = expr else { unreachable!() };
306
307 let object = self.evaluate(&set.object)?;
308
309 if let Object::Instance(instance) = object {
310 let value = self.evaluate(&set.value)?;
311 instance.borrow_mut().set(&set.name, value.clone());
312 return Ok(value);
313 } else {
314 return Err(ReturnType::Error(RuntimeError {
315 token: set.name.clone(),
316 message: "Only instances can have fields".to_string(),
317 }));
318 }
319 }
320
321 fn visit_this_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
322 let Expr::This(this) = expr else { unreachable!() };
323
324 self.lookup_variable(&this.keyword)
325 }
326
327 fn visit_super_expr(&mut self, expr: &Expr) -> Result<Object, ReturnType> {
328 let Expr::Super(super_expr) = expr else { unreachable!() };
329
330 let distance = self.locals.get(&super_expr.keyword).unwrap();
333 let superclass = match self.environment.borrow().get_at(*distance, &super_expr.keyword) {
334 Ok(value) => Ok(value),
335 Err(error) => Err(ReturnType::Error(error)),
336 }?;
337
338 let object = match self.environment.borrow().get_at(distance - 1, &Token::from("this")) {
339 Ok(value) => Ok(value),
340 Err(error) => Err(ReturnType::Error(error)),
341 }?;
342
343 if let Object::Class(superclass) = superclass {
344 let method = superclass.borrow().get_method(&super_expr.method.lexeme);
345
346 if let Some(mut method) = method {
347 return Ok(Object::from(method.bind(object)));
348 } else {
349 return Err(ReturnType::Error(RuntimeError {
350 token: super_expr.method.clone(),
351 message: format!("Undefined property '{}'", super_expr.method.lexeme)
352 }));
353 }
354 } else {
355 unreachable!();
356 }
357 }
358}
359
360impl<'w> StmtVisitor<Result<(), ReturnType>> for Interpreter<'w> {
361 fn visit_expression_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
362 let Stmt::Expression(data) = stmt else { unreachable!() };
363 self.evaluate(&data.expr)?;
364
365 Ok(())
366 }
367
368 fn visit_function_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
369 let Stmt::Function(_) = stmt else { unreachable!() };
370
371 let function = Function::new(stmt.to_owned(), Rc::clone(&self.environment), false);
372
373 self.environment.borrow_mut().define(&function.name.lexeme.clone(), Object::from(function));
374
375 Ok(())
376 }
377
378 fn visit_if_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
379 let Stmt::If(data) = stmt else { unreachable!() };
380 if self.evaluate(&data.condition)?.as_bool().is_some_and(|x| x) {
381 self.execute(&data.then_branch)
382 } else if let Some(else_branch) = &data.else_branch {
383 self.execute(else_branch)
384 } else {
385 Ok(())
386 }
387 }
388
389 fn visit_print_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
390 let Stmt::Print(data) = stmt else { unreachable!() };
391 let value = self.evaluate(&data.expr)?;
392
393 if error::did_error() {
395 return Ok(());
396 }
397
398 writeln!(self.writer, "{value}").expect("writer to not fail on write");
399
400 Ok(())
401 }
402
403 fn visit_return_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
404 let Stmt::Return(data) = stmt else { unreachable!() };
405
406 let value = if let Some(expr) = &data.value {
407 self.evaluate(expr)?
408 } else {
409 Object::from(Literal::Null)
410 };
411
412 Err(ReturnType::Return(ReturnError { value }))
413 }
414
415 fn visit_break_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
416 let Stmt::Break(_) = stmt else { unreachable!() };
417
418 Err(ReturnType::Break(BreakError {}))
419 }
420
421 fn visit_var_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
422 let Stmt::Var(data) = stmt else { unreachable!() };
423 let value = match &data.initializer {
424 Some(value) => self.evaluate(value)?,
425 None => Object::from(Literal::Null),
426 };
427
428 self.environment.borrow_mut().define(&data.name.lexeme, value);
429
430 Ok(())
431 }
432
433 fn visit_while_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
434 let Stmt::While(data) = stmt else { unreachable!() };
435 while self.evaluate(&data.condition)?.as_bool().is_some_and(|x| x) {
436 match self.execute(&data.body) {
437 Err(ReturnType::Break(_)) => break,
438 Err(err)=> return Err(err),
439 _ => {},
440 }
441 }
442
443 Ok(())
444 }
445
446 fn visit_block_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
447 let Stmt::Block(data) = stmt else { unreachable!() };
448 self.execute_block(
449 &data.statements,
450 Rc::new(RefCell::new(Environment::new(Some(Rc::clone(&self.environment)))))
451 )
452 }
453
454 fn visit_class_stmt(&mut self, stmt: &Stmt) -> Result<(), ReturnType> {
455 let Stmt::Class(data) = stmt else { unreachable!() };
456
457 let superclass = match data.superclass.as_ref() {
458 Some(class) => Some(self.evaluate(class)?),
459 None => None,
460 };
461
462 if let Some(ref superclass) = superclass {
463 match superclass {
464 Object::Class(_) => (),
465 _ => {
466 return Err(ReturnType::Error(RuntimeError {
467 token: data.name.clone(),
470 message: "Superclass must be a class".to_string()
471 }));
472 },
473 }
474 }
475
476 self.environment.borrow_mut().define(&data.name.lexeme, Object::Literal(Literal::Null));
477
478 if let Some(ref superclass) = superclass {
479 let mut environment = Environment::new(Some(Rc::clone(&self.environment)));
480 environment.define("super", superclass.clone());
481 self.environment = Rc::new(RefCell::new(environment));
482 }
483
484 let mut methods: HashMap<String, Function> = HashMap::new();
485 for method in &data.methods {
486 if let Stmt::Function(function) = method {
487 let function = Function::new(
488 method.clone(),
489 Rc::clone(&self.environment),
490 function.name.lexeme.eq("init")
491 );
492 methods.insert(function.name.lexeme.clone(), function);
493 } else {
494 unreachable!();
495 }
496 }
497
498 let class = Class::new(data.name.lexeme.clone(), superclass.clone(), methods);
499
500 if superclass.is_some() {
501 let enclosing = self.environment.borrow().enclosing.clone().expect("enclosing to exist");
502 self.environment = enclosing;
503 }
504
505 self.environment.borrow_mut().assign(&data.name, Object::from(Rc::new(RefCell::new(class))));
506
507 Ok(())
508 }
509}