1use crate::ast::{Env, EvalError, ExprKind, Value};
2use lasso::Rodeo;
3use std::cell::RefCell;
4use std::rc::Rc;
5
6#[derive(Clone, Debug)]
7pub struct Thunk<'bump> {
8 expr: &'bump ExprKind<'bump>,
9 env: Rc<RefCell<Env<'bump>>>,
10 value: Rc<RefCell<Option<Value<'bump>>>>,
11}
12
13impl<'bump> Thunk<'bump> {
14 pub fn new(expr: &'bump ExprKind<'bump>, env: Env<'bump>) -> Self {
15 Self {
16 expr,
17 env: Rc::new(RefCell::new(env)),
18 value: Rc::new(RefCell::new(None)),
19 }
20 }
21
22 pub fn new_shared(expr: &'bump ExprKind<'bump>, env: Rc<RefCell<Env<'bump>>>) -> Self {
23 Self {
24 expr,
25 env,
26 value: Rc::new(RefCell::new(None)),
27 }
28 }
29
30 pub fn env_cell(&self) -> Rc<RefCell<Env<'bump>>> {
31 Rc::clone(&self.env)
32 }
33
34 pub fn force(&self, rodeo: &Rodeo) -> Result<Value<'bump>, EvalError> {
35 if let Some(val) = self.value.borrow().as_ref() {
36 return Ok(val.clone());
37 }
38 let env = self.env.borrow().clone();
39 let val = self.expr.eval_lazy(&env, rodeo)?;
40 *self.value.borrow_mut() = Some(val.clone());
41 Ok(val)
42 }
43}