dazzle_core/scheme/
evaluator.rs

1//! Scheme evaluator (eval loop)
2//!
3//! Ported from OpenJade's `Interpreter.cxx` (~2,000 lines).
4//!
5//! ## Core Responsibilities
6//!
7//! 1. **Evaluate expressions** - Transform Values into results
8//! 2. **Special forms** - Handle if, let, define, lambda, quote, etc.
9//! 3. **Function application** - Call procedures with arguments
10//! 4. **Tail call optimization** - Prevent stack overflow in recursive functions
11//!
12//! ## OpenJade Correspondence
13//!
14//! | Dazzle          | OpenJade                  | Purpose                    |
15//! |-----------------|---------------------------|----------------------------|
16//! | `Evaluator`     | `Interpreter`             | Main evaluator state       |
17//! | `eval()`        | `Interpreter::eval()`     | Core eval loop             |
18//! | `apply()`       | `Interpreter::apply()`    | Function application       |
19//! | `eval_special()`| `Interpreter::evalXXX()`  | Special form handlers      |
20//!
21//! ## Evaluation Rules (R4RS)
22//!
23//! - **Self-evaluating**: Numbers, strings, booleans, characters → return as-is
24//! - **Symbols**: Look up in environment
25//! - **Lists**: First element determines behavior:
26//!   - Special form keyword → handle specially
27//!   - Otherwise → evaluate all elements, apply first to rest
28
29use crate::scheme::environment::Environment;
30use crate::scheme::value::{Procedure, Value};
31use crate::grove::{Grove, Node};
32use crate::fot::FotBuilder;
33use gc::Gc;
34use std::rc::Rc;
35use std::cell::RefCell;
36
37// Thread-local evaluator context for primitives
38//
39// Similar to OpenJade's approach, we use thread-local storage to give
40// primitives access to the evaluator state (current node, grove, etc.)
41// without changing all primitive signatures.
42//
43// This is safe because:
44// 1. Scheme evaluation is single-threaded in our implementation
45// 2. The context is set/cleared around each eval call
46// 3. Primitives only run during evaluation
47thread_local! {
48    static EVALUATOR_CONTEXT: RefCell<Option<EvaluatorContext>> = RefCell::new(None);
49}
50
51/// Context available to primitives during evaluation
52#[derive(Clone)]
53pub struct EvaluatorContext {
54    pub grove: Option<Rc<dyn Grove>>,
55    pub current_node: Option<Rc<Box<dyn Node>>>,
56}
57
58/// Get the current evaluator context (for use in primitives)
59pub fn get_evaluator_context() -> Option<EvaluatorContext> {
60    EVALUATOR_CONTEXT.with(|ctx| ctx.borrow().clone())
61}
62
63/// Set the evaluator context (called by evaluator before eval)
64fn set_evaluator_context(ctx: EvaluatorContext) {
65    EVALUATOR_CONTEXT.with(|c| *c.borrow_mut() = Some(ctx));
66}
67
68/// Clear the evaluator context (called by evaluator after eval)
69fn clear_evaluator_context() {
70    EVALUATOR_CONTEXT.with(|c| *c.borrow_mut() = None);
71}
72
73// =============================================================================
74// Evaluation Error
75// =============================================================================
76
77/// Evaluation error
78#[derive(Debug, Clone)]
79pub struct EvalError {
80    pub message: String,
81}
82
83impl EvalError {
84    pub fn new(message: String) -> Self {
85        EvalError { message }
86    }
87}
88
89impl std::fmt::Display for EvalError {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        write!(f, "Eval error: {}", self.message)
92    }
93}
94
95impl std::error::Error for EvalError {}
96
97pub type EvalResult = Result<Value, EvalError>;
98
99// =============================================================================
100// DSSSL Processing Mode (OpenJade ProcessingMode.h/ProcessingMode.cxx)
101// =============================================================================
102
103/// Construction rule for DSSSL processing
104///
105/// Corresponds to OpenJade's `ElementRule` + `Rule` + `Action`.
106/// Stores the pattern (element name) and action (expression to evaluate).
107#[derive(Clone)]
108pub struct ConstructionRule {
109    /// Element name pattern (GI)
110    pub element_name: String,
111
112    /// Construction expression (returns sosofo when evaluated)
113    pub expr: Value,
114}
115
116/// Processing mode containing construction rules
117///
118/// Corresponds to OpenJade's `ProcessingMode` class.
119/// Stores all element construction rules defined in the template.
120pub struct ProcessingMode {
121    /// Construction rules indexed by element name
122    /// In OpenJade, rules are stored in intrusive linked lists and indexed lazily.
123    /// We use a simple Vec for now - can optimize later with HashMap if needed.
124    pub rules: Vec<ConstructionRule>,
125}
126
127impl ProcessingMode {
128    /// Create a new empty processing mode
129    pub fn new() -> Self {
130        ProcessingMode {
131            rules: Vec::new(),
132        }
133    }
134
135    /// Add a construction rule
136    pub fn add_rule(&mut self, element_name: String, expr: Value) {
137        self.rules.push(ConstructionRule { element_name, expr });
138    }
139
140    /// Find matching rule for an element
141    ///
142    /// Corresponds to OpenJade's `ProcessingMode::findMatch()`.
143    /// Returns the first rule matching the given element name.
144    pub fn find_match(&self, gi: &str) -> Option<&ConstructionRule> {
145        self.rules.iter().find(|rule| rule.element_name == gi)
146    }
147}
148
149// =============================================================================
150// Evaluator
151// =============================================================================
152
153/// Scheme evaluator
154///
155/// Corresponds to OpenJade's `Interpreter` class.
156///
157/// ## Usage
158///
159/// ```ignore
160/// let mut evaluator = Evaluator::new();
161/// let result = evaluator.eval(expr, env)?;
162/// ```
163pub struct Evaluator {
164    /// The document grove (for element-with-id, etc.)
165    grove: Option<Rc<dyn Grove>>,
166
167    /// Current node context (for current-node primitive)
168    ///
169    /// This changes dynamically as we process the document tree.
170    /// When evaluating a template, this starts as the root node.
171    /// When processing children, it changes to each child node.
172    current_node: Option<Rc<Box<dyn Node>>>,
173
174    /// Processing mode containing construction rules
175    ///
176    /// Corresponds to OpenJade's `Interpreter::initialProcessingMode_`.
177    /// Rules are stored here during template loading, then used during processing.
178    processing_mode: ProcessingMode,
179
180    /// Backend for output generation (FotBuilder)
181    ///
182    /// This is used by the `make` special form to write flow objects to output.
183    /// Wrapped in Rc<RefCell<>> to allow shared mutable access.
184    backend: Option<Rc<RefCell<dyn FotBuilder>>>,
185}
186
187impl Evaluator {
188    /// Create a new evaluator without a grove
189    pub fn new() -> Self {
190        Evaluator {
191            grove: None,
192            current_node: None,
193            processing_mode: ProcessingMode::new(),
194            backend: None,
195        }
196    }
197
198    /// Create a new evaluator with a grove
199    pub fn with_grove(grove: Rc<dyn Grove>) -> Self {
200        Evaluator {
201            grove: Some(grove),
202            current_node: None,
203            processing_mode: ProcessingMode::new(),
204            backend: None,
205        }
206    }
207
208    /// Set the backend
209    pub fn set_backend(&mut self, backend: Rc<RefCell<dyn FotBuilder>>) {
210        self.backend = Some(backend);
211    }
212
213    /// Set the grove
214    pub fn set_grove(&mut self, grove: Rc<dyn Grove>) {
215        self.grove = Some(grove);
216    }
217
218    /// Get the grove
219    pub fn grove(&self) -> Option<&Rc<dyn Grove>> {
220        self.grove.as_ref()
221    }
222
223    /// Set the current node
224    pub fn set_current_node(&mut self, node: Box<dyn Node>) {
225        self.current_node = Some(Rc::new(node));
226    }
227
228    /// Get the current node
229    pub fn current_node(&self) -> Option<Rc<Box<dyn Node>>> {
230        self.current_node.clone()
231    }
232
233    /// Clear the current node
234    pub fn clear_current_node(&mut self) {
235        self.current_node = None;
236    }
237
238    // =========================================================================
239    // DSSSL Processing (OpenJade ProcessContext.cxx)
240    // =========================================================================
241
242    /// Start DSSSL processing from the root node
243    ///
244    /// Corresponds to OpenJade's `ProcessContext::process()`.
245    /// After template loading, this triggers automatic tree processing.
246    pub fn process_root(&mut self, env: Gc<Environment>) -> EvalResult {
247        // Get the root node from the grove
248        let root_node = match &self.grove {
249            Some(grove) => grove.root(),
250            None => return Err(EvalError::new("No grove set".to_string())),
251        };
252
253        // Set as current node and start processing
254        self.current_node = Some(Rc::new(root_node));
255        self.process_node(env)
256    }
257
258    /// Process the current node
259    ///
260    /// Corresponds to OpenJade's `ProcessContext::processNode()`.
261    ///
262    /// ## Algorithm (from OpenJade):
263    /// 1. If character data node, output directly
264    /// 2. If element node:
265    ///    a. Find matching construction rule by GI
266    ///    b. If rule found, evaluate it (returns sosofo)
267    ///    c. If no rule, default behavior: process-children
268    pub fn process_node(&mut self, env: Gc<Environment>) -> EvalResult {
269        let node = match &self.current_node {
270            Some(n) => n.clone(),
271            None => return Err(EvalError::new("No current node".to_string())),
272        };
273
274        // Get element name (GI)
275        let gi = match node.gi() {
276            Some(gi) => gi,
277            None => {
278                // Not an element (e.g., text node, comment, etc.)
279                // For code generation, we typically ignore non-elements
280                return Ok(Value::Unspecified);
281            }
282        };
283
284        // Find matching construction rule
285        let rule = self.processing_mode.find_match(&gi);
286
287        if let Some(rule) = rule {
288            // Rule found - evaluate the construction expression
289            // The expression should return a sosofo (in practice, it evaluates to a string or calls primitives)
290            self.eval(rule.expr.clone(), env)
291        } else {
292            // No rule found - default behavior is to process children
293            // This is implemented by the process-children primitive
294            // For now, return Unspecified (template should call process-children explicitly)
295            Ok(Value::Unspecified)
296        }
297    }
298
299    /// Evaluate an expression in an environment
300    ///
301    /// Corresponds to OpenJade's `Interpreter::eval()`.
302    ///
303    /// ## Evaluation Rules
304    ///
305    /// 1. **Self-evaluating**: Numbers, strings, bools, chars → return as-is
306    /// 2. **Symbols**: Variable lookup in environment
307    /// 3. **Lists**: Check first element for special forms, otherwise apply
308    pub fn eval(&mut self, expr: Value, env: Gc<Environment>) -> EvalResult {
309        // Set evaluator context for primitives
310        set_evaluator_context(EvaluatorContext {
311            grove: self.grove.clone(),
312            current_node: self.current_node.clone(),
313        });
314
315        // Evaluate (and ensure context is cleared on return or error)
316        let result = self.eval_inner(expr, env);
317
318        // Clear context (important for nested evals)
319        clear_evaluator_context();
320
321        result
322    }
323
324    /// Inner eval implementation (separated to ensure context cleanup)
325    fn eval_inner(&mut self, expr: Value, env: Gc<Environment>) -> EvalResult {
326        match expr {
327            // Self-evaluating literals
328            Value::Nil => Ok(Value::Nil),
329            Value::Bool(_) => Ok(expr),
330            Value::Integer(_) => Ok(expr),
331            Value::Real(_) => Ok(expr),
332            Value::Char(_) => Ok(expr),
333            Value::String(_) => Ok(expr),
334            Value::Procedure(_) => Ok(expr),
335            Value::Vector(_) => Ok(expr), // Vectors are self-evaluating in R4RS
336            Value::Unspecified => Ok(expr),
337            Value::Error => Ok(expr),
338
339            // DSSSL types (self-evaluating for now)
340            Value::Node(_) => Ok(expr),
341            Value::NodeList(_) => Ok(expr),
342            Value::Sosofo => Ok(expr),
343
344            // Symbols: variable lookup
345            Value::Symbol(ref name) => env
346                .lookup(name)
347                .ok_or_else(|| EvalError::new(format!("Undefined variable: {}", name))),
348
349            // Keywords are self-evaluating
350            Value::Keyword(_) => Ok(expr),
351
352            // Lists: special forms or function application
353            Value::Pair(_) => self.eval_list(expr, env),
354        }
355    }
356
357    /// Evaluate a list (special form or function call)
358    fn eval_list(&mut self, expr: Value, env: Gc<Environment>) -> EvalResult {
359        // Extract the operator (first element)
360        let (operator, args) = self.list_car_cdr(&expr)?;
361
362        // Check if operator is a symbol (special form keyword)
363        if let Value::Symbol(ref sym) = operator {
364            match &**sym {
365                "quote" => self.eval_quote(args),
366                "if" => self.eval_if(args, env),
367                "define" => self.eval_define(args, env),
368                "set!" => self.eval_set(args, env),
369                "lambda" => self.eval_lambda(args, env),
370                "let" => self.eval_let(args, env),
371                "let*" => self.eval_let_star(args, env),
372                "letrec" => self.eval_letrec(args, env),
373                "begin" => self.eval_begin(args, env),
374                "cond" => self.eval_cond(args, env),
375                "case" => self.eval_case(args, env),
376                "and" => self.eval_and(args, env),
377                "or" => self.eval_or(args, env),
378                "apply" => self.eval_apply(args, env),
379                "map" => self.eval_map(args, env),
380                "for-each" => self.eval_for_each(args, env),
381                "load" => self.eval_load(args, env),
382
383                // DSSSL special forms
384                "define-language" => self.eval_define_language(args, env),
385                "declare-flow-object-class" => self.eval_declare_flow_object_class(args, env),
386                "declare-characteristic" => self.eval_declare_characteristic(args, env),
387                "element" => self.eval_element(args, env),
388                "process-children" => self.eval_process_children(env),
389                "make" => self.eval_make(args, env),
390
391                // Not a special form - evaluate as function call
392                _ => self.eval_application(operator, args, env),
393            }
394        } else {
395            // Operator is not a symbol - evaluate and apply
396            self.eval_application(operator, args, env)
397        }
398    }
399
400    /// Extract car and cdr from a list
401    fn list_car_cdr(&self, list: &Value) -> Result<(Value, Value), EvalError> {
402        if let Value::Pair(ref p) = list {
403            let pair = p.borrow();
404            Ok((pair.car.clone(), pair.cdr.clone()))
405        } else {
406            Err(EvalError::new("Expected list".to_string()))
407        }
408    }
409
410    /// Convert a Vec to a list
411    fn vec_to_list(&self, vec: Vec<Value>) -> Value {
412        let mut result = Value::Nil;
413        for val in vec.iter().rev() {
414            result = Value::cons(val.clone(), result);
415        }
416        result
417    }
418
419    /// Convert a list to a Vec of elements
420    fn list_to_vec(&self, list: Value) -> Result<Vec<Value>, EvalError> {
421        let mut result = Vec::new();
422        let mut current = list;
423
424        loop {
425            match current {
426                Value::Nil => break,
427                Value::Pair(ref p) => {
428                    let pair = p.borrow();
429                    result.push(pair.car.clone());
430                    let cdr = pair.cdr.clone();
431                    drop(pair); // Explicitly drop borrow before reassigning
432                    current = cdr;
433                }
434                _ => return Err(EvalError::new("Improper list".to_string())),
435            }
436        }
437
438        Ok(result)
439    }
440
441    // =========================================================================
442    // Special Forms
443    // =========================================================================
444
445    /// (quote expr) → expr
446    fn eval_quote(&mut self, args: Value) -> EvalResult {
447        let args_vec = self.list_to_vec(args)?;
448        if args_vec.len() != 1 {
449            return Err(EvalError::new("quote requires exactly 1 argument".to_string()));
450        }
451        Ok(args_vec[0].clone())
452    }
453
454    /// (if test consequent [alternate])
455    fn eval_if(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
456        let args_vec = self.list_to_vec(args)?;
457        if args_vec.len() < 2 || args_vec.len() > 3 {
458            return Err(EvalError::new(
459                "if requires 2 or 3 arguments".to_string(),
460            ));
461        }
462
463        let test = self.eval_inner(args_vec[0].clone(), env.clone())?;
464
465        if test.is_true() {
466            self.eval_inner(args_vec[1].clone(), env)
467        } else if args_vec.len() == 3 {
468            self.eval_inner(args_vec[2].clone(), env)
469        } else {
470            Ok(Value::Unspecified)
471        }
472    }
473
474    /// (define name value) or (define (name params...) body...)
475    fn eval_define(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
476        let args_vec = self.list_to_vec(args)?;
477        if args_vec.len() < 2 {
478            return Err(EvalError::new(
479                "define requires at least 2 arguments".to_string(),
480            ));
481        }
482
483        // Check if first arg is a symbol or a list
484        match &args_vec[0] {
485            Value::Symbol(ref name) => {
486                // Simple variable definition: (define x value)
487                if args_vec.len() != 2 {
488                    return Err(EvalError::new(
489                        "define with symbol requires exactly 2 arguments".to_string(),
490                    ));
491                }
492                let value = self.eval_inner(args_vec[1].clone(), env.clone())?;
493                env.define(name, value);
494                Ok(Value::Unspecified)
495            }
496
497            Value::Pair(_) => {
498                // Function definition: (define (name params...) body...)
499                // This is syntactic sugar for: (define name (lambda (params...) body...))
500                let (name_val, params) = self.list_car_cdr(&args_vec[0])?;
501
502                if let Value::Symbol(ref name) = name_val {
503                    // Build lambda: (lambda params body...)
504                    let lambda_body = args_vec[1..].to_vec();
505                    let mut body_list = Value::Nil;
506                    for expr in lambda_body.into_iter().rev() {
507                        body_list = Value::cons(expr, body_list);
508                    }
509                    let lambda_expr = Value::cons(
510                        Value::symbol("lambda"),
511                        Value::cons(params, body_list),
512                    );
513
514                    let lambda_value = self.eval_inner(lambda_expr, env.clone())?;
515                    env.define(name, lambda_value);
516                    Ok(Value::Unspecified)
517                } else {
518                    Err(EvalError::new(
519                        "First element of define must be a symbol".to_string(),
520                    ))
521                }
522            }
523
524            _ => Err(EvalError::new(
525                "First argument to define must be symbol or list".to_string(),
526            )),
527        }
528    }
529
530    /// Evaluate (define-language name props...)
531    /// DSSSL language definition - defines the language name as a symbol
532    fn eval_define_language(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
533        let args_vec = self.list_to_vec(args)?;
534
535        if args_vec.is_empty() {
536            return Err(EvalError::new(
537                "define-language requires at least 1 argument".to_string(),
538            ));
539        }
540
541        // First argument must be a symbol (language name)
542        if let Value::Symbol(ref name) = args_vec[0] {
543            // Define the language name as a symbol bound to itself
544            // This allows it to be used in (declare-default-language name)
545            env.define(name, args_vec[0].clone());
546            Ok(Value::Unspecified)
547        } else {
548            Err(EvalError::new(
549                "First argument to define-language must be a symbol".to_string(),
550            ))
551        }
552    }
553
554    /// Evaluate (declare-flow-object-class name public-id)
555    /// DSSSL flow object class declaration - defines the class name as a symbol
556    fn eval_declare_flow_object_class(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
557        let args_vec = self.list_to_vec(args)?;
558
559        if args_vec.is_empty() {
560            return Err(EvalError::new(
561                "declare-flow-object-class requires at least 1 argument".to_string(),
562            ));
563        }
564
565        // First argument must be a symbol (flow object class name)
566        if let Value::Symbol(ref name) = args_vec[0] {
567            // Define the class name as a symbol bound to itself
568            // This allows it to be used in (make name ...) constructs
569            env.define(name, args_vec[0].clone());
570            Ok(Value::Unspecified)
571        } else {
572            Err(EvalError::new(
573                "First argument to declare-flow-object-class must be a symbol".to_string(),
574            ))
575        }
576    }
577
578    /// Evaluate (declare-characteristic name public-id default-value)
579    /// DSSSL characteristic declaration - defines the characteristic with its default value
580    fn eval_declare_characteristic(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
581        let args_vec = self.list_to_vec(args)?;
582
583        if args_vec.len() < 3 {
584            return Err(EvalError::new(
585                "declare-characteristic requires at least 3 arguments (name, public-id, default-value)".to_string(),
586            ));
587        }
588
589        // First argument must be a symbol (characteristic name)
590        if let Value::Symbol(ref name) = args_vec[0] {
591            // Third argument is the default value - evaluate it
592            let default_value = self.eval(args_vec[2].clone(), env.clone())?;
593
594            // Define the characteristic name as a variable with its default value
595            env.define(name, default_value);
596            Ok(Value::Unspecified)
597        } else {
598            Err(EvalError::new(
599                "First argument to declare-characteristic must be a symbol".to_string(),
600            ))
601        }
602    }
603
604    /// DSSSL element construction rule (OpenJade SchemeParser::doElement)
605    /// Syntax: (element element-name construction-expression)
606    ///
607    /// Stores the rule in processing mode WITHOUT evaluating the body.
608    /// The body will be evaluated later during tree processing when a matching element is found.
609    fn eval_element(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
610        let args_vec = self.list_to_vec(args)?;
611
612        if args_vec.len() < 2 {
613            return Err(EvalError::new(
614                "element requires at least 2 arguments (element-name and construction-expression)".to_string(),
615            ));
616        }
617
618        // First argument is the element name (symbol)
619        let element_name = if let Value::Symbol(ref name) = args_vec[0] {
620            name.clone()
621        } else {
622            return Err(EvalError::new(
623                "First argument to element must be a symbol".to_string(),
624            ));
625        };
626
627        // Second argument is the construction expression (NOT evaluated yet!)
628        // Store it for later evaluation during processing
629        self.processing_mode.add_rule(element_name.to_string(), args_vec[1].clone());
630
631        Ok(Value::Unspecified)
632    }
633
634    /// DSSSL process-children (OpenJade ProcessContext::processChildren)
635    /// Syntax: (process-children)
636    ///
637    /// Processes all children of the current node.
638    /// For each child, matches construction rules and evaluates them.
639    fn eval_process_children(&mut self, env: Gc<Environment>) -> EvalResult {
640        // Get current node
641        let current_node = match &self.current_node {
642            Some(node) => node.clone(),
643            None => return Err(EvalError::new("No current node".to_string())),
644        };
645
646        // Get children
647        let mut children = current_node.children();
648
649        // Process each child (using DSSSL node-list iteration pattern)
650        let mut result = Value::Unspecified;
651        while !children.is_empty() {
652            // Get first child
653            if let Some(child_node) = children.first() {
654                // Save current node
655                let saved_node = self.current_node.clone();
656
657                // Set child as current node
658                self.current_node = Some(Rc::new(child_node));
659
660                // Process the child node
661                result = self.process_node(env.clone())?;
662
663                // Restore current node
664                self.current_node = saved_node;
665            }
666
667            // Move to rest of children
668            children = children.rest();
669        }
670
671        Ok(result)
672    }
673
674    /// DSSSL make flow object (OpenJade FotBuilder)
675    /// Syntax: (make flow-object-type keyword: value ... body-sosofo)
676    ///
677    /// Creates flow objects and writes them to the backend.
678    /// Supports: entity, formatting-instruction
679    fn eval_make(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
680        let args_vec = self.list_to_vec(args)?;
681
682        if args_vec.is_empty() {
683            return Err(EvalError::new(
684                "make requires at least a flow object type".to_string(),
685            ));
686        }
687
688        // First argument is the flow object type (symbol)
689        let fo_type = match &args_vec[0] {
690            Value::Symbol(s) => s.as_ref(),
691            _ => return Err(EvalError::new(
692                "make: first argument must be a flow object type symbol".to_string(),
693            )),
694        };
695
696        // Parse keyword arguments and body
697        let mut i = 1;
698        let mut system_id = None;
699        let mut data = None;
700
701        while i < args_vec.len() {
702            match &args_vec[i] {
703                Value::Keyword(kw) => {
704                    // Next argument is the keyword value
705                    if i + 1 >= args_vec.len() {
706                        return Err(EvalError::new(
707                            format!("make: keyword {} requires a value", kw),
708                        ));
709                    }
710                    let value = self.eval(args_vec[i + 1].clone(), env.clone())?;
711
712                    match kw.as_ref() {
713                        "system-id" => {
714                            if let Value::String(s) = value {
715                                system_id = Some(s);
716                            } else {
717                                return Err(EvalError::new(
718                                    "make: system-id must be a string".to_string(),
719                                ));
720                            }
721                        }
722                        "data" => {
723                            if let Value::String(s) = value {
724                                data = Some(s);
725                            } else {
726                                return Err(EvalError::new(
727                                    "make: data must be a string".to_string(),
728                                ));
729                            }
730                        }
731                        _ => {
732                            // Ignore unknown keywords for now
733                        }
734                    }
735                    i += 2;
736                }
737                _ => {
738                    // Non-keyword argument - evaluate as body sosofo
739                    // Nested make calls will append to backend buffer
740                    let _result = self.eval(args_vec[i].clone(), env.clone())?;
741                    i += 1;
742                }
743            }
744        }
745
746        // Call backend method based on flow object type
747        match self.backend {
748            Some(ref backend) => {
749                match fo_type {
750                    "entity" => {
751                        if let Some(sid) = system_id {
752                            // Get current buffer content and write to file
753                            let content = backend.borrow().current_output().to_string();
754                            backend.borrow_mut().entity(&sid, &content)
755                                .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
756                            // Clear buffer after writing file
757                            backend.borrow_mut().clear_buffer();
758                        } else {
759                            return Err(EvalError::new(
760                                "make entity requires system-id: keyword".to_string(),
761                            ));
762                        }
763                    }
764                    "formatting-instruction" => {
765                        if let Some(d) = data {
766                            // Append to current buffer
767                            backend.borrow_mut().formatting_instruction(&d)
768                                .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
769                        } else {
770                            return Err(EvalError::new(
771                                "make formatting-instruction requires data: keyword".to_string(),
772                            ));
773                        }
774                    }
775                    _ => {
776                        // Unknown flow object type - just return unspecified for now
777                        return Ok(Value::Unspecified);
778                    }
779                }
780            }
781            None => {
782                return Err(EvalError::new(
783                    "make: no backend available".to_string(),
784                ));
785            }
786        }
787
788        Ok(Value::Unspecified)
789    }
790
791    /// (set! name value)
792    fn eval_set(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
793        let args_vec = self.list_to_vec(args)?;
794        if args_vec.len() != 2 {
795            return Err(EvalError::new(
796                "set! requires exactly 2 arguments".to_string(),
797            ));
798        }
799
800        if let Value::Symbol(ref name) = args_vec[0] {
801            let value = self.eval(args_vec[1].clone(), env.clone())?;
802            env.set(name, value)
803                .map_err(|e| EvalError::new(e))?;
804            Ok(Value::Unspecified)
805        } else {
806            Err(EvalError::new(
807                "First argument to set! must be a symbol".to_string(),
808            ))
809        }
810    }
811
812    /// (lambda (params...) body...)
813    fn eval_lambda(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
814        let args_vec = self.list_to_vec(args)?;
815        if args_vec.len() < 2 {
816            return Err(EvalError::new(
817                "lambda requires at least 2 arguments (params and body)".to_string(),
818            ));
819        }
820
821        // Extract parameter list
822        let params_list = &args_vec[0];
823        let params_vec = if params_list.is_nil() {
824            // No parameters: (lambda () body)
825            Vec::new()
826        } else {
827            self.list_to_vec(params_list.clone())?
828        };
829
830        // Convert parameter values to strings
831        let mut param_names = Vec::new();
832        for param in params_vec {
833            if let Value::Symbol(ref name) = param {
834                param_names.push(name.to_string());
835            } else {
836                return Err(EvalError::new(format!(
837                    "Lambda parameter must be a symbol, got: {:?}",
838                    param
839                )));
840            }
841        }
842
843        // Extract body (one or more expressions)
844        let body = if args_vec.len() == 2 {
845            // Single body expression
846            args_vec[1].clone()
847        } else {
848            // Multiple body expressions - wrap in (begin ...)
849            let mut body_list = Value::Nil;
850            for expr in args_vec[1..].iter().rev() {
851                body_list = Value::cons(expr.clone(), body_list);
852            }
853            Value::cons(Value::symbol("begin"), body_list)
854        };
855
856        // Create lambda closure capturing current environment
857        Ok(Value::lambda(param_names, body, env))
858    }
859
860    /// (let ((var val)...) body...)
861    fn eval_let(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
862        let args_vec = self.list_to_vec(args)?;
863        if args_vec.len() < 2 {
864            return Err(EvalError::new(
865                "let requires at least 2 arguments".to_string(),
866            ));
867        }
868
869        // Check if this is named let: (let name ((var val)...) body...)
870        if let Value::Symbol(ref loop_name) = args_vec[0] {
871            if args_vec.len() < 3 {
872                return Err(EvalError::new(
873                    "named let requires at least 3 arguments".to_string(),
874                ));
875            }
876
877            // Named let: transform to (letrec ((name (lambda (vars...) body...))) (name vals...))
878            let bindings_list = &args_vec[1];
879            let bindings = self.list_to_vec(bindings_list.clone())?;
880            let body = &args_vec[2..];
881
882            // Extract variable names and initial values
883            let mut var_names = Vec::new();
884            let mut init_values = Vec::new();
885            for binding in &bindings {
886                let binding_vec = self.list_to_vec(binding.clone())?;
887                if binding_vec.len() != 2 {
888                    return Err(EvalError::new(
889                        "named let binding must have exactly 2 elements".to_string(),
890                    ));
891                }
892                var_names.push(binding_vec[0].clone());
893                init_values.push(binding_vec[1].clone());
894            }
895
896            // Create lambda: (lambda (vars...) body...)
897            let lambda_params = self.vec_to_list(var_names);
898            let mut lambda_body = vec![Value::symbol("lambda"), lambda_params];
899            lambda_body.extend_from_slice(body);
900            let lambda_expr = self.vec_to_list(lambda_body);
901
902            // Create letrec binding: ((name (lambda ...)))
903            let letrec_binding = Value::cons(
904                Value::symbol(loop_name),
905                Value::cons(lambda_expr, Value::Nil),
906            );
907            let letrec_bindings = Value::cons(letrec_binding, Value::Nil);
908
909            // Create function call: (name vals...)
910            let mut call_expr = vec![Value::symbol(loop_name)];
911            call_expr.extend_from_slice(&init_values);
912            let call = self.vec_to_list(call_expr);
913
914            // Evaluate: (letrec ((name (lambda ...))) (name vals...))
915            return self.eval_letrec(self.vec_to_list(vec![letrec_bindings, call]), env);
916        }
917
918        // Standard let: (let ((var val)...) body...)
919        let bindings_list = &args_vec[0];
920        let bindings = self.list_to_vec(bindings_list.clone())?;
921
922        // Create new environment extending current
923        let new_env = Environment::extend(env.clone());
924
925        // Evaluate bindings in OLD environment, define in NEW environment
926        for binding in bindings {
927            let binding_vec = self.list_to_vec(binding)?;
928            if binding_vec.len() != 2 {
929                return Err(EvalError::new(
930                    "let binding must have exactly 2 elements".to_string(),
931                ));
932            }
933
934            if let Value::Symbol(ref name) = binding_vec[0] {
935                let value = self.eval_inner(binding_vec[1].clone(), env.clone())?;
936                new_env.define(name, value);
937            } else {
938                return Err(EvalError::new(
939                    "Binding variable must be a symbol".to_string(),
940                ));
941            }
942        }
943
944        // Evaluate body in new environment
945        let body = &args_vec[1..];
946        self.eval_sequence(body, new_env)
947    }
948
949    /// (let* ((var val)...) body...)
950    fn eval_let_star(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
951        let args_vec = self.list_to_vec(args)?;
952        if args_vec.len() < 2 {
953            return Err(EvalError::new(
954                "let* requires at least 2 arguments".to_string(),
955            ));
956        }
957
958        // Parse bindings
959        let bindings_list = &args_vec[0];
960        let bindings = self.list_to_vec(bindings_list.clone())?;
961
962        // Create new environment
963        let current_env = Environment::extend(env);
964
965        // Evaluate bindings sequentially in CURRENT environment
966        for binding in bindings {
967            let binding_vec = self.list_to_vec(binding)?;
968            if binding_vec.len() != 2 {
969                return Err(EvalError::new(
970                    "let* binding must have exactly 2 elements".to_string(),
971                ));
972            }
973
974            if let Value::Symbol(ref name) = binding_vec[0] {
975                let value = self.eval_inner(binding_vec[1].clone(), current_env.clone())?;
976                current_env.define(name, value);
977            } else {
978                return Err(EvalError::new(
979                    "Binding variable must be a symbol".to_string(),
980                ));
981            }
982        }
983
984        // Evaluate body
985        let body = &args_vec[1..];
986        self.eval_sequence(body, current_env)
987    }
988
989    /// (letrec ((var val)...) body...)
990    ///
991    /// letrec allows recursive definitions - all bindings can refer to each other.
992    /// Implementation:
993    /// 1. Create new environment
994    /// 2. Bind all variables to Unspecified first
995    /// 3. Evaluate all values in the new environment
996    /// 4. Update bindings with evaluated values
997    /// 5. Evaluate body in the new environment
998    fn eval_letrec(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
999        let args_vec = self.list_to_vec(args)?;
1000        if args_vec.len() < 2 {
1001            return Err(EvalError::new(
1002                "letrec requires at least 2 arguments".to_string(),
1003            ));
1004        }
1005
1006        // Parse bindings
1007        let bindings_list = &args_vec[0];
1008        let bindings = self.list_to_vec(bindings_list.clone())?;
1009
1010        // Create new environment extending current
1011        let new_env = Environment::extend(env);
1012
1013        // First pass: bind all variables to Unspecified
1014        let mut var_names = Vec::new();
1015        for binding in &bindings {
1016            let binding_vec = self.list_to_vec(binding.clone())?;
1017            if binding_vec.len() != 2 {
1018                return Err(EvalError::new(
1019                    "letrec binding must have exactly 2 elements".to_string(),
1020                ));
1021            }
1022
1023            if let Value::Symbol(ref name) = binding_vec[0] {
1024                var_names.push(name.to_string());
1025                new_env.define(name, Value::Unspecified);
1026            } else {
1027                return Err(EvalError::new(
1028                    "Binding variable must be a symbol".to_string(),
1029                ));
1030            }
1031        }
1032
1033        // Second pass: evaluate all values in the new environment and update bindings
1034        for (i, binding) in bindings.iter().enumerate() {
1035            let binding_vec = self.list_to_vec(binding.clone())?;
1036            let value = self.eval_inner(binding_vec[1].clone(), new_env.clone())?;
1037
1038            // Update the binding (set! will work since we already defined it)
1039            new_env.set(&var_names[i], value)
1040                .map_err(|e| EvalError::new(e))?;
1041        }
1042
1043        // Evaluate body in new environment
1044        let body = &args_vec[1..];
1045        self.eval_sequence(body, new_env)
1046    }
1047
1048    /// (begin expr...)
1049    fn eval_begin(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1050        let args_vec = self.list_to_vec(args)?;
1051        self.eval_sequence(&args_vec, env)
1052    }
1053
1054    /// (cond (test expr...)...)
1055    fn eval_cond(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1056        let clauses = self.list_to_vec(args)?;
1057
1058        for clause in clauses {
1059            let clause_vec = self.list_to_vec(clause)?;
1060            if clause_vec.is_empty() {
1061                return Err(EvalError::new("Empty cond clause".to_string()));
1062            }
1063
1064            // Check for else clause
1065            if let Value::Symbol(ref sym) = clause_vec[0] {
1066                if &**sym == "else" {
1067                    return self.eval_sequence(&clause_vec[1..], env);
1068                }
1069            }
1070
1071            // Evaluate test
1072            let test = self.eval_inner(clause_vec[0].clone(), env.clone())?;
1073            if test.is_true() {
1074                if clause_vec.len() == 1 {
1075                    return Ok(test);
1076                } else {
1077                    return self.eval_sequence(&clause_vec[1..], env);
1078                }
1079            }
1080        }
1081
1082        Ok(Value::Unspecified)
1083    }
1084
1085    /// (case key ((datum...) expr...)...)
1086    ///
1087    /// R4RS case statement:
1088    /// ```scheme
1089    /// (case expr
1090    ///   ((datum1 datum2 ...) result1 result2 ...)
1091    ///   ((datum3 datum4 ...) result3 result4 ...)
1092    ///   ...
1093    ///   [else resultN ...])
1094    /// ```
1095    ///
1096    /// The key expression is evaluated and compared with each datum using eqv?.
1097    /// The datums are NOT evaluated (they are literal constants).
1098    fn eval_case(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1099        let args_vec = self.list_to_vec(args)?;
1100        if args_vec.is_empty() {
1101            return Err(EvalError::new("case requires at least 1 argument".to_string()));
1102        }
1103
1104        // Evaluate the key expression
1105        let key = self.eval_inner(args_vec[0].clone(), env.clone())?;
1106
1107        // Iterate through clauses
1108        for clause in &args_vec[1..] {
1109            let clause_vec = self.list_to_vec(clause.clone())?;
1110            if clause_vec.is_empty() {
1111                return Err(EvalError::new("Empty case clause".to_string()));
1112            }
1113
1114            // Check for else clause
1115            if let Value::Symbol(ref sym) = clause_vec[0] {
1116                if &**sym == "else" {
1117                    return self.eval_sequence(&clause_vec[1..], env);
1118                }
1119            }
1120
1121            // First element should be a list of datums
1122            let datums = self.list_to_vec(clause_vec[0].clone())?;
1123
1124            // Check if key matches any datum using eqv?
1125            for datum in datums {
1126                if key.eqv(&datum) {
1127                    // Match found - evaluate body expressions
1128                    if clause_vec.len() == 1 {
1129                        // No expressions in clause - return unspecified
1130                        return Ok(Value::Unspecified);
1131                    } else {
1132                        return self.eval_sequence(&clause_vec[1..], env);
1133                    }
1134                }
1135            }
1136        }
1137
1138        // No match found
1139        Ok(Value::Unspecified)
1140    }
1141
1142    /// (and expr...)
1143    fn eval_and(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1144        let args_vec = self.list_to_vec(args)?;
1145
1146        if args_vec.is_empty() {
1147            return Ok(Value::bool(true));
1148        }
1149
1150        let mut result = Value::bool(true);
1151        for expr in args_vec {
1152            result = self.eval_inner(expr, env.clone())?;
1153            if !result.is_true() {
1154                return Ok(Value::bool(false));
1155            }
1156        }
1157
1158        Ok(result)
1159    }
1160
1161    /// (or expr...)
1162    fn eval_or(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1163        let args_vec = self.list_to_vec(args)?;
1164
1165        for expr in args_vec {
1166            let result = self.eval_inner(expr, env.clone())?;
1167            if result.is_true() {
1168                return Ok(result);
1169            }
1170        }
1171
1172        Ok(Value::bool(false))
1173    }
1174
1175    /// Evaluate a sequence of expressions, return last result
1176    fn eval_sequence(&mut self, exprs: &[Value], env: Gc<Environment>) -> EvalResult {
1177        if exprs.is_empty() {
1178            return Ok(Value::Unspecified);
1179        }
1180
1181        let mut result = Value::Unspecified;
1182        for expr in exprs {
1183            result = self.eval_inner(expr.clone(), env.clone())?;
1184        }
1185
1186        Ok(result)
1187    }
1188
1189    /// (apply proc args)
1190    ///
1191    /// Apply a procedure to a list of arguments.
1192    /// Example: (apply + '(1 2 3)) → 6
1193    fn eval_apply(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1194        let args_vec = self.list_to_vec(args)?;
1195        if args_vec.len() != 2 {
1196            return Err(EvalError::new(
1197                "apply requires exactly 2 arguments".to_string(),
1198            ));
1199        }
1200
1201        // Evaluate the procedure
1202        let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
1203
1204        // Evaluate the argument list
1205        let arg_list = self.eval_inner(args_vec[1].clone(), env)?;
1206
1207        // Convert argument list to vector
1208        let arg_values = self.list_to_vec(arg_list)?;
1209
1210        // Apply the procedure
1211        self.apply(proc, arg_values)
1212    }
1213
1214    /// (map proc list)
1215    ///
1216    /// Apply procedure to each element of list, return list of results.
1217    /// Example: (map (lambda (x) (* x 2)) '(1 2 3)) → '(2 4 6)
1218    /// (map proc list1 list2 ...)
1219    ///
1220    /// R4RS: Apply procedure to corresponding elements of lists.
1221    /// All lists must have the same length.
1222    /// Returns a list of results.
1223    ///
1224    /// Examples:
1225    /// - (map + '(1 2 3) '(4 5 6)) => (5 7 9)
1226    /// - (map list '(1 2) '(a b) '(x y)) => ((1 a x) (2 b y))
1227    fn eval_map(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1228        let args_vec = self.list_to_vec(args)?;
1229        if args_vec.len() < 2 {
1230            return Err(EvalError::new("map requires at least 2 arguments".to_string()));
1231        }
1232
1233        // Evaluate the procedure
1234        let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
1235
1236        // Evaluate all lists
1237        let mut lists = Vec::new();
1238        for i in 1..args_vec.len() {
1239            let list = self.eval_inner(args_vec[i].clone(), env.clone())?;
1240            let list_vec = self.list_to_vec(list)?;
1241            lists.push(list_vec);
1242        }
1243
1244        // Check all lists have the same length
1245        if lists.is_empty() {
1246            return Ok(Value::Nil);
1247        }
1248
1249        let length = lists[0].len();
1250        for list in &lists[1..] {
1251            if list.len() != length {
1252                return Err(EvalError::new(
1253                    "map: all lists must have the same length".to_string(),
1254                ));
1255            }
1256        }
1257
1258        // Apply procedure to corresponding elements
1259        let mut result_vec = Vec::new();
1260        for i in 0..length {
1261            // Gather i-th element from each list
1262            let mut proc_args = Vec::new();
1263            for list in &lists {
1264                proc_args.push(list[i].clone());
1265            }
1266
1267            // Apply procedure
1268            let result = self.apply(proc.clone(), proc_args)?;
1269            result_vec.push(result);
1270        }
1271
1272        // Convert result vector back to list
1273        let mut result_list = Value::Nil;
1274        for elem in result_vec.into_iter().rev() {
1275            result_list = Value::cons(elem, result_list);
1276        }
1277
1278        Ok(result_list)
1279    }
1280
1281    /// (for-each proc list1 list2 ...)
1282    ///
1283    /// R4RS: Apply procedure to corresponding elements of lists for side effects.
1284    /// All lists must have the same length.
1285    /// Returns unspecified.
1286    ///
1287    /// Example: (for-each display '("a" "b" "c"))
1288    fn eval_for_each(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1289        let args_vec = self.list_to_vec(args)?;
1290        if args_vec.len() < 2 {
1291            return Err(EvalError::new(
1292                "for-each requires at least 2 arguments".to_string(),
1293            ));
1294        }
1295
1296        // Evaluate the procedure
1297        let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
1298
1299        // Evaluate all lists
1300        let mut lists = Vec::new();
1301        for i in 1..args_vec.len() {
1302            let list = self.eval_inner(args_vec[i].clone(), env.clone())?;
1303            let list_vec = self.list_to_vec(list)?;
1304            lists.push(list_vec);
1305        }
1306
1307        // Check all lists have the same length
1308        if lists.is_empty() {
1309            return Ok(Value::Unspecified);
1310        }
1311
1312        let length = lists[0].len();
1313        for list in &lists[1..] {
1314            if list.len() != length {
1315                return Err(EvalError::new(
1316                    "for-each: all lists must have the same length".to_string(),
1317                ));
1318            }
1319        }
1320
1321        // Apply procedure to corresponding elements (for side effects)
1322        for i in 0..length {
1323            // Gather i-th element from each list
1324            let mut proc_args = Vec::new();
1325            for list in &lists {
1326                proc_args.push(list[i].clone());
1327            }
1328
1329            // Apply procedure for side effects
1330            self.apply(proc.clone(), proc_args)?;
1331        }
1332
1333        Ok(Value::Unspecified)
1334    }
1335
1336    /// (load filename)
1337    ///
1338    /// Load and evaluate Scheme code from a file.
1339    /// Returns the result of the last expression in the file.
1340    fn eval_load(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
1341        let args_vec = self.list_to_vec(args)?;
1342        if args_vec.len() != 1 {
1343            return Err(EvalError::new(
1344                "load requires exactly 1 argument".to_string(),
1345            ));
1346        }
1347
1348        // Evaluate the filename argument
1349        let filename_val = self.eval_inner(args_vec[0].clone(), env.clone())?;
1350
1351        let filename = match filename_val {
1352            Value::String(s) => s.to_string(),
1353            _ => return Err(EvalError::new(
1354                format!("load: filename must be a string, got {:?}", filename_val)
1355            )),
1356        };
1357
1358        // Read the file
1359        let contents = std::fs::read_to_string(&filename)
1360            .map_err(|e| EvalError::new(format!("load: cannot read file '{}': {}", filename, e)))?;
1361
1362        // Parse the file contents
1363        let mut parser = crate::scheme::parser::Parser::new(&contents);
1364        let mut result = Value::Unspecified;
1365
1366        // Evaluate each expression in sequence
1367        loop {
1368            match parser.parse() {
1369                Ok(expr) => {
1370                    result = self.eval_inner(expr, env.clone())?;
1371                }
1372                Err(e) => {
1373                    // Check if we've reached end of input (not an error)
1374                    let error_msg = e.to_string();
1375                    if error_msg.contains("Unexpected end of input")
1376                        || error_msg.contains("Expected")
1377                        || error_msg.contains("EOF") {
1378                        break;
1379                    }
1380                    return Err(EvalError::new(
1381                        format!("load: parse error in '{}': {}", filename, e)
1382                    ));
1383                }
1384            }
1385        }
1386
1387        Ok(result)
1388    }
1389
1390    // =========================================================================
1391    // Function Application
1392    // =========================================================================
1393
1394    /// Apply a function to arguments
1395    fn eval_application(
1396        &mut self,
1397        operator: Value,
1398        args: Value,
1399        env: Gc<Environment>,
1400    ) -> EvalResult {
1401        // Evaluate operator
1402        let proc = self.eval_inner(operator, env.clone())?;
1403
1404        // Evaluate arguments
1405        let args_vec = self.list_to_vec(args)?;
1406        let mut evaled_args = Vec::new();
1407        for arg in args_vec {
1408            evaled_args.push(self.eval_inner(arg, env.clone())?);
1409        }
1410
1411        // Apply procedure
1412        self.apply(proc, evaled_args)
1413    }
1414
1415    /// Apply a procedure to evaluated arguments
1416    fn apply(&mut self, proc: Value, args: Vec<Value>) -> EvalResult {
1417        if let Value::Procedure(ref p) = proc {
1418            match &**p {
1419                Procedure::Primitive { func, .. } => {
1420                    func(&args).map_err(|e| EvalError::new(e))
1421                }
1422                Procedure::Lambda { params, body, env } => {
1423                    // Check argument count
1424                    if args.len() != params.len() {
1425                        return Err(EvalError::new(format!(
1426                            "Lambda expects {} arguments, got {}",
1427                            params.len(),
1428                            args.len()
1429                        )));
1430                    }
1431
1432                    // Create new environment extending the closure environment
1433                    let lambda_env = Environment::extend(env.clone());
1434
1435                    // Bind parameters to arguments
1436                    for (param_name, arg_value) in params.iter().zip(args.iter()) {
1437                        lambda_env.define(param_name, arg_value.clone());
1438                    }
1439
1440                    // Evaluate body in the new environment
1441                    self.eval_inner((**body).clone(), lambda_env)
1442                }
1443            }
1444        } else {
1445            Err(EvalError::new(format!(
1446                "Not a procedure: {:?}",
1447                proc
1448            )))
1449        }
1450    }
1451}
1452
1453impl Default for Evaluator {
1454    fn default() -> Self {
1455        Self::new()
1456    }
1457}
1458
1459// =============================================================================
1460// Tests
1461// =============================================================================
1462
1463#[cfg(test)]
1464mod tests {
1465    use super::*;
1466
1467    fn make_env() -> Gc<Environment> {
1468        Environment::new_global()
1469    }
1470
1471    #[test]
1472    fn test_eval_self_evaluating() {
1473        let mut eval = Evaluator::new();
1474        let env = make_env();
1475
1476        assert!(eval.eval(Value::integer(42), env.clone()).unwrap().is_integer());
1477        assert!(eval.eval(Value::bool(true), env.clone()).unwrap().is_bool());
1478        assert!(eval.eval(Value::string("hello".to_string()), env).unwrap().is_string());
1479    }
1480
1481    #[test]
1482    fn test_eval_quote() {
1483        let mut eval = Evaluator::new();
1484        let env = make_env();
1485
1486        // (quote (1 2 3))
1487        let expr = Value::cons(
1488            Value::symbol("quote"),
1489            Value::cons(
1490                Value::cons(
1491                    Value::integer(1),
1492                    Value::cons(Value::integer(2), Value::cons(Value::integer(3), Value::Nil)),
1493                ),
1494                Value::Nil,
1495            ),
1496        );
1497
1498        let result = eval.eval(expr, env).unwrap();
1499        assert!(result.is_list());
1500    }
1501
1502    #[test]
1503    fn test_eval_if_true() {
1504        let mut eval = Evaluator::new();
1505        let env = make_env();
1506
1507        // (if #t 1 2)
1508        let expr = Value::cons(
1509            Value::symbol("if"),
1510            Value::cons(
1511                Value::bool(true),
1512                Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
1513            ),
1514        );
1515
1516        let result = eval.eval(expr, env).unwrap();
1517        if let Value::Integer(n) = result {
1518            assert_eq!(n, 1);
1519        } else {
1520            panic!("Expected integer 1");
1521        }
1522    }
1523
1524    #[test]
1525    fn test_eval_if_false() {
1526        let mut eval = Evaluator::new();
1527        let env = make_env();
1528
1529        // (if #f 1 2)
1530        let expr = Value::cons(
1531            Value::symbol("if"),
1532            Value::cons(
1533                Value::bool(false),
1534                Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
1535            ),
1536        );
1537
1538        let result = eval.eval(expr, env).unwrap();
1539        if let Value::Integer(n) = result {
1540            assert_eq!(n, 2);
1541        } else {
1542            panic!("Expected integer 2");
1543        }
1544    }
1545
1546    #[test]
1547    fn test_eval_define() {
1548        let mut eval = Evaluator::new();
1549        let env = make_env();
1550
1551        // (define x 42)
1552        let expr = Value::cons(
1553            Value::symbol("define"),
1554            Value::cons(Value::symbol("x"), Value::cons(Value::integer(42), Value::Nil)),
1555        );
1556
1557        eval.eval(expr, env.clone()).unwrap();
1558
1559        // Check that x is defined
1560        assert!(env.is_defined("x"));
1561        if let Value::Integer(n) = env.lookup("x").unwrap() {
1562            assert_eq!(n, 42);
1563        }
1564    }
1565
1566    #[test]
1567    fn test_eval_symbol_lookup() {
1568        let mut eval = Evaluator::new();
1569        let env = make_env();
1570
1571        env.define("x", Value::integer(99));
1572
1573        let result = eval.eval(Value::symbol("x"), env).unwrap();
1574        if let Value::Integer(n) = result {
1575            assert_eq!(n, 99);
1576        } else {
1577            panic!("Expected integer 99");
1578        }
1579    }
1580
1581    #[test]
1582    fn test_eval_and() {
1583        let mut eval = Evaluator::new();
1584        let env = make_env();
1585
1586        // (and #t #t)
1587        let expr = Value::cons(
1588            Value::symbol("and"),
1589            Value::cons(Value::bool(true), Value::cons(Value::bool(true), Value::Nil)),
1590        );
1591
1592        let result = eval.eval(expr, env.clone()).unwrap();
1593        assert!(result.is_true());
1594
1595        // (and #t #f)
1596        let expr = Value::cons(
1597            Value::symbol("and"),
1598            Value::cons(Value::bool(true), Value::cons(Value::bool(false), Value::Nil)),
1599        );
1600
1601        let result = eval.eval(expr, env).unwrap();
1602        assert!(!result.is_true());
1603    }
1604
1605    #[test]
1606    fn test_eval_or() {
1607        let mut eval = Evaluator::new();
1608        let env = make_env();
1609
1610        // (or #f #t)
1611        let expr = Value::cons(
1612            Value::symbol("or"),
1613            Value::cons(Value::bool(false), Value::cons(Value::bool(true), Value::Nil)),
1614        );
1615
1616        let result = eval.eval(expr, env.clone()).unwrap();
1617        assert!(result.is_true());
1618
1619        // (or #f #f)
1620        let expr = Value::cons(
1621            Value::symbol("or"),
1622            Value::cons(Value::bool(false), Value::cons(Value::bool(false), Value::Nil)),
1623        );
1624
1625        let result = eval.eval(expr, env).unwrap();
1626        assert!(!result.is_true());
1627    }
1628
1629    #[test]
1630    fn test_eval_lambda_creation() {
1631        let mut eval = Evaluator::new();
1632        let env = make_env();
1633
1634        // (lambda (x) x)
1635        let expr = Value::cons(
1636            Value::symbol("lambda"),
1637            Value::cons(
1638                Value::cons(Value::symbol("x"), Value::Nil),
1639                Value::cons(Value::symbol("x"), Value::Nil),
1640            ),
1641        );
1642
1643        let result = eval.eval(expr, env).unwrap();
1644        assert!(result.is_procedure());
1645    }
1646
1647    #[test]
1648    fn test_eval_lambda_application() {
1649        let mut eval = Evaluator::new();
1650        let env = make_env();
1651
1652        // ((lambda (x) x) 42)
1653        let lambda_expr = Value::cons(
1654            Value::symbol("lambda"),
1655            Value::cons(
1656                Value::cons(Value::symbol("x"), Value::Nil),
1657                Value::cons(Value::symbol("x"), Value::Nil),
1658            ),
1659        );
1660
1661        let app_expr = Value::cons(lambda_expr, Value::cons(Value::integer(42), Value::Nil));
1662
1663        let result = eval.eval(app_expr, env).unwrap();
1664        if let Value::Integer(n) = result {
1665            assert_eq!(n, 42);
1666        } else {
1667            panic!("Expected integer 42");
1668        }
1669    }
1670
1671    #[test]
1672    fn test_eval_lambda_multiple_params() {
1673        let mut eval = Evaluator::new();
1674        let env = make_env();
1675
1676        // ((lambda (x y) x) 1 2) - Just return first param
1677        let params = Value::cons(Value::symbol("x"), Value::cons(Value::symbol("y"), Value::Nil));
1678        let body = Value::symbol("x");
1679
1680        let lambda_expr = Value::cons(Value::symbol("lambda"), Value::cons(params, Value::cons(body, Value::Nil)));
1681
1682        let app_expr = Value::cons(
1683            lambda_expr,
1684            Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
1685        );
1686
1687        let result = eval.eval(app_expr, env).unwrap();
1688        if let Value::Integer(n) = result {
1689            assert_eq!(n, 1);
1690        } else {
1691            panic!("Expected integer 1");
1692        }
1693    }
1694
1695    #[test]
1696    fn test_eval_lambda_wrong_arg_count() {
1697        let mut eval = Evaluator::new();
1698        let env = make_env();
1699
1700        // ((lambda (x) x) 1 2) - wrong argument count
1701        let lambda_expr = Value::cons(
1702            Value::symbol("lambda"),
1703            Value::cons(
1704                Value::cons(Value::symbol("x"), Value::Nil),
1705                Value::cons(Value::symbol("x"), Value::Nil),
1706            ),
1707        );
1708
1709        let app_expr = Value::cons(
1710            lambda_expr,
1711            Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
1712        );
1713
1714        let result = eval.eval(app_expr, env);
1715        assert!(result.is_err());
1716    }
1717
1718    #[test]
1719    fn test_eval_lambda_closure() {
1720        let mut eval = Evaluator::new();
1721        let env = make_env();
1722
1723        // (define x 10)
1724        env.define("x", Value::integer(10));
1725
1726        // ((lambda (y) x) 20)
1727        // Should capture x from outer environment and ignore y
1728        let lambda_expr = Value::cons(
1729            Value::symbol("lambda"),
1730            Value::cons(
1731                Value::cons(Value::symbol("y"), Value::Nil),
1732                Value::cons(Value::symbol("x"), Value::Nil),
1733            ),
1734        );
1735
1736        let app_expr = Value::cons(lambda_expr, Value::cons(Value::integer(20), Value::Nil));
1737
1738        let result = eval.eval(app_expr, env).unwrap();
1739        if let Value::Integer(n) = result {
1740            assert_eq!(n, 10); // Should get x from outer environment
1741        } else {
1742            panic!("Expected integer 10 from closure");
1743        }
1744    }
1745
1746    #[test]
1747    fn test_eval_lambda_no_params() {
1748        let mut eval = Evaluator::new();
1749        let env = make_env();
1750
1751        // ((lambda () 42))
1752        let lambda_expr = Value::cons(
1753            Value::symbol("lambda"),
1754            Value::cons(Value::Nil, Value::cons(Value::integer(42), Value::Nil)),
1755        );
1756
1757        let app_expr = Value::cons(lambda_expr, Value::Nil);
1758
1759        let result = eval.eval(app_expr, env).unwrap();
1760        if let Value::Integer(n) = result {
1761            assert_eq!(n, 42);
1762        } else {
1763            panic!("Expected integer 42");
1764        }
1765    }
1766
1767    #[test]
1768    fn test_eval_lambda_multiple_body_expressions() {
1769        let mut eval = Evaluator::new();
1770        let env = make_env();
1771
1772        // ((lambda (x) 1 2 x) 99)
1773        // Should return x (last expression)
1774        let params = Value::cons(Value::symbol("x"), Value::Nil);
1775        let body1 = Value::integer(1);
1776        let body2 = Value::integer(2);
1777        let body3 = Value::symbol("x");
1778
1779        let lambda_expr = Value::cons(
1780            Value::symbol("lambda"),
1781            Value::cons(
1782                params,
1783                Value::cons(body1, Value::cons(body2, Value::cons(body3, Value::Nil))),
1784            ),
1785        );
1786
1787        let app_expr = Value::cons(lambda_expr, Value::cons(Value::integer(99), Value::Nil));
1788
1789        let result = eval.eval(app_expr, env).unwrap();
1790        if let Value::Integer(n) = result {
1791            assert_eq!(n, 99);
1792        } else {
1793            panic!("Expected integer 99");
1794        }
1795    }
1796}