scheme_rs/
eval.rs

1use crate::{
2    ast,
3    continuation::{
4        Continuation, ResumableAnd, ResumableApply, ResumableBody, ResumableCall,
5        ResumableDefineVar, ResumableIf, ResumableLet, ResumableOr, ResumableSet,
6        ResumableSyntaxCase,
7    },
8    env::Env,
9    error::RuntimeError,
10    gc::{Gc, Trace},
11    lists::list_to_vec,
12    proc::{PreparedCall, Procedure},
13    util::{self, ArcSlice, RequireOne},
14    value::Value,
15};
16use async_trait::async_trait;
17use std::sync::Arc;
18
19pub enum ValuesOrPreparedCall {
20    Values(Vec<Gc<Value>>),
21    PreparedCall(PreparedCall),
22}
23
24impl ValuesOrPreparedCall {
25    pub async fn eval(
26        self,
27        cont: &Option<Arc<Continuation>>,
28    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
29        match self {
30            Self::Values(val) => Ok(val),
31            Self::PreparedCall(prepared_call) => prepared_call.eval(cont).await,
32        }
33    }
34}
35
36/// Core evaulation trait for expressions.
37///
38/// Any struct implementing this trait must either implement `eval`, `tail_eval`, or
39/// both, even though both methods are provided.
40#[async_trait]
41pub trait Eval: Trace + Send + Sync + 'static {
42    async fn eval(
43        &self,
44        env: &Env,
45        cont: &Option<Arc<Continuation>>,
46    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
47        self.tail_eval(env, cont).await?.eval(cont).await
48    }
49
50    /// Evaluate the expression in a tail environment
51    async fn tail_eval(
52        &self,
53        env: &Env,
54        cont: &Option<Arc<Continuation>>,
55    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
56        Ok(ValuesOrPreparedCall::Values(self.eval(env, cont).await?))
57    }
58}
59
60#[async_trait]
61impl Eval for Value {
62    async fn eval(
63        &self,
64        _env: &Env,
65        _cont: &Option<Arc<Continuation>>,
66    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
67        Ok(vec![Gc::new(self.clone())])
68    }
69}
70
71#[async_trait]
72impl Eval for Vec<Gc<Value>> {
73    async fn eval(
74        &self,
75        _env: &Env,
76        _cont: &Option<Arc<Continuation>>,
77    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
78        Ok(self.clone())
79    }
80}
81
82#[async_trait]
83impl Eval for ast::Literal {
84    async fn eval(
85        &self,
86        _env: &Env,
87        _cont: &Option<Arc<Continuation>>,
88    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
89        Ok(vec![Gc::new(Value::from_literal(self))])
90    }
91}
92
93#[async_trait]
94impl Eval for ast::Quote {
95    async fn eval(
96        &self,
97        _env: &Env,
98        _cont: &Option<Arc<Continuation>>,
99    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
100        Ok(vec![Gc::new(self.val.clone())])
101    }
102}
103
104#[async_trait]
105impl Eval for ast::Body {
106    async fn tail_eval(
107        &self,
108        env: &Env,
109        cont: &Option<Arc<Continuation>>,
110    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
111        let Some(last) = self.exprs.last() else {
112            return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Null)]));
113        };
114        for (expr, tail) in self.exprs.skip_last() {
115            let cont = Some(Arc::new(Continuation::new(
116                Arc::new(ResumableBody::new(env, &tail)),
117                cont,
118            )));
119            // Discard values that aren't returned
120            expr.eval(env, &cont).await?;
121        }
122        last.tail_eval(env, cont).await
123    }
124}
125
126#[async_trait]
127impl Eval for ast::Let {
128    async fn tail_eval(
129        &self,
130        env: &Env,
131        cont: &Option<Arc<Continuation>>,
132    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
133        let scope = Gc::new(env.new_lexical_contour());
134        for ((ident, expr), remaining) in util::iter_arc(&self.bindings) {
135            let cont = Arc::new(Continuation::new(
136                Arc::new(ResumableLet::new(&scope, ident, remaining, &self.body)),
137                cont,
138            ));
139            let val = expr
140                .eval(&Env::from(scope.clone()), &Some(cont))
141                .await?
142                .require_one()?;
143            scope.write().await.def_var(ident, val);
144        }
145        self.body.tail_eval(&Env::from(scope), cont).await
146    }
147}
148
149#[async_trait]
150impl Eval for ast::Call {
151    async fn tail_eval(
152        &self,
153        env: &Env,
154        cont: &Option<Arc<Continuation>>,
155    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
156        let mut collected = Vec::new();
157        for (arg, remaining) in self.args.iter() {
158            let cont = Arc::new(Continuation::new(
159                Arc::new(ResumableCall::new(
160                    &self.proc_name,
161                    &self.location,
162                    env,
163                    &collected,
164                    remaining,
165                )),
166                cont,
167            ));
168            let arg = arg.eval(env, &Some(cont)).await?.require_one()?;
169            collected.push(arg);
170        }
171        Ok(ValuesOrPreparedCall::PreparedCall(PreparedCall::prepare(
172            &self.proc_name,
173            &self.location,
174            collected,
175        )))
176    }
177}
178
179#[async_trait]
180impl Eval for ast::If {
181    async fn tail_eval(
182        &self,
183        env: &Env,
184        cont: &Option<Arc<Continuation>>,
185    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
186        let cond_cont = Arc::new(Continuation::new(
187            Arc::new(ResumableIf::new(env, &self.success, &self.failure)),
188            cont,
189        ));
190        let condition = self
191            .cond
192            .eval(env, &Some(cond_cont))
193            .await?
194            .require_one()?
195            .read()
196            .await
197            .is_true();
198        if condition {
199            self.success.tail_eval(env, cont).await
200        } else if let Some(ref failure) = self.failure {
201            failure.tail_eval(env, cont).await
202        } else {
203            Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Null)]))
204        }
205    }
206}
207
208#[async_trait]
209impl Eval for ast::DefineFunc {
210    async fn eval(
211        &self,
212        env: &Env,
213        _cont: &Option<Arc<Continuation>>,
214    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
215        let (args, remaining) = self.args.to_args_and_remaining();
216        let func = Gc::new(Value::Procedure(Procedure {
217            up: env.clone(),
218            args,
219            remaining,
220            // mark: self.mark,
221            body: self.body.clone(),
222            is_variable_transformer: false,
223        }));
224        env.def_var(&self.name, func).await;
225        Ok(vec![Gc::new(Value::Null)])
226    }
227}
228
229#[async_trait]
230impl Eval for ast::DefineVar {
231    async fn eval(
232        &self,
233        env: &Env,
234        cont: &Option<Arc<Continuation>>,
235    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
236        let cont = Arc::new(Continuation::new(
237            Arc::new(ResumableDefineVar::new(env, &self.name)),
238            cont,
239        ));
240        let val = self.val.eval(env, &Some(cont)).await?.require_one()?;
241        env.def_var(&self.name, val).await;
242        Ok(vec![Gc::new(Value::Null)])
243    }
244}
245
246#[async_trait]
247impl Eval for ast::Define {
248    async fn eval(
249        &self,
250        env: &Env,
251        cont: &Option<Arc<Continuation>>,
252    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
253        match self {
254            ast::Define::DefineFunc(define_func) => define_func.eval(env, cont).await,
255            ast::Define::DefineVar(define_var) => define_var.eval(env, cont).await,
256        }
257    }
258}
259
260#[async_trait]
261impl Eval for ast::DefineSyntax {
262    async fn eval(
263        &self,
264        _env: &Env,
265        _cont: &Option<Arc<Continuation>>,
266    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
267        Ok(vec![Gc::new(Value::Null)])
268    }
269}
270
271#[async_trait]
272impl Eval for ast::And {
273    async fn tail_eval(
274        &self,
275        env: &Env,
276        cont: &Option<Arc<Continuation>>,
277    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
278        let Some(last) = self.args.last() else {
279            return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean(
280                true,
281            ))]));
282        };
283        for (arg, tail) in self.args.skip_last() {
284            let cont = Arc::new(Continuation::new(
285                Arc::new(ResumableAnd::new(env, &tail)),
286                cont,
287            ));
288            // If one of the arguments does not evaluate to true, then the result
289            // is false
290            if !arg
291                .eval(env, &Some(cont))
292                .await?
293                .require_one()?
294                .read()
295                .await
296                .is_true()
297            {
298                return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean(
299                    false,
300                ))]));
301            }
302        }
303        // If all of the other arguments are true, then the result is the last expression
304        last.tail_eval(env, cont).await
305    }
306}
307
308#[async_trait]
309impl Eval for ast::Or {
310    async fn tail_eval(
311        &self,
312        env: &Env,
313        cont: &Option<Arc<Continuation>>,
314    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
315        let Some(last) = self.args.last() else {
316            return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean(
317                false,
318            ))]));
319        };
320        for (arg, tail) in self.args.skip_last() {
321            let cont = Arc::new(Continuation::new(
322                Arc::new(ResumableOr::new(env, &tail)),
323                cont,
324            ));
325            // If one of the arguments evaluates to true, then the result is true
326            if arg
327                .eval(env, &Some(cont))
328                .await?
329                .require_one()?
330                .read()
331                .await
332                .is_true()
333            {
334                return Ok(ValuesOrPreparedCall::Values(vec![Gc::new(Value::Boolean(
335                    true,
336                ))]));
337            }
338        }
339        // If all of the other arguments are false, then the result is the last expression
340        last.tail_eval(env, cont).await
341    }
342}
343
344#[async_trait]
345impl Eval for ast::Vector {
346    async fn eval(
347        &self,
348        _env: &Env,
349        _cont: &Option<Arc<Continuation>>,
350    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
351        /*
352        let mut output = Vec::new();
353        for item in &self.vals {
354            output.push(item.eval(env, cont.clone()).await?);
355        }
356        Ok(Gc::new(Value::Vector(output)))
357         */
358        todo!("FIXME: Vectors don't evaluate their arguments, take the literals")
359    }
360}
361
362#[async_trait]
363impl Eval for ast::Set {
364    async fn eval(
365        &self,
366        env: &Env,
367        cont: &Option<Arc<Continuation>>,
368    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
369        let new_cont = Arc::new(Continuation::new(
370            Arc::new(ResumableSet::new(env, &self.var)),
371            cont,
372        ));
373        // TODO: Add try_unwrap to GC to avoid the clone of the inner value
374        let val = self
375            .val
376            .eval(env, &Some(new_cont))
377            .await?
378            .require_one()?
379            .read()
380            .await
381            .clone();
382        *env.fetch_var(&self.var)
383            .await
384            .ok_or_else(|| RuntimeError::undefined_variable(self.var.clone()))?
385            .write()
386            .await = val;
387        Ok(vec![Gc::new(Value::Null)])
388    }
389}
390
391#[async_trait]
392impl Eval for ast::Lambda {
393    async fn eval(
394        &self,
395        env: &Env,
396        _cont: &Option<Arc<Continuation>>,
397    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
398        // TODO: Optimize the AST with smart pointers to prevent constantly
399        // cloning.
400
401        let (args, remaining) = self.args.to_args_and_remaining();
402        Ok(vec![Gc::new(Value::Procedure(Procedure {
403            up: env.clone(),
404            args,
405            remaining,
406            body: self.body.clone(),
407            is_variable_transformer: false,
408        }))])
409    }
410}
411
412#[async_trait]
413impl Eval for ast::SyntaxQuote {
414    async fn eval(
415        &self,
416        _env: &Env,
417        _cont: &Option<Arc<Continuation>>,
418    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
419        Ok(vec![Gc::new(Value::Syntax(self.syn.clone()))])
420    }
421}
422
423#[async_trait]
424impl Eval for ast::SyntaxCase {
425    async fn eval(
426        &self,
427        env: &Env,
428        cont: &Option<Arc<Continuation>>,
429    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
430        let new_cont = Arc::new(Continuation::new(
431            Arc::new(ResumableSyntaxCase::new(env, &self.transformer)),
432            cont,
433        ));
434        let val = self.arg.eval(env, &Some(new_cont)).await?.require_one()?;
435        let val = val.read().await;
436        match &*val {
437            Value::Syntax(syntax) => {
438                let result = self.transformer.expand(syntax).unwrap();
439                result.compile(env, cont).await?.eval(env, cont).await
440            }
441            _ => todo!(),
442        }
443    }
444}
445
446#[async_trait]
447impl Eval for ast::SyntaxRules {
448    async fn eval(
449        &self,
450        _env: &Env,
451        _cont: &Option<Arc<Continuation>>,
452    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
453        Ok(vec![Gc::new(Value::Transformer(self.transformer.clone()))])
454    }
455}
456
457#[async_trait]
458impl Eval for ast::Apply {
459    async fn tail_eval(
460        &self,
461        env: &Env,
462        cont: &Option<Arc<Continuation>>,
463    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
464        let mut collected = Vec::new();
465
466        for (arg, remaining) in self.args.iter() {
467            let cont = Arc::new(Continuation::new(
468                Arc::new(ResumableApply::new(
469                    &self.proc_name,
470                    &self.location,
471                    env,
472                    &collected,
473                    remaining,
474                    Some(self.rest_args.clone()),
475                )),
476                cont,
477            ));
478            let arg = arg.eval(env, &Some(cont)).await?.require_one()?;
479            collected.push(arg);
480        }
481
482        let cont = Arc::new(Continuation::new(
483            Arc::new(ResumableApply::new(
484                &self.proc_name,
485                &self.location,
486                env,
487                &collected,
488                ArcSlice::empty(),
489                None,
490            )),
491            cont,
492        ));
493        let rest_args = self.rest_args.eval(env, &Some(cont)).await?.require_one()?;
494        // TODO: Throw an error if rest_args is not a list
495        list_to_vec(&rest_args, &mut collected).await;
496
497        Ok(ValuesOrPreparedCall::PreparedCall(PreparedCall::prepare(
498            &self.proc_name,
499            &self.location,
500            collected,
501        )))
502    }
503}
504
505#[async_trait]
506impl Eval for ast::FetchVar {
507    async fn eval(
508        &self,
509        env: &Env,
510        _cont: &Option<Arc<Continuation>>,
511    ) -> Result<Vec<Gc<Value>>, RuntimeError> {
512        Ok(vec![env.fetch_var(&self.ident).await.ok_or_else(|| {
513            RuntimeError::undefined_variable(self.ident.clone())
514        })?])
515    }
516}
517
518#[async_trait]
519impl Eval for ast::MacroExpansionPoint {
520    async fn tail_eval(
521        &self,
522        env: &Env,
523        cont: &Option<Arc<Continuation>>,
524    ) -> Result<ValuesOrPreparedCall, RuntimeError> {
525        let env = Gc::new(env.new_expansion_context(self.mark, self.macro_env.clone()));
526        self.expr.tail_eval(&Env::from(env), cont).await
527    }
528}