1use crate::scheme::environment::Environment;
30use crate::scheme::parser::Position;
31use crate::scheme::value::{Procedure, Value};
32use crate::scheme::arena::{Arena, ValueId, ValueData};
33use crate::scheme::vm::VM;
34use crate::scheme::compiler::Compiler;
35use crate::scheme::instruction::Instruction;
36use crate::scheme::bridge::{value_to_arena, arena_to_value};
37use crate::grove::{Grove, Node};
38use crate::fot::FotBuilder;
39use gc::Gc;
40use std::rc::Rc;
41use std::cell::RefCell;
42use std::collections::HashMap;
43
44thread_local! {
55 static EVALUATOR_CONTEXT: RefCell<Option<EvaluatorContext>> = RefCell::new(None);
56}
57
58#[derive(Clone)]
60pub struct EvaluatorContext {
61 pub grove: Option<Rc<dyn Grove>>,
62 pub current_node: Option<Rc<Box<dyn Node>>>,
63 pub backend: Option<Rc<RefCell<dyn FotBuilder>>>,
64}
65
66pub fn get_evaluator_context() -> Option<EvaluatorContext> {
68 EVALUATOR_CONTEXT.with(|ctx| ctx.borrow().clone())
69}
70
71fn has_evaluator_context() -> bool {
73 EVALUATOR_CONTEXT.with(|ctx| ctx.borrow().is_some())
74}
75
76fn set_evaluator_context(ctx: EvaluatorContext) {
78 EVALUATOR_CONTEXT.with(|c| *c.borrow_mut() = Some(ctx));
79}
80
81fn clear_evaluator_context() {
83 EVALUATOR_CONTEXT.with(|c| *c.borrow_mut() = None);
84}
85
86use crate::scheme::value::SourceInfo;
91
92#[derive(Debug, Clone)]
96pub struct CallFrame {
97 pub function_name: String,
99 pub source: Option<SourceInfo>,
101}
102
103impl CallFrame {
104 pub fn new(function_name: String, source: Option<SourceInfo>) -> Self {
105 CallFrame {
106 function_name,
107 source,
108 }
109 }
110}
111
112#[derive(Debug, Clone)]
118pub struct EvalError {
119 pub message: String,
120 pub call_stack: Vec<CallFrame>,
121}
122
123impl EvalError {
124 pub fn new(message: String) -> Self {
125 EvalError {
126 message,
127 call_stack: Vec::new(),
128 }
129 }
130
131 pub fn with_stack(message: String, call_stack: Vec<CallFrame>) -> Self {
133 EvalError {
134 message,
135 call_stack,
136 }
137 }
138}
139
140impl std::fmt::Display for EvalError {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 write!(f, "{}", self.message)?;
144
145 for (i, frame) in self.call_stack.iter().rev().enumerate() {
147 if let Some(ref source) = frame.source {
148 if i == 0 {
150 writeln!(f, "\n{}:{}:{}:I: called from here",
151 source.file, source.pos.line, source.pos.column)?;
152 } else {
153 writeln!(f, "{}:{}:{}:I: called from here",
154 source.file, source.pos.line, source.pos.column)?;
155 }
156 } else {
157 if i == 0 {
158 writeln!(f, "\n{}:I: called from here", frame.function_name)?;
159 } else {
160 writeln!(f, "{}:I: called from here", frame.function_name)?;
161 }
162 }
163 }
164
165 Ok(())
166 }
167}
168
169impl std::error::Error for EvalError {}
170
171pub type EvalResult = Result<Value, EvalError>;
172
173#[derive(Clone)]
182pub struct ConstructionRule {
183 pub element_name: String,
185
186 pub context: Vec<String>,
190
191 pub expr: Value,
193
194 pub source_file: Option<String>,
196 pub source_pos: Option<Position>,
197
198 pub cached_instructions: RefCell<Option<(Vec<Instruction>, usize)>>,
205}
206
207pub struct ProcessingMode {
212 pub rules: std::collections::HashMap<String, Vec<ConstructionRule>>,
216
217 pub default_rule: Option<Value>,
219}
220
221impl ProcessingMode {
222 pub fn new() -> Self {
224 ProcessingMode {
225 rules: std::collections::HashMap::new(),
226 default_rule: None,
227 }
228 }
229
230 pub fn add_rule(&mut self, element_name: String, context: Vec<String>, expr: Value, source_file: Option<String>, source_pos: Option<Position>) {
232 self.rules
234 .entry(element_name.clone())
235 .or_insert_with(Vec::new)
236 .push(ConstructionRule {
237 element_name,
238 context,
239 expr,
240 source_file,
241 source_pos,
242 cached_instructions: RefCell::new(None),
243 });
244 }
245
246 pub fn add_default_rule(&mut self, expr: Value) {
248 self.default_rule = Some(expr);
249 }
250
251 pub fn find_match(&self, gi: &str, node: &dyn crate::grove::Node) -> Option<&ConstructionRule> {
259 let rules_for_element = self.rules.get(gi)?;
261
262 rules_for_element.iter().find(|rule| {
264 if rule.context.is_empty() {
268 return true;
269 }
270
271 let mut current = node.parent();
273 for expected_parent in rule.context.iter().rev() {
274 match current {
275 Some(ref parent_node) => {
276 if let Some(parent_gi) = parent_node.gi() {
277 if parent_gi != *expected_parent {
278 return false;
279 }
280 current = parent_node.parent();
281 } else {
282 return false;
283 }
284 }
285 None => return false,
286 }
287 }
288
289 true
290 })
291 }
292}
293
294pub struct ModeManager {
299 modes: std::collections::HashMap<String, ProcessingMode>,
301}
302
303impl ModeManager {
304 pub fn new() -> Self {
306 let mut modes = std::collections::HashMap::new();
307 modes.insert(String::new(), ProcessingMode::new());
308 ModeManager { modes }
309 }
310
311 pub fn get_or_create_mode(&mut self, name: &str) -> &mut ProcessingMode {
313 self.modes.entry(name.to_string()).or_insert_with(ProcessingMode::new)
314 }
315
316 pub fn get_mode(&self, name: &str) -> Option<&ProcessingMode> {
318 self.modes.get(name)
319 }
320
321 pub fn default_mode(&mut self) -> &mut ProcessingMode {
323 self.get_or_create_mode("")
324 }
325
326 pub fn get_default_mode(&self) -> Option<&ProcessingMode> {
328 self.get_mode("")
329 }
330}
331
332pub struct Evaluator {
347 arena: Arena,
353
354 mode_manager: ModeManager,
359
360 current_mode: String,
366
367 current_processing_mode: String,
373
374 backend: Option<Rc<RefCell<dyn FotBuilder>>>,
379
380 call_stack: Vec<CallFrame>,
385
386 current_source_file: Option<String>,
390
391 current_position: Option<Position>,
395
396 line_mappings: Vec<LineMapping>,
402
403 use_vm: bool,
409
410 lambda_cache: HashMap<usize, (Vec<Instruction>, usize)>,
415
416 vm_globals: HashMap<String, ValueId>,
421
422 nodes_processed: usize,
427}
428
429#[derive(Debug, Clone)]
431pub struct LineMapping {
432 pub output_line: usize,
434 pub source_file: String,
436 pub source_line: usize,
438}
439
440impl Evaluator {
441 pub fn new() -> Self {
443 Evaluator {
444 arena: Arena::new(),
445 mode_manager: ModeManager::new(),
446 current_mode: String::new(), current_processing_mode: String::new(), backend: None,
449 call_stack: Vec::new(),
450 current_source_file: None,
451 current_position: None,
452 line_mappings: Vec::new(),
453 use_vm: std::env::var("DAZZLE_VM").is_ok(), lambda_cache: HashMap::new(),
455 vm_globals: HashMap::new(), nodes_processed: 0,
457 }
458 }
459
460 pub fn with_grove(grove: Rc<dyn Grove>) -> Self {
462 let mut arena = Arena::new();
463 arena.grove = Some(grove);
464 Evaluator {
465 arena,
466 mode_manager: ModeManager::new(),
467 current_mode: String::new(), current_processing_mode: String::new(), backend: None,
470 call_stack: Vec::new(),
471 current_source_file: None,
472 current_position: None,
473 line_mappings: Vec::new(),
474 use_vm: std::env::var("DAZZLE_VM").is_ok(), lambda_cache: HashMap::new(),
476 vm_globals: HashMap::new(), nodes_processed: 0,
478 }
479 }
480
481 pub fn enable_vm(&mut self) {
483 self.use_vm = true;
484 }
485
486 pub fn disable_vm(&mut self) {
488 self.use_vm = false;
489 }
490
491 pub fn set_line_mappings(&mut self, mappings: Vec<LineMapping>) {
493 self.line_mappings = mappings;
494 }
495
496 pub fn set_source_file(&mut self, file: String) {
498 self.current_source_file = Some(file);
499 }
500
501 pub fn source_file(&self) -> Option<&str> {
503 self.current_source_file.as_deref()
504 }
505
506 pub fn set_position(&mut self, position: Position) {
508 self.current_position = Some(position);
509 }
510
511 fn push_call_frame(&mut self, function_name: String, source: Option<SourceInfo>) {
513 self.call_stack.push(CallFrame::new(function_name, source));
514 }
515
516 fn pop_call_frame(&mut self) {
518 self.call_stack.pop();
519 }
520
521 fn error_with_stack(&self, message: String) -> EvalError {
523 let full_message = match (&self.current_source_file, &self.current_position) {
525 (Some(file), Some(pos)) => {
526 format!("{}:{}:{}:E: {}", file, pos.line, pos.column, message)
527 }
528 (Some(file), None) => {
529 format!("{}:E: {}", file, message)
530 }
531 _ => message,
532 };
533 EvalError::with_stack(full_message, self.call_stack.clone())
534 }
535
536 pub fn set_backend(&mut self, backend: Rc<RefCell<dyn FotBuilder>>) {
538 self.backend = Some(backend);
539 }
540
541 pub fn set_grove(&mut self, grove: Rc<dyn Grove>) {
543 self.arena.grove = Some(grove);
544 }
545
546 pub fn grove(&self) -> Option<&Rc<dyn Grove>> {
548 self.arena.grove.as_ref()
549 }
550
551 fn get_primitive_static_name(&self, name: &str) -> Option<&'static str> {
556 match name {
557 "cons" => Some("cons"),
559 "car" => Some("car"),
560 "cdr" => Some("cdr"),
561 "cadr" => Some("cadr"),
562 "caddr" => Some("caddr"),
563 "cadddr" => Some("cadddr"),
564 "list" => Some("list"),
565 "length" => Some("length"),
566 "append" => Some("append"),
567 "reverse" => Some("reverse"),
568 "list-ref" => Some("list-ref"),
569 "list-tail" => Some("list-tail"),
570 "member" => Some("member"),
571 "memv" => Some("memv"),
572 "memq" => Some("memq"),
573 "assoc" => Some("assoc"),
574 "assv" => Some("assv"),
575 "assq" => Some("assq"),
576 "null?" => Some("null?"),
577 "pair?" => Some("pair?"),
578 "list?" => Some("list?"),
579
580 "boolean?" => Some("boolean?"),
582 "symbol?" => Some("symbol?"),
583 "char?" => Some("char?"),
584 "string?" => Some("string?"),
585 "number?" => Some("number?"),
586 "integer?" => Some("integer?"),
587 "real?" => Some("real?"),
588 "exact?" => Some("exact?"),
589 "inexact?" => Some("inexact?"),
590 "procedure?" => Some("procedure?"),
591 "vector?" => Some("vector?"),
592 "zero?" => Some("zero?"),
593 "positive?" => Some("positive?"),
594 "negative?" => Some("negative?"),
595 "odd?" => Some("odd?"),
596 "even?" => Some("even?"),
597
598 "eq?" => Some("eq?"),
600 "eqv?" => Some("eqv?"),
601 "equal?" => Some("equal?"),
602 "=" => Some("="),
603 "<" => Some("<"),
604 ">" => Some(">"),
605 "<=" => Some("<="),
606 ">=" => Some(">="),
607
608 "+" => Some("+"),
610 "-" => Some("-"),
611 "*" => Some("*"),
612 "/" => Some("/"),
613 "quotient" => Some("quotient"),
614 "remainder" => Some("remainder"),
615 "modulo" => Some("modulo"),
616 "abs" => Some("abs"),
617 "max" => Some("max"),
618 "min" => Some("min"),
619 "floor" => Some("floor"),
620 "ceiling" => Some("ceiling"),
621 "truncate" => Some("truncate"),
622 "round" => Some("round"),
623 "sqrt" => Some("sqrt"),
624 "expt" => Some("expt"),
625 "exp" => Some("exp"),
626 "log" => Some("log"),
627 "sin" => Some("sin"),
628 "cos" => Some("cos"),
629 "tan" => Some("tan"),
630 "asin" => Some("asin"),
631 "acos" => Some("acos"),
632 "atan" => Some("atan"),
633 "number->string" => Some("number->string"),
634 "string->number" => Some("string->number"),
635
636 "string" => Some("string"),
638 "string-append" => Some("string-append"),
639 "substring" => Some("substring"),
640 "string-ref" => Some("string-ref"),
641 "string-length" => Some("string-length"),
642 "string=?" => Some("string=?"),
643 "string<?" => Some("string<?"),
644 "string>?" => Some("string>?"),
645 "string<=?" => Some("string<=?"),
646 "string>=?" => Some("string>=?"),
647 "string-ci=?" => Some("string-ci=?"),
648 "string-ci<?" => Some("string-ci<?"),
649 "string-ci>?" => Some("string-ci>?"),
650 "string-ci<=?" => Some("string-ci<=?"),
651 "string-ci>=?" => Some("string-ci>=?"),
652 "string->list" => Some("string->list"),
653 "list->string" => Some("list->string"),
654 "symbol->string" => Some("symbol->string"),
655 "string->symbol" => Some("string->symbol"),
656 "keyword?" => Some("keyword?"),
657 "keyword->string" => Some("keyword->string"),
658 "string->keyword" => Some("string->keyword"),
659
660 "char=?" => Some("char=?"),
662 "char<?" => Some("char<?"),
663 "char>?" => Some("char>?"),
664 "char<=?" => Some("char<=?"),
665 "char>=?" => Some("char>=?"),
666 "char-ci=?" => Some("char-ci=?"),
667 "char-ci<?" => Some("char-ci<?"),
668 "char-ci>?" => Some("char-ci>?"),
669 "char-ci<=?" => Some("char-ci<=?"),
670 "char-ci>=?" => Some("char-ci>=?"),
671 "char-alphabetic?" => Some("char-alphabetic?"),
672 "char-numeric?" => Some("char-numeric?"),
673 "char-whitespace?" => Some("char-whitespace?"),
674 "char-upper-case?" => Some("char-upper-case?"),
675 "char-lower-case?" => Some("char-lower-case?"),
676 "char-upcase" => Some("char-upcase"),
677 "char-downcase" => Some("char-downcase"),
678 "char->integer" => Some("char->integer"),
679 "integer->char" => Some("integer->char"),
680 "char-property" => Some("char-property"),
681 "char-script-case" => Some("char-script-case"),
682
683 "vector" => Some("vector"),
685 "make-vector" => Some("make-vector"),
686 "vector-ref" => Some("vector-ref"),
687 "vector-set!" => Some("vector-set!"),
688 "vector-length" => Some("vector-length"),
689 "vector->list" => Some("vector->list"),
690 "list->vector" => Some("list->vector"),
691 "vector-fill!" => Some("vector-fill!"),
692
693 "not" => Some("not"),
695
696 "display" => Some("display"),
698 "write" => Some("write"),
699 "newline" => Some("newline"),
700 "read" => Some("read"),
701 "node?" => Some("node?"),
708 "sosofo?" => Some("sosofo?"),
709 "current-node" => Some("current-node"),
710 "gi" => Some("gi"),
711 "id" => Some("id"),
712 "data" => Some("data"),
713 "node-property" => Some("node-property"),
714 "attribute-string" => Some("attribute-string"),
715 "parent" => Some("parent"),
716 "ancestor" => Some("ancestor"),
717 "children" => Some("children"),
718 "descendants" => Some("descendants"),
719 "follow" => Some("follow"),
720 "preced" => Some("preced"),
721 "ipreced" => Some("ipreced"),
722 "attributes" => Some("attributes"),
723 "ancestors" => Some("ancestors"),
724 "document-element" => Some("document-element"),
725 "have-ancestor?" => Some("have-ancestor?"),
726 "hierarchical-number" => Some("hierarchical-number"),
727 "hierarchical-number-recursive" => Some("hierarchical-number-recursive"),
728 "absolute-first-sibling?" => Some("absolute-first-sibling?"),
729 "absolute-last-sibling?" => Some("absolute-last-sibling?"),
730 "select-elements" => Some("select-elements"),
731 "element-with-id" => Some("element-with-id"),
732 "match-element?" => Some("match-element?"),
733 "first-sibling?" => Some("first-sibling?"),
734 "last-sibling?" => Some("last-sibling?"),
735 "child-number" => Some("child-number"),
736 "element-number" => Some("element-number"),
737 "node-list?" => Some("node-list?"),
738 "node-list-first" => Some("node-list-first"),
739 "node-list-rest" => Some("node-list-rest"),
740 "node-list-length" => Some("node-list-length"),
741 "empty-node-list" => Some("empty-node-list"),
742 "node-list-empty?" => Some("node-list-empty?"),
743 "node-list-head" => Some("node-list-head"),
744 "node-list-tail" => Some("node-list-tail"),
745 "node-list-sublist" => Some("node-list-sublist"),
746 "node-list-ref" => Some("node-list-ref"),
747 "node-list-reduce" => Some("node-list-reduce"),
748 "node-list-reduce-right" => Some("node-list-reduce-right"),
749 "node-list-map" => Some("node-list-map"),
750 "node-list-filter" => Some("node-list-filter"),
751 "node-list-contains?" => Some("node-list-contains?"),
752 "node-list-some?" => Some("node-list-some?"),
753 "node-list-every?" => Some("node-list-every?"),
754 "node-list->list" => Some("node-list->list"),
755 "node-list-union" => Some("node-list-union"),
756 "node-list-intersection" => Some("node-list-intersection"),
757 "node-list-difference" => Some("node-list-difference"),
758 "node-list-remove-duplicates" => Some("node-list-remove-duplicates"),
759 "node-list-last" => Some("node-list-last"),
760 "node-list-reverse" => Some("node-list-reverse"),
761
762 "literal" => Some("literal"),
766 "next-match" => Some("next-match"),
767 "sosofo-append" => Some("sosofo-append"),
768 "empty-sosofo" => Some("empty-sosofo"),
769 "format-number" => Some("format-number"),
770 "format-number-list" => Some("format-number-list"),
771
772 "entity-system-id" => Some("entity-system-id"),
774 "entity-public-id" => Some("entity-public-id"),
775 "entity-text" => Some("entity-text"),
776 "entity-type" => Some("entity-type"),
777 "notation-system-id" => Some("notation-system-id"),
778 "notation-public-id" => Some("notation-public-id"),
779
780 "quantity?" => Some("quantity?"),
782 "quantity" => Some("quantity"),
783 "quantity->number" => Some("quantity->number"),
784 "number->quantity" => Some("number->quantity"),
785 "quantity-convert" => Some("quantity-convert"),
786 "device-length" => Some("device-length"),
787 "label-distance" => Some("label-distance"),
788
789 "color?" => Some("color?"),
791 "color" => Some("color"),
792 "color-space?" => Some("color-space?"),
793 "color-space" => Some("color-space"),
794
795 "address?" => Some("address?"),
797 "address" => Some("address"),
798 "address-local?" => Some("address-local?"),
799 "address-visited?" => Some("address-visited?"),
800
801 "glyph-id?" => Some("glyph-id?"),
803 "glyph-id" => Some("glyph-id"),
804 "glyph-subst-table?" => Some("glyph-subst-table?"),
805 "glyph-subst-table" => Some("glyph-subst-table"),
806 "glyph-subst" => Some("glyph-subst"),
807
808 "display-space" => Some("display-space"),
810 "inline-space" => Some("inline-space"),
811 "display-space?" => Some("display-space?"),
812 "inline-space?" => Some("inline-space?"),
813
814 "time" => Some("time"),
816 "time->string" => Some("time->string"),
817 "time<=?" => Some("time<=?"),
818 "time<?" => Some("time<?"),
819 "time>=?" => Some("time>=?"),
820 "time>?" => Some("time>?"),
821 "language?" => Some("language?"),
822 "language" => Some("language"),
823 "style?" => Some("style?"),
824 "string-equiv?" => Some("string-equiv?"),
825 "label-length" => Some("label-length"),
826 "external-procedure" => Some("external-procedure"),
827 "declaration" => Some("declaration"),
828 "dtd" => Some("dtd"),
829 "epilog" => Some("epilog"),
830 "prolog" => Some("prolog"),
831 "sgml-declaration" => Some("sgml-declaration"),
832 "sgml-parse" => Some("sgml-parse"),
833 "entity-address" => Some("entity-address"),
834 "entity-generated-system-id" => Some("entity-generated-system-id"),
835 "entity-name-normalize" => Some("entity-name-normalize"),
836 "general-name-normalize" => Some("general-name-normalize"),
837 "normalize" => Some("normalize"),
838 "first-child-gi" => Some("first-child-gi"),
839 "tree-root" => Some("tree-root"),
840 "declare-default-language" => Some("declare-default-language"),
841 "read-entity" => Some("read-entity"),
842 "set-visited!" => Some("set-visited!"),
843 "sosofo-contains-node?" => Some("sosofo-contains-node?"),
844 "page-number-sosofo" => Some("page-number-sosofo"),
845 "ifollow" => Some("ifollow"),
846 "with-language" => Some("with-language"),
847 "all-element-number" => Some("all-element-number"),
848 "ancestor-child-number" => Some("ancestor-child-number"),
849 "element-number-list" => Some("element-number-list"),
850 "inherited-attribute-string" => Some("inherited-attribute-string"),
851 "inherited-element-attribute-string" => Some("inherited-element-attribute-string"),
852 "inherited-start-indent" => Some("inherited-start-indent"),
853 "inherited-end-indent" => Some("inherited-end-indent"),
854 "inherited-line-spacing" => Some("inherited-line-spacing"),
855 "inherited-font-family-name" => Some("inherited-font-family-name"),
856 "inherited-font-size" => Some("inherited-font-size"),
857 "inherited-font-weight" => Some("inherited-font-weight"),
858 "inherited-font-posture" => Some("inherited-font-posture"),
859 "inherited-dbhtml-value" => Some("inherited-dbhtml-value"),
860 "inherited-pi-value" => Some("inherited-pi-value"),
861 "node-list" => Some("node-list"),
862 "node-list=?" => Some("node-list=?"),
863 "node-list-count" => Some("node-list-count"),
864 "node-list-union-map" => Some("node-list-union-map"),
865 "node-list-symmetrical-difference" => Some("node-list-symmetrical-difference"),
866 "node-list-address" => Some("node-list-address"),
867 "node-list-error" => Some("node-list-error"),
868 "node-list-no-order" => Some("node-list-no-order"),
869 "origin-to-subnode-rel-forest-addr" => Some("origin-to-subnode-rel-forest-addr"),
870 "named-node" => Some("named-node"),
871 "named-node-list?" => Some("named-node-list?"),
872 "named-node-list-names" => Some("named-node-list-names"),
873 "select-by-class" => Some("select-by-class"),
874 "select-children" => Some("select-children"),
875 "process-children-trim" => Some("process-children-trim"),
876 "process-element-with-id" => Some("process-element-with-id"),
877 "process-first-descendant" => Some("process-first-descendant"),
878 "process-matching-children" => Some("process-matching-children"),
879
880 "add" => Some("add"),
882 "divide" => Some("divide"),
883 "equal" => Some("equal"),
884 "char-eq" => Some("char-eq"),
885 "char-lt" => Some("char-lt"),
886 "error" => Some("error"),
887 "eof-object?" => Some("eof-object?"),
888 "debug" => Some("debug"),
889 "current-language" => Some("current-language"),
890 "current-mode" => Some("current-mode"),
891 "current-node-address" => Some("current-node-address"),
892 "current-node-page-number-sosofo" => Some("current-node-page-number-sosofo"),
893
894 _ => None,
896 }
897 }
898
899 fn value_to_arena(&mut self, value: &Value) -> ValueId {
909 use crate::scheme::arena::{NIL_ID, TRUE_ID, FALSE_ID};
910
911 match value {
912 Value::Nil => NIL_ID,
913 Value::Bool(true) => TRUE_ID,
914 Value::Bool(false) => FALSE_ID,
915 Value::Integer(n) => self.arena.int(*n),
916 Value::Real(f) => self.arena.real(*f),
917 Value::Quantity { magnitude, unit } => {
918 self.arena.alloc(ValueData::Quantity { magnitude: *magnitude, unit: *unit })
919 }
920 Value::String(s) => self.arena.string((**s).clone()),
921 Value::Symbol(s) => self.arena.symbol(s.clone()),
922 Value::Keyword(k) => self.arena.keyword(k.clone()),
923 Value::Char(c) => self.arena.char(*c),
924 Value::Pair(pair) => {
925 let p = pair.borrow();
926 let car = self.value_to_arena(&p.car);
927 let cdr = self.value_to_arena(&p.cdr);
928 if let Some(pos) = &p.pos {
929 self.arena.cons_with_pos(car, cdr, pos.clone())
930 } else {
931 self.arena.cons(car, cdr)
932 }
933 }
934 Value::Vector(vec) => {
935 let v = vec.borrow();
936 let elements: Vec<ValueId> = v.iter().map(|val| self.value_to_arena(val)).collect();
937 self.arena.vector(elements)
938 }
939 Value::Node(node) => {
940 self.arena.alloc(ValueData::Node(node.clone()))
941 }
942 Value::NodeList(node_list) => {
943 self.arena.alloc(ValueData::NodeList(node_list.clone()))
944 }
945 Value::Sosofo => {
946 self.arena.alloc(ValueData::Sosofo)
947 }
948 Value::Unspecified => {
949 crate::scheme::arena::UNSPECIFIED_ID
950 }
951 _ => {
952 NIL_ID
954 }
955 }
956 }
957
958 fn arena_to_value(&self, id: ValueId) -> Value {
960 use crate::scheme::arena::{NIL_ID, TRUE_ID, FALSE_ID};
961
962 if id == NIL_ID {
964 return Value::Nil;
965 }
966 if id == TRUE_ID {
967 return Value::Bool(true);
968 }
969 if id == FALSE_ID {
970 return Value::Bool(false);
971 }
972
973 match self.arena.get(id) {
974 ValueData::Nil => Value::Nil,
975 ValueData::Bool(b) => Value::Bool(*b),
976 ValueData::Integer(n) => Value::Integer(*n),
977 ValueData::Real(f) => Value::Real(*f),
978 ValueData::Quantity { magnitude, unit } => {
979 Value::Quantity { magnitude: *magnitude, unit: *unit }
980 }
981 ValueData::String(s) => Value::String(Gc::new(s.clone())),
982 ValueData::Symbol(s) => Value::Symbol(s.clone()),
983 ValueData::Keyword(k) => Value::Keyword(k.clone()),
984 ValueData::Char(c) => Value::Char(*c),
985 ValueData::Pair { car, cdr, pos } => {
986 let car_val = self.arena_to_value(*car);
987 let cdr_val = self.arena_to_value(*cdr);
988 if let Some(p) = pos {
989 Value::cons_with_pos(car_val, cdr_val, p.clone())
990 } else {
991 Value::cons(car_val, cdr_val)
992 }
993 }
994 ValueData::Vector(elements) => {
995 let vals: Vec<Value> = elements.iter().map(|id| self.arena_to_value(*id)).collect();
996 Value::vector(vals)
997 }
998 ValueData::Node(node) => {
999 Value::Node(node.clone())
1000 }
1001 ValueData::NodeList(node_list) => {
1002 Value::NodeList(node_list.clone())
1003 }
1004 ValueData::Sosofo => Value::Sosofo,
1005 ValueData::Unspecified => Value::Unspecified,
1006 ValueData::Error => Value::Error,
1007 ValueData::Procedure(_) => {
1008 Value::Unspecified
1011 }
1012 }
1013 }
1014
1015 fn apply_primitive(&mut self, name: &str, args: &[Value]) -> EvalResult {
1017 use crate::scheme::primitives::{
1018 car, cdr, cons, null, equal,
1019 cadr, caddr, cadddr, list, length,
1020 reverse, append, list_p, list_ref,
1021 pair_p, number_p, integer_p, real_p,
1022 string_p, symbol_p, char_p, boolean_p,
1023 zero_p, positive_p, negative_p, odd_p, even_p,
1024 add, subtract, multiply, divide,
1025 quotient, remainder, modulo,
1026 num_eq, num_lt, num_gt, num_le, num_ge,
1027 abs, min, max,
1028 floor, ceiling, truncate, round,
1029 sqrt, sin, cos, tan,
1030 asin, acos, atan, exp, log, expt,
1031 string_length, string_ref, substring, string_append,
1032 string_eq, string_lt, string_gt, string_le, string_ge,
1033 string_ci_eq, string_ci_lt, string_ci_gt,
1034 string_ci_le, string_ci_ge,
1035 char_eq, char_lt, char_gt, char_le, char_ge,
1036 char_ci_eq, char_ci_lt, char_ci_gt, char_ci_le, char_ci_ge,
1037 char_upcase, char_downcase,
1038 char_alphabetic_p, char_numeric_p, char_whitespace_p,
1039 char_to_integer, integer_to_char,
1040 char_property, char_script_case,
1041 symbol_to_string, string_to_symbol,
1042 keyword_p, keyword_to_string, string_to_keyword,
1043 memq, memv, member,
1044 assq, assv, assoc,
1045 not, eq_p, eqv_p,
1046 caar, cdar, cddr,
1047 caaar, caadr, cadar,
1048 cdaar, cdadr, cddar, cdddr,
1049 vector, make_vector, vector_length,
1050 vector_ref, vector_set,
1051 vector_to_list, list_to_vector, vector_fill,
1052 vector_p, procedure_p,
1053 set_car, set_cdr, list_tail,
1054 string_upcase, string_downcase, case_fold_down,
1055 string_index,
1056 string_to_list, list_to_string,
1057 gcd, lcm,
1058 exact_to_inexact, inexact_to_exact,
1059 make_string, string, reverse_bang,
1060 string_set, string_copy, string_fill,
1061 char_lower_case_p, char_upper_case_p,
1062 last, last_pair, list_copy,
1063 append_bang, iota,
1064 take, drop, split_at,
1065 filter, remove,
1066 numerator, denominator, rationalize,
1067 angle, magnitude, string_to_number_radix,
1068 number_to_string_radix,
1069 null_list_p, improper_list_p, circular_list_p,
1070 bitwise_and, bitwise_ior, bitwise_xor, bitwise_not,
1071 arithmetic_shift, bit_extract,
1072 bitwise_bit_set_p, bitwise_bit_count,
1073 display, newline, write, write_char,
1074 read_char, eof_object_p,
1075 format_number, format_number_list,
1076 empty_sosofo, sosofo_append, if_first_page, if_front_page,
1077 current_node,
1078 gi, data, id,
1079 children, parent, attributes,
1080 node_list_p, empty_node_list, node_list_empty_p,
1081 node_list_length, node_list_first,
1082 attribute_string,
1083 node_list_rest, node_list_ref, node_list_reverse,
1084 node_p, sosofo_p, quantity_p,
1085 color_p, color, display_space_p, inline_space_p,
1086 quantity_to_number, number_to_quantity, quantity_convert,
1087 device_length, label_distance,
1088 ancestor, descendants, follow, preced, ipreced,
1089 node_list_last, node_list_union, node_list_intersection,
1090 node_list_difference, node_list_remove_duplicates,
1091 select_elements, first_sibling_p, last_sibling_p,
1092 child_number, element_with_id,
1093 element_number, hierarchical_number, hierarchical_number_recursive,
1094 ancestors, document_element, have_ancestor_p,
1095 match_element_p, node_list_map,
1096 node_property, absolute_first_sibling_p, absolute_last_sibling_p,
1097 node_list_to_list, node_list_contains_p,
1098 entity_system_id, entity_public_id, entity_type,
1099 notation_system_id, notation_public_id,
1100 current_language, current_mode, current_node_address,
1101 current_node_page_number_sosofo, debug,
1102 exact_p, inexact_p, error,
1103 address_p, address_local_p, address_visited_p,
1104 color_space_p, color_space, display_space, inline_space,
1105 glyph_id_p, glyph_id, glyph_subst_table_p,
1106 glyph_subst_table, glyph_subst,
1107 time, time_to_string, time_le, time_lt,
1108 time_ge, time_gt,
1109 language_p, language, style_p,
1110 string_equiv_p, label_length, external_procedure,
1111 declaration, dtd, epilog, prolog,
1112 sgml_declaration, sgml_parse,
1113 entity_address, entity_generated_system_id,
1114 entity_name_normalize, general_name_normalize, normalize,
1115 first_child_gi, tree_root, declare_default_language,
1116 read_entity, set_visited,
1117 sosofo_contains_node_p, page_number_sosofo, ifollow, with_language,
1118 all_element_number, ancestor_child_number, element_number_list,
1119 inherited_attribute_string, inherited_element_attribute_string,
1120 inherited_start_indent, inherited_end_indent, inherited_line_spacing,
1121 inherited_font_family_name, inherited_font_size, inherited_font_weight,
1122 inherited_font_posture, inherited_dbhtml_value, inherited_pi_value,
1123 node_list, node_list_eq_p,
1124 node_list_union_map, node_list_symmetrical_difference, node_list_count,
1125 node_list_address, node_list_error, node_list_no_order,
1126 origin_to_subnode_rel_forest_addr,
1127 named_node, named_node_list_p, named_node_list_names,
1128 select_by_class, select_children,
1129 process_children_trim, process_element_with_id, process_first_descendant,
1130 process_matching_children, next_match,
1131 };
1132
1133 if (name == "eq?" || name == "eqv?") && args.len() == 2 {
1136 let ptr_equal = match (&args[0], &args[1]) {
1138 (Value::Pair(p1), Value::Pair(p2)) => gc::Gc::ptr_eq(p1, p2),
1139 (Value::String(s1), Value::String(s2)) => gc::Gc::ptr_eq(s1, s2),
1140 (Value::Procedure(pr1), Value::Procedure(pr2)) => gc::Gc::ptr_eq(pr1, pr2),
1141 _ => false,
1142 };
1143 if ptr_equal {
1144 return Ok(Value::bool(true));
1145 }
1146 }
1147
1148 if name == "vector?" && args.len() == 1 {
1150 return Ok(Value::bool(matches!(args[0], Value::Vector(_))));
1151 }
1152 if name == "procedure?" && args.len() == 1 {
1153 return Ok(Value::bool(matches!(args[0], Value::Procedure(_))));
1154 }
1155
1156 let arena_args: Vec<ValueId> = args.iter().map(|v| self.value_to_arena(v)).collect();
1158
1159 let result_id = match name {
1161 "car" => car(&self.arena, &arena_args),
1162 "cdr" => cdr(&self.arena, &arena_args),
1163 "cons" => cons(&mut self.arena, &arena_args),
1164 "null?" => null(&self.arena, &arena_args),
1165 "equal?" => equal(&self.arena, &arena_args),
1166 "cadr" => cadr(&self.arena, &arena_args),
1167 "caddr" => caddr(&self.arena, &arena_args),
1168 "cadddr" => cadddr(&self.arena, &arena_args),
1169 "list" => list(&mut self.arena, &arena_args),
1170 "length" => length(&mut self.arena, &arena_args),
1171 "reverse" => reverse(&mut self.arena, &arena_args),
1172 "append" => append(&mut self.arena, &arena_args),
1173 "list?" => list_p(&self.arena, &arena_args),
1174 "list-ref" => list_ref(&self.arena, &arena_args),
1175 "pair?" => pair_p(&self.arena, &arena_args),
1176 "number?" => number_p(&self.arena, &arena_args),
1177 "integer?" => integer_p(&self.arena, &arena_args),
1178 "real?" => real_p(&self.arena, &arena_args),
1179 "string?" => string_p(&self.arena, &arena_args),
1180 "symbol?" => symbol_p(&self.arena, &arena_args),
1181 "char?" => char_p(&self.arena, &arena_args),
1182 "boolean?" => boolean_p(&self.arena, &arena_args),
1183 "zero?" => zero_p(&self.arena, &arena_args),
1184 "positive?" => positive_p(&self.arena, &arena_args),
1185 "negative?" => negative_p(&self.arena, &arena_args),
1186 "odd?" => odd_p(&self.arena, &arena_args),
1187 "even?" => even_p(&self.arena, &arena_args),
1188 "+" => add(&mut self.arena, &arena_args),
1189 "-" => subtract(&mut self.arena, &arena_args),
1190 "*" => multiply(&mut self.arena, &arena_args),
1191 "/" => divide(&mut self.arena, &arena_args),
1192 "quotient" => quotient(&mut self.arena, &arena_args),
1193 "remainder" => remainder(&mut self.arena, &arena_args),
1194 "modulo" => modulo(&mut self.arena, &arena_args),
1195 "=" => num_eq(&self.arena, &arena_args),
1196 "<" => num_lt(&self.arena, &arena_args),
1197 ">" => num_gt(&self.arena, &arena_args),
1198 "<=" => num_le(&self.arena, &arena_args),
1199 ">=" => num_ge(&self.arena, &arena_args),
1200 "abs" => abs(&mut self.arena, &arena_args),
1201 "min" => min(&mut self.arena, &arena_args),
1202 "max" => max(&mut self.arena, &arena_args),
1203 "floor" => floor(&mut self.arena, &arena_args),
1204 "ceiling" => ceiling(&mut self.arena, &arena_args),
1205 "truncate" => truncate(&mut self.arena, &arena_args),
1206 "round" => round(&mut self.arena, &arena_args),
1207 "sqrt" => sqrt(&mut self.arena, &arena_args),
1208 "sin" => sin(&mut self.arena, &arena_args),
1209 "cos" => cos(&mut self.arena, &arena_args),
1210 "tan" => tan(&mut self.arena, &arena_args),
1211 "asin" => asin(&mut self.arena, &arena_args),
1212 "acos" => acos(&mut self.arena, &arena_args),
1213 "atan" => atan(&mut self.arena, &arena_args),
1214 "exp" => exp(&mut self.arena, &arena_args),
1215 "log" => log(&mut self.arena, &arena_args),
1216 "expt" => expt(&mut self.arena, &arena_args),
1217 "string-length" => string_length(&mut self.arena, &arena_args),
1218 "string-ref" => string_ref(&mut self.arena, &arena_args),
1219 "substring" => substring(&mut self.arena, &arena_args),
1220 "string-append" => string_append(&mut self.arena, &arena_args),
1221 "string=?" => string_eq(&self.arena, &arena_args),
1222 "string<?" => string_lt(&self.arena, &arena_args),
1223 "string>?" => string_gt(&self.arena, &arena_args),
1224 "string<=?" => string_le(&self.arena, &arena_args),
1225 "string>=?" => string_ge(&self.arena, &arena_args),
1226 "string-ci=?" => string_ci_eq(&self.arena, &arena_args),
1227 "string-ci<?" => string_ci_lt(&self.arena, &arena_args),
1228 "string-ci>?" => string_ci_gt(&self.arena, &arena_args),
1229 "string-ci<=?" => string_ci_le(&self.arena, &arena_args),
1230 "string-ci>=?" => string_ci_ge(&self.arena, &arena_args),
1231
1232 "char=?" => char_eq(&self.arena, &arena_args),
1233 "char<?" => char_lt(&self.arena, &arena_args),
1234 "char>?" => char_gt(&self.arena, &arena_args),
1235 "char<=?" => char_le(&self.arena, &arena_args),
1236 "char>=?" => char_ge(&self.arena, &arena_args),
1237 "char-ci=?" => char_ci_eq(&self.arena, &arena_args),
1238 "char-ci<?" => char_ci_lt(&self.arena, &arena_args),
1239 "char-ci>?" => char_ci_gt(&self.arena, &arena_args),
1240 "char-ci<=?" => char_ci_le(&self.arena, &arena_args),
1241 "char-ci>=?" => char_ci_ge(&self.arena, &arena_args),
1242 "char-upcase" => char_upcase(&mut self.arena, &arena_args),
1243 "char-downcase" => char_downcase(&mut self.arena, &arena_args),
1244 "char-alphabetic?" => char_alphabetic_p(&self.arena, &arena_args),
1245 "char-numeric?" => char_numeric_p(&self.arena, &arena_args),
1246 "char-whitespace?" => char_whitespace_p(&self.arena, &arena_args),
1247 "char->integer" => char_to_integer(&mut self.arena, &arena_args),
1248 "integer->char" => integer_to_char(&mut self.arena, &arena_args),
1249 "char-property" => char_property(&mut self.arena, &arena_args),
1250 "char-script-case" => char_script_case(&mut self.arena, &arena_args),
1251
1252 "symbol->string" => symbol_to_string(&mut self.arena, &arena_args),
1253 "string->symbol" => string_to_symbol(&mut self.arena, &arena_args),
1254 "keyword?" => keyword_p(&self.arena, &arena_args),
1255 "keyword->string" => keyword_to_string(&mut self.arena, &arena_args),
1256 "string->keyword" => string_to_keyword(&mut self.arena, &arena_args),
1257
1258 "memq" => memq(&self.arena, &arena_args),
1259 "memv" => memv(&self.arena, &arena_args),
1260 "member" => member(&self.arena, &arena_args),
1261 "assq" => assq(&self.arena, &arena_args),
1262 "assv" => assv(&self.arena, &arena_args),
1263 "assoc" => assoc(&self.arena, &arena_args),
1264
1265 "not" => not(&self.arena, &arena_args),
1266 "eq?" => eq_p(&self.arena, &arena_args),
1267 "eqv?" => eqv_p(&self.arena, &arena_args),
1268 "caar" => caar(&self.arena, &arena_args),
1269 "cdar" => cdar(&self.arena, &arena_args),
1270 "cddr" => cddr(&self.arena, &arena_args),
1271
1272 "caaar" => caaar(&self.arena, &arena_args),
1273 "caadr" => caadr(&self.arena, &arena_args),
1274 "cadar" => cadar(&self.arena, &arena_args),
1275 "cdaar" => cdaar(&self.arena, &arena_args),
1276 "cdadr" => cdadr(&self.arena, &arena_args),
1277 "cddar" => cddar(&self.arena, &arena_args),
1278 "cdddr" => cdddr(&self.arena, &arena_args),
1279
1280 "vector" => vector(&mut self.arena, &arena_args),
1281 "make-vector" => make_vector(&mut self.arena, &arena_args),
1282 "vector-length" => vector_length(&mut self.arena, &arena_args),
1283 "vector-ref" => vector_ref(&self.arena, &arena_args),
1284 "vector-set!" => vector_set(&mut self.arena, &arena_args),
1285 "vector->list" => vector_to_list(&mut self.arena, &arena_args),
1286 "list->vector" => list_to_vector(&mut self.arena, &arena_args),
1287 "vector-fill!" => vector_fill(&mut self.arena, &arena_args),
1288
1289 "vector?" => vector_p(&self.arena, &arena_args),
1290 "procedure?" => procedure_p(&self.arena, &arena_args),
1291 "set-car!" => set_car(&mut self.arena, &arena_args),
1292 "set-cdr!" => set_cdr(&mut self.arena, &arena_args),
1293 "list-tail" => list_tail(&self.arena, &arena_args),
1294
1295 "string-upcase" => string_upcase(&mut self.arena, &arena_args),
1296 "string-downcase" => string_downcase(&mut self.arena, &arena_args),
1297 "case-fold-down" => case_fold_down(&mut self.arena, &arena_args), "string-index" => string_index(&mut self.arena, &arena_args),
1299 "string->number" => string_to_number_radix(&mut self.arena, &arena_args), "number->string" => number_to_string_radix(&mut self.arena, &arena_args), "string->list" => string_to_list(&mut self.arena, &arena_args),
1302 "list->string" => list_to_string(&mut self.arena, &arena_args),
1303
1304 "gcd" => gcd(&mut self.arena, &arena_args),
1305 "lcm" => lcm(&mut self.arena, &arena_args),
1306 "exact->inexact" => exact_to_inexact(&mut self.arena, &arena_args),
1307 "inexact->exact" => inexact_to_exact(&mut self.arena, &arena_args),
1308 "make-string" => make_string(&mut self.arena, &arena_args),
1309 "string" => string(&mut self.arena, &arena_args),
1310 "reverse!" => reverse_bang(&mut self.arena, &arena_args),
1311
1312 "string-set!" => string_set(&mut self.arena, &arena_args),
1313 "string-copy" => string_copy(&mut self.arena, &arena_args),
1314 "string-fill!" => string_fill(&mut self.arena, &arena_args),
1315 "char-lower-case?" => char_lower_case_p(&self.arena, &arena_args),
1316 "char-upper-case?" => char_upper_case_p(&self.arena, &arena_args),
1317
1318 "last" => last(&self.arena, &arena_args),
1319 "last-pair" => last_pair(&self.arena, &arena_args),
1320 "list-copy" => list_copy(&mut self.arena, &arena_args),
1321 "append!" => append_bang(&mut self.arena, &arena_args),
1322 "iota" => iota(&mut self.arena, &arena_args),
1323
1324 "take" => take(&mut self.arena, &arena_args),
1325 "drop" => drop(&self.arena, &arena_args),
1326 "split-at" => split_at(&mut self.arena, &arena_args),
1327 "filter" => filter(&self.arena, &arena_args),
1328 "remove" => remove(&self.arena, &arena_args),
1329
1330 "numerator" => numerator(&mut self.arena, &arena_args),
1331 "denominator" => denominator(&mut self.arena, &arena_args),
1332 "rationalize" => rationalize(&self.arena, &arena_args),
1333 "angle" => angle(&mut self.arena, &arena_args),
1334 "magnitude" => magnitude(&mut self.arena, &arena_args),
1335
1336 "null-list?" => null_list_p(&self.arena, &arena_args),
1337 "improper-list?" => improper_list_p(&self.arena, &arena_args),
1338 "circular-list?" => circular_list_p(&self.arena, &arena_args),
1339
1340 "bitwise-and" => bitwise_and(&mut self.arena, &arena_args),
1341 "bitwise-ior" => bitwise_ior(&mut self.arena, &arena_args),
1342 "bitwise-xor" => bitwise_xor(&mut self.arena, &arena_args),
1343 "bitwise-not" => bitwise_not(&mut self.arena, &arena_args),
1344 "arithmetic-shift" => arithmetic_shift(&mut self.arena, &arena_args),
1345 "bit-extract" => bit_extract(&mut self.arena, &arena_args),
1346 "bitwise-bit-set?" => bitwise_bit_set_p(&self.arena, &arena_args),
1347 "bitwise-bit-count" => bitwise_bit_count(&mut self.arena, &arena_args),
1348
1349 "display" => display(&self.arena, &arena_args),
1350 "newline" => newline(&self.arena, &arena_args),
1351 "write" => write(&self.arena, &arena_args),
1352 "write-char" => write_char(&self.arena, &arena_args),
1353 "read-char" => read_char(&self.arena, &arena_args),
1354 "eof-object?" => eof_object_p(&self.arena, &arena_args),
1355
1356 "format-number" => format_number(&mut self.arena, &arena_args),
1357 "format-number-list" => format_number_list(&mut self.arena, &arena_args),
1358
1359 "empty-sosofo" => empty_sosofo(&mut self.arena, &arena_args),
1360 "sosofo-append" => sosofo_append(&mut self.arena, &arena_args),
1361 "if-first-page" => if_first_page(&mut self.arena, &arena_args),
1362 "if-front-page" => if_front_page(&mut self.arena, &arena_args),
1363
1364 "current-node" => current_node(&mut self.arena, &arena_args),
1365
1366 "gi" => gi(&mut self.arena, &arena_args),
1367 "data" => data(&mut self.arena, &arena_args),
1368 "id" => id(&mut self.arena, &arena_args),
1369
1370 "children" => children(&mut self.arena, &arena_args),
1371 "parent" => parent(&mut self.arena, &arena_args),
1372 "attributes" => attributes(&mut self.arena, &arena_args),
1373
1374 "node-list?" => node_list_p(&self.arena, &arena_args),
1375 "empty-node-list" => empty_node_list(&mut self.arena, &arena_args),
1376 "node-list-empty?" => node_list_empty_p(&self.arena, &arena_args),
1377 "node-list-length" => node_list_length(&mut self.arena, &arena_args),
1378 "node-list-first" => node_list_first(&mut self.arena, &arena_args),
1379
1380 "attribute-string" => attribute_string(&mut self.arena, &arena_args),
1381
1382 "node-list-rest" => node_list_rest(&mut self.arena, &arena_args),
1383 "node-list-ref" => node_list_ref(&mut self.arena, &arena_args),
1384 "node-list-reverse" => node_list_reverse(&mut self.arena, &arena_args),
1385
1386 "node?" => node_p(&self.arena, &arena_args),
1387 "sosofo?" => sosofo_p(&self.arena, &arena_args),
1388 "quantity?" => quantity_p(&self.arena, &arena_args),
1389
1390 "color?" => color_p(&self.arena, &arena_args),
1391 "color" => color(&mut self.arena, &arena_args),
1392 "display-space?" => display_space_p(&self.arena, &arena_args),
1393 "inline-space?" => inline_space_p(&self.arena, &arena_args),
1394
1395 "quantity->number" => quantity_to_number(&mut self.arena, &arena_args),
1396 "number->quantity" => number_to_quantity(&mut self.arena, &arena_args),
1397 "quantity-convert" => quantity_convert(&mut self.arena, &arena_args),
1398 "device-length" => device_length(&mut self.arena, &arena_args),
1399 "label-distance" => label_distance(&mut self.arena, &arena_args),
1400
1401 "ancestor" => ancestor(&mut self.arena, &arena_args),
1402 "descendants" => descendants(&mut self.arena, &arena_args),
1403 "follow" => follow(&mut self.arena, &arena_args),
1404 "preced" => preced(&mut self.arena, &arena_args),
1405 "ipreced" => ipreced(&mut self.arena, &arena_args),
1406
1407 "node-list-last" => node_list_last(&mut self.arena, &arena_args),
1408 "node-list-union" => node_list_union(&mut self.arena, &arena_args),
1409 "node-list-intersection" => node_list_intersection(&mut self.arena, &arena_args),
1410 "node-list-difference" => node_list_difference(&mut self.arena, &arena_args),
1411 "node-list-remove-duplicates" => node_list_remove_duplicates(&mut self.arena, &arena_args),
1412
1413 "select-elements" => select_elements(&mut self.arena, &arena_args),
1414 "first-sibling?" => first_sibling_p(&mut self.arena, &arena_args),
1415 "last-sibling?" => last_sibling_p(&mut self.arena, &arena_args),
1416 "child-number" => child_number(&mut self.arena, &arena_args),
1417 "element-with-id" => element_with_id(&mut self.arena, &arena_args),
1418
1419 "element-number" => element_number(&mut self.arena, &arena_args),
1420 "hierarchical-number" => hierarchical_number(&mut self.arena, &arena_args),
1421 "hierarchical-number-recursive" => hierarchical_number_recursive(&mut self.arena, &arena_args),
1422
1423 "ancestors" => ancestors(&mut self.arena, &arena_args),
1424 "document-element" => document_element(&mut self.arena, &arena_args),
1425 "have-ancestor?" => have_ancestor_p(&mut self.arena, &arena_args),
1426 "match-element?" => match_element_p(&mut self.arena, &arena_args),
1427 "node-list-map" => node_list_map(&mut self.arena, &arena_args),
1428
1429 "node-property" => node_property(&mut self.arena, &arena_args),
1430 "absolute-first-sibling?" => absolute_first_sibling_p(&mut self.arena, &arena_args),
1431 "absolute-last-sibling?" => absolute_last_sibling_p(&mut self.arena, &arena_args),
1432 "node-list->list" => node_list_to_list(&mut self.arena, &arena_args),
1433 "node-list-contains?" => node_list_contains_p(&mut self.arena, &arena_args),
1434
1435 "entity-system-id" => entity_system_id(&mut self.arena, &arena_args),
1436 "entity-public-id" => entity_public_id(&mut self.arena, &arena_args),
1437 "entity-type" => entity_type(&mut self.arena, &arena_args),
1438 "notation-system-id" => notation_system_id(&mut self.arena, &arena_args),
1439 "notation-public-id" => notation_public_id(&mut self.arena, &arena_args),
1440
1441 "current-language" => current_language(&self.arena, &arena_args),
1442 "current-mode" => current_mode(&self.arena, &arena_args),
1443 "current-node-address" => current_node_address(&self.arena, &arena_args),
1444 "current-node-page-number-sosofo" => current_node_page_number_sosofo(&mut self.arena, &arena_args),
1445 "debug" => debug(&self.arena, &arena_args),
1446
1447 "add" => add(&mut self.arena, &arena_args),
1448 "divide" => divide(&mut self.arena, &arena_args),
1449 "equal" => equal(&self.arena, &arena_args),
1450 "char-eq" => char_eq(&self.arena, &arena_args),
1451 "char-lt" => char_lt(&self.arena, &arena_args),
1452 "exact?" => exact_p(&self.arena, &arena_args),
1453 "inexact?" => inexact_p(&self.arena, &arena_args),
1454 "error" => error(&mut self.arena, &arena_args),
1455 "address?" => address_p(&self.arena, &arena_args),
1456 "address-local?" => address_local_p(&self.arena, &arena_args),
1457 "address-visited?" => address_visited_p(&self.arena, &arena_args),
1458 "color-space?" => color_space_p(&self.arena, &arena_args),
1459 "color-space" => color_space(&self.arena, &arena_args),
1460 "display-space" => display_space(&mut self.arena, &arena_args),
1461 "inline-space" => inline_space(&mut self.arena, &arena_args),
1462 "glyph-id?" => glyph_id_p(&self.arena, &arena_args),
1463 "glyph-id" => glyph_id(&self.arena, &arena_args),
1464 "glyph-subst-table?" => glyph_subst_table_p(&self.arena, &arena_args),
1465 "glyph-subst-table" => glyph_subst_table(&self.arena, &arena_args),
1466 "glyph-subst" => glyph_subst(&self.arena, &arena_args),
1467 "time" => time(&self.arena, &arena_args),
1468 "time->string" => time_to_string(&mut self.arena, &arena_args),
1469 "time<=?" => time_le(&self.arena, &arena_args),
1470 "time<?" => time_lt(&self.arena, &arena_args),
1471 "time>=?" => time_ge(&self.arena, &arena_args),
1472 "time>?" => time_gt(&self.arena, &arena_args),
1473 "language?" => language_p(&self.arena, &arena_args),
1474 "language" => language(&mut self.arena, &arena_args),
1475 "style?" => style_p(&self.arena, &arena_args),
1476 "string-equiv?" => string_equiv_p(&self.arena, &arena_args),
1477 "label-length" => label_length(&mut self.arena, &arena_args),
1478 "external-procedure" => external_procedure(&mut self.arena, &arena_args),
1479 "declaration" => declaration(&self.arena, &arena_args),
1480 "dtd" => dtd(&self.arena, &arena_args),
1481 "epilog" => epilog(&self.arena, &arena_args),
1482 "prolog" => prolog(&self.arena, &arena_args),
1483 "sgml-declaration" => sgml_declaration(&self.arena, &arena_args),
1484 "sgml-parse" => sgml_parse(&self.arena, &arena_args),
1485 "entity-address" => entity_address(&self.arena, &arena_args),
1486 "entity-generated-system-id" => entity_generated_system_id(&mut self.arena, &arena_args),
1487 "entity-name-normalize" => entity_name_normalize(&mut self.arena, &arena_args),
1488 "general-name-normalize" => general_name_normalize(&mut self.arena, &arena_args),
1489 "normalize" => normalize(&mut self.arena, &arena_args),
1490 "first-child-gi" => first_child_gi(&mut self.arena, &arena_args),
1491 "tree-root" => tree_root(&mut self.arena, &arena_args),
1492 "declare-default-language" => declare_default_language(&self.arena, &arena_args),
1493 "read-entity" => read_entity(&mut self.arena, &arena_args),
1494 "set-visited!" => set_visited(&self.arena, &arena_args),
1495 "sosofo-contains-node?" => sosofo_contains_node_p(&self.arena, &arena_args),
1496 "page-number-sosofo" => page_number_sosofo(&mut self.arena, &arena_args),
1497 "ifollow" => ifollow(&self.arena, &arena_args),
1498 "with-language" => with_language(&self.arena, &arena_args),
1499 "all-element-number" => all_element_number(&mut self.arena, &arena_args),
1500 "ancestor-child-number" => ancestor_child_number(&mut self.arena, &arena_args),
1501 "element-number-list" => element_number_list(&self.arena, &arena_args),
1502 "inherited-attribute-string" => inherited_attribute_string(&mut self.arena, &arena_args),
1503 "inherited-element-attribute-string" => inherited_element_attribute_string(&mut self.arena, &arena_args),
1504 "inherited-start-indent" => inherited_start_indent(&mut self.arena, &arena_args),
1505 "inherited-end-indent" => inherited_end_indent(&mut self.arena, &arena_args),
1506 "inherited-line-spacing" => inherited_line_spacing(&mut self.arena, &arena_args),
1507 "inherited-font-family-name" => inherited_font_family_name(&mut self.arena, &arena_args),
1508 "inherited-font-size" => inherited_font_size(&mut self.arena, &arena_args),
1509 "inherited-font-weight" => inherited_font_weight(&mut self.arena, &arena_args),
1510 "inherited-font-posture" => inherited_font_posture(&mut self.arena, &arena_args),
1511 "inherited-dbhtml-value" => inherited_dbhtml_value(&mut self.arena, &arena_args),
1512 "inherited-pi-value" => inherited_pi_value(&mut self.arena, &arena_args),
1513 "node-list" => node_list(&mut self.arena, &arena_args),
1514 "node-list=?" => node_list_eq_p(&self.arena, &arena_args),
1515 "node-list-count" => node_list_count(&mut self.arena, &arena_args),
1516 "node-list-union-map" => node_list_union_map(&self.arena, &arena_args),
1517 "node-list-symmetrical-difference" => node_list_symmetrical_difference(&self.arena, &arena_args),
1518 "node-list-address" => node_list_address(&self.arena, &arena_args),
1519 "node-list-error" => node_list_error(&mut self.arena, &arena_args),
1520 "node-list-no-order" => node_list_no_order(&self.arena, &arena_args),
1521 "origin-to-subnode-rel-forest-addr" => origin_to_subnode_rel_forest_addr(&self.arena, &arena_args),
1522 "named-node" => named_node(&self.arena, &arena_args),
1523 "named-node-list?" => named_node_list_p(&self.arena, &arena_args),
1524 "named-node-list-names" => named_node_list_names(&self.arena, &arena_args),
1525 "select-by-class" => select_by_class(&self.arena, &arena_args),
1526 "select-children" => select_children(&self.arena, &arena_args),
1527 "process-children-trim" => process_children_trim(&self.arena, &arena_args),
1528 "process-element-with-id" => process_element_with_id(&self.arena, &arena_args),
1529 "process-first-descendant" => process_first_descendant(&self.arena, &arena_args),
1530 "process-matching-children" => process_matching_children(&self.arena, &arena_args),
1531 "next-match" => next_match(&self.arena, &arena_args),
1532
1533 "literal" => {
1535 if args.is_empty() {
1539 return Err(self.error_with_stack("literal: expected at least 1 argument".to_string()));
1540 }
1541
1542 let text = if args.len() == 1 {
1544 match &args[0] {
1546 Value::String(s) => s.to_string(),
1547 _ => return Err(self.error_with_stack("literal: argument must be a string".to_string())),
1548 }
1549 } else if args.len() == 2 {
1550 match &args[1] {
1552 Value::String(s) => s.to_string(),
1553 _ => return Err(self.error_with_stack("literal: text argument must be a string".to_string())),
1554 }
1555 } else {
1556 return Err(self.error_with_stack(format!(
1557 "literal: expected 1 or 2 arguments, got {}",
1558 args.len()
1559 )));
1560 };
1561
1562 if let Some(ref backend) = self.backend {
1563 backend.borrow_mut().formatting_instruction(&text)
1564 .map_err(|e| self.error_with_stack(format!("Backend error: {}", e)))?;
1565 }
1566
1567 return Ok(Value::Unspecified);
1568 }
1569
1570 _ => unreachable!("apply_primitive called with non-arena primitive: {}", name),
1571 }
1572 .map_err(|e| self.error_with_stack(e))?;
1573
1574 Ok(self.arena_to_value(result_id))
1576 }
1577
1578 pub fn set_current_node(&mut self, node: Box<dyn Node>) {
1580 self.arena.current_node = Some(Rc::new(node));
1581 }
1582
1583 pub fn current_node(&self) -> Option<Rc<Box<dyn Node>>> {
1585 self.arena.current_node.clone()
1586 }
1587
1588 pub fn clear_current_node(&mut self) {
1590 self.arena.current_node = None;
1591 }
1592
1593 pub fn restore_current_node(&mut self, node: Option<Rc<Box<dyn Node>>>) {
1595 self.arena.current_node = node;
1596 }
1597
1598 pub fn process_root(&mut self, env: Gc<Environment>) -> EvalResult {
1607 let root_node = match self.grove() {
1609 Some(grove) => grove.root(),
1610 None => return Err(EvalError::new("No grove set".to_string())),
1611 };
1612
1613 self.set_current_node(root_node);
1615 self.process_node(env)
1616 }
1617
1618 pub fn process_node(&mut self, env: Gc<Environment>) -> EvalResult {
1629 self.nodes_processed += 1;
1631
1632 if self.nodes_processed % 100 == 0 {
1634 gc::force_collect();
1636
1637 let roots: Vec<_> = self.vm_globals.values().copied().collect();
1640 self.arena.gc(&roots);
1641 }
1642
1643 let node = match self.current_node() {
1644 Some(n) => n.clone(),
1645 None => return Err(EvalError::new("No current node".to_string())),
1646 };
1647
1648 let gi = match node.gi() {
1650 Some(gi) => gi.to_string(),
1651 None => {
1652 if node.is_text() {
1656 if let Some(text) = node.data() {
1657 if !text.trim().is_empty() {
1659 if let Some(ref backend) = self.backend {
1661 backend.borrow_mut().literal(&text)
1662 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
1663 }
1664 }
1665 }
1666 }
1667 return Ok(Value::Unspecified);
1668 }
1669 };
1670
1671 let mode_name = self.current_processing_mode.clone();
1673 let mode = self.mode_manager.get_mode(&mode_name);
1674 let rule = mode.and_then(|m| m.find_match(&gi, &**node));
1675
1676 if let Some(rule) = rule {
1677 let saved_file = self.current_source_file.clone();
1680 let saved_pos = self.current_position.clone();
1681
1682 if let Some(ref rule_file) = rule.source_file {
1685 self.current_source_file = Some(rule_file.clone());
1686 }
1687 if let Some(ref rule_pos) = rule.source_pos {
1688 self.current_position = Some(rule_pos.clone());
1689 }
1690
1691 let rule_expr = rule.expr.clone();
1693 let rule_cached = rule.cached_instructions.clone();
1694
1695 let result = if self.use_vm {
1697 self.eval_rule_with_cache(rule_expr, rule_cached, env)
1698 } else {
1699 self.eval(rule_expr, env)
1700 };
1701
1702 self.current_source_file = saved_file;
1704 self.current_position = saved_pos;
1705
1706 result
1707 } else if let Some(default_expr) = mode.and_then(|m| m.default_rule.as_ref()).cloned() {
1708 self.eval(default_expr, env)
1710 } else {
1711 self.eval_process_children(env)
1714 }
1715 }
1716
1717 fn eval_rule_with_cache(
1733 &mut self,
1734 rule_expr: Value,
1735 rule_cached: RefCell<Option<(Vec<Instruction>, usize)>>,
1736 _env: Gc<Environment>
1737 ) -> EvalResult {
1738 let cached_data = rule_cached.borrow().clone();
1740
1741 if let Some((instructions, start_ip)) = cached_data {
1742 let mut vm = VM::with_primitives(&mut self.arena);
1745 vm.extend_globals(self.vm_globals.clone());
1746
1747 let result_id = vm.run(&instructions, start_ip)
1748 .map_err(|e| EvalError::new(format!("VM error: {}", e)))?;
1749
1750 self.vm_globals = vm.get_user_globals();
1752
1753 if std::env::var("DAZZLE_DEBUG").is_ok() {
1755 let saved: Vec<_> = self.vm_globals.keys().filter(|k| k.starts_with('%')).collect();
1756 if !saved.is_empty() {
1757 eprintln!("Evaluator: Saved {} user globals (% vars: {:?})", self.vm_globals.len(), saved);
1758 }
1759 }
1760
1761 return Ok(arena_to_value(&self.arena, result_id));
1763 }
1764
1765 let expr_id = value_to_arena(&mut self.arena, &rule_expr);
1767
1768 let mut compiler = Compiler::new(&self.arena);
1769 let start_ip = compiler.compile(expr_id)
1770 .map_err(|e| EvalError::new(format!("Compilation error: {}", e)))?;
1771
1772 let mut program = compiler.into_program();
1773 program.emit(Instruction::Return);
1774
1775 let instructions = program.instructions.clone();
1777 *rule_cached.borrow_mut() = Some((instructions.clone(), start_ip));
1778
1779 let mut vm = VM::with_primitives(&mut self.arena);
1781 vm.extend_globals(self.vm_globals.clone());
1782
1783 let result_id = vm.run(&instructions, start_ip)
1784 .map_err(|e| EvalError::new(format!("VM error: {}", e)))?;
1785
1786 self.vm_globals = vm.get_user_globals();
1788
1789 if std::env::var("DAZZLE_DEBUG").is_ok() {
1791 let saved: Vec<_> = self.vm_globals.keys().filter(|k| k.starts_with('%')).collect();
1792 if !saved.is_empty() {
1793 eprintln!("Evaluator: Saved {} user globals (% vars: {:?})", self.vm_globals.len(), saved);
1794 }
1795 }
1796
1797 Ok(arena_to_value(&self.arena, result_id))
1799 }
1800
1801 fn eval_with_vm(&mut self, expr: Value, _env: Gc<Environment>) -> EvalResult {
1812 let expr_id = value_to_arena(&mut self.arena, &expr);
1814
1815 let mut compiler = Compiler::new(&self.arena);
1817 let start_ip = compiler.compile(expr_id)
1818 .map_err(|e| EvalError::new(format!("Compilation error: {}", e)))?;
1819
1820 let mut program = compiler.into_program();
1821
1822 program.emit(Instruction::Return);
1824
1825 let mut vm = VM::with_primitives(&mut self.arena);
1827 vm.extend_globals(self.vm_globals.clone());
1828
1829 let result_id = vm.run(&program.instructions, start_ip)
1831 .map_err(|e| EvalError::new(format!("VM error: {}", e)))?;
1832
1833 self.vm_globals = vm.get_user_globals();
1835
1836 if std::env::var("DAZZLE_DEBUG").is_ok() {
1838 let saved: Vec<_> = self.vm_globals.keys().filter(|k| k.starts_with('%')).collect();
1839 if !saved.is_empty() {
1840 eprintln!("Evaluator: Saved {} user globals (% vars: {:?})", self.vm_globals.len(), saved);
1841 }
1842 }
1843
1844 Ok(arena_to_value(&self.arena, result_id))
1846 }
1847
1848 pub fn set_use_vm(&mut self, enabled: bool) -> bool {
1853 let previous = self.use_vm;
1854 self.use_vm = enabled;
1855 previous
1856 }
1857
1858 pub fn sync_env_to_vm(&mut self, env: Gc<Environment>) -> Result<(), EvalError> {
1864 use crate::scheme::bridge::value_to_arena;
1865
1866 let bindings = env.all_bindings();
1868
1869 for (name, value) in bindings {
1871 let value_id = value_to_arena(&mut self.arena, &value);
1872 self.vm_globals.insert(name, value_id);
1873 }
1874
1875 Ok(())
1876 }
1877
1878 pub fn gc_if_needed(&mut self) {
1883 gc::force_collect();
1885
1886 let roots: Vec<_> = self.vm_globals.values().copied().collect();
1889 self.arena.gc(&roots);
1890 }
1891
1892 pub fn eval(&mut self, expr: Value, env: Gc<Environment>) -> EvalResult {
1902 if self.use_vm {
1904 return self.eval_with_vm(expr, env);
1905 }
1906
1907 let context_was_set = has_evaluator_context();
1909 let previous_context = get_evaluator_context();
1910
1911 set_evaluator_context(EvaluatorContext {
1914 grove: self.arena.grove.clone(),
1915 current_node: self.arena.current_node.clone(),
1916 backend: self.backend.clone(),
1917 });
1918
1919 let result = self.eval_inner(expr, env);
1921
1922 if context_was_set {
1924 if let Some(prev_ctx) = previous_context {
1925 set_evaluator_context(prev_ctx);
1926 }
1927 } else {
1928 clear_evaluator_context();
1929 }
1930
1931 result
1932 }
1933
1934 fn eval_inner(&mut self, expr: Value, env: Gc<Environment>) -> EvalResult {
1936 match expr {
1937 Value::Nil => Ok(Value::Nil),
1939 Value::Bool(_) => Ok(expr),
1940 Value::Integer(_) => Ok(expr),
1941 Value::Real(_) => Ok(expr),
1942 Value::Quantity { .. } => Ok(expr),
1943 Value::Char(_) => Ok(expr),
1944 Value::String(_) => Ok(expr),
1945 Value::Procedure(_) => Ok(expr),
1946 Value::Vector(_) => Ok(expr), Value::Unspecified => Ok(expr),
1948 Value::Error => Ok(expr),
1949
1950 Value::Node(_) => Ok(expr),
1952 Value::NodeList(_) => Ok(expr),
1953 Value::Sosofo => Ok(expr),
1954
1955 Value::Symbol(ref name) => {
1957 if let Some(val) = env.lookup(name) {
1959 return Ok(val);
1960 }
1961
1962 if let Some(static_name) = self.get_primitive_static_name(name) {
1964 return Ok(Value::primitive(static_name, |_args| {
1967 Err("Primitive should be dispatched through apply_primitive".to_string())
1968 }));
1969 }
1970
1971 Err(self.error_with_stack(format!("Undefined variable: {}", name)))
1972 },
1973
1974 Value::Keyword(_) => Ok(expr),
1976
1977 Value::Pair(_) => self.eval_list(expr, env),
1979 }
1980 }
1981
1982 fn eval_list(&mut self, expr: Value, env: Gc<Environment>) -> EvalResult {
1984 if let Value::Pair(ref p) = expr {
1986 let pair_data = p.borrow();
1987 if let Some(ref pos) = pair_data.pos {
1988 if !self.line_mappings.is_empty() {
1990 if let Some(mapping) = self.line_mappings.iter().find(|m| m.output_line == pos.line) {
1991 self.current_source_file = Some(mapping.source_file.clone());
1992 self.current_position = Some(Position {
1993 line: mapping.source_line,
1994 column: pos.column,
1995 });
1996 } else {
1997 self.current_position = Some(pos.clone());
1999 }
2000 } else {
2001 self.current_position = Some(pos.clone());
2003 }
2004 }
2005 }
2006
2007 let (operator, args) = self.list_car_cdr(&expr)?;
2009
2010 if let Value::Symbol(ref sym) = operator {
2012 match &**sym {
2013 "quote" => self.eval_quote(args),
2014 "if" => self.eval_if(args, env),
2015 "define" => self.eval_define(args, env),
2016 "set!" => self.eval_set(args, env),
2017 "lambda" => self.eval_lambda(args, env),
2018 "let" => self.eval_let(args, env),
2019 "let*" => self.eval_let_star(args, env),
2020 "letrec" => self.eval_letrec(args, env),
2021 "begin" => self.eval_begin(args, env),
2022 "cond" => self.eval_cond(args, env),
2023 "case" => self.eval_case(args, env),
2024 "and" => self.eval_and(args, env),
2025 "or" => self.eval_or(args, env),
2026 "apply" => self.eval_apply(args, env),
2027 "map" => self.eval_map(args, env),
2028 "for-each" => self.eval_for_each(args, env),
2029 "node-list-filter" => self.eval_node_list_filter(args, env),
2030 "node-list-map" => self.eval_node_list_map(args, env),
2031 "node-list-some?" => self.eval_node_list_some(args, env),
2032 "load" => self.eval_load(args, env),
2033
2034 "define-unit" => self.eval_define_unit(args, env),
2036 "define-language" => self.eval_define_language(args, env),
2037 "declare-flow-object-class" => self.eval_declare_flow_object_class(args, env),
2038 "declare-characteristic" => self.eval_declare_characteristic(args, env),
2039 "declare-initial-value" => self.eval_declare_initial_value(args, env),
2040 "mode" => self.eval_mode(args, env),
2041 "with-mode" => self.eval_with_mode(args, env),
2042 "element" => self.eval_element(args, env),
2043 "default" => self.eval_default(args, env),
2044 "process-children" => self.eval_process_children(env),
2045 "process-children-trim" => self.eval_process_children_trim(env),
2046 "process-node-list" => self.eval_process_node_list(args, env),
2047 "make" => self.eval_make(args, env),
2048 "style" => self.eval_style(args, env),
2049
2050 _ => self.eval_application(operator, args, env),
2052 }
2053 } else {
2054 self.eval_application(operator, args, env)
2056 }
2057 }
2058
2059 fn list_car_cdr(&self, list: &Value) -> Result<(Value, Value), EvalError> {
2061 if let Value::Pair(ref p) = list {
2062 let pair = p.borrow();
2063 Ok((pair.car.clone(), pair.cdr.clone()))
2064 } else {
2065 Err(EvalError::new("Expected list".to_string()))
2066 }
2067 }
2068
2069 fn vec_to_list(&self, vec: Vec<Value>) -> Value {
2071 let mut result = Value::Nil;
2072 for val in vec.iter().rev() {
2073 result = Value::cons(val.clone(), result);
2074 }
2075 result
2076 }
2077
2078 pub fn list_to_vec(&self, list: Value) -> Result<Vec<Value>, EvalError> {
2080 let mut result = Vec::new();
2081 let mut current = list;
2082
2083 loop {
2084 match current {
2085 Value::Nil => break,
2086 Value::Pair(ref p) => {
2087 let pair = p.borrow();
2088 result.push(pair.car.clone());
2089 let cdr = pair.cdr.clone();
2090 drop(pair); current = cdr;
2092 }
2093 _ => return Err(EvalError::new("Improper list".to_string())),
2094 }
2095 }
2096
2097 Ok(result)
2098 }
2099
2100 fn eval_quote(&mut self, args: Value) -> EvalResult {
2106 let args_vec = self.list_to_vec(args)?;
2107 if args_vec.len() != 1 {
2108 return Err(EvalError::new("quote requires exactly 1 argument".to_string()));
2109 }
2110 Ok(args_vec[0].clone())
2111 }
2112
2113 fn eval_if(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2115 let args_vec = self.list_to_vec(args)?;
2116 if args_vec.len() < 2 || args_vec.len() > 3 {
2117 return Err(EvalError::new(
2118 "if requires 2 or 3 arguments".to_string(),
2119 ));
2120 }
2121
2122 let test = self.eval_inner(args_vec[0].clone(), env.clone())?;
2123
2124 if test.is_true() {
2125 self.eval_inner(args_vec[1].clone(), env)
2126 } else if args_vec.len() == 3 {
2127 self.eval_inner(args_vec[2].clone(), env)
2128 } else {
2129 Ok(Value::Unspecified)
2130 }
2131 }
2132
2133 fn eval_define(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2135 let args_vec = self.list_to_vec(args)?;
2136 if args_vec.len() < 2 {
2137 return Err(EvalError::new(
2138 "define requires at least 2 arguments".to_string(),
2139 ));
2140 }
2141
2142 match &args_vec[0] {
2144 Value::Symbol(ref name) => {
2145 if args_vec.len() != 2 {
2147 return Err(EvalError::new(
2148 "define with symbol requires exactly 2 arguments".to_string(),
2149 ));
2150 }
2151 let value = self.eval_inner(args_vec[1].clone(), env.clone())?;
2152 env.define(name, value);
2153 Ok(Value::Unspecified)
2154 }
2155
2156 Value::Pair(_) => {
2157 let (name_val, params) = self.list_car_cdr(&args_vec[0])?;
2160
2161 if let Value::Symbol(ref name) = name_val {
2162 let (param_names, required_count, optional_defaults) =
2164 self.parse_lambda_params(params)?;
2165
2166 let body = if args_vec.len() == 2 {
2168 args_vec[1].clone()
2169 } else {
2170 let mut body_list = Value::Nil;
2171 for expr in args_vec[1..].iter().rev() {
2172 body_list = Value::cons(expr.clone(), body_list);
2173 }
2174 Value::cons(Value::symbol("begin"), body_list)
2175 };
2176
2177 let source_info = self.current_source_file.as_ref().map(|file| {
2179 use crate::scheme::parser::Position;
2180 SourceInfo::new(file.clone(), Position::new())
2181 });
2182
2183 let lambda_value = if optional_defaults.is_empty() {
2184 Value::lambda_with_source(
2185 param_names,
2186 body,
2187 env.clone(),
2188 source_info,
2189 Some(name.to_string()),
2190 )
2191 } else {
2192 Value::lambda_with_optional(
2193 param_names,
2194 required_count,
2195 optional_defaults,
2196 body,
2197 env.clone(),
2198 source_info,
2199 Some(name.to_string()),
2200 )
2201 };
2202
2203 env.define(name, lambda_value);
2204 Ok(Value::Unspecified)
2205 } else {
2206 Err(EvalError::new(
2207 "First element of define must be a symbol".to_string(),
2208 ))
2209 }
2210 }
2211
2212 _ => Err(EvalError::new(
2213 "First argument to define must be symbol or list".to_string(),
2214 )),
2215 }
2216 }
2217
2218 fn eval_define_unit(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2224 let args_vec = self.list_to_vec(args)?;
2225
2226 if args_vec.len() != 2 {
2227 return Err(EvalError::new(
2228 "define-unit requires exactly 2 arguments: name and value".to_string(),
2229 ));
2230 }
2231
2232 if let Value::Symbol(ref name) = args_vec[0] {
2234 let value = self.eval_inner(args_vec[1].clone(), env.clone())?;
2236 env.define(name, value);
2238 Ok(Value::Unspecified)
2239 } else {
2240 Err(EvalError::new(
2241 "First argument to define-unit must be a symbol".to_string(),
2242 ))
2243 }
2244 }
2245
2246 fn eval_define_language(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2249 let args_vec = self.list_to_vec(args)?;
2250
2251 if args_vec.is_empty() {
2252 return Err(EvalError::new(
2253 "define-language requires at least 1 argument".to_string(),
2254 ));
2255 }
2256
2257 if let Value::Symbol(ref name) = args_vec[0] {
2259 env.define(name, args_vec[0].clone());
2262 Ok(Value::Unspecified)
2263 } else {
2264 Err(EvalError::new(
2265 "First argument to define-language must be a symbol".to_string(),
2266 ))
2267 }
2268 }
2269
2270 fn eval_declare_flow_object_class(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2273 let args_vec = self.list_to_vec(args)?;
2274
2275 if args_vec.is_empty() {
2276 return Err(EvalError::new(
2277 "declare-flow-object-class requires at least 1 argument".to_string(),
2278 ));
2279 }
2280
2281 if let Value::Symbol(ref name) = args_vec[0] {
2283 env.define(name, args_vec[0].clone());
2286 Ok(Value::Unspecified)
2287 } else {
2288 Err(EvalError::new(
2289 "First argument to declare-flow-object-class must be a symbol".to_string(),
2290 ))
2291 }
2292 }
2293
2294 fn eval_declare_characteristic(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2297 let args_vec = self.list_to_vec(args)?;
2298
2299 if args_vec.len() < 3 {
2300 return Err(EvalError::new(
2301 "declare-characteristic requires at least 3 arguments (name, public-id, default-value)".to_string(),
2302 ));
2303 }
2304
2305 if let Value::Symbol(ref name) = args_vec[0] {
2307 let default_value = self.eval(args_vec[2].clone(), env.clone())?;
2309
2310 env.define(name, default_value);
2312 Ok(Value::Unspecified)
2313 } else {
2314 Err(EvalError::new(
2315 "First argument to declare-characteristic must be a symbol".to_string(),
2316 ))
2317 }
2318 }
2319
2320 fn eval_declare_initial_value(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2324 let args_vec = self.list_to_vec(args)?;
2325
2326 if args_vec.len() != 2 {
2327 return Err(EvalError::new(
2328 "declare-initial-value requires exactly 2 arguments (name and value)".to_string(),
2329 ));
2330 }
2331
2332 if let Value::Symbol(ref name) = args_vec[0] {
2334 let value = self.eval_inner(args_vec[1].clone(), env.clone())?;
2336
2337 env.define(name, value);
2339 Ok(Value::Unspecified)
2340 } else {
2341 Err(EvalError::new(
2342 "First argument to declare-initial-value must be a symbol".to_string(),
2343 ))
2344 }
2345 }
2346
2347 fn eval_element(&mut self, args: Value, _env: Gc<Environment>) -> EvalResult {
2357 let args_vec = self.list_to_vec(args)?;
2358
2359 if args_vec.len() < 2 {
2360 return Err(self.error_with_stack(
2361 "element requires at least 2 arguments (element-pattern and construction-expression)".to_string(),
2362 ));
2363 }
2364
2365 let (element_name, context) = match &args_vec[0] {
2368 Value::Symbol(ref name) => (name.clone(), Vec::new()),
2369 Value::Pair(_) => {
2370 let pattern_list = self.list_to_vec(args_vec[0].clone())?;
2372 if pattern_list.is_empty() {
2373 return Err(self.error_with_stack(
2374 "Element pattern list cannot be empty".to_string(),
2375 ));
2376 }
2377 let element_name = if let Value::Symbol(ref name) = pattern_list[pattern_list.len() - 1] {
2379 name.clone()
2380 } else {
2381 return Err(self.error_with_stack(
2382 "Element pattern must contain only symbols".to_string(),
2383 ));
2384 };
2385 let mut context = Vec::new();
2387 for i in 0..pattern_list.len() - 1 {
2388 if let Value::Symbol(ref parent_name) = pattern_list[i] {
2389 context.push(parent_name.to_string());
2390 } else {
2391 return Err(self.error_with_stack(
2392 "Element pattern must contain only symbols".to_string(),
2393 ));
2394 }
2395 }
2396 (element_name, context)
2397 }
2398 _ => {
2399 return Err(self.error_with_stack(
2400 "First argument to element must be a symbol or list of symbols".to_string(),
2401 ));
2402 }
2403 };
2404
2405 if args_vec.len() > 2 {
2409 return Err(self.error_with_stack(
2410 "element can only contain one sosofo expression. Use (sosofo-append ...) to combine multiple sosofos".to_string(),
2411 ));
2412 }
2413
2414 let construction_expr = args_vec[1].clone();
2415
2416 let mode_name = self.current_mode.clone();
2420 self.mode_manager.get_or_create_mode(&mode_name).add_rule(
2421 element_name.to_string(),
2422 context,
2423 construction_expr,
2424 self.current_source_file.clone(),
2425 self.current_position.clone()
2426 );
2427
2428 Ok(Value::Unspecified)
2429 }
2430
2431 fn eval_default(&mut self, args: Value, _env: Gc<Environment>) -> EvalResult {
2437 let args_vec = self.list_to_vec(args)?;
2438
2439 if args_vec.is_empty() {
2440 return Err(self.error_with_stack(
2441 "default requires at least 1 argument (construction-expression)".to_string(),
2442 ));
2443 }
2444
2445 if args_vec.len() > 1 {
2448 return Err(self.error_with_stack(
2449 "default can only contain one sosofo expression. Use (sosofo-append ...) to combine multiple sosofos".to_string(),
2450 ));
2451 }
2452
2453 let construction_expr = args_vec[0].clone();
2454
2455 let mode_name = self.current_mode.clone();
2457 self.mode_manager.get_or_create_mode(&mode_name).add_default_rule(construction_expr);
2458
2459 Ok(Value::Unspecified)
2460 }
2461
2462 fn eval_mode(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2468 let args_vec = self.list_to_vec(args)?;
2469
2470 if args_vec.is_empty() {
2471 return Err(self.error_with_stack(
2472 "mode requires at least 1 argument (mode-name)".to_string(),
2473 ));
2474 }
2475
2476 let mode_name = if let Value::Symbol(ref name) = args_vec[0] {
2478 name.clone()
2479 } else {
2480 return Err(self.error_with_stack(
2481 "First argument to mode must be a symbol".to_string(),
2482 ));
2483 };
2484
2485 let saved_mode = self.current_mode.clone();
2487
2488 self.current_mode = mode_name.to_string();
2490
2491 let mut result = Value::Unspecified;
2493 for expr in args_vec.iter().skip(1) {
2494 result = self.eval(expr.clone(), env.clone())?;
2495 }
2496
2497 self.current_mode = saved_mode;
2499
2500 Ok(result)
2501 }
2502
2503 fn eval_with_mode(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2509 let args_vec = self.list_to_vec(args)?;
2510
2511 if args_vec.len() < 2 {
2512 return Err(self.error_with_stack(
2513 "with-mode requires 2 arguments (mode-name and expression)".to_string(),
2514 ));
2515 }
2516
2517 let mode_name = if let Value::Symbol(ref name) = args_vec[0] {
2519 name.clone()
2520 } else {
2521 return Err(self.error_with_stack(
2522 "First argument to with-mode must be a symbol".to_string(),
2523 ));
2524 };
2525
2526 let saved_processing_mode = self.current_processing_mode.clone();
2528
2529 self.current_processing_mode = mode_name.to_string();
2531
2532 let result = self.eval(args_vec[1].clone(), env);
2534
2535 self.current_processing_mode = saved_processing_mode;
2537
2538 result
2539 }
2540
2541 fn eval_process_children(&mut self, env: Gc<Environment>) -> EvalResult {
2547 let current_node = match self.current_node() {
2549 Some(node) => node.clone(),
2550 None => return Err(EvalError::new("No current node".to_string())),
2551 };
2552
2553 let mut children = current_node.all_children();
2556
2557 let mut result = Value::Unspecified;
2559
2560 while !children.is_empty() {
2561 if let Some(child_node) = children.first() {
2563 let saved_node = self.current_node();
2565
2566 self.set_current_node(child_node);
2568
2569 result = self.process_node(env.clone())?;
2571
2572 self.restore_current_node(saved_node);
2574 }
2575
2576 children = children.rest();
2578 }
2579
2580 Ok(result)
2581 }
2582
2583 fn eval_process_children_trim(&mut self, env: Gc<Environment>) -> EvalResult {
2591 let current_node = match self.current_node() {
2593 Some(node) => node.clone(),
2594 None => return Err(EvalError::new("No current node".to_string())),
2595 };
2596
2597 let mut children = current_node.all_children();
2599
2600 let mut child_nodes = Vec::new();
2602 while !children.is_empty() {
2603 if let Some(child) = children.first() {
2604 child_nodes.push(child);
2605 }
2606 children = children.rest();
2607 }
2608
2609 if child_nodes.is_empty() {
2610 return Ok(Value::Unspecified);
2611 }
2612
2613 let mut at_start = true;
2615
2616 for (index, child_node) in child_nodes.iter().enumerate() {
2618 let is_last = index == child_nodes.len() - 1;
2619
2620 if child_node.is_text() {
2621 if let Some(mut text) = child_node.data() {
2623 if at_start {
2625 let trimmed = text.trim_start();
2626 if trimmed.is_empty() {
2627 continue;
2629 }
2630 text = trimmed.to_string();
2631 at_start = false;
2632 }
2633
2634 if is_last {
2636 text = text.trim_end().to_string();
2637 }
2638
2639 if !text.is_empty() {
2640 if let Some(ref backend) = self.backend {
2642 backend.borrow_mut().literal(&text)
2643 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2644 }
2645 }
2646 }
2647 } else if child_node.is_element() {
2648 at_start = false;
2650
2651 let saved_node = self.current_node();
2653 self.set_current_node(child_node.clone_node());
2654 let _result = self.process_node(env.clone())?;
2655 self.restore_current_node(saved_node);
2656 }
2657 }
2658
2659 Ok(Value::Unspecified)
2660 }
2661
2662 fn eval_process_node_list(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2668 let args_vec = self.list_to_vec(args)?;
2669 if args_vec.len() != 1 {
2670 return Err(EvalError::new(
2671 "process-node-list requires exactly 1 argument".to_string(),
2672 ));
2673 }
2674
2675 let node_list_value = self.eval(args_vec[0].clone(), env.clone())?;
2677
2678 let mut nodes = match node_list_value {
2680 Value::NodeList(ref nl) => nl.clone(),
2681 Value::Node(ref n) => {
2682 let node_box: Box<dyn crate::grove::Node> = (**n).clone_node();
2685 Rc::new(Box::new(crate::grove::VecNodeList::new(vec![node_box])) as Box<dyn crate::grove::NodeList>)
2686 }
2687 _ => {
2688 return Err(EvalError::new(format!(
2689 "process-node-list: not a node-list: {:?}",
2690 node_list_value
2691 )))
2692 }
2693 };
2694
2695 let mut result = Value::Unspecified;
2697 while !nodes.is_empty() {
2698 if let Some(node) = nodes.first() {
2700 let saved_node = self.current_node();
2702
2703 self.set_current_node(node);
2705
2706 result = self.process_node(env.clone())?;
2708
2709 self.restore_current_node(saved_node);
2711 }
2712
2713 nodes = Rc::new(nodes.rest());
2715 }
2716
2717 Ok(result)
2718 }
2719
2720 fn eval_make(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
2726 let args_vec = self.list_to_vec(args)?;
2727
2728 if args_vec.is_empty() {
2729 return Err(EvalError::new(
2730 "make requires at least a flow object type".to_string(),
2731 ));
2732 }
2733
2734 let fo_type = match &args_vec[0] {
2736 Value::Symbol(s) => s.as_ref(),
2737 _ => return Err(EvalError::new(
2738 "make: first argument must be a flow object type symbol".to_string(),
2739 )),
2740 };
2741
2742 let mut i = 1;
2744 let mut system_id = None;
2745 let mut data = None;
2746 let mut path = None;
2747 let mut gi = None;
2748 let mut attributes = None;
2749 let mut body_exprs = Vec::new();
2750
2751 while i < args_vec.len() {
2752 match &args_vec[i] {
2753 Value::Keyword(kw) => {
2754 if i + 1 >= args_vec.len() {
2756 return Err(EvalError::new(
2757 format!("make: keyword {} requires a value", kw),
2758 ));
2759 }
2760
2761 if std::env::var("DAZZLE_DEBUG").is_ok() {
2763 eprintln!("EVAL_MAKE: Processing keyword '{}:', value expr = {:?}",
2764 kw, args_vec[i + 1]);
2765 }
2766
2767 let value = self.eval(args_vec[i + 1].clone(), env.clone())?;
2768
2769 if std::env::var("DAZZLE_DEBUG").is_ok() {
2771 eprintln!("EVAL_MAKE: Keyword '{}' evaluated to {:?}", kw, value);
2772 }
2773
2774 match kw.as_ref() {
2775 "system-id" => {
2776 if let Value::String(s) = value {
2777 system_id = Some(s);
2778 } else {
2779 return Err(EvalError::new(
2780 "make: system-id must be a string".to_string(),
2781 ));
2782 }
2783 }
2784 "data" => {
2785 if let Value::String(s) = value {
2786 data = Some(s);
2787 } else {
2788 return Err(EvalError::new(
2789 format!("make: data must be a string, got {:?}", value),
2790 ));
2791 }
2792 }
2793 "path" => {
2794 if let Value::String(s) = value {
2795 path = Some(s);
2796 } else {
2797 return Err(EvalError::new(
2798 "make: path must be a string".to_string(),
2799 ));
2800 }
2801 }
2802 "gi" => {
2803 if let Value::String(s) = value {
2804 gi = Some(s);
2805 } else {
2806 return Err(EvalError::new(
2807 "make element: gi must be a string".to_string(),
2808 ));
2809 }
2810 }
2811 "attributes" => {
2812 attributes = Some(value);
2814 }
2815 _ => {
2816 }
2818 }
2819 i += 2;
2820 }
2821 _ => {
2822 body_exprs.push(args_vec[i].clone());
2824 i += 1;
2825 }
2826 }
2827 }
2828
2829 let backend = self.backend.clone();
2831 match backend {
2832 Some(ref backend) => {
2833 match fo_type {
2834 "entity" => {
2835 if let Some(sid) = system_id {
2836 let saved_buffer = backend.borrow().current_output().to_string();
2838 backend.borrow_mut().clear_buffer();
2839
2840 for expr in body_exprs {
2842 self.eval(expr, env.clone())?;
2843 }
2844
2845 let content = backend.borrow().current_output().to_string();
2847 backend.borrow_mut().entity(&sid, &content)
2848 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2849
2850 backend.borrow_mut().clear_buffer();
2852 backend.borrow_mut().formatting_instruction(&saved_buffer)
2853 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2854 } else {
2855 return Err(EvalError::new(
2856 "make entity requires system-id: keyword".to_string(),
2857 ));
2858 }
2859 }
2860 "formatting-instruction" => {
2861 if let Some(d) = data {
2862 backend.borrow_mut().formatting_instruction(&d)
2864 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2865 } else {
2866 return Err(EvalError::new(
2867 "make formatting-instruction requires data: keyword".to_string(),
2868 ));
2869 }
2870 }
2871 "literal" => {
2872 if let Some(d) = data {
2875 backend.borrow_mut().formatting_instruction(&d)
2876 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2877 } else {
2878 return Err(EvalError::new(
2879 "make literal requires data: keyword or a string body".to_string(),
2880 ));
2881 }
2882 }
2883 "directory" => {
2884 if let Some(p) = path {
2885 let prev_dir = backend.borrow().current_directory().map(|s| s.to_string());
2887
2888 backend.borrow_mut().directory(&p)
2890 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2891
2892 for expr in body_exprs {
2895 self.eval(expr, env.clone())?;
2896 }
2897
2898 backend.borrow_mut().set_current_directory(prev_dir);
2900 } else {
2901 return Err(EvalError::new(
2902 "make directory requires path: keyword".to_string(),
2903 ));
2904 }
2905 }
2906 "sequence" => {
2907 for expr in body_exprs {
2910 self.eval(expr, env.clone())?;
2911 }
2912 }
2913 "element" => {
2914 let gi = gi.ok_or_else(|| EvalError::new(
2921 "make element requires gi: keyword".to_string()
2922 ))?;
2923
2924 backend.borrow_mut().formatting_instruction(&format!("<{}\n", gi))
2926 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2927
2928 if let Some(attrs_val) = attributes {
2930 let attrs_list = self.list_to_vec(attrs_val)?;
2932 for attr_pair in attrs_list {
2933 let pair_vec = self.list_to_vec(attr_pair)?;
2934 if pair_vec.len() == 2 {
2935 if let (Value::String(name), Value::String(value)) =
2936 (&pair_vec[0], &pair_vec[1]) {
2937 let escaped_value = value
2939 .replace('&', "&")
2940 .replace('"', """)
2941 .replace('<', "<")
2942 .replace('>', ">");
2943 backend.borrow_mut().formatting_instruction(&format!("{}=\"{}\"\n", name, escaped_value))
2944 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2945 }
2946 }
2947 }
2948 }
2949
2950 backend.borrow_mut().formatting_instruction(">")
2952 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2953
2954 for expr in body_exprs {
2956 self.eval(expr, env.clone())?;
2957 }
2958
2959 backend.borrow_mut().formatting_instruction(&format!("</{}\n>", gi))
2961 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2962 }
2963 "paragraph" => {
2964 backend.borrow_mut().start_paragraph()
2967 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2968
2969 for expr in body_exprs {
2971 self.eval(expr, env.clone())?;
2972 }
2973
2974 backend.borrow_mut().end_paragraph()
2976 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2977 }
2978 "display-group" => {
2979 backend.borrow_mut().start_display_group()
2981 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2982
2983 for expr in body_exprs {
2984 self.eval(expr, env.clone())?;
2985 }
2986
2987 backend.borrow_mut().end_display_group()
2988 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2989 }
2990 "simple-page-sequence" => {
2991 backend.borrow_mut().start_simple_page_sequence()
2993 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
2994
2995 for expr in body_exprs {
2996 self.eval(expr, env.clone())?;
2997 }
2998
2999 backend.borrow_mut().end_simple_page_sequence()
3000 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
3001 }
3002 "line-field" => {
3003 backend.borrow_mut().start_line_field()
3005 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
3006
3007 for expr in body_exprs {
3008 self.eval(expr, env.clone())?;
3009 }
3010
3011 backend.borrow_mut().end_line_field()
3012 .map_err(|e| EvalError::new(format!("Backend error: {}", e)))?;
3013 }
3014 "link" | "scroll" | "marginalia" | "leader" | "table" | "table-row" | "table-cell" | "table-column" | "table-part" | "paragraph-break" => {
3015 for expr in body_exprs {
3018 self.eval(expr, env.clone())?;
3019 }
3020 }
3021 _ => {
3022 return Err(EvalError::new(
3024 format!("make: unknown flow object type '{}'", fo_type),
3025 ));
3026 }
3027 }
3028 }
3029 None => {
3030 return Err(EvalError::new(
3031 "make: no backend available".to_string(),
3032 ));
3033 }
3034 }
3035
3036 Ok(Value::Sosofo)
3038 }
3039
3040 fn eval_style(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3045 let args_vec = self.list_to_vec(args)?;
3047 let mut i = 0;
3048
3049 while i < args_vec.len() {
3050 match &args_vec[i] {
3051 Value::Keyword(_kw) => {
3052 if i + 1 >= args_vec.len() {
3054 return Err(EvalError::new(
3055 "style: keyword requires a value".to_string(),
3056 ));
3057 }
3058 let _value = self.eval(args_vec[i + 1].clone(), env.clone())?;
3060 i += 2;
3061 }
3062 _ => {
3063 return Err(EvalError::new(
3064 format!("style: unexpected argument {:?}", args_vec[i]),
3065 ));
3066 }
3067 }
3068 }
3069
3070 Ok(Value::Symbol(Rc::from("dummy-style")))
3072 }
3073
3074 fn eval_set(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3076 let args_vec = self.list_to_vec(args)?;
3077 if args_vec.len() != 2 {
3078 return Err(EvalError::new(
3079 "set! requires exactly 2 arguments".to_string(),
3080 ));
3081 }
3082
3083 if let Value::Symbol(ref name) = args_vec[0] {
3084 let value = self.eval(args_vec[1].clone(), env.clone())?;
3085 env.set(name, value)
3086 .map_err(|e| EvalError::new(e))?;
3087 Ok(Value::Unspecified)
3088 } else {
3089 Err(EvalError::new(
3090 "First argument to set! must be a symbol".to_string(),
3091 ))
3092 }
3093 }
3094
3095 fn eval_lambda(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3097 let args_vec = self.list_to_vec(args)?;
3098 if args_vec.len() < 2 {
3099 return Err(EvalError::new(
3100 "lambda requires at least 2 arguments (params and body)".to_string(),
3101 ));
3102 }
3103
3104 let params_list = &args_vec[0];
3106 let (param_names, required_count, optional_defaults) =
3107 self.parse_lambda_params(params_list.clone())?;
3108
3109 let body = if args_vec.len() == 2 {
3111 args_vec[1].clone()
3113 } else {
3114 let mut body_list = Value::Nil;
3116 for expr in args_vec[1..].iter().rev() {
3117 body_list = Value::cons(expr.clone(), body_list);
3118 }
3119 Value::cons(Value::symbol("begin"), body_list)
3120 };
3121
3122 let source_info = match (&self.current_source_file, &self.current_position) {
3125 (Some(file), Some(pos)) => {
3126 Some(SourceInfo::new(file.clone(), pos.clone()))
3128 }
3129 (Some(file), None) => {
3130 use crate::scheme::parser::Position;
3131 Some(SourceInfo::new(file.clone(), Position::new()))
3132 }
3133 _ => None,
3134 };
3135
3136 if optional_defaults.is_empty() {
3138 Ok(Value::lambda_with_source(param_names, body, env, source_info, None))
3139 } else {
3140 Ok(Value::lambda_with_optional(
3141 param_names,
3142 required_count,
3143 optional_defaults,
3144 body,
3145 env,
3146 source_info,
3147 None,
3148 ))
3149 }
3150 }
3151
3152 fn parse_lambda_params(
3156 &mut self,
3157 params: Value,
3158 ) -> Result<(Vec<String>, usize, Vec<Value>), EvalError> {
3159 if params.is_nil() {
3160 return Ok((Vec::new(), 0, Vec::new()));
3161 }
3162
3163 let params_vec = self.list_to_vec(params)?;
3164 let mut param_names = Vec::new();
3165 let mut required_count = 0;
3166 let mut optional_defaults = Vec::new();
3167 let mut in_optional = false;
3168
3169 for param in params_vec {
3170 if let Value::Symbol(ref sym) = param {
3172 if sym.as_ref() == "#!optional" {
3173 in_optional = true;
3174 continue;
3175 }
3176 }
3177
3178 if !in_optional {
3179 if let Value::Symbol(ref name) = param {
3181 param_names.push(name.to_string());
3182 required_count += 1;
3183 } else {
3184 return Err(EvalError::new(format!(
3185 "Parameter must be a symbol, got: {:?}",
3186 param
3187 )));
3188 }
3189 } else {
3190 match param {
3192 Value::Symbol(ref name) => {
3193 param_names.push(name.to_string());
3195 optional_defaults.push(Value::Unspecified);
3196 }
3197 Value::Pair(_) => {
3198 let opt_list = self.list_to_vec(param)?;
3200 if opt_list.len() != 2 {
3201 return Err(EvalError::new(format!(
3202 "Optional parameter must be (name default), got list of length {}",
3203 opt_list.len()
3204 )));
3205 }
3206
3207 if let Value::Symbol(ref name) = opt_list[0] {
3208 param_names.push(name.to_string());
3209 if std::env::var("DEBUG_OPTIONAL").is_ok() {
3211 eprintln!("[DEBUG_OPTIONAL] Storing default for param '{}': {:?}", name, opt_list[1]);
3212 }
3213 optional_defaults.push(opt_list[1].clone());
3214 } else {
3215 return Err(EvalError::new(format!(
3216 "Optional parameter name must be a symbol, got: {:?}",
3217 opt_list[0]
3218 )));
3219 }
3220 }
3221 _ => {
3222 return Err(EvalError::new(format!(
3223 "Optional parameter must be symbol or (symbol default), got: {:?}",
3224 param
3225 )));
3226 }
3227 }
3228 }
3229 }
3230
3231 Ok((param_names, required_count, optional_defaults))
3232 }
3233
3234 fn eval_let(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3236 let args_vec = self.list_to_vec(args)?;
3237 if args_vec.len() < 2 {
3238 return Err(EvalError::new(
3239 "let requires at least 2 arguments".to_string(),
3240 ));
3241 }
3242
3243 if let Value::Symbol(ref loop_name) = args_vec[0] {
3245 if args_vec.len() < 3 {
3246 return Err(EvalError::new(
3247 "named let requires at least 3 arguments".to_string(),
3248 ));
3249 }
3250
3251 let bindings_list = &args_vec[1];
3253 let bindings = self.list_to_vec(bindings_list.clone())?;
3254 let body = &args_vec[2..];
3255
3256 let mut var_names = Vec::new();
3258 let mut init_values = Vec::new();
3259 for binding in &bindings {
3260 let binding_vec = self.list_to_vec(binding.clone())?;
3261 if binding_vec.len() != 2 {
3262 return Err(EvalError::new(
3263 "named let binding must have exactly 2 elements".to_string(),
3264 ));
3265 }
3266 var_names.push(binding_vec[0].clone());
3267 init_values.push(binding_vec[1].clone());
3268 }
3269
3270 let lambda_params = self.vec_to_list(var_names);
3272 let mut lambda_body = vec![Value::symbol("lambda"), lambda_params];
3273 lambda_body.extend_from_slice(body);
3274 let lambda_expr = self.vec_to_list(lambda_body);
3275
3276 let letrec_binding = Value::cons(
3278 Value::symbol(loop_name),
3279 Value::cons(lambda_expr, Value::Nil),
3280 );
3281 let letrec_bindings = Value::cons(letrec_binding, Value::Nil);
3282
3283 let mut call_expr = vec![Value::symbol(loop_name)];
3285 call_expr.extend_from_slice(&init_values);
3286 let call = self.vec_to_list(call_expr);
3287
3288 return self.eval_letrec(self.vec_to_list(vec![letrec_bindings, call]), env);
3290 }
3291
3292 let bindings_list = &args_vec[0];
3294 let bindings = self.list_to_vec(bindings_list.clone())?;
3295
3296 let new_env = Environment::extend(env.clone());
3298
3299 for binding in bindings {
3301 let binding_vec = self.list_to_vec(binding)?;
3302 if binding_vec.len() != 2 {
3303 return Err(EvalError::new(
3304 "let binding must have exactly 2 elements".to_string(),
3305 ));
3306 }
3307
3308 if let Value::Symbol(ref name) = binding_vec[0] {
3309 let value = self.eval_inner(binding_vec[1].clone(), env.clone())?;
3310 new_env.define(name, value);
3311 } else {
3312 return Err(EvalError::new(
3313 "Binding variable must be a symbol".to_string(),
3314 ));
3315 }
3316 }
3317
3318 let body = &args_vec[1..];
3320 self.eval_sequence(body, new_env)
3321 }
3322
3323 fn eval_let_star(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3325 let args_vec = self.list_to_vec(args)?;
3326 if args_vec.len() < 2 {
3327 return Err(EvalError::new(
3328 "let* requires at least 2 arguments".to_string(),
3329 ));
3330 }
3331
3332 let bindings_list = &args_vec[0];
3334 let bindings = self.list_to_vec(bindings_list.clone())?;
3335
3336 let current_env = Environment::extend(env);
3338
3339 for binding in bindings {
3341 let binding_vec = self.list_to_vec(binding)?;
3342 if binding_vec.len() != 2 {
3343 return Err(EvalError::new(
3344 "let* binding must have exactly 2 elements".to_string(),
3345 ));
3346 }
3347
3348 if let Value::Symbol(ref name) = binding_vec[0] {
3349 let value = self.eval_inner(binding_vec[1].clone(), current_env.clone())?;
3350 current_env.define(name, value);
3351 } else {
3352 return Err(EvalError::new(
3353 "Binding variable must be a symbol".to_string(),
3354 ));
3355 }
3356 }
3357
3358 let body = &args_vec[1..];
3360 self.eval_sequence(body, current_env)
3361 }
3362
3363 fn eval_letrec(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3373 let args_vec = self.list_to_vec(args)?;
3374 if args_vec.len() < 2 {
3375 return Err(EvalError::new(
3376 "letrec requires at least 2 arguments".to_string(),
3377 ));
3378 }
3379
3380 let bindings_list = &args_vec[0];
3382 let bindings = self.list_to_vec(bindings_list.clone())?;
3383
3384 let new_env = Environment::extend(env);
3386
3387 let mut var_names = Vec::new();
3389 for binding in &bindings {
3390 let binding_vec = self.list_to_vec(binding.clone())?;
3391 if binding_vec.len() != 2 {
3392 return Err(EvalError::new(
3393 "letrec binding must have exactly 2 elements".to_string(),
3394 ));
3395 }
3396
3397 if let Value::Symbol(ref name) = binding_vec[0] {
3398 var_names.push(name.to_string());
3399 new_env.define(name, Value::Unspecified);
3400 } else {
3401 return Err(EvalError::new(
3402 "Binding variable must be a symbol".to_string(),
3403 ));
3404 }
3405 }
3406
3407 for (i, binding) in bindings.iter().enumerate() {
3409 let binding_vec = self.list_to_vec(binding.clone())?;
3410 let value = self.eval_inner(binding_vec[1].clone(), new_env.clone())?;
3411
3412 new_env.set(&var_names[i], value)
3414 .map_err(|e| EvalError::new(e))?;
3415 }
3416
3417 let body = &args_vec[1..];
3419 self.eval_sequence(body, new_env)
3420 }
3421
3422 fn eval_begin(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3424 let args_vec = self.list_to_vec(args)?;
3425 self.eval_sequence(&args_vec, env)
3426 }
3427
3428 fn eval_cond(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3430 let clauses = self.list_to_vec(args)?;
3431
3432 for clause in clauses {
3433 let clause_vec = self.list_to_vec(clause)?;
3434 if clause_vec.is_empty() {
3435 return Err(EvalError::new("Empty cond clause".to_string()));
3436 }
3437
3438 if let Value::Symbol(ref sym) = clause_vec[0] {
3440 if &**sym == "else" {
3441 return self.eval_sequence(&clause_vec[1..], env);
3442 }
3443 }
3444
3445 let test = self.eval_inner(clause_vec[0].clone(), env.clone())?;
3447 if test.is_true() {
3448 if clause_vec.len() == 1 {
3449 return Ok(test);
3450 } else {
3451 return self.eval_sequence(&clause_vec[1..], env);
3452 }
3453 }
3454 }
3455
3456 Ok(Value::Unspecified)
3457 }
3458
3459 fn eval_case(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3473 let args_vec = self.list_to_vec(args)?;
3474 if args_vec.is_empty() {
3475 return Err(EvalError::new("case requires at least 1 argument".to_string()));
3476 }
3477
3478 let key = self.eval_inner(args_vec[0].clone(), env.clone())?;
3480
3481 for clause in &args_vec[1..] {
3483 let clause_vec = self.list_to_vec(clause.clone())?;
3484 if clause_vec.is_empty() {
3485 return Err(EvalError::new("Empty case clause".to_string()));
3486 }
3487
3488 if let Value::Symbol(ref sym) = clause_vec[0] {
3490 if &**sym == "else" {
3491 return self.eval_sequence(&clause_vec[1..], env);
3492 }
3493 }
3494
3495 let datums = self.list_to_vec(clause_vec[0].clone())?;
3497
3498 for datum in datums {
3502 if key.equal(&datum) {
3503 if clause_vec.len() == 1 {
3505 return Ok(Value::Unspecified);
3507 } else {
3508 return self.eval_sequence(&clause_vec[1..], env);
3509 }
3510 }
3511 }
3512 }
3513
3514 Err(EvalError::new("case: no matching clause and no else clause".to_string()))
3517 }
3518
3519 fn eval_and(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3521 let args_vec = self.list_to_vec(args)?;
3522
3523 if args_vec.is_empty() {
3524 return Ok(Value::bool(true));
3525 }
3526
3527 let mut result = Value::bool(true);
3528 for expr in args_vec {
3529 result = self.eval_inner(expr, env.clone())?;
3530 if !result.is_true() {
3531 return Ok(Value::bool(false));
3532 }
3533 }
3534
3535 Ok(result)
3536 }
3537
3538 fn eval_or(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3540 let args_vec = self.list_to_vec(args)?;
3541
3542 for expr in args_vec {
3543 let result = self.eval_inner(expr, env.clone())?;
3544 if result.is_true() {
3545 return Ok(result);
3546 }
3547 }
3548
3549 Ok(Value::bool(false))
3550 }
3551
3552 fn eval_sequence(&mut self, exprs: &[Value], env: Gc<Environment>) -> EvalResult {
3554 if exprs.is_empty() {
3555 return Ok(Value::Unspecified);
3556 }
3557
3558 let mut result = Value::Unspecified;
3559 for expr in exprs {
3560 result = self.eval_inner(expr.clone(), env.clone())?;
3561 }
3562
3563 Ok(result)
3564 }
3565
3566 fn eval_apply(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3571 let args_vec = self.list_to_vec(args)?;
3572 if args_vec.len() != 2 {
3573 return Err(EvalError::new(
3574 "apply requires exactly 2 arguments".to_string(),
3575 ));
3576 }
3577
3578 let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
3580
3581 let arg_list = self.eval_inner(args_vec[1].clone(), env)?;
3583
3584 let arg_values = self.list_to_vec(arg_list)?;
3586
3587 self.apply(proc, arg_values)
3589 }
3590
3591 fn eval_map(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3605 let args_vec = self.list_to_vec(args)?;
3606 if args_vec.len() < 2 {
3607 return Err(EvalError::new("map requires at least 2 arguments".to_string()));
3608 }
3609
3610 let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
3612
3613 let mut lists = Vec::new();
3615 for i in 1..args_vec.len() {
3616 let list = self.eval_inner(args_vec[i].clone(), env.clone())?;
3617 let list_vec = self.list_to_vec(list)?;
3618 lists.push(list_vec);
3619 }
3620
3621 if lists.is_empty() {
3623 return Ok(Value::Nil);
3624 }
3625
3626 let length = lists[0].len();
3627 for list in &lists[1..] {
3628 if list.len() != length {
3629 return Err(EvalError::new(
3630 "map: all lists must have the same length".to_string(),
3631 ));
3632 }
3633 }
3634
3635 let mut result_vec = Vec::new();
3637 for i in 0..length {
3638 let mut proc_args = Vec::new();
3640 for list in &lists {
3641 proc_args.push(list[i].clone());
3642 }
3643
3644 let result = self.apply(proc.clone(), proc_args)?;
3646 result_vec.push(result);
3647 }
3648
3649 let mut result_list = Value::Nil;
3651 for elem in result_vec.into_iter().rev() {
3652 result_list = Value::cons(elem, result_list);
3653 }
3654
3655 Ok(result_list)
3656 }
3657
3658 fn eval_for_each(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3666 let args_vec = self.list_to_vec(args)?;
3667 if args_vec.len() < 2 {
3668 return Err(EvalError::new(
3669 "for-each requires at least 2 arguments".to_string(),
3670 ));
3671 }
3672
3673 let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
3675
3676 let mut lists = Vec::new();
3678 for i in 1..args_vec.len() {
3679 let list = self.eval_inner(args_vec[i].clone(), env.clone())?;
3680 let list_vec = self.list_to_vec(list)?;
3681 lists.push(list_vec);
3682 }
3683
3684 if lists.is_empty() {
3686 return Ok(Value::Unspecified);
3687 }
3688
3689 let length = lists[0].len();
3690 for list in &lists[1..] {
3691 if list.len() != length {
3692 return Err(EvalError::new(
3693 "for-each: all lists must have the same length".to_string(),
3694 ));
3695 }
3696 }
3697
3698 for i in 0..length {
3700 let mut proc_args = Vec::new();
3702 for list in &lists {
3703 proc_args.push(list[i].clone());
3704 }
3705
3706 self.apply(proc.clone(), proc_args)?;
3708 }
3709
3710 Ok(Value::Unspecified)
3711 }
3712
3713 fn eval_node_list_filter(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3720 let args_vec = self.list_to_vec(args)?;
3721 if args_vec.len() != 2 {
3722 return Err(EvalError::new("node-list-filter requires exactly 2 arguments".to_string()));
3723 }
3724
3725 let pred = self.eval_inner(args_vec[0].clone(), env.clone())?;
3727
3728 let node_list_val = self.eval_inner(args_vec[1].clone(), env.clone())?;
3730
3731 match node_list_val {
3732 Value::NodeList(ref nl) => {
3733 let mut filtered_nodes = Vec::new();
3734
3735 let mut index = 0;
3737 loop {
3738 if let Some(node) = nl.get(index) {
3739 let node_val = Value::node(node);
3741 let result = self.apply(pred.clone(), vec![node_val.clone()])?;
3742
3743 if !matches!(result, Value::Bool(false)) {
3745 if let Value::Node(n) = node_val {
3747 filtered_nodes.push(n.as_ref().clone_node());
3748 }
3749 }
3750
3751 index += 1;
3752 } else {
3753 break;
3754 }
3755 }
3756
3757 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(filtered_nodes))))
3758 }
3759 _ => Err(EvalError::new(format!("node-list-filter: second argument not a node-list: {:?}", node_list_val))),
3760 }
3761 }
3762
3763 fn eval_node_list_map(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3773 let args_vec = self.list_to_vec(args)?;
3774 if args_vec.len() != 2 {
3775 return Err(EvalError::new("node-list-map requires exactly 2 arguments".to_string()));
3776 }
3777
3778 let proc = self.eval_inner(args_vec[0].clone(), env.clone())?;
3780
3781 let node_list_val = self.eval_inner(args_vec[1].clone(), env.clone())?;
3783
3784 let mut result_nodes: Vec<Box<dyn crate::grove::Node>> = Vec::new();
3786
3787 match node_list_val {
3788 Value::Node(ref n) => {
3789 let node_val = Value::node(n.as_ref().clone_node());
3791 let result = self.apply(proc, vec![node_val])?;
3792
3793 match result {
3796 Value::Node(n) => {
3797 result_nodes.push(n.as_ref().clone_node());
3799 }
3800 Value::NodeList(nl) => {
3801 let mut index = 0;
3803 while let Some(node) = nl.get(index) {
3804 result_nodes.push(node);
3805 index += 1;
3806 }
3807 }
3808 _ => {
3809 }
3812 }
3813 }
3814 Value::NodeList(ref nl) => {
3815 let mut index = 0;
3817 loop {
3818 if let Some(node) = nl.get(index) {
3819 let node_val = Value::node(node);
3821 let result = self.apply(proc.clone(), vec![node_val])?;
3822
3823 match result {
3825 Value::Node(n) => {
3826 result_nodes.push(n.as_ref().clone_node());
3828 index += 1;
3829 }
3830 Value::NodeList(nl_result) => {
3831 let mut nl_index = 0;
3833 while let Some(node) = nl_result.get(nl_index) {
3834 result_nodes.push(node);
3835 nl_index += 1;
3836 }
3837 index += 1;
3838 }
3839 _ => {
3840 break;
3842 }
3843 }
3844 } else {
3845 break;
3846 }
3847 }
3848 }
3849 _ => return Err(EvalError::new(format!("node-list-map: second argument must be a node or node-list: {:?}", node_list_val))),
3850 }
3851
3852 Ok(Value::node_list(Box::new(crate::grove::VecNodeList::new(result_nodes))))
3854 }
3855
3856 fn eval_node_list_some(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3862 let args_vec = self.list_to_vec(args)?;
3863 if args_vec.len() != 2 {
3864 return Err(EvalError::new("node-list-some? requires exactly 2 arguments".to_string()));
3865 }
3866
3867 let pred = self.eval_inner(args_vec[0].clone(), env.clone())?;
3869
3870 let node_list_val = self.eval_inner(args_vec[1].clone(), env.clone())?;
3872
3873 match node_list_val {
3874 Value::NodeList(ref nl) => {
3875 let mut index = 0;
3877 loop {
3878 if let Some(node) = nl.get(index) {
3879 let node_val = Value::node(node);
3881 let result = self.apply(pred.clone(), vec![node_val])?;
3882
3883 if !matches!(result, Value::Bool(false)) {
3885 return Ok(Value::bool(true));
3886 }
3887
3888 index += 1;
3889 } else {
3890 break;
3891 }
3892 }
3893
3894 Ok(Value::bool(false))
3896 }
3897 _ => Err(EvalError::new(format!("node-list-some?: second argument not a node-list: {:?}", node_list_val))),
3898 }
3899 }
3900
3901 fn eval_load(&mut self, args: Value, env: Gc<Environment>) -> EvalResult {
3906 let args_vec = self.list_to_vec(args)?;
3907 if args_vec.len() != 1 {
3908 return Err(EvalError::new(
3909 "load requires exactly 1 argument".to_string(),
3910 ));
3911 }
3912
3913 let filename_val = self.eval(args_vec[0].clone(), env.clone())?;
3915
3916 let filename = match filename_val {
3917 Value::String(s) => s.to_string(),
3918 _ => return Err(EvalError::new(
3919 format!("load: filename must be a string, got {:?}", filename_val)
3920 )),
3921 };
3922
3923 let contents = std::fs::read_to_string(&filename)
3925 .map_err(|e| EvalError::new(format!("load: cannot read file '{}': {}", filename, e)))?;
3926
3927 let mut parser = crate::scheme::parser::Parser::new_with_filename(&contents, filename.clone());
3929 let mut result = Value::Unspecified;
3930
3931 let prev_source_file = self.current_source_file.clone();
3933 let prev_position = self.current_position.clone();
3934 self.current_source_file = Some(filename.clone());
3935
3936 let eval_result = loop {
3938 let pos = parser.current_position();
3940
3941 match parser.parse() {
3942 Ok(expr) => {
3943 self.current_position = Some(pos);
3945
3946 match self.eval(expr, env.clone()) {
3947 Ok(val) => result = val,
3948 Err(e) => break Err(e),
3949 }
3950 }
3951 Err(e) => {
3952 let error_msg = e.to_string();
3954 if error_msg.contains("Unexpected end of input")
3955 || error_msg.contains("Expected")
3956 || error_msg.contains("EOF") {
3957 break Ok(result);
3958 }
3959 break Err(EvalError::new(
3960 format!("load: parse error in '{}': {}", filename, e)
3961 ));
3962 }
3963 }
3964 };
3965
3966 self.current_source_file = prev_source_file;
3968 self.current_position = prev_position;
3969
3970 eval_result
3971 }
3972
3973 fn eval_application(
3979 &mut self,
3980 operator: Value,
3981 args: Value,
3982 env: Gc<Environment>,
3983 ) -> EvalResult {
3984 let application_pos = self.current_position.clone();
3986 let application_file = self.current_source_file.clone();
3987
3988 let proc = self.eval_inner(operator, env.clone())?;
3990
3991 let mut evaled_args = Vec::new();
3993 let mut current_args = args;
3994 loop {
3995 match current_args {
3996 Value::Nil => break,
3997 Value::Pair(ref p) => {
3998 let pair_borrow = p.borrow();
3999
4000 if let Some(ref pos) = pair_borrow.pos {
4003 if !self.line_mappings.is_empty() {
4005 if let Some(mapping) = self.line_mappings.iter().find(|m| m.output_line == pos.line) {
4006 self.current_source_file = Some(mapping.source_file.clone());
4007 self.current_position = Some(Position {
4008 line: mapping.source_line,
4009 column: pos.column,
4010 });
4011 } else {
4012 self.current_position = Some(pos.clone());
4013 }
4014 } else {
4015 self.current_position = Some(pos.clone());
4016 }
4017 }
4018
4019 let arg = pair_borrow.car.clone();
4020 let cdr = pair_borrow.cdr.clone();
4021 drop(pair_borrow); evaled_args.push(self.eval_inner(arg, env.clone())?);
4024 current_args = cdr;
4025 }
4026 _ => return Err(EvalError::new("Improper argument list".to_string())),
4027 }
4028 }
4029
4030 self.current_position = application_pos;
4033 self.current_source_file = application_file;
4034
4035 self.apply(proc, evaled_args)
4037 }
4038
4039 fn apply(&mut self, proc: Value, args: Vec<Value>) -> EvalResult {
4041 if let Value::Procedure(ref p) = proc {
4042 match &**p {
4043 Procedure::Primitive { name, func } => {
4044 match *name {
4045 "car" | "cdr" | "cons" | "null?" | "equal?" |
4046 "cadr" | "caddr" | "cadddr" | "list" | "length" |
4047 "reverse" | "append" | "list?" | "list-ref" |
4048 "pair?" | "number?" | "integer?" | "real?" | "string?" |
4049 "symbol?" | "char?" | "boolean?" | "zero?" | "positive?" |
4050 "negative?" | "odd?" | "even?" |
4051 "+" | "-" | "*" | "/" | "quotient" | "remainder" | "modulo" |
4052 "=" | "<" | ">" | "<=" | ">=" |
4053 "abs" | "min" | "max" |
4054 "floor" | "ceiling" | "truncate" | "round" |
4055 "sqrt" | "sin" | "cos" | "tan" | "asin" | "acos" | "atan" |
4056 "exp" | "log" | "expt" |
4057 "string-length" | "string-ref" | "substring" | "string-append" |
4058 "string=?" | "string<?" | "string>?" | "string<=?" | "string>=?" |
4059 "string-ci=?" | "string-ci<?" | "string-ci>?" | "string-ci<=?" | "string-ci>=?" |
4060 "char=?" | "char<?" | "char>?" | "char<=?" | "char>=?" |
4061 "char-ci=?" | "char-ci<?" | "char-ci>?" | "char-ci<=?" | "char-ci>=?" |
4062 "char-upcase" | "char-downcase" |
4063 "char-alphabetic?" | "char-numeric?" | "char-whitespace?" |
4064 "char->integer" | "integer->char" |
4065 "char-property" | "char-script-case" |
4066 "symbol->string" | "string->symbol" |
4067 "keyword?" | "keyword->string" | "string->keyword" |
4068 "memq" | "memv" | "member" |
4069 "assq" | "assv" | "assoc" |
4070 "not" | "eq?" | "eqv?" |
4071 "caar" | "cdar" | "cddr" |
4072 "caaar" | "caadr" | "cadar" |
4073 "cdaar" | "cdadr" | "cddar" | "cdddr" |
4074 "vector" | "make-vector" | "vector-length" |
4075 "vector-ref" | "vector-set!" |
4076 "vector->list" | "list->vector" | "vector-fill!" |
4077 "vector?" | "procedure?" |
4078 "set-car!" | "set-cdr!" | "list-tail" |
4079 "string-upcase" | "string-downcase" | "case-fold-down" |
4080 "string-index" |
4081 "string->number" | "number->string" |
4082 "string->list" | "list->string" |
4083 "gcd" | "lcm" |
4084 "exact->inexact" | "inexact->exact" |
4085 "make-string" | "string" | "reverse!" |
4086 "string-set!" | "string-copy" | "string-fill!" |
4087 "char-lower-case?" | "char-upper-case?" |
4088 "last" | "last-pair" | "list-copy" |
4089 "append!" | "iota" |
4090 "take" | "drop" | "split-at" |
4091 "filter" | "remove" |
4092 "numerator" | "denominator" | "rationalize" |
4093 "angle" | "magnitude" |
4094 "null-list?" | "improper-list?" | "circular-list?" |
4095 "bitwise-and" | "bitwise-ior" | "bitwise-xor" | "bitwise-not" |
4096 "arithmetic-shift" | "bit-extract" |
4097 "bitwise-bit-set?" | "bitwise-bit-count" |
4098 "format-number" | "format-number-list" |
4099 "empty-sosofo" | "sosofo-append" | "if-first-page" | "if-front-page" |
4100 "current-node" |
4101 "gi" | "data" | "id" |
4102 "children" | "parent" | "attributes" |
4103 "node-list?" | "empty-node-list" | "node-list-empty?" |
4104 "node-list-length" | "node-list-first" |
4105 "attribute-string" |
4106 "node-list-rest" | "node-list-ref" | "node-list-reverse" |
4107 "node?" | "sosofo?" | "quantity?" |
4108 "color?" | "color" | "display-space?" | "inline-space?" |
4109 "quantity->number" | "number->quantity" | "quantity-convert" |
4110 "device-length" | "label-distance" |
4111 "ancestor" | "descendants" | "follow" | "preced" | "ipreced" |
4112 "node-list-last" | "node-list-union" | "node-list-intersection" |
4113 "node-list-difference" | "node-list-remove-duplicates" |
4114 "select-elements" | "first-sibling?" | "last-sibling?" |
4115 "child-number" | "element-with-id" |
4116 "element-number" | "hierarchical-number" | "hierarchical-number-recursive" |
4117 "ancestors" | "document-element" | "have-ancestor?" |
4118 "match-element?" | "node-list-map" |
4119 "node-property" | "absolute-first-sibling?" | "absolute-last-sibling?" |
4120 "node-list->list" | "node-list-contains?" |
4121 "entity-system-id" | "entity-public-id" | "entity-type" |
4122 "notation-system-id" | "notation-public-id" |
4123 "current-language" | "current-mode" | "current-node-address" |
4124 "current-node-page-number-sosofo" | "debug" |
4125 "add" | "divide" | "equal" | "char-eq" | "char-lt" |
4126 "exact?" | "inexact?" | "error" |
4127 "address?" | "address-local?" | "address-visited?" |
4128 "color-space?" | "color-space" | "display-space" | "inline-space" |
4129 "glyph-id?" | "glyph-id" | "glyph-subst-table?" | "glyph-subst-table" | "glyph-subst" |
4130 "time" | "time->string" | "time<=?" | "time<?" | "time>=?" | "time>?" |
4131 "language?" | "language" | "style?" |
4132 "string-equiv?" | "label-length" | "external-procedure" |
4133 "declaration" | "dtd" | "epilog" | "prolog" | "sgml-declaration" | "sgml-parse" |
4134 "entity-address" | "entity-generated-system-id" | "entity-name-normalize" | "general-name-normalize" | "normalize" |
4135 "first-child-gi" | "tree-root" | "declare-default-language" | "read-entity" | "set-visited!" |
4136 "sosofo-contains-node?" | "page-number-sosofo" | "ifollow" | "with-language" |
4137 "all-element-number" | "ancestor-child-number" | "element-number-list" |
4138 "inherited-attribute-string" | "inherited-element-attribute-string" |
4139 "inherited-start-indent" | "inherited-end-indent" | "inherited-line-spacing" |
4140 "inherited-font-family-name" | "inherited-font-size" | "inherited-font-weight" |
4141 "inherited-font-posture" | "inherited-dbhtml-value" | "inherited-pi-value" |
4142 "node-list" | "node-list=?" | "node-list-count" | "node-list-union-map" |
4143 "node-list-symmetrical-difference" |
4144 "node-list-address" | "node-list-error" | "node-list-no-order" |
4145 "origin-to-subnode-rel-forest-addr" |
4146 "named-node" | "named-node-list?" | "named-node-list-names" |
4147 "select-by-class" | "select-children" |
4148 "process-children-trim" | "process-element-with-id" | "process-first-descendant" |
4149 "process-matching-children" | "next-match" => {
4150 self.apply_primitive(name, &args)
4151 }
4152 _ => {
4155 if self.get_primitive_static_name(name).is_some() {
4158 self.apply_primitive(name, &args)
4159 } else {
4160 func(&args).map_err(|e| self.error_with_stack(e))
4164 }
4165 }
4166 }
4167 }
4168 Procedure::Lambda { params, required_count, optional_defaults, body, env, source, name } => {
4169 if args.len() < *required_count {
4171 return Err(self.error_with_stack(format!(
4172 "Lambda expects at least {} arguments, got {}",
4173 required_count,
4174 args.len()
4175 )));
4176 }
4177 if args.len() > params.len() {
4178 return Err(self.error_with_stack(format!(
4179 "Lambda expects at most {} arguments, got {}",
4180 params.len(),
4181 args.len()
4182 )));
4183 }
4184
4185 let saved_file = self.current_source_file.clone();
4187 let saved_pos = self.current_position.clone();
4188
4189 let pushed_frame = if let Some(func_name) = name.clone() {
4192 let call_site = match (&saved_file, &saved_pos) {
4193 (Some(file), Some(pos)) => Some(SourceInfo {
4194 file: file.clone(),
4195 pos: pos.clone(),
4196 }),
4197 _ => None,
4198 };
4199 self.push_call_frame(func_name, call_site);
4200 true
4201 } else {
4202 false
4203 };
4204
4205 if let Some(ref src) = source {
4207 self.current_source_file = Some(src.file.clone());
4208 self.current_position = Some(src.pos.clone());
4209 }
4210
4211 let lambda_env = Environment::extend(env.clone());
4213
4214 for (param_name, arg_value) in params.iter().zip(args.iter()) {
4216 lambda_env.define(param_name, arg_value.clone());
4217 }
4218
4219 if args.len() < params.len() {
4221 let num_optional_provided = args.len().saturating_sub(*required_count);
4222 let num_optional_defaults_needed = (params.len() - *required_count) - num_optional_provided;
4223
4224 for i in 0..num_optional_defaults_needed {
4225 let param_idx = *required_count + num_optional_provided + i;
4226 let param_name = ¶ms[param_idx];
4227 let default_expr = &optional_defaults[num_optional_provided + i];
4228
4229 if std::env::var("DEBUG_OPTIONAL").is_ok() {
4230 eprintln!("[DEBUG_OPTIONAL] Evaluating default for param '{}': {:?}", param_name, default_expr);
4231 if let Some(val) = env.lookup(param_name) {
4233 eprintln!("[DEBUG_OPTIONAL] Found '{}' in closure env: {:?}", param_name, val);
4234 } else {
4235 eprintln!("[DEBUG_OPTIONAL] '{}' not found in closure env (expected)", param_name);
4236 }
4237 }
4238
4239 let default_value = self.eval_inner(default_expr.clone(), env.clone())?;
4241
4242 if std::env::var("DEBUG_OPTIONAL").is_ok() {
4243 eprintln!("[DEBUG_OPTIONAL] Evaluated to: {:?}", default_value);
4244 }
4245
4246 lambda_env.define(param_name, default_value);
4247 }
4248 }
4249
4250 let result = self.eval_inner((**body).clone(), lambda_env);
4252
4253 self.current_source_file = saved_file;
4255 self.current_position = saved_pos;
4256
4257 if pushed_frame {
4259 self.pop_call_frame();
4260 }
4261
4262 result
4263 }
4264 }
4265 } else if let Value::Symbol(sym) = &proc {
4266 let sym_str = sym.as_ref();
4269
4270 self.apply_primitive(sym_str, &args)
4272 } else {
4273 Err(self.error_with_stack(format!(
4274 "Not a procedure: {:?}",
4275 proc
4276 )))
4277 }
4278 }
4279}
4280
4281impl Default for Evaluator {
4282 fn default() -> Self {
4283 Self::new()
4284 }
4285}
4286
4287#[cfg(test)]
4292mod tests {
4293 use super::*;
4294
4295 fn make_env() -> Gc<Environment> {
4296 Environment::new_global()
4297 }
4298
4299 #[test]
4300 fn test_eval_self_evaluating() {
4301 let mut eval = Evaluator::new();
4302 let env = make_env();
4303
4304 assert!(eval.eval(Value::integer(42), env.clone()).unwrap().is_integer());
4305 assert!(eval.eval(Value::bool(true), env.clone()).unwrap().is_bool());
4306 assert!(eval.eval(Value::string("hello".to_string()), env).unwrap().is_string());
4307 }
4308
4309 #[test]
4310 fn test_eval_quote() {
4311 let mut eval = Evaluator::new();
4312 let env = make_env();
4313
4314 let expr = Value::cons(
4316 Value::symbol("quote"),
4317 Value::cons(
4318 Value::cons(
4319 Value::integer(1),
4320 Value::cons(Value::integer(2), Value::cons(Value::integer(3), Value::Nil)),
4321 ),
4322 Value::Nil,
4323 ),
4324 );
4325
4326 let result = eval.eval(expr, env).unwrap();
4327 assert!(result.is_list());
4328 }
4329
4330 #[test]
4331 fn test_eval_if_true() {
4332 let mut eval = Evaluator::new();
4333 let env = make_env();
4334
4335 let expr = Value::cons(
4337 Value::symbol("if"),
4338 Value::cons(
4339 Value::bool(true),
4340 Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
4341 ),
4342 );
4343
4344 let result = eval.eval(expr, env).unwrap();
4345 if let Value::Integer(n) = result {
4346 assert_eq!(n, 1);
4347 } else {
4348 panic!("Expected integer 1");
4349 }
4350 }
4351
4352 #[test]
4353 fn test_eval_if_false() {
4354 let mut eval = Evaluator::new();
4355 let env = make_env();
4356
4357 let expr = Value::cons(
4359 Value::symbol("if"),
4360 Value::cons(
4361 Value::bool(false),
4362 Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
4363 ),
4364 );
4365
4366 let result = eval.eval(expr, env).unwrap();
4367 if let Value::Integer(n) = result {
4368 assert_eq!(n, 2);
4369 } else {
4370 panic!("Expected integer 2");
4371 }
4372 }
4373
4374 #[test]
4375 fn test_eval_define() {
4376 let mut eval = Evaluator::new();
4377 let env = make_env();
4378
4379 let expr = Value::cons(
4381 Value::symbol("define"),
4382 Value::cons(Value::symbol("x"), Value::cons(Value::integer(42), Value::Nil)),
4383 );
4384
4385 eval.eval(expr, env.clone()).unwrap();
4386
4387 assert!(env.is_defined("x"));
4389 if let Value::Integer(n) = env.lookup("x").unwrap() {
4390 assert_eq!(n, 42);
4391 }
4392 }
4393
4394 #[test]
4395 fn test_eval_symbol_lookup() {
4396 let mut eval = Evaluator::new();
4397 let env = make_env();
4398
4399 env.define("x", Value::integer(99));
4400
4401 let result = eval.eval(Value::symbol("x"), env).unwrap();
4402 if let Value::Integer(n) = result {
4403 assert_eq!(n, 99);
4404 } else {
4405 panic!("Expected integer 99");
4406 }
4407 }
4408
4409 #[test]
4410 fn test_eval_and() {
4411 let mut eval = Evaluator::new();
4412 let env = make_env();
4413
4414 let expr = Value::cons(
4416 Value::symbol("and"),
4417 Value::cons(Value::bool(true), Value::cons(Value::bool(true), Value::Nil)),
4418 );
4419
4420 let result = eval.eval(expr, env.clone()).unwrap();
4421 assert!(result.is_true());
4422
4423 let expr = Value::cons(
4425 Value::symbol("and"),
4426 Value::cons(Value::bool(true), Value::cons(Value::bool(false), Value::Nil)),
4427 );
4428
4429 let result = eval.eval(expr, env).unwrap();
4430 assert!(!result.is_true());
4431 }
4432
4433 #[test]
4434 fn test_eval_or() {
4435 let mut eval = Evaluator::new();
4436 let env = make_env();
4437
4438 let expr = Value::cons(
4440 Value::symbol("or"),
4441 Value::cons(Value::bool(false), Value::cons(Value::bool(true), Value::Nil)),
4442 );
4443
4444 let result = eval.eval(expr, env.clone()).unwrap();
4445 assert!(result.is_true());
4446
4447 let expr = Value::cons(
4449 Value::symbol("or"),
4450 Value::cons(Value::bool(false), Value::cons(Value::bool(false), Value::Nil)),
4451 );
4452
4453 let result = eval.eval(expr, env).unwrap();
4454 assert!(!result.is_true());
4455 }
4456
4457 #[test]
4458 fn test_eval_lambda_creation() {
4459 let mut eval = Evaluator::new();
4460 let env = make_env();
4461
4462 let expr = Value::cons(
4464 Value::symbol("lambda"),
4465 Value::cons(
4466 Value::cons(Value::symbol("x"), Value::Nil),
4467 Value::cons(Value::symbol("x"), Value::Nil),
4468 ),
4469 );
4470
4471 let result = eval.eval(expr, env).unwrap();
4472 assert!(result.is_procedure());
4473 }
4474
4475 #[test]
4476 fn test_eval_lambda_application() {
4477 let mut eval = Evaluator::new();
4478 let env = make_env();
4479
4480 let lambda_expr = Value::cons(
4482 Value::symbol("lambda"),
4483 Value::cons(
4484 Value::cons(Value::symbol("x"), Value::Nil),
4485 Value::cons(Value::symbol("x"), Value::Nil),
4486 ),
4487 );
4488
4489 let app_expr = Value::cons(lambda_expr, Value::cons(Value::integer(42), Value::Nil));
4490
4491 let result = eval.eval(app_expr, env).unwrap();
4492 if let Value::Integer(n) = result {
4493 assert_eq!(n, 42);
4494 } else {
4495 panic!("Expected integer 42");
4496 }
4497 }
4498
4499 #[test]
4500 fn test_eval_lambda_multiple_params() {
4501 let mut eval = Evaluator::new();
4502 let env = make_env();
4503
4504 let params = Value::cons(Value::symbol("x"), Value::cons(Value::symbol("y"), Value::Nil));
4506 let body = Value::symbol("x");
4507
4508 let lambda_expr = Value::cons(Value::symbol("lambda"), Value::cons(params, Value::cons(body, Value::Nil)));
4509
4510 let app_expr = Value::cons(
4511 lambda_expr,
4512 Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
4513 );
4514
4515 let result = eval.eval(app_expr, env).unwrap();
4516 if let Value::Integer(n) = result {
4517 assert_eq!(n, 1);
4518 } else {
4519 panic!("Expected integer 1");
4520 }
4521 }
4522
4523 #[test]
4524 fn test_eval_lambda_wrong_arg_count() {
4525 let mut eval = Evaluator::new();
4526 let env = make_env();
4527
4528 let lambda_expr = Value::cons(
4530 Value::symbol("lambda"),
4531 Value::cons(
4532 Value::cons(Value::symbol("x"), Value::Nil),
4533 Value::cons(Value::symbol("x"), Value::Nil),
4534 ),
4535 );
4536
4537 let app_expr = Value::cons(
4538 lambda_expr,
4539 Value::cons(Value::integer(1), Value::cons(Value::integer(2), Value::Nil)),
4540 );
4541
4542 let result = eval.eval(app_expr, env);
4543 assert!(result.is_err());
4544 }
4545
4546 #[test]
4547 fn test_eval_lambda_closure() {
4548 let mut eval = Evaluator::new();
4549 let env = make_env();
4550
4551 env.define("x", Value::integer(10));
4553
4554 let lambda_expr = Value::cons(
4557 Value::symbol("lambda"),
4558 Value::cons(
4559 Value::cons(Value::symbol("y"), Value::Nil),
4560 Value::cons(Value::symbol("x"), Value::Nil),
4561 ),
4562 );
4563
4564 let app_expr = Value::cons(lambda_expr, Value::cons(Value::integer(20), Value::Nil));
4565
4566 let result = eval.eval(app_expr, env).unwrap();
4567 if let Value::Integer(n) = result {
4568 assert_eq!(n, 10); } else {
4570 panic!("Expected integer 10 from closure");
4571 }
4572 }
4573
4574 #[test]
4575 fn test_eval_lambda_no_params() {
4576 let mut eval = Evaluator::new();
4577 let env = make_env();
4578
4579 let lambda_expr = Value::cons(
4581 Value::symbol("lambda"),
4582 Value::cons(Value::Nil, Value::cons(Value::integer(42), Value::Nil)),
4583 );
4584
4585 let app_expr = Value::cons(lambda_expr, Value::Nil);
4586
4587 let result = eval.eval(app_expr, env).unwrap();
4588 if let Value::Integer(n) = result {
4589 assert_eq!(n, 42);
4590 } else {
4591 panic!("Expected integer 42");
4592 }
4593 }
4594
4595 #[test]
4596 fn test_eval_lambda_multiple_body_expressions() {
4597 let mut eval = Evaluator::new();
4598 let env = make_env();
4599
4600 let params = Value::cons(Value::symbol("x"), Value::Nil);
4603 let body1 = Value::integer(1);
4604 let body2 = Value::integer(2);
4605 let body3 = Value::symbol("x");
4606
4607 let lambda_expr = Value::cons(
4608 Value::symbol("lambda"),
4609 Value::cons(
4610 params,
4611 Value::cons(body1, Value::cons(body2, Value::cons(body3, Value::Nil))),
4612 ),
4613 );
4614
4615 let app_expr = Value::cons(lambda_expr, Value::cons(Value::integer(99), Value::Nil));
4616
4617 let result = eval.eval(app_expr, env).unwrap();
4618 if let Value::Integer(n) = result {
4619 assert_eq!(n, 99);
4620 } else {
4621 panic!("Expected integer 99");
4622 }
4623 }
4624
4625 #[test]
4626 fn test_element_rule_multiple_sosofos_error() {
4627 let mut eval = Evaluator::new();
4628 let env = make_env();
4629
4630 let expr = Value::cons(
4632 Value::symbol("element"),
4633 Value::cons(
4634 Value::symbol("foo"),
4635 Value::cons(
4636 Value::symbol("expr1"),
4637 Value::cons(Value::symbol("expr2"), Value::Nil),
4638 ),
4639 ),
4640 );
4641
4642 let result = eval.eval(expr, env);
4643 assert!(result.is_err());
4644 let err_msg = result.unwrap_err().to_string();
4645 assert!(err_msg.contains("can only contain one sosofo expression"));
4646 assert!(err_msg.contains("sosofo-append"));
4647 }
4648
4649 #[test]
4650 fn test_element_rule_single_sosofo_ok() {
4651 let mut eval = Evaluator::new();
4652 let env = make_env();
4653
4654 let expr = Value::cons(
4656 Value::symbol("element"),
4657 Value::cons(
4658 Value::symbol("foo"),
4659 Value::cons(Value::symbol("expr"), Value::Nil),
4660 ),
4661 );
4662
4663 let result = eval.eval(expr, env);
4664 assert!(result.is_ok());
4665 }
4666
4667 #[test]
4668 fn test_default_rule_multiple_sosofos_error() {
4669 let mut eval = Evaluator::new();
4670 let env = make_env();
4671
4672 let expr = Value::cons(
4674 Value::symbol("default"),
4675 Value::cons(
4676 Value::symbol("expr1"),
4677 Value::cons(Value::symbol("expr2"), Value::Nil),
4678 ),
4679 );
4680
4681 let result = eval.eval(expr, env);
4682 assert!(result.is_err());
4683 let err_msg = result.unwrap_err().to_string();
4684 assert!(err_msg.contains("can only contain one sosofo expression"));
4685 assert!(err_msg.contains("sosofo-append"));
4686 }
4687
4688 #[test]
4689 fn test_default_rule_single_sosofo_ok() {
4690 let mut eval = Evaluator::new();
4691 let env = make_env();
4692
4693 let expr = Value::cons(
4695 Value::symbol("default"),
4696 Value::cons(Value::symbol("expr"), Value::Nil),
4697 );
4698
4699 let result = eval.eval(expr, env);
4700 assert!(result.is_ok());
4701 }
4702
4703 #[test]
4704 fn test_vm_simple_arithmetic() {
4705 let mut eval = Evaluator::new();
4706 eval.enable_vm(); let env = make_env();
4709
4710 let expr = Value::cons(
4712 Value::symbol("+"),
4713 Value::cons(
4714 Value::Integer(10),
4715 Value::cons(Value::Integer(32), Value::Nil),
4716 ),
4717 );
4718
4719 let result = eval.eval(expr, env);
4720 assert!(result.is_ok());
4721 let value = result.unwrap();
4722 assert!(matches!(value, Value::Integer(42)));
4723 }
4724
4725 #[test]
4726 fn test_vm_vs_tree_walker() {
4727 let expr = Value::cons(
4729 Value::symbol("+"),
4730 Value::cons(
4731 Value::Integer(10),
4732 Value::cons(Value::Integer(32), Value::Nil),
4733 ),
4734 );
4735
4736 let mut eval1 = Evaluator::new();
4738 eval1.disable_vm();
4739 let env1 = make_env();
4740 let result1 = eval1.eval(expr.clone(), env1).unwrap();
4741
4742 let mut eval2 = Evaluator::new();
4744 eval2.enable_vm();
4745 let env2 = make_env();
4746 let result2 = eval2.eval(expr, env2).unwrap();
4747
4748 assert!(matches!(result1, Value::Integer(42)));
4750 assert!(matches!(result2, Value::Integer(42)));
4751 }
4752}