1use super::error_codes;
2use super::Ast;
3use super::Binary;
4use super::Expr;
5use super::Function as FunctionDecl;
6use super::Literal;
7use super::Logical;
8use super::Stmt;
9use super::Unary;
10
11use std::cell::Cell;
12use std::cell::RefCell;
13use std::cmp;
14use std::collections::HashMap;
15use std::fmt;
16use std::rc::Rc;
17use std::rc::Weak;
18
19use flexi_parse::error::Error;
20use flexi_parse::group::Delimiters as _;
21use flexi_parse::group::Parentheses;
22use flexi_parse::new_error;
23use flexi_parse::token::Ident;
24use flexi_parse::token::Token;
25use flexi_parse::Punct;
26use flexi_parse::Result;
27
28mod natives {
29 use super::Value;
30
31 use std::time::SystemTime;
32
33 use flexi_parse::Result;
34
35 #[allow(clippy::unnecessary_wraps)]
36 pub(super) fn clock(_: Vec<Value>) -> Result<Value> {
37 Ok(Value::Number(
38 SystemTime::now()
39 .duration_since(SystemTime::UNIX_EPOCH)
40 .unwrap()
41 .as_secs_f64(),
42 ))
43 }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47enum Ordering {
48 Less,
49 Equal,
50 Greater,
51 None,
52}
53
54impl Ordering {
55 fn gt(self) -> bool {
56 self == Ordering::Greater
57 }
58
59 fn ge(self) -> bool {
60 self == Ordering::Greater || self == Ordering::Equal
61 }
62
63 fn lt(self) -> bool {
64 self == Ordering::Less
65 }
66
67 fn le(self) -> bool {
68 self == Ordering::Less || self == Ordering::Equal
69 }
70}
71
72impl From<cmp::Ordering> for Ordering {
73 fn from(value: cmp::Ordering) -> Self {
74 match value {
75 cmp::Ordering::Less => Ordering::Less,
76 cmp::Ordering::Equal => Ordering::Equal,
77 cmp::Ordering::Greater => Ordering::Greater,
78 }
79 }
80}
81
82impl From<Option<cmp::Ordering>> for Ordering {
83 fn from(value: Option<cmp::Ordering>) -> Self {
84 value.map_or(Ordering::None, Into::into)
85 }
86}
87
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89struct NativeFunction {
90 function: fn(Vec<Value>) -> Result<Value>,
91 arity: usize,
92 name: &'static str,
93}
94
95#[derive(Debug, Clone)]
96struct Function {
97 declaration: FunctionDecl,
98 closure: State,
99 is_initialiser: bool,
100}
101
102impl Function {
103 const fn new(declaration: FunctionDecl, closure: State, is_initialiser: bool) -> Function {
104 Function {
105 declaration,
106 closure,
107 is_initialiser,
108 }
109 }
110
111 fn call(&self, arguments: Vec<Value>, parentheses: &Parentheses) -> Result<Value> {
112 let state = self.closure.start_scope();
113 if self.declaration.params.len() != arguments.len() {
114 return Err(arity_error(
115 parentheses,
116 self.declaration.params.len(),
117 arguments.len(),
118 ));
119 }
120 for (name, arg) in self.declaration.params.iter().zip(arguments) {
121 state
122 .environment
123 .borrow_mut()
124 .define(name.string().to_owned(), arg);
125 }
126 for stmt in &self.declaration.body {
127 if let Some(value) = stmt.execute(&state)? {
128 return Ok(value);
129 }
130 }
131 Ok(Value::Nil)
132 }
133
134 fn bind(&self, instance: &'static RefCell<Instance>) -> Function {
135 let scope = self.closure.start_scope();
136 scope
137 .environment
138 .borrow_mut()
139 .define("this".to_string(), Value::Instance(instance));
140 Function {
141 declaration: self.declaration.clone(),
142 closure: scope,
143 is_initialiser: self.is_initialiser,
144 }
145 }
146}
147
148impl PartialEq for Function {
149 fn eq(&self, other: &Self) -> bool {
150 self.declaration == other.declaration
151 }
152}
153
154#[derive(Debug, Clone, PartialEq)]
155struct Class {
156 name: String,
157 superclass: Option<Rc<Class>>,
158 methods: HashMap<String, Function>,
159}
160
161impl Class {
162 const fn new(
163 name: String,
164 superclass: Option<Rc<Class>>,
165 methods: HashMap<String, Function>,
166 ) -> Class {
167 Class {
168 name,
169 superclass,
170 methods,
171 }
172 }
173
174 fn find_method(&self, name: &str) -> Option<&Function> {
175 self.methods.get(name).map_or_else(
176 || {
177 self.superclass
178 .as_ref()
179 .and_then(|superclass| superclass.find_method(name))
180 },
181 Some,
182 )
183 }
184
185 fn arity(&self) -> usize {
186 self.find_method("init")
187 .map_or(0, |f| f.declaration.params.len())
188 }
189}
190
191#[derive(Clone, PartialEq)]
192struct Instance {
193 class: Rc<Class>,
194 fields: HashMap<String, Value>,
195}
196
197impl Instance {
198 fn new(class: Rc<Class>) -> Instance {
199 Instance {
200 class,
201 fields: HashMap::new(),
202 }
203 }
204
205 fn set(&mut self, name: &Ident, value: Value) {
206 self.fields.insert(name.string().to_string(), value);
207 }
208}
209
210fn get(instance: &'static RefCell<Instance>, name: &Ident) -> Result<Value> {
211 let this = instance.borrow();
212 if let Some(value) = this.fields.get(name.string()) {
213 Ok(value.to_owned())
214 } else if let Some(function) = this.class.find_method(name.string()) {
215 Ok(Value::Function(function.bind(instance)))
216 } else {
217 Err(new_error(
218 format!("Undefined property '{}'", name.string()),
219 name,
220 error_codes::UNDEFINED_NAME,
221 ))
222 }
223}
224
225impl fmt::Debug for Instance {
226 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227 f.debug_struct("Instance")
228 .field("class", &self.class.name)
229 .field("fields", &self.fields)
230 .finish()
231 }
232}
233
234#[derive(Debug, Clone, PartialEq)]
235enum Value {
236 Nil,
237 String(String),
238 Number(f64),
239 Bool(bool),
240 Native(NativeFunction),
241 Function(Function),
242 Class(Rc<Class>),
243 Instance(&'static RefCell<Instance>),
244}
245
246fn arity_error(parentheses: &Parentheses, expected: usize, actual: usize) -> Error {
247 new_error(
248 format!("Expected {expected} arguments but got {actual}"),
249 parentheses.span().to_owned(),
250 error_codes::INCORRECT_ARITY,
251 )
252}
253
254impl Value {
255 const fn as_class(&self) -> Option<&Rc<Class>> {
256 if let Value::Class(class) = self {
257 Some(class)
258 } else {
259 None
260 }
261 }
262
263 const fn as_instance(&self) -> Option<&'static RefCell<Instance>> {
264 if let Value::Instance(instance) = self {
265 Some(*instance)
266 } else {
267 None
268 }
269 }
270
271 const fn is_truthy(&self) -> bool {
272 !matches!(self, Value::Nil | Value::Bool(false))
273 }
274
275 fn add(&self, op: &Punct!["+"], other: &Value) -> Result<Value> {
276 match (self, other) {
277 (Value::Number(n1), Value::Number(n2)) => Ok(Value::Number(n1 + n2)),
278 (Value::String(s1), Value::String(s2)) => Ok(Value::String(s1.to_owned() + s2)),
279 _ => Err(new_error(
280 format!("Can't add '{self}' to '{other}'"),
281 op,
282 error_codes::TYPE_ERROR,
283 )),
284 }
285 }
286
287 fn sub(&self, op: &Punct!["-"], other: &Value) -> Result<Value> {
288 if let (Value::Number(n1), Value::Number(n2)) = (self, other) {
289 Ok(Value::Number(n1 - n2))
290 } else {
291 Err(new_error(
292 format!("Can't subtract '{other}' from '{self}'"),
293 op,
294 error_codes::TYPE_ERROR,
295 ))
296 }
297 }
298
299 fn mul(&self, op: &Punct!["*"], other: &Value) -> Result<Value> {
300 if let (Value::Number(n1), Value::Number(n2)) = (self, other) {
301 Ok(Value::Number(n1 * n2))
302 } else {
303 Err(new_error(
304 format!("Can't multiply '{self}' by '{other}'"),
305 op,
306 error_codes::TYPE_ERROR,
307 ))
308 }
309 }
310
311 fn div(&self, op: &Punct!["/"], other: &Value) -> Result<Value> {
312 if let (Value::Number(n1), Value::Number(n2)) = (self, other) {
313 Ok(Value::Number(n1 / n2))
314 } else {
315 Err(new_error(
316 format!("Can't divide '{other}' by '{self}'"),
317 op,
318 error_codes::TYPE_ERROR,
319 ))
320 }
321 }
322
323 fn neg(&self, op: &Punct!["-"]) -> Result<Value> {
324 if let Value::Number(n) = self {
325 Ok(Value::Number(-n))
326 } else {
327 Err(new_error(
328 format!("Can't negate '{self}'"),
329 op,
330 error_codes::TYPE_ERROR,
331 ))
332 }
333 }
334
335 fn cmp<T: Token>(&self, op: &T, other: &Value) -> Result<Ordering> {
336 if self == other {
337 return Ok(Ordering::Equal);
338 }
339
340 match (self, other) {
341 (Value::String(s1), Value::String(s2)) => Ok(s1.cmp(s2).into()),
342 (Value::Number(n1), Value::Number(n2)) => Ok(n1.partial_cmp(n2).into()),
343 (Value::Bool(b1), Value::Bool(b2)) => Ok(b1.cmp(b2).into()),
344 _ => Err(new_error(
345 format!("Can't compare '{self}' with '{other}'"),
346 op,
347 error_codes::TYPE_ERROR,
348 )),
349 }
350 }
351
352 fn call(&self, arguments: Vec<Value>, parentheses: &Parentheses) -> Result<Value> {
353 match self {
354 Value::Native(NativeFunction {
355 function, arity, ..
356 }) => {
357 if *arity != arguments.len() {
358 return Err(arity_error(parentheses, *arity, arguments.len()));
359 }
360 function(arguments)
361 }
362 Value::Function(function) => function.call(arguments, parentheses),
363 Value::Class(class) => {
364 if class.arity() != arguments.len() {
365 return Err(arity_error(parentheses, class.arity(), arguments.len()));
366 }
367
368 let instance = allocate(Instance::new(Rc::clone(class)));
369 if let Some(initialiser) = class.find_method("init") {
370 initialiser.bind(instance).call(arguments, parentheses)?;
371 }
372 Ok(Value::Instance(instance))
373 }
374 Value::Nil
375 | Value::String(_)
376 | Value::Number(_)
377 | Value::Bool(_)
378 | Value::Instance(_) => Err(new_error(
379 format!("Can't call '{self}'"),
380 parentheses.span().clone(),
381 error_codes::TYPE_ERROR,
382 )),
383 }
384 }
385}
386
387impl fmt::Display for Value {
388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 match self {
390 Value::Nil => f.write_str("nil"),
391 Value::String(s) => f.write_str(s),
392 Value::Number(n) => write!(f, "{n}"),
393 Value::Bool(b) => write!(f, "{b}"),
394 Value::Native(NativeFunction { name, .. }) => write!(f, "<native fn '{name}'>"),
395 Value::Function(Function {
396 declaration: FunctionDecl { name, .. },
397 ..
398 }) => write!(f, "<fn {}>", name.string()),
399 Value::Class(class) => f.write_str(&class.name),
400 Value::Instance(instance) => write!(f, "'{}' instance", instance.borrow().class.name),
401 }
402 }
403}
404
405#[derive(Debug, Clone)]
406struct State {
407 environment: Rc<RefCell<Environment>>,
408 globals: Rc<RefCell<Environment>>,
409}
410
411impl State {
412 fn new() -> Self {
413 let mut values = HashMap::new();
414
415 values.insert(
416 "clock".to_string(),
417 Value::Native(NativeFunction {
418 function: natives::clock,
419 arity: 0,
420 name: "clock",
421 }),
422 );
423
424 let environment = Rc::new(RefCell::new(Environment {
425 values,
426 enclosing: None,
427 sub: vec![],
428 mark: Cell::new(false),
429 }));
430
431 State {
432 environment: Rc::clone(&environment),
433 globals: environment,
434 }
435 }
436
437 #[must_use]
438 fn start_scope(&self) -> State {
439 let environment = Rc::new(RefCell::new(Environment {
440 values: HashMap::new(),
441 enclosing: Some(Rc::clone(&self.environment)),
442 sub: vec![],
443 mark: Cell::new(false),
444 }));
445 self.environment
446 .borrow_mut()
447 .sub
448 .push(Rc::downgrade(&environment));
449 State {
450 environment,
451 globals: Rc::clone(&self.globals),
452 }
453 }
454
455 fn super_scope(self) -> Option<State> {
456 Some(State {
457 environment: Rc::clone(self.environment.borrow().enclosing.as_ref()?),
458 globals: self.globals,
459 })
460 }
461}
462
463fn allocate<T>(value: T) -> &'static RefCell<T> {
464 Box::leak(Box::new(RefCell::new(value)))
465}
466
467struct Environment {
468 values: HashMap<String, Value>,
469 enclosing: Option<Rc<RefCell<Environment>>>,
470 sub: Vec<Weak<RefCell<Environment>>>,
471 mark: Cell<bool>,
472}
473
474impl Environment {
475 fn get(&self, name: &Ident) -> Result<Value> {
476 self.values.get(name.string()).map_or_else(
477 || {
478 self.enclosing.as_ref().map_or_else(
479 || {
480 Err(new_error(
481 format!("Undefined variable '{}'", name.string()),
482 name,
483 error_codes::UNDEFINED_NAME,
484 ))
485 },
486 |enclosing| enclosing.borrow().get(name),
487 )
488 },
489 |value| Ok(value.to_owned()),
490 )
491 }
492
493 fn get_at(&self, name: &Ident, distance: usize) -> Result<Value> {
494 if distance == 0 {
495 self.get(name)
496 } else {
497 self.enclosing
498 .as_ref()
499 .unwrap()
500 .borrow()
501 .get_at(name, distance - 1)
502 }
503 }
504
505 fn define(&mut self, name: String, value: Value) {
506 self.values.insert(name, value);
507 }
508
509 fn assign(&mut self, name: &Ident, value: Value) -> Result<()> {
510 if self.values.contains_key(name.string()) {
511 self.values.insert(name.string().clone(), value);
512 Ok(())
513 } else if let Some(enclosing) = &self.enclosing {
514 enclosing.borrow_mut().assign(name, value)
515 } else {
516 Err(new_error(
517 format!("Undefined variable '{}'", name.string()),
518 name,
519 error_codes::UNDEFINED_NAME,
520 ))
521 }
522 }
523
524 fn assign_at(&mut self, name: &Ident, value: Value, distance: usize) -> Result<()> {
525 if distance == 0 {
526 self.assign(name, value)
527 } else {
528 self.enclosing
529 .as_ref()
530 .unwrap()
531 .borrow_mut()
532 .assign_at(name, value, distance - 1)
533 }
534 }
535}
536
537struct EnvValuesDebug<'a>(&'a HashMap<String, Value>);
538
539impl fmt::Debug for EnvValuesDebug<'_> {
540 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
541 f.debug_map()
542 .entries(self.0.iter().map(|(k, v)| (k, v.to_string())))
543 .finish()
544 }
545}
546
547impl fmt::Debug for Environment {
548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549 f.debug_struct("Environment")
550 .field("values", &EnvValuesDebug(&self.values))
551 .field("enclosing", &self.enclosing)
552 .field("sub", &self.sub)
553 .field("mark", &self.mark)
554 .finish()
555 }
556}
557
558impl Binary {
559 fn evaluate(&self, state: &State) -> Result<Value> {
560 match self {
561 Binary::Mul(left, op, right) => left.evaluate(state)?.mul(op, &right.evaluate(state)?),
562 Binary::Div(left, op, right) => left.evaluate(state)?.div(op, &right.evaluate(state)?),
563 Binary::Add(left, op, right) => left.evaluate(state)?.add(op, &right.evaluate(state)?),
564 Binary::Sub(left, op, right) => left.evaluate(state)?.sub(op, &right.evaluate(state)?),
565 Binary::Equal(left, _, right) => {
566 Ok(Value::Bool(left.evaluate(state)? == right.evaluate(state)?))
567 }
568 Binary::NotEqual(left, _, right) => {
569 Ok(Value::Bool(left.evaluate(state)? != right.evaluate(state)?))
570 }
571 Binary::Greater(left, op, right) => Ok(Value::Bool(
572 left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.gt(),
573 )),
574 Binary::GreaterEqual(left, op, right) => Ok(Value::Bool(
575 left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.ge(),
576 )),
577 Binary::Less(left, op, right) => Ok(Value::Bool(
578 left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.lt(),
579 )),
580 Binary::LessEqual(left, op, right) => Ok(Value::Bool(
581 left.evaluate(state)?.cmp(op, &right.evaluate(state)?)?.le(),
582 )),
583 }
584 }
585}
586
587impl Literal {
588 fn evaluate(&self) -> Value {
589 match self {
590 Literal::False(_) => Value::Bool(false),
591 Literal::Float(value) => Value::Number(value.value()),
592 #[allow(clippy::cast_precision_loss)]
593 Literal::Int(value) => Value::Number(value.value() as f64),
594 Literal::Nil(_) => Value::Nil,
595 Literal::String(string) => Value::String(string.string().clone()),
596 Literal::True(_) => Value::Bool(true),
597 }
598 }
599}
600
601impl Logical {
602 fn evaluate(&self, state: &State) -> Result<Value> {
603 match self {
604 Logical::And(left, _, right) => {
605 let left = left.evaluate(state)?;
606 if left.is_truthy() {
607 Ok(left)
608 } else {
609 right.evaluate(state)
610 }
611 }
612 Logical::Or(left, _, right) => {
613 let left = left.evaluate(state)?;
614 if left.is_truthy() {
615 right.evaluate(state)
616 } else {
617 Ok(left)
618 }
619 }
620 }
621 }
622}
623
624impl Unary {
625 fn evaluate(&self, state: &State) -> Result<Value> {
626 match self {
627 Unary::Neg(op, expr) => expr.evaluate(state)?.neg(op),
628 Unary::Not(_, expr) => Ok(Value::Bool(!expr.evaluate(state)?.is_truthy())),
629 }
630 }
631}
632
633impl Expr {
634 fn evaluate(&self, state: &State) -> Result<Value> {
635 match self {
636 Expr::Assign {
637 name,
638 value,
639 distance,
640 } => {
641 let value = value.evaluate(state)?;
642 if let Some(distance) = distance.get() {
643 state
644 .environment
645 .borrow_mut()
646 .assign_at(name, value.clone(), distance)?;
647 } else {
648 state.globals.borrow_mut().assign(name, value.clone())?;
649 }
650 Ok(value)
651 }
652 Expr::Binary(binary) => binary.evaluate(state),
653 Expr::Call {
654 callee,
655 paren,
656 arguments,
657 } => {
658 let callee = callee.evaluate(state)?;
659 let mut evaluated_args = Vec::with_capacity(arguments.len());
660 for arg in arguments {
661 evaluated_args.push(arg.evaluate(state)?);
662 }
663 callee.call(evaluated_args, paren)
664 }
665 Expr::Get { object, name } => {
666 if let Value::Instance(instance) = object.evaluate(state)? {
667 get(instance, name)
668 } else {
669 Err(new_error(
670 "Only instances have properties".to_string(),
671 name,
672 error_codes::TYPE_ERROR,
673 ))
674 }
675 }
676 Expr::Group(expr) => expr.evaluate(state),
677 Expr::Literal(literal) => Ok(literal.evaluate()),
678 Expr::Logical(logical) => logical.evaluate(state),
679 Expr::Set {
680 object,
681 name,
682 value,
683 } => {
684 if let Value::Instance(instance) = object.evaluate(state)? {
685 let value = value.evaluate(state)?;
686 instance.borrow_mut().set(name, value.clone());
687 Ok(value)
688 } else {
689 Err(new_error(
690 "Only instances have fields".to_string(),
691 name,
692 error_codes::TYPE_ERROR,
693 ))
694 }
695 }
696 Expr::Super {
697 keyword,
698 distance,
699 dot: _,
700 method,
701 } => {
702 let superclass = state
703 .environment
704 .borrow()
705 .get_at(keyword.ident(), distance.clone().into_inner().unwrap())?;
706
707 let object = state.environment.borrow().get_at(
708 &Ident::new("this".to_string(), keyword.span().clone()),
709 distance.clone().into_inner().unwrap() - 1,
710 )?;
711
712 superclass
713 .as_class()
714 .unwrap()
715 .find_method(method.string())
716 .map_or_else(
717 || {
718 Err(new_error(
719 format!("Undefined property '{}'", method.string()),
720 method,
721 error_codes::UNDEFINED_NAME,
722 ))
723 },
724 |method| Ok(Value::Function(method.bind(object.as_instance().unwrap()))),
725 )
726 }
727 Expr::This { keyword, distance } => distance.get().map_or_else(
728 || state.globals.borrow().get(keyword.ident()),
729 |distance| state.environment.borrow().get_at(keyword.ident(), distance),
730 ),
731 Expr::Unary(unary) => unary.evaluate(state),
732 Expr::Variable { name, distance } => distance.get().map_or_else(
733 || state.globals.borrow().get(name),
734 |distance| state.environment.borrow().get_at(name, distance),
735 ),
736 }
737 }
738}
739
740macro_rules! propagate_return {
741 ( $expr:expr ) => {
742 if let Some(_tmp) = $expr {
743 return Ok(Some(_tmp));
744 }
745 };
746}
747
748impl Stmt {
749 fn execute(&self, state: &State) -> Result<Option<Value>> {
750 match self {
751 Stmt::Block(stmts) => {
752 let inner_state = state.start_scope();
753 for stmt in stmts {
754 propagate_return!(stmt.execute(&inner_state)?);
755 }
756 }
757 Stmt::Class {
758 name,
759 superclass,
760 superclass_distance,
761 methods,
762 } => {
763 let superclass = if let Some(superclass_name) = superclass {
764 let superclass = Expr::Variable {
765 name: superclass_name.clone(),
766 distance: superclass_distance.clone(),
767 }
768 .evaluate(state)?;
769 if let Value::Class(superclass) = superclass {
770 Some(superclass)
771 } else {
772 return Err(new_error(
773 "Superclass must be a class".to_string(),
774 superclass_name,
775 error_codes::INHERIT_FROM_VALUE,
776 ));
777 }
778 } else {
779 None
780 };
781
782 state
783 .environment
784 .borrow_mut()
785 .define(name.string().to_owned(), Value::Nil);
786
787 let superclass_is_some = superclass.is_some();
788 let mut state = superclass.as_ref().map_or_else(
789 || state.clone(),
790 |superclass| {
791 let state = state.start_scope();
792 state
793 .environment
794 .borrow_mut()
795 .define("super".to_string(), Value::Class(Rc::clone(superclass)));
796 state
797 },
798 );
799
800 let methods = methods
801 .iter()
802 .map(|declaration| {
803 (
804 declaration.name.string().to_owned(),
805 Function::new(
806 declaration.clone(),
807 state.clone(),
808 declaration.name.string() == "init",
809 ),
810 )
811 })
812 .collect();
813 let class = Class::new(name.string().to_owned(), superclass, methods);
814
815 if superclass_is_some {
816 state = state.super_scope().unwrap();
817 }
818
819 state
820 .environment
821 .borrow_mut()
822 .assign(name, Value::Class(Rc::new(class)))?;
823 }
824 Stmt::Expr(expr) => {
825 expr.evaluate(state)?;
826 }
827 Stmt::Function(function) => {
828 let value =
829 Value::Function(Function::new(function.to_owned(), state.clone(), false));
830 state
831 .environment
832 .borrow_mut()
833 .define(function.name.string().to_owned(), value);
834 }
835 Stmt::If {
836 condition,
837 then_branch,
838 else_branch,
839 } => {
840 if condition.evaluate(state)?.is_truthy() {
841 propagate_return!(then_branch.execute(state)?);
842 } else if let Some(else_branch) = else_branch {
843 propagate_return!(else_branch.execute(state)?);
844 }
845 }
846 Stmt::Print(expr) => {
847 let value = expr.evaluate(state)?;
848 println!("{value}");
849 }
850 Stmt::Return { keyword: _, value } => {
851 return Ok(Some(
852 value
853 .as_ref()
854 .map_or(Ok(Value::Nil), |v| v.evaluate(state))?,
855 ));
856 }
857 Stmt::Variable { name, initialiser } => {
858 let value = if let Some(initialiser) = initialiser {
859 initialiser.evaluate(state)?
860 } else {
861 Value::Nil
862 };
863 state
864 .environment
865 .borrow_mut()
866 .define(name.string().to_owned(), value);
867 }
868 Stmt::While { condition, body } => {
869 while condition.evaluate(state)?.is_truthy() {
870 propagate_return!(body.execute(state)?);
871 }
872 }
873 }
874
875 Ok(None)
876 }
877}
878
879pub(super) fn interpret(ast: Ast) -> Result<()> {
880 let state = State::new();
881 for stmt in ast.0 {
882 stmt.execute(&state)?;
883 }
884 Ok(())
885}