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