1use crate::ast::*;
6use crate::span::Span;
7use std::cell::RefCell;
8use std::collections::{HashMap, HashSet};
9use std::fmt;
10use std::path::PathBuf;
11use std::rc::Rc;
12use std::sync::{mpsc, Arc, Mutex};
13use std::thread::JoinHandle;
14
15#[derive(Clone)]
17pub enum Value {
18 Null,
20 Bool(bool),
22 Int(i64),
24 Float(f64),
26 String(Rc<String>),
28 Char(char),
30 Array(Rc<RefCell<Vec<Value>>>),
32 Tuple(Rc<Vec<Value>>),
34 Struct {
36 name: String,
37 fields: Rc<RefCell<HashMap<String, Value>>>,
38 },
39 Variant {
41 enum_name: String,
42 variant_name: String,
43 fields: Option<Rc<Vec<Value>>>,
44 },
45 Function(Rc<Function>),
47 BuiltIn(Rc<BuiltInFn>),
49 Ref(Rc<RefCell<Value>>),
51 Infinity,
53 Empty,
54 Evidential {
56 value: Box<Value>,
57 evidence: Evidence,
58 },
59 Affective {
61 value: Box<Value>,
62 affect: RuntimeAffect,
63 },
64 Map(Rc<RefCell<HashMap<String, Value>>>),
66 Set(Rc<RefCell<std::collections::HashSet<String>>>),
68 Channel(Arc<ChannelInner>),
70 ThreadHandle(Arc<Mutex<Option<JoinHandle<Value>>>>),
72 Actor(Arc<ActorInner>),
74 Future(Rc<RefCell<FutureInner>>),
76 VariantConstructor {
78 enum_name: String,
79 variant_name: String,
80 },
81 DefaultConstructor {
83 type_name: String,
84 },
85 Range {
87 start: Option<i64>,
88 end: Option<i64>,
89 inclusive: bool,
90 },
91}
92
93#[derive(Clone)]
95pub enum FutureState {
96 Pending,
98 Running,
100 Ready(Box<Value>),
102 Failed(String),
104}
105
106pub struct FutureInner {
108 pub state: FutureState,
110 pub computation: Option<FutureComputation>,
112 pub complete_at: Option<std::time::Instant>,
114}
115
116impl Clone for FutureInner {
117 fn clone(&self) -> Self {
118 FutureInner {
119 state: self.state.clone(),
120 computation: self.computation.clone(),
121 complete_at: self.complete_at,
122 }
123 }
124}
125
126#[derive(Clone)]
128pub enum FutureComputation {
129 Immediate(Box<Value>),
131 Timer(std::time::Duration),
133 Lazy {
135 func: Rc<Function>,
136 args: Vec<Value>,
137 },
138 Join(Vec<Rc<RefCell<FutureInner>>>),
140 Race(Vec<Rc<RefCell<FutureInner>>>),
142}
143
144pub struct ChannelInner {
146 pub sender: Mutex<mpsc::Sender<Value>>,
147 pub receiver: Mutex<mpsc::Receiver<Value>>,
148}
149
150impl Clone for ChannelInner {
151 fn clone(&self) -> Self {
152 panic!("Channels cannot be cloned directly - use channel_clone()")
155 }
156}
157
158pub struct ActorInner {
161 pub name: String,
162 pub message_queue: Mutex<Vec<(String, String)>>, pub message_count: std::sync::atomic::AtomicUsize,
164}
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq)]
168pub enum Evidence {
169 Known, Uncertain, Reported, Paradox, }
174
175#[derive(Debug, Clone, PartialEq)]
177pub struct RuntimeAffect {
178 pub sentiment: Option<RuntimeSentiment>,
179 pub sarcasm: bool, pub intensity: Option<RuntimeIntensity>,
181 pub formality: Option<RuntimeFormality>,
182 pub emotion: Option<RuntimeEmotion>,
183 pub confidence: Option<RuntimeConfidence>,
184}
185
186#[derive(Debug, Clone, Copy, PartialEq, Eq)]
187pub enum RuntimeSentiment {
188 Positive, Negative, Neutral, }
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194pub enum RuntimeIntensity {
195 Up, Down, Max, }
199
200#[derive(Debug, Clone, Copy, PartialEq, Eq)]
201pub enum RuntimeFormality {
202 Formal, Informal, }
205
206#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207pub enum RuntimeEmotion {
208 Joy, Sadness, Anger, Fear, Surprise, Love, }
215
216#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub enum RuntimeConfidence {
218 High, Medium, Low, }
222
223pub struct Function {
225 pub name: Option<String>,
226 pub params: Vec<String>,
227 pub body: Expr,
228 pub closure: Rc<RefCell<Environment>>,
229}
230
231pub struct BuiltInFn {
233 pub name: String,
234 pub arity: Option<usize>, pub func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
236}
237
238impl fmt::Debug for Value {
239 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240 match self {
241 Value::Null => write!(f, "null"),
242 Value::Bool(b) => write!(f, "{}", b),
243 Value::Int(n) => write!(f, "{}", n),
244 Value::Float(n) => write!(f, "{}", n),
245 Value::String(s) => write!(f, "\"{}\"", s),
246 Value::Char(c) => write!(f, "'{}'", c),
247 Value::Array(arr) => {
248 let arr = arr.borrow();
249 write!(f, "[")?;
250 for (i, v) in arr.iter().enumerate() {
251 if i > 0 {
252 write!(f, ", ")?;
253 }
254 write!(f, "{:?}", v)?;
255 }
256 write!(f, "]")
257 }
258 Value::Tuple(vals) => {
259 write!(f, "(")?;
260 for (i, v) in vals.iter().enumerate() {
261 if i > 0 {
262 write!(f, ", ")?;
263 }
264 write!(f, "{:?}", v)?;
265 }
266 write!(f, ")")
267 }
268 Value::Struct { name, fields } => {
269 write!(f, "{} {{ ", name)?;
270 let fields = fields.borrow();
271 for (i, (k, v)) in fields.iter().enumerate() {
272 if i > 0 {
273 write!(f, ", ")?;
274 }
275 write!(f, "{}: {:?}", k, v)?;
276 }
277 write!(f, " }}")
278 }
279 Value::Variant {
280 enum_name,
281 variant_name,
282 fields,
283 } => {
284 write!(f, "{}::{}", enum_name, variant_name)?;
285 if let Some(fields) = fields {
286 write!(f, "(")?;
287 for (i, v) in fields.iter().enumerate() {
288 if i > 0 {
289 write!(f, ", ")?;
290 }
291 write!(f, "{:?}", v)?;
292 }
293 write!(f, ")")?;
294 }
295 Ok(())
296 }
297 Value::Function(func) => {
298 write!(f, "<fn {}>", func.name.as_deref().unwrap_or("anonymous"))
299 }
300 Value::BuiltIn(b) => write!(f, "<builtin {}>", b.name),
301 Value::Ref(r) => write!(f, "&{:?}", r.borrow()),
302 Value::Infinity => write!(f, "∞"),
303 Value::Empty => write!(f, "∅"),
304 Value::Evidential { value, evidence } => {
305 write!(f, "{:?}", value)?;
306 match evidence {
307 Evidence::Known => write!(f, "!"),
308 Evidence::Uncertain => write!(f, "?"),
309 Evidence::Reported => write!(f, "~"),
310 Evidence::Paradox => write!(f, "‽"),
311 }
312 }
313 Value::Map(map) => {
314 let map = map.borrow();
315 write!(f, "{{")?;
316 for (i, (k, v)) in map.iter().enumerate() {
317 if i > 0 {
318 write!(f, ", ")?;
319 }
320 write!(f, "{:?}: {:?}", k, v)?;
321 }
322 write!(f, "}}")
323 }
324 Value::Set(set) => {
325 let set = set.borrow();
326 write!(f, "Set{{")?;
327 for (i, k) in set.iter().enumerate() {
328 if i > 0 {
329 write!(f, ", ")?;
330 }
331 write!(f, "{:?}", k)?;
332 }
333 write!(f, "}}")
334 }
335 Value::Channel(_) => write!(f, "<channel>"),
336 Value::ThreadHandle(_) => write!(f, "<thread>"),
337 Value::Actor(actor) => write!(f, "<actor {}>", actor.name),
338 Value::Future(fut) => {
339 let fut = fut.borrow();
340 match &fut.state {
341 FutureState::Pending => write!(f, "<future pending>"),
342 FutureState::Running => write!(f, "<future running>"),
343 FutureState::Ready(v) => write!(f, "<future ready: {:?}>", v),
344 FutureState::Failed(e) => write!(f, "<future failed: {}>", e),
345 }
346 }
347 Value::Affective { value, affect } => {
348 write!(f, "{:?}", value)?;
349 if let Some(s) = &affect.sentiment {
350 match s {
351 RuntimeSentiment::Positive => write!(f, "⊕")?,
352 RuntimeSentiment::Negative => write!(f, "⊖")?,
353 RuntimeSentiment::Neutral => write!(f, "⊜")?,
354 }
355 }
356 if affect.sarcasm {
357 write!(f, "⸮")?;
358 }
359 if let Some(i) = &affect.intensity {
360 match i {
361 RuntimeIntensity::Up => write!(f, "↑")?,
362 RuntimeIntensity::Down => write!(f, "↓")?,
363 RuntimeIntensity::Max => write!(f, "⇈")?,
364 }
365 }
366 if let Some(fo) = &affect.formality {
367 match fo {
368 RuntimeFormality::Formal => write!(f, "♔")?,
369 RuntimeFormality::Informal => write!(f, "♟")?,
370 }
371 }
372 if let Some(e) = &affect.emotion {
373 match e {
374 RuntimeEmotion::Joy => write!(f, "☺")?,
375 RuntimeEmotion::Sadness => write!(f, "☹")?,
376 RuntimeEmotion::Anger => write!(f, "⚡")?,
377 RuntimeEmotion::Fear => write!(f, "❄")?,
378 RuntimeEmotion::Surprise => write!(f, "✦")?,
379 RuntimeEmotion::Love => write!(f, "♡")?,
380 }
381 }
382 if let Some(c) = &affect.confidence {
383 match c {
384 RuntimeConfidence::High => write!(f, "◉")?,
385 RuntimeConfidence::Medium => write!(f, "◎")?,
386 RuntimeConfidence::Low => write!(f, "○")?,
387 }
388 }
389 Ok(())
390 }
391 Value::VariantConstructor { enum_name, variant_name } => {
392 write!(f, "<constructor {}::{}>", enum_name, variant_name)
393 }
394 Value::DefaultConstructor { type_name } => {
395 write!(f, "<default {}>", type_name)
396 }
397 Value::Range { start, end, inclusive } => {
398 match (start, end) {
399 (Some(s), Some(e)) => if *inclusive {
400 write!(f, "{}..={}", s, e)
401 } else {
402 write!(f, "{}..{}", s, e)
403 },
404 (Some(s), None) => write!(f, "{}..", s),
405 (None, Some(e)) => if *inclusive {
406 write!(f, "..={}", e)
407 } else {
408 write!(f, "..{}", e)
409 },
410 (None, None) => write!(f, ".."),
411 }
412 }
413 }
414 }
415}
416
417impl fmt::Display for Value {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 match self {
420 Value::Null => write!(f, "null"),
421 Value::Bool(b) => write!(f, "{}", b),
422 Value::Int(n) => write!(f, "{}", n),
423 Value::Float(n) => write!(f, "{}", n),
424 Value::String(s) => write!(f, "{}", s),
425 Value::Char(c) => write!(f, "{}", c),
426 Value::Array(arr) => {
427 let arr = arr.borrow();
428 write!(f, "[")?;
429 for (i, v) in arr.iter().enumerate() {
430 if i > 0 {
431 write!(f, ", ")?;
432 }
433 write!(f, "{}", v)?;
434 }
435 write!(f, "]")
436 }
437 Value::Evidential { value, .. } => write!(f, "{}", value),
438 Value::Affective { value, affect } => {
439 let mut suffix = String::new();
441 if let Some(sent) = &affect.sentiment {
442 suffix.push(match sent {
443 RuntimeSentiment::Positive => '⊕',
444 RuntimeSentiment::Negative => '⊖',
445 RuntimeSentiment::Neutral => '⊜',
446 });
447 }
448 if affect.sarcasm {
449 suffix.push('⸮');
450 }
451 if let Some(int) = &affect.intensity {
452 suffix.push(match int {
453 RuntimeIntensity::Up => '↑',
454 RuntimeIntensity::Down => '↓',
455 RuntimeIntensity::Max => '⇈',
456 });
457 }
458 if let Some(form) = &affect.formality {
459 suffix.push(match form {
460 RuntimeFormality::Formal => '♔',
461 RuntimeFormality::Informal => '♟',
462 });
463 }
464 if let Some(emo) = &affect.emotion {
465 suffix.push(match emo {
466 RuntimeEmotion::Joy => '☺',
467 RuntimeEmotion::Sadness => '☹',
468 RuntimeEmotion::Anger => '⚡',
469 RuntimeEmotion::Fear => '❄',
470 RuntimeEmotion::Surprise => '✦',
471 RuntimeEmotion::Love => '♡',
472 });
473 }
474 if let Some(conf) = &affect.confidence {
475 suffix.push(match conf {
476 RuntimeConfidence::High => '◉',
477 RuntimeConfidence::Medium => '◎',
478 RuntimeConfidence::Low => '○',
479 });
480 }
481 write!(f, "{}{}", value, suffix)
482 }
483 _ => write!(f, "{:?}", self),
484 }
485 }
486}
487
488#[derive(Debug)]
490pub struct RuntimeError {
491 pub message: String,
492 pub span: Option<Span>,
493}
494
495impl RuntimeError {
496 pub fn new(message: impl Into<String>) -> Self {
497 Self {
498 message: message.into(),
499 span: None,
500 }
501 }
502
503 pub fn with_span(message: impl Into<String>, span: Span) -> Self {
504 Self {
505 message: message.into(),
506 span: Some(span),
507 }
508 }
509}
510
511impl fmt::Display for RuntimeError {
512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
513 write!(f, "Runtime error: {}", self.message)?;
514 if let Some(span) = self.span {
515 write!(f, " at {}", span)?;
516 }
517 Ok(())
518 }
519}
520
521#[derive(Debug, Clone)]
523pub enum ControlFlow {
524 Return(Value),
525 Break(Option<Value>),
526 Continue,
527}
528
529impl From<ControlFlow> for RuntimeError {
530 fn from(cf: ControlFlow) -> Self {
531 match cf {
532 ControlFlow::Return(_) => RuntimeError::new("return outside function"),
533 ControlFlow::Break(_) => RuntimeError::new("break outside loop"),
534 ControlFlow::Continue => RuntimeError::new("continue outside loop"),
535 }
536 }
537}
538
539pub type EvalResult = Result<Value, EvalError>;
541
542#[derive(Debug)]
544pub enum EvalError {
545 Runtime(RuntimeError),
546 Control(ControlFlow),
547}
548
549impl From<RuntimeError> for EvalError {
550 fn from(e: RuntimeError) -> Self {
551 EvalError::Runtime(e)
552 }
553}
554
555impl From<ControlFlow> for EvalError {
556 fn from(cf: ControlFlow) -> Self {
557 EvalError::Control(cf)
558 }
559}
560
561impl fmt::Display for EvalError {
562 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
563 match self {
564 EvalError::Runtime(e) => write!(f, "{}", e),
565 EvalError::Control(cf) => write!(f, "Unexpected control flow: {:?}", cf),
566 }
567 }
568}
569
570#[derive(Clone)]
572pub struct Environment {
573 values: HashMap<String, Value>,
574 parent: Option<Rc<RefCell<Environment>>>,
575}
576
577impl Environment {
578 pub fn new() -> Self {
579 Self {
580 values: HashMap::new(),
581 parent: None,
582 }
583 }
584
585 pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
586 Self {
587 values: HashMap::new(),
588 parent: Some(parent),
589 }
590 }
591
592 pub fn define(&mut self, name: String, value: Value) {
593 self.values.insert(name, value);
594 }
595
596 pub fn get(&self, name: &str) -> Option<Value> {
597 if let Some(value) = self.values.get(name) {
598 Some(value.clone())
599 } else if let Some(ref parent) = self.parent {
600 parent.borrow().get(name)
601 } else {
602 None
603 }
604 }
605
606 pub fn set(&mut self, name: &str, value: Value) -> Result<(), RuntimeError> {
607 if self.values.contains_key(name) {
608 self.values.insert(name.to_string(), value);
609 Ok(())
610 } else if let Some(ref parent) = self.parent {
611 parent.borrow_mut().set(name, value)
612 } else {
613 Err(RuntimeError::new(format!("Undefined variable: {}", name)))
614 }
615 }
616}
617
618impl Default for Environment {
619 fn default() -> Self {
620 Self::new()
621 }
622}
623
624pub struct Interpreter {
626 pub globals: Rc<RefCell<Environment>>,
628 pub environment: Rc<RefCell<Environment>>,
630 pub types: HashMap<String, TypeDef>,
632 pub variant_constructors: HashMap<String, (String, String, usize)>,
634 pub default_structs: HashMap<String, StructDef>,
636 pub output: Vec<String>,
638 return_value: Option<Value>,
640 pub program_args: Option<Vec<String>>,
642 pub current_module: Option<String>,
644 pub current_self_type: Option<String>,
646 pub current_source_dir: Option<String>,
648 pub loaded_crates: HashSet<String>,
650 pub loading_crates: HashSet<String>,
652 pub project_root: Option<PathBuf>,
654 pub workspace_members: HashMap<String, PathBuf>,
656 pub drop_types: HashSet<String>,
658}
659
660#[derive(Clone)]
662pub enum TypeDef {
663 Struct(StructDef),
664 Enum(EnumDef),
665}
666
667impl Interpreter {
668 pub fn new() -> Self {
669 let globals = Rc::new(RefCell::new(Environment::new()));
670 let environment = globals.clone();
671
672 let mut interp = Self {
673 globals: globals.clone(),
674 environment,
675 types: HashMap::new(),
676 variant_constructors: HashMap::new(),
677 default_structs: HashMap::new(),
678 return_value: None,
679 output: Vec::new(),
680 program_args: None,
681 current_module: None,
682 current_self_type: None,
683 current_source_dir: None,
684 loaded_crates: HashSet::new(),
685 loading_crates: HashSet::new(),
686 project_root: None,
687 workspace_members: HashMap::new(),
688 drop_types: HashSet::new(),
689 };
690
691 interp.register_builtins();
693
694 interp
695 }
696
697 pub fn set_program_args(&mut self, args: Vec<String>) {
699 self.program_args = Some(args);
700 }
701
702 pub fn set_current_module(&mut self, module: Option<String>) {
704 self.current_module = module;
705 }
706
707 pub fn set_current_source_dir(&mut self, dir: Option<String>) {
709 self.current_source_dir = dir;
710 }
711
712 pub fn get_program_args(&self) -> Vec<String> {
714 self.program_args.clone().unwrap_or_else(|| std::env::args().collect())
715 }
716
717 pub fn discover_project(&mut self, source_dir: &str) -> Result<(), RuntimeError> {
720 let mut current = PathBuf::from(source_dir);
721
722 loop {
724 let sigil_toml = current.join("Sigil.toml");
725 if sigil_toml.exists() {
726 if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml) {
727 if result {
728 return Ok(());
729 }
730 }
732 }
733
734 let sigil_toml_lower = current.join("sigil.toml");
736 if sigil_toml_lower.exists() {
737 if let Ok(result) = self.try_parse_workspace_toml(&sigil_toml_lower) {
738 if result {
739 return Ok(());
740 }
741 }
743 }
744
745 if !current.pop() {
746 crate::sigil_debug!("DEBUG discover_project: no workspace Sigil.toml found from {}", source_dir);
748 return Ok(());
749 }
750 }
751 }
752
753 fn try_parse_workspace_toml(&mut self, path: &PathBuf) -> Result<bool, RuntimeError> {
756 let content = std::fs::read_to_string(path)
757 .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
758
759 let toml_value: toml::Value = content.parse()
760 .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
761
762 if let Some(workspace) = toml_value.get("workspace") {
764 if workspace.get("members").and_then(|m| m.as_array()).is_some() {
765 return self.parse_sigil_toml(path).map(|_| true);
767 }
768 }
769
770 crate::sigil_debug!("DEBUG try_parse_workspace_toml: {:?} is not a workspace config", path);
772 Ok(false)
773 }
774
775 fn parse_sigil_toml(&mut self, path: &PathBuf) -> Result<(), RuntimeError> {
777 let content = std::fs::read_to_string(path)
778 .map_err(|e| RuntimeError::new(format!("Failed to read Sigil.toml: {}", e)))?;
779
780 let toml_value: toml::Value = content.parse()
781 .map_err(|e| RuntimeError::new(format!("Failed to parse Sigil.toml: {}", e)))?;
782
783 self.project_root = path.parent().map(|p| p.to_path_buf());
784
785 if let Some(workspace) = toml_value.get("workspace") {
787 if let Some(members) = workspace.get("members").and_then(|m| m.as_array()) {
788 for member in members {
789 if let Some(member_path) = member.as_str() {
790 let crate_name = std::path::Path::new(member_path)
792 .file_name()
793 .and_then(|n| n.to_str())
794 .map(|n| n.replace("-", "_"))
795 .unwrap_or_default();
796
797 if !crate_name.is_empty() {
798 crate::sigil_debug!("DEBUG parse_sigil_toml: registered workspace member: {} -> {}",
799 &crate_name, member_path);
800 self.workspace_members.insert(crate_name, PathBuf::from(member_path));
801 }
802 }
803 }
804 }
805 }
806
807 crate::sigil_debug!("DEBUG parse_sigil_toml: loaded {} workspace members from {:?}",
808 self.workspace_members.len(), path);
809
810 Ok(())
811 }
812
813 pub fn load_crate(&mut self, crate_name: &str) -> Result<bool, RuntimeError> {
815 if self.loaded_crates.contains(crate_name) {
817 return Ok(true);
818 }
819
820 if self.loading_crates.contains(crate_name) {
822 return Err(RuntimeError::new(format!(
823 "Circular dependency detected: crate '{}' is already being loaded", crate_name
824 )));
825 }
826
827 let crate_path = match self.workspace_members.get(crate_name) {
829 Some(p) => p.clone(),
830 None => {
831 crate::sigil_debug!("DEBUG load_crate: crate '{}' not found in workspace members", crate_name);
832 return Ok(false);
833 }
834 };
835
836 let project_root = match &self.project_root {
837 Some(r) => r.clone(),
838 None => {
839 crate::sigil_debug!("DEBUG load_crate: no project root set");
840 return Ok(false);
841 }
842 };
843
844 let lib_path = project_root.join(&crate_path).join("src").join("lib.sigil");
846
847 if !lib_path.exists() {
848 crate::sigil_debug!("DEBUG load_crate: lib.sigil not found at {:?}", lib_path);
849 return Ok(false);
850 }
851
852 self.loading_crates.insert(crate_name.to_string());
854
855 crate::sigil_debug!("DEBUG load_crate: loading crate '{}' from {:?}", crate_name, lib_path);
856
857 let source = std::fs::read_to_string(&lib_path)
859 .map_err(|e| RuntimeError::new(format!("Failed to read {:?}: {}", lib_path, e)))?;
860
861 let prev_module = self.current_module.clone();
863 let prev_source_dir = self.current_source_dir.clone();
864
865 self.current_module = Some(crate_name.to_string());
867 self.current_source_dir = lib_path.parent().map(|p| p.to_string_lossy().to_string());
868
869 let mut parser = crate::Parser::new(&source);
871
872 match parser.parse_file() {
873 Ok(parsed_file) => {
874 for item in &parsed_file.items {
876 if let Err(e) = self.execute_item(&item.node) {
877 crate::sigil_warn!("Warning: error loading crate '{}': {}", crate_name, e);
878 }
879 }
880 }
881 Err(e) => {
882 crate::sigil_warn!("Warning: failed to parse crate '{}': {:?}", crate_name, e);
883 }
884 }
885
886 self.current_module = prev_module;
888 self.current_source_dir = prev_source_dir;
889
890 self.loading_crates.remove(crate_name);
892 self.loaded_crates.insert(crate_name.to_string());
893
894 crate::sigil_debug!("DEBUG load_crate: successfully loaded crate '{}'", crate_name);
895
896 Ok(true)
897 }
898
899 fn register_builtins(&mut self) {
900 self.globals.borrow_mut().define("PhantomData".to_string(), Value::Null);
902
903 self.define_builtin("print", None, |interp, args| {
905 let output: Vec<String> = args.iter().map(|v| format!("{}", v)).collect();
906 let line = output.join(" ");
907 println!("{}", line);
908 interp.output.push(line);
909 Ok(Value::Null)
910 });
911
912 self.define_builtin("type_of", Some(1), |_, args| {
914 let type_name = match &args[0] {
915 Value::Null => "null",
916 Value::Bool(_) => "bool",
917 Value::Int(_) => "i64",
918 Value::Float(_) => "f64",
919 Value::String(_) => "str",
920 Value::Char(_) => "char",
921 Value::Array(_) => "array",
922 Value::Tuple(_) => "tuple",
923 Value::Struct { name, .. } => name,
924 Value::Variant { enum_name, .. } => enum_name,
925 Value::Function(_) => "fn",
926 Value::BuiltIn(_) => "builtin",
927 Value::Ref(_) => "ref",
928 Value::Infinity => "infinity",
929 Value::Empty => "empty",
930 Value::Evidential { .. } => "evidential",
931 Value::Affective { .. } => "affective",
932 Value::Map(_) => "map",
933 Value::Set(_) => "set",
934 Value::Channel(_) => "channel",
935 Value::ThreadHandle(_) => "thread",
936 Value::Actor(_) => "actor",
937 Value::Future(_) => "future",
938 Value::VariantConstructor { .. } => "variant_constructor",
939 Value::DefaultConstructor { .. } => "default_constructor",
940 Value::Range { .. } => "range",
941 };
942 Ok(Value::String(Rc::new(type_name.to_string())))
943 });
944
945 self.define_builtin("len", Some(1), |_, args| match &args[0] {
947 Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
948 Value::String(s) => Ok(Value::Int(s.len() as i64)),
949 Value::Tuple(t) => Ok(Value::Int(t.len() as i64)),
950 _ => Err(RuntimeError::new("len() requires array, string, or tuple")),
951 });
952
953 self.define_builtin("push", Some(2), |_, args| match &args[0] {
954 Value::Array(arr) => {
955 arr.borrow_mut().push(args[1].clone());
956 Ok(Value::Null)
957 }
958 _ => Err(RuntimeError::new("push() requires array")),
959 });
960
961 self.define_builtin("pop", Some(1), |_, args| match &args[0] {
962 Value::Array(arr) => arr
963 .borrow_mut()
964 .pop()
965 .ok_or_else(|| RuntimeError::new("pop() on empty array")),
966 _ => Err(RuntimeError::new("pop() requires array")),
967 });
968
969 self.define_builtin("abs", Some(1), |_, args| match &args[0] {
971 Value::Int(n) => Ok(Value::Int(n.abs())),
972 Value::Float(n) => Ok(Value::Float(n.abs())),
973 _ => Err(RuntimeError::new("abs() requires number")),
974 });
975
976 self.define_builtin("sqrt", Some(1), |_, args| match &args[0] {
977 Value::Int(n) => Ok(Value::Float((*n as f64).sqrt())),
978 Value::Float(n) => Ok(Value::Float(n.sqrt())),
979 _ => Err(RuntimeError::new("sqrt() requires number")),
980 });
981
982 self.define_builtin("sin", Some(1), |_, args| match &args[0] {
983 Value::Int(n) => Ok(Value::Float((*n as f64).sin())),
984 Value::Float(n) => Ok(Value::Float(n.sin())),
985 _ => Err(RuntimeError::new("sin() requires number")),
986 });
987
988 self.define_builtin("cos", Some(1), |_, args| match &args[0] {
989 Value::Int(n) => Ok(Value::Float((*n as f64).cos())),
990 Value::Float(n) => Ok(Value::Float(n.cos())),
991 _ => Err(RuntimeError::new("cos() requires number")),
992 });
993
994 self.define_builtin("known", Some(1), |_, args| {
996 Ok(Value::Evidential {
997 value: Box::new(args[0].clone()),
998 evidence: Evidence::Known,
999 })
1000 });
1001
1002 self.define_builtin("uncertain", Some(1), |_, args| {
1003 Ok(Value::Evidential {
1004 value: Box::new(args[0].clone()),
1005 evidence: Evidence::Uncertain,
1006 })
1007 });
1008
1009 self.define_builtin("reported", Some(1), |_, args| {
1010 Ok(Value::Evidential {
1011 value: Box::new(args[0].clone()),
1012 evidence: Evidence::Reported,
1013 })
1014 });
1015
1016 self.globals.borrow_mut().define(
1018 "Box·new".to_string(),
1019 Value::BuiltIn(Rc::new(BuiltInFn {
1020 name: "Box·new".to_string(),
1021 arity: Some(1),
1022 func: |_, args| Ok(args[0].clone()),
1023 })),
1024 );
1025
1026 self.globals.borrow_mut().define(
1028 "Map·new".to_string(),
1029 Value::BuiltIn(Rc::new(BuiltInFn {
1030 name: "Map·new".to_string(),
1031 arity: Some(0),
1032 func: |_, _| Ok(Value::Map(Rc::new(RefCell::new(HashMap::new())))),
1033 })),
1034 );
1035
1036 self.define_builtin("range", Some(2), |_, args| {
1038 let start = match &args[0] {
1039 Value::Int(n) => *n,
1040 _ => return Err(RuntimeError::new("range() requires integers")),
1041 };
1042 let end = match &args[1] {
1043 Value::Int(n) => *n,
1044 _ => return Err(RuntimeError::new("range() requires integers")),
1045 };
1046 let values: Vec<Value> = (start..end).map(Value::Int).collect();
1047 Ok(Value::Array(Rc::new(RefCell::new(values))))
1048 });
1049
1050 self.globals.borrow_mut().define(
1052 "ExitCode·SUCCESS".to_string(),
1053 Value::Variant {
1054 enum_name: "ExitCode".to_string(),
1055 variant_name: "SUCCESS".to_string(),
1056 fields: Some(Rc::new(vec![Value::Int(0)])),
1057 },
1058 );
1059 self.globals.borrow_mut().define(
1060 "ExitCode·FAILURE".to_string(),
1061 Value::Variant {
1062 enum_name: "ExitCode".to_string(),
1063 variant_name: "FAILURE".to_string(),
1064 fields: Some(Rc::new(vec![Value::Int(1)])),
1065 },
1066 );
1067
1068 self.define_builtin("PathBuf·from", Some(1), |_, args| {
1070 let arg = match &args[0] {
1072 Value::Ref(r) => r.borrow().clone(),
1073 other => other.clone(),
1074 };
1075 let path = match &arg {
1076 Value::String(s2) => s2.as_str().to_string(),
1077 _ => return Err(RuntimeError::new("PathBuf::from expects a string")),
1078 };
1079 let mut fields = HashMap::new();
1081 fields.insert("path".to_string(), Value::String(Rc::new(path)));
1082 Ok(Value::Struct {
1083 name: "PathBuf".to_string(),
1084 fields: Rc::new(RefCell::new(fields)),
1085 })
1086 });
1087
1088 self.define_builtin("Path·new", Some(1), |_, args| {
1090 let arg = match &args[0] {
1092 Value::Ref(r) => r.borrow().clone(),
1093 other => other.clone(),
1094 };
1095 let path = match &arg {
1096 Value::String(s2) => s2.as_str().to_string(),
1097 _ => return Err(RuntimeError::new("Path::new expects a string")),
1098 };
1099 let mut fields = HashMap::new();
1100 fields.insert("path".to_string(), Value::String(Rc::new(path)));
1101 Ok(Value::Struct {
1102 name: "Path".to_string(),
1103 fields: Rc::new(RefCell::new(fields)),
1104 })
1105 });
1106
1107 self.define_builtin("std·fs·read_to_string", Some(1), |interp, args| {
1109 fn unwrap_refs(v: &Value) -> Value {
1111 match v {
1112 Value::Ref(r) => unwrap_refs(&r.borrow()),
1113 other => other.clone(),
1114 }
1115 }
1116 let arg = unwrap_refs(&args[0]);
1117 crate::sigil_debug!("DEBUG read_to_string: arg = {:?}", arg);
1118 crate::sigil_debug!("DEBUG read_to_string: env has path = {:?}", interp.environment.borrow().get("path"));
1120 let path = match &arg {
1121 Value::String(s) => s.to_string(),
1122 Value::Struct { name, fields, .. } => {
1124 crate::sigil_debug!("DEBUG read_to_string: struct name = {}", name);
1125 fields.borrow().get("path")
1126 .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1127 .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1128 }
1129 Value::Variant { enum_name, variant_name, fields } if enum_name == "Option" && variant_name == "Some" => {
1131 if let Some(fields) = fields {
1132 if let Some(Value::String(s)) = fields.first() {
1133 s.to_string()
1134 } else {
1135 return Err(RuntimeError::new("read_to_string: Option::Some does not contain a string"));
1136 }
1137 } else {
1138 return Err(RuntimeError::new("read_to_string: Option::Some has no fields"));
1139 }
1140 }
1141 _ => return Err(RuntimeError::new(&format!("read_to_string expects a path string or PathBuf, got {:?}", arg))),
1142 };
1143 match std::fs::read_to_string(&path) {
1144 Ok(content) => Ok(Value::Variant {
1145 enum_name: "Result".to_string(),
1146 variant_name: "Ok".to_string(),
1147 fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1148 }),
1149 Err(e) => Ok(Value::Variant {
1150 enum_name: "Result".to_string(),
1151 variant_name: "Err".to_string(),
1152 fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1153 }),
1154 }
1155 });
1156
1157 self.define_builtin("fs·read_to_string", Some(1), |_, args| {
1159 let arg = match &args[0] {
1160 Value::Ref(r) => r.borrow().clone(),
1161 other => other.clone(),
1162 };
1163 let path = match &arg {
1164 Value::String(s) => s.to_string(),
1165 Value::Struct { fields, .. } => {
1166 fields.borrow().get("path")
1167 .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1168 .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1169 }
1170 _ => return Err(RuntimeError::new("read_to_string expects a path string or PathBuf")),
1171 };
1172 match std::fs::read_to_string(&path) {
1173 Ok(content) => Ok(Value::Variant {
1174 enum_name: "Result".to_string(),
1175 variant_name: "Ok".to_string(),
1176 fields: Some(Rc::new(vec![Value::String(Rc::new(content))])),
1177 }),
1178 Err(e) => Ok(Value::Variant {
1179 enum_name: "Result".to_string(),
1180 variant_name: "Err".to_string(),
1181 fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1182 }),
1183 }
1184 });
1185
1186 self.define_builtin("std·fs·read_dir", Some(1), |_, args| {
1188 fn unwrap_refs(v: &Value) -> Value {
1189 match v {
1190 Value::Ref(r) => unwrap_refs(&r.borrow()),
1191 other => other.clone(),
1192 }
1193 }
1194 let arg = unwrap_refs(&args[0]);
1195 let path = match &arg {
1196 Value::String(s) => s.to_string(),
1197 Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => {
1198 fields.borrow().get("path")
1199 .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1200 .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1201 }
1202 _ => return Err(RuntimeError::new(&format!("read_dir expects a path, got {:?}", arg))),
1203 };
1204 match std::fs::read_dir(&path) {
1205 Ok(entries) => {
1206 let entry_values: Vec<Value> = entries
1208 .filter_map(|e| e.ok())
1209 .map(|e| {
1210 let entry_path = e.path().to_string_lossy().to_string();
1211 let mut fields = HashMap::new();
1212 fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1213 Value::Variant {
1215 enum_name: "Result".to_string(),
1216 variant_name: "Ok".to_string(),
1217 fields: Some(Rc::new(vec![Value::Struct {
1218 name: "DirEntry".to_string(),
1219 fields: Rc::new(RefCell::new(fields)),
1220 }])),
1221 }
1222 })
1223 .collect();
1224 Ok(Value::Variant {
1226 enum_name: "Result".to_string(),
1227 variant_name: "Ok".to_string(),
1228 fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(entry_values)))])),
1229 })
1230 }
1231 Err(e) => Ok(Value::Variant {
1232 enum_name: "Result".to_string(),
1233 variant_name: "Err".to_string(),
1234 fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1235 }),
1236 }
1237 });
1238
1239 self.define_builtin("fs·read_dir", Some(1), |_, args| {
1241 fn unwrap_refs(v: &Value) -> Value {
1242 match v {
1243 Value::Ref(r) => unwrap_refs(&r.borrow()),
1244 other => other.clone(),
1245 }
1246 }
1247 let arg = unwrap_refs(&args[0]);
1248 let path = match &arg {
1249 Value::String(s) => s.to_string(),
1250 Value::Struct { name, fields, .. } if name == "Path" || name == "PathBuf" => {
1251 fields.borrow().get("path")
1252 .and_then(|v| if let Value::String(s) = v { Some(s.to_string()) } else { None })
1253 .ok_or_else(|| RuntimeError::new("Expected path field in struct"))?
1254 }
1255 _ => return Err(RuntimeError::new(&format!("read_dir expects a path, got {:?}", arg))),
1256 };
1257 match std::fs::read_dir(&path) {
1258 Ok(entries) => {
1259 let entry_values: Vec<Value> = entries
1260 .filter_map(|e| e.ok())
1261 .map(|e| {
1262 let entry_path = e.path().to_string_lossy().to_string();
1263 let mut fields = HashMap::new();
1264 fields.insert("path".to_string(), Value::String(Rc::new(entry_path)));
1265 Value::Variant {
1266 enum_name: "Result".to_string(),
1267 variant_name: "Ok".to_string(),
1268 fields: Some(Rc::new(vec![Value::Struct {
1269 name: "DirEntry".to_string(),
1270 fields: Rc::new(RefCell::new(fields)),
1271 }])),
1272 }
1273 })
1274 .collect();
1275 Ok(Value::Variant {
1276 enum_name: "Result".to_string(),
1277 variant_name: "Ok".to_string(),
1278 fields: Some(Rc::new(vec![Value::Array(Rc::new(RefCell::new(entry_values)))])),
1279 })
1280 }
1281 Err(e) => Ok(Value::Variant {
1282 enum_name: "Result".to_string(),
1283 variant_name: "Err".to_string(),
1284 fields: Some(Rc::new(vec![Value::String(Rc::new(e.to_string()))])),
1285 }),
1286 }
1287 });
1288
1289 self.define_builtin("std·env·var", Some(1), |_, args| {
1291 fn unwrap_refs(v: &Value) -> Value {
1292 match v {
1293 Value::Ref(r) => unwrap_refs(&r.borrow()),
1294 other => other.clone(),
1295 }
1296 }
1297 let arg = unwrap_refs(&args[0]);
1298 let var_name = match &arg {
1299 Value::String(s) => s.to_string(),
1300 _ => return Err(RuntimeError::new("env::var expects a string")),
1301 };
1302 match std::env::var(&var_name) {
1303 Ok(value) => Ok(Value::Variant {
1304 enum_name: "Result".to_string(),
1305 variant_name: "Ok".to_string(),
1306 fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1307 }),
1308 Err(_) => Ok(Value::Variant {
1309 enum_name: "Result".to_string(),
1310 variant_name: "Err".to_string(),
1311 fields: Some(Rc::new(vec![Value::String(Rc::new("Environment variable not found".to_string()))])),
1312 }),
1313 }
1314 });
1315
1316 self.define_builtin("env·var", Some(1), |_, args| {
1318 fn unwrap_refs(v: &Value) -> Value {
1319 match v {
1320 Value::Ref(r) => unwrap_refs(&r.borrow()),
1321 other => other.clone(),
1322 }
1323 }
1324 let arg = unwrap_refs(&args[0]);
1325 let var_name = match &arg {
1326 Value::String(s) => s.to_string(),
1327 _ => return Err(RuntimeError::new("env::var expects a string")),
1328 };
1329 match std::env::var(&var_name) {
1330 Ok(value) => Ok(Value::Variant {
1331 enum_name: "Result".to_string(),
1332 variant_name: "Ok".to_string(),
1333 fields: Some(Rc::new(vec![Value::String(Rc::new(value))])),
1334 }),
1335 Err(_) => Ok(Value::Variant {
1336 enum_name: "Result".to_string(),
1337 variant_name: "Err".to_string(),
1338 fields: Some(Rc::new(vec![Value::String(Rc::new("Environment variable not found".to_string()))])),
1339 }),
1340 }
1341 });
1342
1343 self.define_builtin("std·env·args", Some(0), |interp, _| {
1346 let args = interp.get_program_args();
1347 let arg_values: Vec<Value> = args.iter()
1348 .map(|s| Value::String(Rc::new(s.clone())))
1349 .collect();
1350 Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1351 });
1352
1353 self.define_builtin("env·args", Some(0), |interp, _| {
1355 let args = interp.get_program_args();
1356 let arg_values: Vec<Value> = args.iter()
1357 .map(|s| Value::String(Rc::new(s.clone())))
1358 .collect();
1359 Ok(Value::Array(Rc::new(RefCell::new(arg_values))))
1360 });
1361
1362 self.define_builtin("fs_read", Some(1), |_, args| {
1368 let path = match &args[0] {
1369 Value::String(s) => s.to_string(),
1370 _ => return Err(RuntimeError::new("fs_read requires a string path")),
1371 };
1372 match std::fs::read_to_string(&path) {
1373 Ok(content) => Ok(Value::String(Rc::new(content))),
1374 Err(e) => {
1375 crate::sigil_debug!("DEBUG fs_read error for '{}': {}", path, e);
1376 Ok(Value::Null)
1377 }
1378 }
1379 });
1380
1381 self.define_builtin("fs_list", Some(1), |_, args| {
1383 let path = match &args[0] {
1384 Value::String(s) => s.to_string(),
1385 _ => return Err(RuntimeError::new("fs_list requires a string path")),
1386 };
1387 match std::fs::read_dir(&path) {
1388 Ok(entries) => {
1389 let files: Vec<Value> = entries
1390 .filter_map(|e| e.ok())
1391 .map(|e| Value::String(Rc::new(e.file_name().to_string_lossy().to_string())))
1392 .collect();
1393 Ok(Value::Array(Rc::new(RefCell::new(files))))
1394 }
1395 Err(e) => {
1396 crate::sigil_debug!("DEBUG fs_list error for '{}': {}", path, e);
1397 Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))))
1398 }
1399 }
1400 });
1401
1402 self.define_builtin("fs_is_dir", Some(1), |_, args| {
1404 let path = match &args[0] {
1405 Value::String(s) => s.to_string(),
1406 _ => return Err(RuntimeError::new("fs_is_dir requires a string path")),
1407 };
1408 Ok(Value::Bool(std::path::Path::new(&path).is_dir()))
1409 });
1410
1411 self.define_builtin("fs_is_file", Some(1), |_, args| {
1413 let path = match &args[0] {
1414 Value::String(s) => s.to_string(),
1415 _ => return Err(RuntimeError::new("fs_is_file requires a string path")),
1416 };
1417 Ok(Value::Bool(std::path::Path::new(&path).is_file()))
1418 });
1419
1420 self.define_builtin("fs_exists", Some(1), |_, args| {
1422 let path = match &args[0] {
1423 Value::String(s) => s.to_string(),
1424 _ => return Err(RuntimeError::new("fs_exists requires a string path")),
1425 };
1426 Ok(Value::Bool(std::path::Path::new(&path).exists()))
1427 });
1428
1429 self.define_builtin("path_extension", Some(1), |_, args| {
1431 let path = match &args[0] {
1432 Value::String(s) => s.to_string(),
1433 _ => return Err(RuntimeError::new("path_extension requires a string path")),
1434 };
1435 let ext = std::path::Path::new(&path)
1436 .extension()
1437 .and_then(|e| e.to_str())
1438 .map(|s| s.to_string());
1439 match ext {
1440 Some(e) => Ok(Value::String(Rc::new(e))),
1441 None => Ok(Value::Null),
1442 }
1443 });
1444
1445 self.define_builtin("path_join", Some(2), |_, args| {
1447 let base = match &args[0] {
1448 Value::String(s) => s.to_string(),
1449 _ => return Err(RuntimeError::new("path_join requires string paths")),
1450 };
1451 let part = match &args[1] {
1452 Value::String(s) => s.to_string(),
1453 _ => return Err(RuntimeError::new("path_join requires string paths")),
1454 };
1455 let joined = std::path::Path::new(&base).join(&part);
1456 Ok(Value::String(Rc::new(joined.to_string_lossy().to_string())))
1457 });
1458
1459 self.define_builtin("path_parent", Some(1), |_, args| {
1461 let path = match &args[0] {
1462 Value::String(s) => s.to_string(),
1463 _ => return Err(RuntimeError::new("path_parent requires a string path")),
1464 };
1465 match std::path::Path::new(&path).parent() {
1466 Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
1467 None => Ok(Value::Null),
1468 }
1469 });
1470
1471 self.define_builtin("path_file_name", Some(1), |_, args| {
1473 let path = match &args[0] {
1474 Value::String(s) => s.to_string(),
1475 _ => return Err(RuntimeError::new("path_file_name requires a string path")),
1476 };
1477 match std::path::Path::new(&path).file_name() {
1478 Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
1479 None => Ok(Value::Null),
1480 }
1481 });
1482
1483 self.define_builtin("TreeSitterParser·new", Some(1), |_, args| {
1489 use crate::tree_sitter_support::{TSLanguage, TSParser};
1490
1491 let lang_str = match &args[0] {
1493 Value::String(s) => s.to_string(),
1494 Value::Variant { enum_name, variant_name, .. } => {
1495 format!("{}::{}", enum_name, variant_name)
1497 }
1498 other => format!("{:?}", other),
1499 };
1500
1501 let language = match TSLanguage::from_str(&lang_str) {
1503 Some(lang) => lang,
1504 None => {
1505 return Ok(Value::Variant {
1506 enum_name: "Result".to_string(),
1507 variant_name: "Err".to_string(),
1508 fields: Some(Rc::new(vec![Value::Struct {
1509 name: "ParseError".to_string(),
1510 fields: Rc::new(RefCell::new({
1511 let mut f = HashMap::new();
1512 f.insert("kind".to_string(), Value::String(Rc::new("ParserNotFound".to_string())));
1513 f.insert("message".to_string(), Value::String(Rc::new(format!("Unsupported language: {}", lang_str))));
1514 f
1515 })),
1516 }])),
1517 });
1518 }
1519 };
1520
1521 match TSParser::new(language) {
1523 Ok(_) => {
1524 let mut fields = HashMap::new();
1526 fields.insert("language".to_string(), Value::String(Rc::new(lang_str)));
1527 fields.insert("_ts_language".to_string(), Value::String(Rc::new(format!("{:?}", language))));
1528
1529 Ok(Value::Variant {
1530 enum_name: "Result".to_string(),
1531 variant_name: "Ok".to_string(),
1532 fields: Some(Rc::new(vec![Value::Struct {
1533 name: "TreeSitterParser".to_string(),
1534 fields: Rc::new(RefCell::new(fields)),
1535 }])),
1536 })
1537 }
1538 Err(e) => {
1539 Ok(Value::Variant {
1540 enum_name: "Result".to_string(),
1541 variant_name: "Err".to_string(),
1542 fields: Some(Rc::new(vec![Value::Struct {
1543 name: "ParseError".to_string(),
1544 fields: Rc::new(RefCell::new({
1545 let mut f = HashMap::new();
1546 f.insert("kind".to_string(), Value::String(Rc::new("ParserNotFound".to_string())));
1547 f.insert("message".to_string(), Value::String(Rc::new(e)));
1548 f
1549 })),
1550 }])),
1551 })
1552 }
1553 }
1554 });
1555
1556 self.define_builtin("tree_sitter_parse", Some(2), |_, args| {
1558 use crate::tree_sitter_support::{parse_source, node_to_value};
1559
1560 let lang_str = match &args[0] {
1562 Value::String(s) => s.to_string(),
1563 Value::Variant { enum_name, variant_name, .. } => {
1564 format!("{}::{}", enum_name, variant_name)
1565 }
1566 other => format!("{:?}", other),
1567 };
1568
1569 let source = match &args[1] {
1570 Value::String(s) => s.to_string(),
1571 _ => return Err(RuntimeError::new("tree_sitter_parse expects source code string as second argument")),
1572 };
1573
1574 match parse_source(&lang_str, &source) {
1576 Ok(tree) => {
1577 let root = tree.root_node();
1579 let root_fields = node_to_value(&root);
1580
1581 let mut tree_fields = HashMap::new();
1583 tree_fields.insert("root".to_string(), Value::Struct {
1584 name: "SyntaxNode".to_string(),
1585 fields: Rc::new(RefCell::new(root_fields)),
1586 });
1587 tree_fields.insert("source".to_string(), Value::String(Rc::new(source)));
1588
1589 Ok(Value::Variant {
1590 enum_name: "Result".to_string(),
1591 variant_name: "Ok".to_string(),
1592 fields: Some(Rc::new(vec![Value::Struct {
1593 name: "TSTree".to_string(),
1594 fields: Rc::new(RefCell::new(tree_fields)),
1595 }])),
1596 })
1597 }
1598 Err(e) => {
1599 Ok(Value::Variant {
1600 enum_name: "Result".to_string(),
1601 variant_name: "Err".to_string(),
1602 fields: Some(Rc::new(vec![Value::Struct {
1603 name: "ParseError".to_string(),
1604 fields: Rc::new(RefCell::new({
1605 let mut f = HashMap::new();
1606 f.insert("kind".to_string(), Value::String(Rc::new("SyntaxError".to_string())));
1607 f.insert("message".to_string(), Value::String(Rc::new(e)));
1608 f
1609 })),
1610 }])),
1611 })
1612 }
1613 }
1614 });
1615
1616 self.define_builtin("tree_sitter_supported_languages", Some(0), |_, _| {
1618 use crate::tree_sitter_support::supported_languages;
1619
1620 let languages: Vec<Value> = supported_languages()
1621 .iter()
1622 .map(|s| Value::String(Rc::new(s.to_string())))
1623 .collect();
1624
1625 Ok(Value::Array(Rc::new(RefCell::new(languages))))
1626 });
1627
1628 self.define_builtin("tree_sitter_node_text", Some(2), |_, args| {
1630 let (start_byte, end_byte) = match &args[0] {
1632 Value::Struct { fields, .. } => {
1633 let fields = fields.borrow();
1634 let start = match fields.get("start_byte") {
1635 Some(Value::Int(n)) => *n as usize,
1636 _ => return Err(RuntimeError::new("Node missing start_byte field")),
1637 };
1638 let end = match fields.get("end_byte") {
1639 Some(Value::Int(n)) => *n as usize,
1640 _ => return Err(RuntimeError::new("Node missing end_byte field")),
1641 };
1642 (start, end)
1643 }
1644 _ => return Err(RuntimeError::new("tree_sitter_node_text expects a SyntaxNode struct")),
1645 };
1646
1647 let source = match &args[1] {
1648 Value::String(s) => s.to_string(),
1649 _ => return Err(RuntimeError::new("tree_sitter_node_text expects source string as second argument")),
1650 };
1651
1652 if end_byte <= source.len() && start_byte <= end_byte {
1653 Ok(Value::String(Rc::new(source[start_byte..end_byte].to_string())))
1654 } else {
1655 Err(RuntimeError::new("Byte range out of bounds"))
1656 }
1657 });
1658
1659 let rc_new = Value::BuiltIn(Rc::new(BuiltInFn {
1661 name: "Rc·new".to_string(),
1662 arity: Some(1),
1663 func: |_, args| {
1664 let mut fields = HashMap::new();
1665 fields.insert("_value".to_string(), args[0].clone());
1666 Ok(Value::Struct {
1667 name: "Rc".to_string(),
1668 fields: std::rc::Rc::new(RefCell::new(fields)),
1669 })
1670 },
1671 }));
1672 self.globals.borrow_mut().define("Rc·new".to_string(), rc_new);
1673
1674 let cell_new = Value::BuiltIn(Rc::new(BuiltInFn {
1676 name: "Cell·new".to_string(),
1677 arity: Some(1),
1678 func: |_, args| {
1679 let mut fields = HashMap::new();
1680 fields.insert("_value".to_string(), args[0].clone());
1681 Ok(Value::Struct {
1682 name: "Cell".to_string(),
1683 fields: std::rc::Rc::new(RefCell::new(fields)),
1684 })
1685 },
1686 }));
1687 self.globals.borrow_mut().define("Cell·new".to_string(), cell_new);
1688 }
1689
1690 fn define_builtin(
1691 &mut self,
1692 name: &str,
1693 arity: Option<usize>,
1694 func: fn(&mut Interpreter, Vec<Value>) -> Result<Value, RuntimeError>,
1695 ) {
1696 let builtin = Value::BuiltIn(Rc::new(BuiltInFn {
1697 name: name.to_string(),
1698 arity,
1699 func,
1700 }));
1701 self.globals.borrow_mut().define(name.to_string(), builtin);
1702 }
1703
1704 pub fn execute(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1706 let mut result = Value::Null;
1707
1708 for item in &file.items {
1709 result = self.execute_item(&item.node)?;
1710 }
1711
1712 let main_fn = self.globals.borrow().get("main").and_then(|v| {
1714 if let Value::Function(f) = v {
1715 Some(f.clone())
1716 } else {
1717 None
1718 }
1719 });
1720 if let Some(f) = main_fn {
1721 if f.params.is_empty() {
1724 result = self.call_function(&f, vec![])?;
1725 }
1726 }
1727
1728 Ok(result)
1729 }
1730
1731 pub fn execute_definitions(&mut self, file: &SourceFile) -> Result<Value, RuntimeError> {
1734 let mut result = Value::Null;
1735
1736 for item in &file.items {
1737 result = self.execute_item(&item.node)?;
1738 }
1739
1740 Ok(result)
1741 }
1742
1743 fn execute_item(&mut self, item: &Item) -> Result<Value, RuntimeError> {
1744 match item {
1745 Item::Function(func) => {
1746 let fn_value = self.create_function(func)?;
1747 let fn_name = func.name.name.clone();
1748
1749 self.globals.borrow_mut().define(fn_name.clone(), fn_value.clone());
1751
1752 if let Some(ref module) = self.current_module {
1754 let qualified_name = format!("{}·{}", module, fn_name);
1755 self.globals.borrow_mut().define(qualified_name, fn_value);
1756 }
1757
1758 Ok(Value::Null)
1759 }
1760 Item::Struct(s) => {
1761 self.types
1763 .insert(s.name.name.clone(), TypeDef::Struct(s.clone()));
1764
1765 if let Some(ref module) = self.current_module {
1767 let qualified_name = format!("{}·{}", module, s.name.name);
1768 self.types.insert(qualified_name, TypeDef::Struct(s.clone()));
1769 }
1770
1771 if matches!(&s.fields, crate::ast::StructFields::Unit) {
1773 let unit_value = Value::Struct {
1774 name: s.name.name.clone(),
1775 fields: Rc::new(RefCell::new(HashMap::new())),
1776 };
1777 self.globals.borrow_mut().define(s.name.name.clone(), unit_value.clone());
1778
1779 if let Some(ref module) = self.current_module {
1781 let qualified_name = format!("{}·{}", module, s.name.name);
1782 self.globals.borrow_mut().define(qualified_name, unit_value);
1783 }
1784 }
1785
1786 let has_default = s.attrs.derives.iter().any(|d| matches!(d, DeriveTrait::Default));
1788 if has_default {
1789 self.default_structs.insert(s.name.name.clone(), s.clone());
1790 if let Some(ref module) = self.current_module {
1791 let qualified_name = format!("{}·{}", module, s.name.name);
1792 self.default_structs.insert(qualified_name, s.clone());
1793 }
1794 }
1795
1796 Ok(Value::Null)
1797 }
1798 Item::Enum(e) => {
1799 self.types
1801 .insert(e.name.name.clone(), TypeDef::Enum(e.clone()));
1802
1803 if let Some(ref module) = self.current_module {
1805 let qualified_name = format!("{}·{}", module, e.name.name);
1806 self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
1807 }
1808
1809 let enum_name = e.name.name.clone();
1812 for variant in &e.variants {
1813 let variant_name = variant.name.name.clone();
1814 let qualified_name = format!("{}·{}", enum_name, variant_name);
1815
1816 let arity = match &variant.fields {
1817 crate::ast::StructFields::Unit => 0,
1818 crate::ast::StructFields::Tuple(types) => types.len(),
1819 crate::ast::StructFields::Named(fields) => fields.len(),
1820 };
1821
1822 self.variant_constructors.insert(qualified_name.clone(), (enum_name.clone(), variant_name.clone(), arity));
1824 }
1825 Ok(Value::Null)
1826 }
1827 Item::Const(c) => {
1828 let value = self.evaluate(&c.value)?;
1829 self.globals.borrow_mut().define(c.name.name.clone(), value);
1830 Ok(Value::Null)
1831 }
1832 Item::Static(s) => {
1833 let value = self.evaluate(&s.value)?;
1834 self.globals.borrow_mut().define(s.name.name.clone(), value);
1835 Ok(Value::Null)
1836 }
1837 Item::ExternBlock(extern_block) => {
1838 for item in &extern_block.items {
1840 if let ExternItem::Function(func) = item {
1841 let name = func.name.name.clone();
1842 match name.as_str() {
1844 "sigil_read_file" => {
1845 self.define_builtin("sigil_read_file", Some(2), |_, args| {
1846 let path = match &args[0] {
1848 Value::String(s) => (**s).clone(),
1849 _ => return Err(RuntimeError::new("sigil_read_file expects string path")),
1850 };
1851 match std::fs::read_to_string(&path) {
1852 Ok(content) => {
1853 Ok(Value::String(Rc::new(content)))
1855 }
1856 Err(_) => Ok(Value::Null),
1857 }
1858 });
1859 }
1860 "sigil_file_len" => {
1861 self.define_builtin("sigil_file_len", Some(0), |_, _| {
1862 Ok(Value::Int(0))
1864 });
1865 }
1866 "sigil_write_file" => {
1867 self.define_builtin("sigil_write_file", Some(4), |_, args| {
1868 let path = match &args[0] {
1869 Value::String(s) => (**s).clone(),
1870 _ => return Err(RuntimeError::new("sigil_write_file expects string path")),
1871 };
1872 let content = match &args[2] {
1873 Value::String(s) => (**s).clone(),
1874 _ => return Err(RuntimeError::new("sigil_write_file expects string content")),
1875 };
1876 match std::fs::write(&path, &content) {
1877 Ok(_) => Ok(Value::Bool(true)),
1878 Err(_) => Ok(Value::Bool(false)),
1879 }
1880 });
1881 }
1882 "write" => {
1883 self.define_builtin("write", Some(3), |_, args| {
1884 let fd = match &args[0] {
1886 Value::Int(n) => *n,
1887 _ => 1,
1888 };
1889 let content = match &args[1] {
1890 Value::String(s) => (**s).clone(),
1891 _ => format!("{}", args[1]),
1892 };
1893 if fd == 1 {
1894 print!("{}", content);
1895 } else if fd == 2 {
1896 eprint!("{}", content);
1897 }
1898 Ok(Value::Int(content.len() as i64))
1899 });
1900 }
1901 _ => {
1902 }
1904 }
1905 }
1906 }
1907 Ok(Value::Null)
1908 }
1909 Item::Impl(impl_block) => {
1910 let type_name = match &impl_block.self_ty {
1912 TypeExpr::Path(path) => {
1913 path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::")
1914 }
1915 _ => return Ok(Value::Null), };
1917
1918 if let Some(trait_path) = &impl_block.trait_ {
1920 let trait_name = trait_path.segments.iter()
1921 .map(|s| s.ident.name.as_str())
1922 .collect::<Vec<_>>()
1923 .join("::");
1924 if trait_name == "Drop" {
1925 self.drop_types.insert(type_name.clone());
1926 }
1927 }
1928
1929 for impl_item in &impl_block.items {
1931 if let ImplItem::Function(func) = impl_item {
1932 let fn_value = self.create_function(func)?;
1933 let qualified_name = format!("{}·{}", type_name, func.name.name);
1934 if type_name == "Lexer" && func.name.name.contains("keyword") {
1936 crate::sigil_debug!("DEBUG registering: {}", qualified_name);
1937 }
1938 self.globals.borrow_mut().define(qualified_name.clone(), fn_value.clone());
1939
1940 if let Some(ref module) = self.current_module {
1942 let fully_qualified = format!("{}·{}", module, qualified_name);
1943 self.globals.borrow_mut().define(fully_qualified, fn_value);
1944 }
1945 }
1946 }
1947 Ok(Value::Null)
1948 }
1949 Item::Module(module) => {
1950 let module_name = &module.name.name;
1952
1953 if let Some(items) = &module.items {
1954 for item in items {
1957 match &item.node {
1958 Item::Const(c) => {
1959 let value = self.evaluate(&c.value)?;
1960 let qualified_name = format!("{}·{}", module_name, c.name.name);
1961 self.globals.borrow_mut().define(qualified_name, value);
1962 }
1963 Item::Static(s) => {
1964 let value = self.evaluate(&s.value)?;
1965 let qualified_name = format!("{}·{}", module_name, s.name.name);
1966 self.globals.borrow_mut().define(qualified_name, value);
1967 }
1968 Item::Function(func) => {
1969 let fn_value = self.create_function(func)?;
1970 let qualified_name = format!("{}·{}", module_name, func.name.name);
1971 self.globals.borrow_mut().define(qualified_name, fn_value);
1972 }
1973 Item::Struct(s) => {
1974 let qualified_name = format!("{}·{}", module_name, s.name.name);
1975 self.types.insert(qualified_name, TypeDef::Struct(s.clone()));
1976 }
1977 Item::Enum(e) => {
1978 let qualified_name = format!("{}·{}", module_name, e.name.name);
1979 self.types.insert(qualified_name, TypeDef::Enum(e.clone()));
1980 }
1981 _ => {} }
1983 }
1984 } else {
1985 if let Some(ref source_dir) = self.current_source_dir {
1987 let module_path = std::path::Path::new(source_dir)
1988 .join(format!("{}.sigil", module_name));
1989
1990 if module_path.exists() {
1991 crate::sigil_debug!("DEBUG Loading external module: {}", module_path.display());
1992
1993 match std::fs::read_to_string(&module_path) {
1994 Ok(source) => {
1995 let mut parser = crate::Parser::new(&source);
1997 match parser.parse_file() {
1998 Ok(parsed_file) => {
1999 let prev_module = self.current_module.clone();
2001
2002 self.current_module = Some(module_name.clone());
2004
2005 for item in &parsed_file.items {
2007 if let Err(e) = self.execute_item(&item.node) {
2008 crate::sigil_warn!("Warning: error in module {}: {}", module_name, e);
2009 }
2010 }
2011
2012 self.current_module = prev_module;
2014 }
2015 Err(e) => {
2016 crate::sigil_warn!("Warning: failed to parse module {}: {:?}", module_name, e);
2017 }
2018 }
2019 }
2020 Err(e) => {
2021 crate::sigil_warn!("Warning: failed to read module file {}: {}", module_path.display(), e);
2022 }
2023 }
2024 } else {
2025 crate::sigil_debug!("DEBUG Module file not found: {} (source_dir={})", module_path.display(), source_dir);
2026 }
2027 } else {
2028 crate::sigil_debug!("DEBUG No source_dir set, cannot load external module: {}", module_name);
2029 }
2030 }
2031 Ok(Value::Null)
2032 }
2033 Item::Use(use_decl) => {
2034 self.process_use_tree(&use_decl.tree, &[])?;
2036 Ok(Value::Null)
2037 }
2038 _ => Ok(Value::Null), }
2040 }
2041
2042 fn process_use_tree(&mut self, tree: &crate::ast::UseTree, prefix: &[String]) -> Result<(), RuntimeError> {
2044 use crate::ast::UseTree;
2045 match tree {
2046 UseTree::Path { prefix: path_prefix, suffix } => {
2047 let mut new_prefix = prefix.to_vec();
2049 new_prefix.push(path_prefix.name.clone());
2050 self.process_use_tree(suffix, &new_prefix)
2051 }
2052 UseTree::Name(name) => {
2053 let mut path = prefix.to_vec();
2055 path.push(name.name.clone());
2056 let qualified = path.join("·");
2057 let simple_name = name.name.clone();
2058
2059 if !prefix.is_empty() {
2062 let crate_name = &prefix[0];
2063 if !self.types.contains_key(&qualified)
2064 && self.globals.borrow().get(&qualified).is_none()
2065 && !self.loaded_crates.contains(crate_name)
2066 {
2067 if let Err(e) = self.load_crate(crate_name) {
2069 crate::sigil_debug!("DEBUG process_use_tree: failed to load crate '{}': {}", crate_name, e);
2070 }
2071 }
2072 }
2073
2074 if let Some(type_def) = self.types.get(&qualified).cloned() {
2077 self.types.insert(simple_name.clone(), type_def);
2078 }
2079 let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2081 if let Some(val) = func {
2082 self.globals.borrow_mut().define(simple_name.clone(), val);
2083 }
2084
2085 let method_prefix = format!("{}·", qualified);
2089 let matching_methods: Vec<(String, Value)> = {
2090 let globals = self.globals.borrow();
2091 globals.values.iter()
2092 .filter(|(k, _)| k.starts_with(&method_prefix))
2093 .map(|(k, v)| {
2094 let method_suffix = k.strip_prefix(&method_prefix).unwrap();
2096 let new_name = format!("{}·{}", simple_name, method_suffix);
2097 (new_name, v.clone())
2098 })
2099 .collect()
2100 };
2101 for (name, val) in matching_methods {
2102 self.globals.borrow_mut().define(name, val);
2103 }
2104 Ok(())
2105 }
2106 UseTree::Rename { name, alias } => {
2107 let mut path = prefix.to_vec();
2109 path.push(name.name.clone());
2110 let qualified = path.join("·");
2111 let alias_name = alias.name.clone();
2112
2113 if let Some(type_def) = self.types.get(&qualified).cloned() {
2114 self.types.insert(alias_name.clone(), type_def);
2115 }
2116 let func = self.globals.borrow().get(&qualified).map(|v| v.clone());
2117 if let Some(val) = func {
2118 self.globals.borrow_mut().define(alias_name, val);
2119 }
2120 Ok(())
2121 }
2122 UseTree::Glob => {
2123 let path_prefix = prefix.join("·");
2125 let matching_types: Vec<(String, TypeDef)> = self.types.iter()
2127 .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2128 .map(|(k, v)| {
2129 let suffix = k.strip_prefix(&path_prefix).unwrap().trim_start_matches('·');
2130 (suffix.to_string(), v.clone())
2131 })
2132 .filter(|(k, _)| !k.contains('·')) .collect();
2134 for (name, def) in matching_types {
2135 self.types.insert(name, def);
2136 }
2137 let matching_funcs: Vec<(String, Value)> = {
2139 let globals = self.globals.borrow();
2140 globals.values.iter()
2141 .filter(|(k, _)| k.starts_with(&path_prefix) && k.len() > path_prefix.len())
2142 .map(|(k, v)| {
2143 let suffix = k.strip_prefix(&path_prefix).unwrap().trim_start_matches('·');
2144 (suffix.to_string(), v.clone())
2145 })
2146 .filter(|(k, _)| !k.contains('·'))
2147 .collect()
2148 };
2149 for (name, val) in matching_funcs {
2150 self.globals.borrow_mut().define(name, val);
2151 }
2152 Ok(())
2153 }
2154 UseTree::Group(trees) => {
2155 for tree in trees {
2157 self.process_use_tree(tree, prefix)?;
2158 }
2159 Ok(())
2160 }
2161 }
2162 }
2163
2164 fn create_function(&self, func: &crate::ast::Function) -> Result<Value, RuntimeError> {
2165 let params: Vec<String> = func
2166 .params
2167 .iter()
2168 .map(|p| Self::extract_param_name(&p.pattern))
2169 .collect();
2170
2171 let body = func
2172 .body
2173 .as_ref()
2174 .map(|b| Expr::Block(b.clone()))
2175 .unwrap_or(Expr::Literal(Literal::Bool(false)));
2176
2177 Ok(Value::Function(Rc::new(Function {
2178 name: Some(func.name.name.clone()),
2179 params,
2180 body,
2181 closure: self.environment.clone(),
2182 })))
2183 }
2184
2185 fn extract_param_name(pattern: &Pattern) -> String {
2187 match pattern {
2188 Pattern::Ident { name, .. } => name.name.clone(),
2189 Pattern::Ref { pattern: inner, .. } => Self::extract_param_name(inner),
2191 Pattern::RefBinding { name, .. } => name.name.clone(),
2193 _ => "_".to_string(),
2194 }
2195 }
2196
2197 pub fn evaluate(&mut self, expr: &Expr) -> Result<Value, RuntimeError> {
2199 match expr {
2200 Expr::Literal(lit) => self.eval_literal(lit),
2201 Expr::Path(path) => self.eval_path(path),
2202 Expr::Binary { left, op, right } => self.eval_binary(left, op, right),
2203 Expr::Unary { op, expr } => self.eval_unary(op, expr),
2204 Expr::Call { func, args } => self.eval_call(func, args),
2205 Expr::Array(elements) => self.eval_array(elements),
2206 Expr::Tuple(elements) => self.eval_tuple(elements),
2207 Expr::Block(block) => self.eval_block(block),
2208 Expr::If {
2209 condition,
2210 then_branch,
2211 else_branch,
2212 } => self.eval_if(condition, then_branch, else_branch),
2213 Expr::Match { expr, arms } => self.eval_match(expr, arms),
2214 Expr::For {
2215 pattern,
2216 iter,
2217 body,
2218 ..
2219 } => self.eval_for(pattern, iter, body),
2220 Expr::While { condition, body, .. } => self.eval_while(condition, body),
2221 Expr::Loop { body, .. } => self.eval_loop(body),
2222 Expr::Return(value) => self.eval_return(value),
2223 Expr::Break { value, .. } => self.eval_break(value),
2224 Expr::Continue { .. } => Err(RuntimeError::new("continue")),
2225 Expr::Index { expr, index } => self.eval_index(expr, index),
2226 Expr::Field { expr, field } => self.eval_field(expr, field),
2227 Expr::MethodCall {
2228 receiver,
2229 method,
2230 args,
2231 ..
2232 } => self.eval_method_call(receiver, method, args),
2233 Expr::Incorporation { segments } => self.eval_incorporation(segments),
2236 Expr::Pipe { expr, operations } => self.eval_pipe(expr, operations),
2237 Expr::Closure { params, body, .. } => self.eval_closure(params, body),
2238 Expr::Struct { path, fields, rest } => self.eval_struct_literal(path, fields, rest),
2239 Expr::Evidential {
2240 expr,
2241 evidentiality,
2242 } => self.eval_evidential(expr, evidentiality),
2243 Expr::Range {
2244 start,
2245 end,
2246 inclusive,
2247 } => {
2248 crate::sigil_debug!("DEBUG evaluate: Expr::Range being evaluated standalone");
2249 self.eval_range(start, end, *inclusive)
2250 }
2251 Expr::Assign { target, value } => self.eval_assign(target, value),
2252 Expr::Let { pattern, value } => {
2253 let val = self.evaluate(value)?;
2256 if self.pattern_matches(pattern, &val)? {
2258 self.bind_pattern(pattern, val)?;
2260 Ok(Value::Bool(true))
2261 } else {
2262 Ok(Value::Bool(false))
2264 }
2265 }
2266 Expr::Await {
2267 expr: inner,
2268 evidentiality,
2269 } => {
2270 let value = self.evaluate(inner)?;
2271 let awaited = self.await_value(value)?;
2272 match evidentiality {
2274 Some(Evidentiality::Uncertain) => {
2275 self.unwrap_result_or_option(awaited, true, false)
2277 }
2278 Some(Evidentiality::Known) => {
2279 self.unwrap_result_or_option(awaited, true, true)
2281 }
2282 Some(Evidentiality::Reported) | Some(Evidentiality::Paradox) | Some(Evidentiality::Predicted) => {
2283 self.unwrap_result_or_option(awaited, false, false)
2285 }
2286 None => Ok(awaited),
2287 }
2288 }
2289 Expr::Macro { path, tokens } => {
2291 let macro_name = path.segments.last()
2292 .map(|s| s.ident.name.as_str())
2293 .unwrap_or("");
2294 crate::sigil_debug!("DEBUG Expr::Macro: name='{}', tokens='{}'", macro_name, tokens);
2295
2296 match macro_name {
2297 "format" => self.eval_format_macro(tokens),
2298 "println" => {
2299 let formatted = self.eval_format_macro(tokens)?;
2300 if let Value::String(s) = formatted {
2301 println!("{}", s);
2302 }
2303 Ok(Value::Null)
2304 }
2305 "eprintln" => {
2306 let formatted = self.eval_format_macro(tokens)?;
2307 if let Value::String(s) = formatted {
2308 eprintln!("{}", s);
2309 }
2310 Ok(Value::Null)
2311 }
2312 "print" => {
2313 let formatted = self.eval_format_macro(tokens)?;
2314 if let Value::String(s) = formatted {
2315 print!("{}", s);
2316 }
2317 Ok(Value::Null)
2318 }
2319 "eprint" => {
2320 let formatted = self.eval_format_macro(tokens)?;
2321 if let Value::String(s) = formatted {
2322 eprint!("{}", s);
2323 }
2324 Ok(Value::Null)
2325 }
2326 "vec" => {
2327 self.eval_vec_macro(tokens)
2329 }
2330 "panic" => {
2331 let formatted = self.eval_format_macro(tokens)?;
2332 let msg = if let Value::String(s) = formatted {
2333 s.to_string()
2334 } else {
2335 "panic!".to_string()
2336 };
2337 Err(RuntimeError::new(format!("panic: {}", msg)))
2338 }
2339 "assert" => {
2340 let condition = self.eval_format_macro(tokens)?;
2342 if self.is_truthy(&condition) {
2343 Ok(Value::Null)
2344 } else {
2345 Err(RuntimeError::new("assertion failed"))
2346 }
2347 }
2348 _ => {
2349 Ok(Value::String(Rc::new(tokens.clone())))
2351 }
2352 }
2353 }
2354 Expr::Unsafe(block) => self.eval_block(block),
2356 Expr::Async { block, .. } => self.eval_block(block),
2358 Expr::Try(inner) => {
2360 let value = self.evaluate(inner)?;
2361 match &value {
2364 Value::Variant { enum_name, variant_name, fields } => {
2365 match (enum_name.as_str(), variant_name.as_str()) {
2366 ("Result", "Ok") => {
2367 if let Some(f) = fields {
2368 Ok(f.first().cloned().unwrap_or(Value::Null))
2369 } else {
2370 Ok(Value::Null)
2371 }
2372 }
2373 ("Result", "Err") => {
2374 crate::sigil_debug!("DEBUG Try propagating Result::Err with fields: {:?}", fields);
2375 let err_msg = if let Some(f) = fields {
2376 let first = f.first().cloned().unwrap_or(Value::Null);
2377 crate::sigil_debug!("DEBUG Try error first value: {}", first);
2378 match &first {
2380 Value::Struct { name, fields: sf } => {
2381 let field_str = sf.borrow().iter()
2382 .map(|(k, v)| format!("{}: {}", k, v))
2383 .collect::<Vec<_>>()
2384 .join(", ");
2385 format!("{} {{ {} }}", name, field_str)
2386 }
2387 Value::Variant { enum_name: en, variant_name: vn, fields: vf } => {
2388 let vf_str = vf.as_ref().map(|vs|
2389 vs.iter().map(|v| format!("{}", v)).collect::<Vec<_>>().join(", ")
2390 ).unwrap_or_default();
2391 format!("{}::{} {{ {} }}", en, vn, vf_str)
2392 }
2393 _ => format!("{}", first)
2394 }
2395 } else {
2396 "error".to_string()
2397 };
2398 Err(RuntimeError::new(format!("try failed: {}", err_msg)))
2399 }
2400 ("Option", "Some") => {
2401 if let Some(f) = fields {
2402 Ok(f.first().cloned().unwrap_or(Value::Null))
2403 } else {
2404 Ok(Value::Null)
2405 }
2406 }
2407 ("Option", "None") => {
2408 Err(RuntimeError::new("try failed: None"))
2409 }
2410 _ => Ok(value), }
2412 }
2413 _ => Ok(value), }
2415 }
2416 Expr::Cast { expr, ty } => {
2418 let value = self.evaluate(expr)?;
2419 let type_name = match ty {
2421 TypeExpr::Path(path) => {
2422 if !path.segments.is_empty() {
2423 path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("")
2424 } else {
2425 ""
2426 }
2427 }
2428 _ => "",
2429 };
2430 match (value, type_name) {
2431 (Value::Char(c), "u8") => Ok(Value::Int(c as i64)),
2433 (Value::Char(c), "u16") => Ok(Value::Int(c as i64)),
2434 (Value::Char(c), "u32") => Ok(Value::Int(c as i64)),
2435 (Value::Char(c), "u64") => Ok(Value::Int(c as i64)),
2436 (Value::Char(c), "i8") => Ok(Value::Int(c as i64)),
2437 (Value::Char(c), "i16") => Ok(Value::Int(c as i64)),
2438 (Value::Char(c), "i32") => Ok(Value::Int(c as i64)),
2439 (Value::Char(c), "i64") => Ok(Value::Int(c as i64)),
2440 (Value::Char(c), "usize") => Ok(Value::Int(c as i64)),
2441 (Value::Char(c), "isize") => Ok(Value::Int(c as i64)),
2442 (Value::Int(i), "u8") => Ok(Value::Int(i)),
2444 (Value::Int(i), "u16") => Ok(Value::Int(i)),
2445 (Value::Int(i), "u32") => Ok(Value::Int(i)),
2446 (Value::Int(i), "u64") => Ok(Value::Int(i)),
2447 (Value::Int(i), "i8") => Ok(Value::Int(i)),
2448 (Value::Int(i), "i16") => Ok(Value::Int(i)),
2449 (Value::Int(i), "i32") => Ok(Value::Int(i)),
2450 (Value::Int(i), "i64") => Ok(Value::Int(i)),
2451 (Value::Int(i), "usize") => Ok(Value::Int(i)),
2452 (Value::Int(i), "isize") => Ok(Value::Int(i)),
2453 (Value::Float(f), "i32") => Ok(Value::Int(f as i64)),
2455 (Value::Float(f), "i64") => Ok(Value::Int(f as i64)),
2456 (Value::Float(f), "u32") => Ok(Value::Int(f as i64)),
2457 (Value::Float(f), "u64") => Ok(Value::Int(f as i64)),
2458 (Value::Int(i), "f32") => Ok(Value::Float(i as f64)),
2460 (Value::Int(i), "f64") => Ok(Value::Float(i as f64)),
2461 (Value::Int(i), "char") => {
2463 if let Some(c) = char::from_u32(i as u32) {
2464 Ok(Value::Char(c))
2465 } else {
2466 Err(RuntimeError::new(format!("invalid char code: {}", i)))
2467 }
2468 }
2469 (v, _) => Ok(v),
2471 }
2472 }
2473 _ => Err(RuntimeError::new(format!(
2474 "Unsupported expression: {:?}",
2475 expr
2476 ))),
2477 }
2478 }
2479
2480 fn eval_assign(&mut self, target: &Expr, value: &Expr) -> Result<Value, RuntimeError> {
2481 let val = self.evaluate(value)?;
2482
2483 match target {
2484 Expr::Path(path) if path.segments.len() == 1 => {
2485 let name = &path.segments[0].ident.name;
2486 self.environment.borrow_mut().set(name, val.clone())?;
2487 Ok(val)
2488 }
2489 Expr::Index { expr, index } => {
2490 let idx = self.evaluate(index)?;
2492 let idx = match idx {
2493 Value::Int(i) => i as usize,
2494 _ => return Err(RuntimeError::new("Index must be an integer")),
2495 };
2496
2497 if let Expr::Path(path) = expr.as_ref() {
2499 if path.segments.len() == 1 {
2500 let name = &path.segments[0].ident.name;
2501 let current = self.environment.borrow().get(name).ok_or_else(|| {
2502 RuntimeError::new(format!("Undefined variable: {}", name))
2503 })?;
2504
2505 if let Value::Array(arr) = current {
2506 let borrowed = arr.borrow();
2507 let mut new_arr = borrowed.clone();
2508 drop(borrowed);
2509 if idx < new_arr.len() {
2510 new_arr[idx] = val.clone();
2511 self.environment
2512 .borrow_mut()
2513 .set(name, Value::Array(Rc::new(RefCell::new(new_arr))))?;
2514 return Ok(val);
2515 }
2516 }
2517 }
2518 }
2519 Err(RuntimeError::new("Invalid index assignment target"))
2520 }
2521 Expr::Field { expr, field } => {
2522 match expr.as_ref() {
2525 Expr::Path(path) if path.segments.len() == 1 => {
2526 let var_name = &path.segments[0].ident.name;
2527 let current = self.environment.borrow().get(var_name).ok_or_else(|| {
2528 RuntimeError::new(format!("Undefined variable: {}", var_name))
2529 })?;
2530
2531 match current {
2532 Value::Struct { fields, .. } => {
2533 fields.borrow_mut().insert(field.name.clone(), val.clone());
2534 Ok(val)
2535 }
2536 Value::Ref(r) => {
2537 let mut borrowed = r.borrow_mut();
2538 if let Value::Struct { fields, .. } = &mut *borrowed {
2539 fields.borrow_mut().insert(field.name.clone(), val.clone());
2540 Ok(val)
2541 } else {
2542 Err(RuntimeError::new("Cannot assign field on non-struct ref"))
2543 }
2544 }
2545 _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2546 }
2547 }
2548 _ => {
2549 let struct_val = self.evaluate(expr)?;
2551 match struct_val {
2552 Value::Struct { fields, .. } => {
2553 fields.borrow_mut().insert(field.name.clone(), val.clone());
2554 Ok(val)
2555 }
2556 Value::Ref(r) => {
2557 let mut borrowed = r.borrow_mut();
2558 if let Value::Struct { fields, .. } = &mut *borrowed {
2559 fields.borrow_mut().insert(field.name.clone(), val.clone());
2560 Ok(val)
2561 } else {
2562 Err(RuntimeError::new("Cannot assign field on non-struct"))
2563 }
2564 }
2565 _ => Err(RuntimeError::new("Cannot assign field on non-struct")),
2566 }
2567 }
2568 }
2569 }
2570 Expr::Unary { op: UnaryOp::Deref, expr: inner } => {
2571 let ptr_val = self.evaluate(inner)?;
2574 match ptr_val {
2575 Value::Ref(r) => {
2576 *r.borrow_mut() = val.clone();
2577 Ok(val)
2578 }
2579 _ => Err(RuntimeError::new("Cannot dereference assign to non-reference")),
2580 }
2581 }
2582 Expr::Deref(inner) => {
2583 let ptr_val = self.evaluate(inner)?;
2586 match ptr_val {
2587 Value::Ref(r) => {
2588 *r.borrow_mut() = val.clone();
2589 Ok(val)
2590 }
2591 _ => Err(RuntimeError::new("Cannot dereference assign to non-reference")),
2592 }
2593 }
2594 _ => Err(RuntimeError::new("Invalid assignment target")),
2595 }
2596 }
2597
2598 fn eval_literal(&mut self, lit: &Literal) -> Result<Value, RuntimeError> {
2599 match lit {
2600 Literal::Int { value, base, .. } => {
2601 let n = self.parse_int(value, base)?;
2602 Ok(Value::Int(n))
2603 }
2604 Literal::Float { value, .. } => {
2605 let n: f64 = value
2606 .parse()
2607 .map_err(|_| RuntimeError::new(format!("Invalid float: {}", value)))?;
2608 Ok(Value::Float(n))
2609 }
2610 Literal::String(s) => Ok(Value::String(Rc::new(s.clone()))),
2611 Literal::MultiLineString(s) => Ok(Value::String(Rc::new(s.clone()))),
2612 Literal::RawString(s) => Ok(Value::String(Rc::new(s.clone()))),
2613 Literal::ByteString(bytes) => {
2614 let arr: Vec<Value> = bytes.iter().map(|&b| Value::Int(b as i64)).collect();
2616 Ok(Value::Array(Rc::new(RefCell::new(arr))))
2617 }
2618 Literal::InterpolatedString { parts } => {
2619 let mut result = String::new();
2621 let mut combined_evidence: Option<Evidence> = None;
2622
2623 for part in parts {
2624 match part {
2625 InterpolationPart::Text(s) => result.push_str(s),
2626 InterpolationPart::Expr(expr) => {
2627 let value = self.evaluate(expr)?;
2628
2629 combined_evidence = Self::combine_evidence(
2631 combined_evidence,
2632 Self::extract_evidence(&value),
2633 );
2634
2635 if let Some(affect) = Self::extract_affect(&value) {
2637 combined_evidence = Self::combine_evidence(
2638 combined_evidence,
2639 Self::affect_to_evidence(affect),
2640 );
2641 }
2642
2643 let display_value = Self::unwrap_value(&value);
2645 result.push_str(&format!("{}", display_value));
2646 }
2647 }
2648 }
2649
2650 let string_value = Value::String(Rc::new(result));
2652 match combined_evidence {
2653 Some(evidence) => Ok(Value::Evidential {
2654 value: Box::new(string_value),
2655 evidence,
2656 }),
2657 None => Ok(string_value),
2658 }
2659 }
2660 Literal::SigilStringSql(s) => {
2661 Ok(Value::String(Rc::new(s.clone())))
2664 }
2665 Literal::SigilStringRoute(s) => {
2666 Ok(Value::String(Rc::new(s.clone())))
2669 }
2670 Literal::Char(c) => Ok(Value::Char(*c)),
2671 Literal::ByteChar(b) => Ok(Value::Int(*b as i64)),
2672 Literal::Bool(b) => Ok(Value::Bool(*b)),
2673 Literal::Null => Ok(Value::Null),
2674 Literal::Empty => Ok(Value::Empty),
2675 Literal::Infinity => Ok(Value::Infinity),
2676 Literal::Circle => Ok(Value::Int(0)), }
2678 }
2679
2680 fn parse_int(&self, value: &str, base: &NumBase) -> Result<i64, RuntimeError> {
2681 let (radix, prefix_len) = match base {
2682 NumBase::Binary => (2, 2), NumBase::Octal => (8, 2), NumBase::Decimal => (10, 0),
2685 NumBase::Hex => (16, 2), NumBase::Vigesimal => (20, 2), NumBase::Sexagesimal => (60, 2), NumBase::Duodecimal => (12, 2), NumBase::Explicit(b) => (*b as u32, 0),
2690 };
2691
2692 let clean = value[prefix_len..].replace('_', "");
2693 i64::from_str_radix(&clean, radix)
2694 .map_err(|_| RuntimeError::new(format!("Invalid integer: {}", value)))
2695 }
2696
2697 fn eval_path(&self, path: &TypePath) -> Result<Value, RuntimeError> {
2698 if path.segments.len() == 1 {
2699 let name = &path.segments[0].ident.name;
2700 if let Some(val) = self.environment.borrow().get(name) {
2704 return Ok(val);
2705 }
2706 if name == "_" {
2708 return Ok(Value::Null);
2709 }
2710 if name == "Self" {
2712 if let Some(ref self_type) = self.current_self_type {
2713 if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
2715 if matches!(struct_def.fields, crate::ast::StructFields::Unit) {
2716 return Ok(Value::Struct {
2717 name: self_type.clone(),
2718 fields: Rc::new(RefCell::new(HashMap::new())),
2719 });
2720 }
2721 }
2722 return Ok(Value::Struct {
2724 name: self_type.clone(),
2725 fields: Rc::new(RefCell::new(HashMap::new())),
2726 });
2727 }
2728 }
2729 if name.len() <= 2 {
2730 crate::sigil_debug!("DEBUG Undefined variable '{}' (len={})", name, name.len());
2731 }
2732 Err(RuntimeError::new(format!("Undefined variable: {}", name)))
2733 } else {
2734 let full_name = path
2737 .segments
2738 .iter()
2739 .map(|s| s.ident.name.as_str())
2740 .collect::<Vec<_>>()
2741 .join("·");
2742
2743 if let Some(val) = self.environment.borrow().get(&full_name) {
2744 return Ok(val);
2745 }
2746
2747 if let Some(val) = self.globals.borrow().get(&full_name) {
2749 return Ok(val);
2750 }
2751
2752 if let Some(ref current_mod) = self.current_module {
2755 let crate_name = current_mod.split('·').next().unwrap_or(current_mod);
2757 let crate_qualified = format!("{}·{}", crate_name, full_name);
2758 if full_name.contains("execute") {
2759 crate::sigil_debug!("DEBUG eval_path: Looking for '{}' with crate_qualified='{}'", full_name, crate_qualified);
2760 }
2761 if let Some(val) = self.globals.borrow().get(&crate_qualified) {
2762 crate::sigil_debug!("DEBUG eval_path: FOUND '{}' via crate_qualified", crate_qualified);
2763 return Ok(val);
2764 }
2765 } else if full_name.contains("execute") {
2766 crate::sigil_debug!("DEBUG eval_path: current_module is None, can't resolve '{}'", full_name);
2767 }
2768
2769 if full_name.ends_with("·new") {
2771 crate::sigil_debug!("DEBUG eval_path: Looking for '{}' - NOT FOUND in globals", full_name);
2772 }
2773
2774 if path.segments.len() == 2 {
2778 let type_name = &path.segments[0].ident.name;
2779 let variant_name = &path.segments[1].ident.name;
2780
2781 if let Some(TypeDef::Enum(enum_def)) = self.types.get(type_name) {
2783 for variant in &enum_def.variants {
2784 if &variant.name.name == variant_name {
2785 if matches!(variant.fields, crate::ast::StructFields::Unit) {
2787 return Ok(Value::Variant {
2788 enum_name: type_name.clone(),
2789 variant_name: variant_name.clone(),
2790 fields: None,
2791 });
2792 }
2793 }
2794 }
2795 }
2796
2797 for (actual_type_name, type_def) in &self.types {
2799 if let TypeDef::Enum(enum_def) = type_def {
2800 for variant in &enum_def.variants {
2801 if &variant.name.name == variant_name {
2802 if matches!(variant.fields, crate::ast::StructFields::Unit) {
2803 return Ok(Value::Variant {
2804 enum_name: actual_type_name.clone(),
2805 variant_name: variant_name.clone(),
2806 fields: None,
2807 });
2808 }
2809 }
2810 }
2811 }
2812 }
2813 }
2814
2815 let last_name = &path.segments.last().unwrap().ident.name;
2817 if let Some(val) = self.environment.borrow().get(last_name) {
2818 if last_name == "new" {
2820 crate::sigil_debug!("DEBUG eval_path: FALLBACK from '{}' to '{}' - found in env", full_name, last_name);
2821 }
2822 return Ok(val);
2823 }
2824
2825 if path.segments.len() == 2 && path.segments[0].ident.name == "Self" {
2827 if let Some(ref self_type) = self.current_self_type {
2828 let qualified = format!("{}·{}", self_type, last_name);
2830 if let Some(val) = self.globals.borrow().get(&qualified) {
2831 return Ok(val);
2832 }
2833 }
2834 }
2835
2836 if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(&full_name).cloned() {
2838 if arity == 0 {
2841 return Ok(Value::Variant {
2842 enum_name,
2843 variant_name,
2844 fields: None,
2845 });
2846 }
2847 }
2851
2852 if path.segments.len() == 2 {
2854 let type_name = &path.segments[0].ident.name;
2855 let method_name = &path.segments[1].ident.name;
2856
2857 let is_method = method_name.chars().next().map_or(false, |c| c.is_lowercase())
2859 || method_name == "new"
2860 || method_name == "default"
2861 || method_name == "from"
2862 || method_name == "try_from"
2863 || method_name == "into"
2864 || method_name == "with_capacity"
2865 || method_name == "from_str";
2866
2867 if is_method {
2868 return Ok(Value::Struct {
2871 name: format!("__constructor__{}", type_name),
2872 fields: Rc::new(RefCell::new(HashMap::new())),
2873 });
2874 } else {
2875 return Ok(Value::Variant {
2877 enum_name: type_name.clone(),
2878 variant_name: method_name.clone(),
2879 fields: None,
2880 });
2881 }
2882 }
2883
2884 Err(RuntimeError::new(format!(
2885 "Undefined: {} (tried {} and {})",
2886 full_name, full_name, last_name
2887 )))
2888 }
2889 }
2890
2891 fn eval_binary(
2892 &mut self,
2893 left: &Expr,
2894 op: &BinOp,
2895 right: &Expr,
2896 ) -> Result<Value, RuntimeError> {
2897 let lhs = self.evaluate(left)?;
2898
2899 match op {
2901 BinOp::And => {
2902 if !self.is_truthy(&lhs) {
2903 return Ok(Value::Bool(false));
2904 }
2905 let rhs = self.evaluate(right)?;
2906 return Ok(Value::Bool(self.is_truthy(&rhs)));
2907 }
2908 BinOp::Or => {
2909 if self.is_truthy(&lhs) {
2910 return Ok(Value::Bool(true));
2911 }
2912 let rhs = self.evaluate(right)?;
2913 return Ok(Value::Bool(self.is_truthy(&rhs)));
2914 }
2915 _ => {}
2916 }
2917
2918 let rhs = self.evaluate(right)?;
2919
2920 let lhs = Self::unwrap_all(&lhs);
2922 let rhs = Self::unwrap_all(&rhs);
2923
2924 if matches!(op, BinOp::Mul) && (matches!(lhs, Value::Null) || matches!(rhs, Value::Null) || matches!(lhs, Value::Struct { .. }) || matches!(rhs, Value::Struct { .. })) {
2926 crate::sigil_debug!("DEBUG eval_binary Mul: left={:?}, right={:?}", left, right);
2927 crate::sigil_debug!("DEBUG eval_binary Mul: lhs={}, rhs={}", self.format_value(&lhs), self.format_value(&rhs));
2928 }
2929
2930 match (lhs, rhs) {
2931 (Value::Int(a), Value::Int(b)) => self.int_binary_op(a, b, op),
2932 (Value::Float(a), Value::Float(b)) => self.float_binary_op(a, b, op),
2933 (Value::Int(a), Value::Float(b)) => self.float_binary_op(a as f64, b, op),
2934 (Value::Float(a), Value::Int(b)) => self.float_binary_op(a, b as f64, op),
2935 (Value::String(a), Value::String(b)) => match op {
2936 BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
2937 BinOp::Eq => Ok(Value::Bool(*a == *b)),
2938 BinOp::Ne => Ok(Value::Bool(*a != *b)),
2939 _ => Err(RuntimeError::new("Invalid string operation")),
2940 },
2941 (Value::Bool(a), Value::Bool(b)) => match op {
2942 BinOp::Eq => Ok(Value::Bool(a == b)),
2943 BinOp::Ne => Ok(Value::Bool(a != b)),
2944 _ => Err(RuntimeError::new("Invalid boolean operation")),
2945 },
2946 (Value::Array(a), Value::Array(b)) => match op {
2947 BinOp::Concat => {
2948 let mut result = a.borrow().clone();
2949 result.extend(b.borrow().iter().cloned());
2950 Ok(Value::Array(Rc::new(RefCell::new(result))))
2951 }
2952 BinOp::Eq => Ok(Value::Bool(Rc::ptr_eq(&a, &b))),
2953 BinOp::Ne => Ok(Value::Bool(!Rc::ptr_eq(&a, &b))),
2954 _ => Err(RuntimeError::new("Invalid array operation")),
2955 },
2956 (Value::Null, Value::Null) => match op {
2958 BinOp::Eq => Ok(Value::Bool(true)),
2959 BinOp::Ne => Ok(Value::Bool(false)),
2960 _ => {
2961 crate::sigil_debug!("DEBUG: null op {:?} on (Null, Null)", op);
2962 Err(RuntimeError::new(format!("Invalid null operation: {:?} on (Null, Null)", op)))
2963 }
2964 },
2965 (Value::Null, other) | (other, Value::Null) => match op {
2966 BinOp::Eq => Ok(Value::Bool(false)),
2967 BinOp::Ne => Ok(Value::Bool(true)),
2968 _ => {
2969 crate::sigil_debug!("DEBUG: null op {:?} with other={}", op, self.format_value(&other));
2970 Err(RuntimeError::new(format!("Invalid null operation: {:?}", op)))
2971 }
2972 },
2973 (Value::Char(a), Value::Char(b)) => match op {
2975 BinOp::Eq => Ok(Value::Bool(a == b)),
2976 BinOp::Ne => Ok(Value::Bool(a != b)),
2977 BinOp::Lt => Ok(Value::Bool(a < b)),
2978 BinOp::Le => Ok(Value::Bool(a <= b)),
2979 BinOp::Gt => Ok(Value::Bool(a > b)),
2980 BinOp::Ge => Ok(Value::Bool(a >= b)),
2981 _ => Err(RuntimeError::new("Invalid char operation")),
2982 },
2983 (Value::String(a), Value::Char(b)) => match op {
2985 BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
2986 _ => Err(RuntimeError::new("Invalid string/char operation")),
2987 },
2988 (Value::Char(a), Value::String(b)) => match op {
2989 BinOp::Add | BinOp::Concat => Ok(Value::String(Rc::new(format!("{}{}", a, b)))),
2990 _ => Err(RuntimeError::new("Invalid char/string operation")),
2991 },
2992 (Value::Variant { enum_name: e1, variant_name: v1, fields: f1 },
2994 Value::Variant { enum_name: e2, variant_name: v2, fields: f2 }) => match op {
2995 BinOp::Eq => {
2996 let eq = e1 == e2 && v1 == v2 && match (f1, f2) {
2997 (None, None) => true,
2998 (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
2999 _ => false,
3000 };
3001 Ok(Value::Bool(eq))
3002 }
3003 BinOp::Ne => {
3004 let eq = e1 == e2 && v1 == v2 && match (f1, f2) {
3005 (None, None) => true,
3006 (Some(a), Some(b)) => Rc::ptr_eq(&a, &b),
3007 _ => false,
3008 };
3009 Ok(Value::Bool(!eq))
3010 }
3011 _ => Err(RuntimeError::new("Invalid variant operation")),
3012 },
3013 (Value::Struct { name: n1, fields: f1 }, Value::Struct { name: n2, fields: f2 }) => match op {
3015 BinOp::Eq => Ok(Value::Bool(n1 == n2 && Rc::ptr_eq(&f1, &f2))),
3016 BinOp::Ne => Ok(Value::Bool(n1 != n2 || !Rc::ptr_eq(&f1, &f2))),
3017 _ => Err(RuntimeError::new("Invalid struct operation")),
3018 },
3019 (l, r) => Err(RuntimeError::new(format!(
3020 "Type mismatch in binary operation: {:?} {:?} {:?}",
3021 l, op, r
3022 ))),
3023 }
3024 }
3025
3026 fn int_binary_op(&self, a: i64, b: i64, op: &BinOp) -> Result<Value, RuntimeError> {
3027 Ok(match op {
3028 BinOp::Add => Value::Int(a + b),
3029 BinOp::Sub => Value::Int(a - b),
3030 BinOp::Mul => Value::Int(a * b),
3031 BinOp::Div => {
3032 if b == 0 {
3033 return Err(RuntimeError::new("Division by zero"));
3034 }
3035 Value::Int(a / b)
3036 }
3037 BinOp::Rem => {
3038 if b == 0 {
3039 return Err(RuntimeError::new("Division by zero"));
3040 }
3041 Value::Int(a % b)
3042 }
3043 BinOp::Pow => Value::Int(a.pow(b as u32)),
3044 BinOp::Eq => Value::Bool(a == b),
3045 BinOp::Ne => Value::Bool(a != b),
3046 BinOp::Lt => Value::Bool(a < b),
3047 BinOp::Le => Value::Bool(a <= b),
3048 BinOp::Gt => Value::Bool(a > b),
3049 BinOp::Ge => Value::Bool(a >= b),
3050 BinOp::BitAnd => Value::Int(a & b),
3051 BinOp::BitOr => Value::Int(a | b),
3052 BinOp::BitXor => Value::Int(a ^ b),
3053 BinOp::Shl => Value::Int(a << b),
3054 BinOp::Shr => Value::Int(a >> b),
3055 _ => return Err(RuntimeError::new("Invalid integer operation")),
3056 })
3057 }
3058
3059 fn float_binary_op(&self, a: f64, b: f64, op: &BinOp) -> Result<Value, RuntimeError> {
3060 Ok(match op {
3061 BinOp::Add => Value::Float(a + b),
3062 BinOp::Sub => Value::Float(a - b),
3063 BinOp::Mul => Value::Float(a * b),
3064 BinOp::Div => Value::Float(a / b),
3065 BinOp::Rem => Value::Float(a % b),
3066 BinOp::Pow => Value::Float(a.powf(b)),
3067 BinOp::Eq => Value::Bool((a - b).abs() < f64::EPSILON),
3068 BinOp::Ne => Value::Bool((a - b).abs() >= f64::EPSILON),
3069 BinOp::Lt => Value::Bool(a < b),
3070 BinOp::Le => Value::Bool(a <= b),
3071 BinOp::Gt => Value::Bool(a > b),
3072 BinOp::Ge => Value::Bool(a >= b),
3073 _ => return Err(RuntimeError::new("Invalid float operation")),
3074 })
3075 }
3076
3077 fn eval_unary(&mut self, op: &UnaryOp, expr: &Expr) -> Result<Value, RuntimeError> {
3078 let val = self.evaluate(expr)?;
3079 match (op, &val) {
3080 (UnaryOp::Neg, Value::Int(n)) => Ok(Value::Int(-n)),
3081 (UnaryOp::Neg, Value::Float(n)) => Ok(Value::Float(-n)),
3082 (UnaryOp::Not, Value::Bool(b)) => Ok(Value::Bool(!b)),
3083 (UnaryOp::Not, Value::Int(n)) => Ok(Value::Int(!n)),
3084 (UnaryOp::Not, Value::Evidential { value, evidence }) => {
3086 match value.as_ref() {
3088 Value::Bool(b) => Ok(Value::Evidential {
3089 value: Box::new(Value::Bool(!b)),
3090 evidence: evidence.clone(),
3091 }),
3092 other => {
3093 let truthy = self.is_truthy(other);
3094 Ok(Value::Evidential {
3095 value: Box::new(Value::Bool(!truthy)),
3096 evidence: evidence.clone(),
3097 })
3098 }
3099 }
3100 }
3101 (UnaryOp::Not, Value::String(s)) => Ok(Value::Bool(s.is_empty())),
3103 (UnaryOp::Not, Value::Array(arr)) => Ok(Value::Bool(arr.borrow().is_empty())),
3105 (UnaryOp::Not, Value::Null) => Ok(Value::Bool(true)),
3107 (UnaryOp::Ref, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3108 (UnaryOp::RefMut, _) => Ok(Value::Ref(Rc::new(RefCell::new(val)))),
3109 (UnaryOp::Deref, Value::Ref(r)) => Ok(r.borrow().clone()),
3110 (UnaryOp::Deref, Value::Struct { name, fields }) if name == "Rc" => {
3111 let borrowed = fields.borrow();
3113 if let Some(value) = borrowed.get("_value") {
3114 Ok(value.clone())
3115 } else {
3116 Err(RuntimeError::new("Rc has no value"))
3117 }
3118 }
3119 (UnaryOp::Deref, other) => {
3120 let unwrapped = Self::unwrap_all(&val);
3122 if let Value::Ref(r) = &unwrapped {
3123 return Ok(r.borrow().clone());
3124 }
3125 Ok(unwrapped)
3128 }
3129 _ => Err(RuntimeError::new(format!("Invalid unary {:?} on {:?}", op, std::mem::discriminant(&val)))),
3130 }
3131 }
3132
3133 fn eval_call(&mut self, func_expr: &Expr, args: &[Expr]) -> Result<Value, RuntimeError> {
3134 if let Expr::Path(path) = func_expr {
3136 let qualified_name = path.segments.iter()
3137 .map(|s| s.ident.name.as_str())
3138 .collect::<Vec<_>>()
3139 .join("·");
3140
3141 if qualified_name == "Self" {
3143 if let Some(ref self_type) = self.current_self_type {
3144 let tuple_arity = if let Some(TypeDef::Struct(struct_def)) = self.types.get(self_type) {
3146 if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3147 Some((self_type.clone(), field_types.len()))
3148 } else {
3149 None
3150 }
3151 } else {
3152 None
3153 };
3154
3155 if let Some((type_name, expected_arity)) = tuple_arity {
3156 let arg_values: Vec<Value> = args
3158 .iter()
3159 .map(|a| self.evaluate(a))
3160 .collect::<Result<_, _>>()?;
3161
3162 if arg_values.len() != expected_arity {
3163 return Err(RuntimeError::new(format!(
3164 "Tuple struct {} expects {} fields, got {}",
3165 type_name, expected_arity, arg_values.len()
3166 )));
3167 }
3168
3169 let mut fields = HashMap::new();
3171 for (i, value) in arg_values.into_iter().enumerate() {
3172 fields.insert(i.to_string(), value);
3173 }
3174 return Ok(Value::Struct {
3175 name: type_name,
3176 fields: Rc::new(RefCell::new(fields)),
3177 });
3178 }
3179 }
3180 }
3181
3182 if path.segments.len() == 1 {
3184 let type_name = &path.segments[0].ident.name;
3185 let tuple_arity = if let Some(TypeDef::Struct(struct_def)) = self.types.get(type_name) {
3187 if let crate::ast::StructFields::Tuple(field_types) = &struct_def.fields {
3188 Some((type_name.clone(), field_types.len()))
3189 } else {
3190 None
3191 }
3192 } else {
3193 None
3194 };
3195
3196 if let Some((struct_name, expected_arity)) = tuple_arity {
3197 let arg_values: Vec<Value> = args
3198 .iter()
3199 .map(|a| self.evaluate(a))
3200 .collect::<Result<_, _>>()?;
3201
3202 if arg_values.len() != expected_arity {
3203 return Err(RuntimeError::new(format!(
3204 "Tuple struct {} expects {} fields, got {}",
3205 struct_name, expected_arity, arg_values.len()
3206 )));
3207 }
3208
3209 let mut fields = HashMap::new();
3210 for (i, value) in arg_values.into_iter().enumerate() {
3211 fields.insert(i.to_string(), value);
3212 }
3213 return Ok(Value::Struct {
3214 name: struct_name,
3215 fields: Rc::new(RefCell::new(fields)),
3216 });
3217 }
3218 }
3219
3220 if qualified_name == "Default·default" && args.is_empty() {
3223 if let Some(type_name) = self.current_self_type.clone() {
3224 let default_fn_name = format!("{}·default", type_name);
3226 crate::sigil_debug!("DEBUG Default::default() looking for '{}', self_type='{}'", default_fn_name, type_name);
3227 let func_clone = self.globals.borrow().get(&default_fn_name).map(|v| v.clone());
3228 if let Some(Value::Function(f)) = func_clone {
3229 crate::sigil_debug!("DEBUG Found function '{}', calling it", default_fn_name);
3230 crate::sigil_debug!("DEBUG current_self_type before call: {:?}", self.current_self_type);
3231 let result = self.call_function(&f, vec![]);
3233 crate::sigil_debug!("DEBUG Default call result: {:?}", result.as_ref().map(|v| self.format_value(v)).unwrap_or_else(|e| format!("ERR: {:?}", e)));
3234 return result;
3235 }
3236 if let Some(struct_def) = self.default_structs.get(&type_name).cloned() {
3238 let mut fields = HashMap::new();
3239 if let StructFields::Named(field_defs) = &struct_def.fields {
3240 for field in field_defs {
3241 let default_val = if let Some(default_expr) = &field.default {
3242 self.evaluate(default_expr)?
3243 } else {
3244 Value::Null
3245 };
3246 fields.insert(field.name.name.clone(), default_val);
3247 }
3248 }
3249 return Ok(Value::Struct {
3250 name: type_name,
3251 fields: Rc::new(RefCell::new(fields)),
3252 });
3253 }
3254 }
3255 }
3256
3257 if qualified_name.ends_with("·default") && args.is_empty() {
3259 let type_name = qualified_name.strip_suffix("·default").unwrap();
3260 let default_fn_name = format!("{}·default", type_name);
3262 let func_clone = self.globals.borrow().get(&default_fn_name).map(|v| v.clone());
3263 if let Some(Value::Function(f)) = func_clone {
3264 return self.call_function(&f, vec![]);
3266 }
3267 if let Some(struct_def) = self.default_structs.get(type_name).cloned() {
3269 let mut fields = HashMap::new();
3270 if let StructFields::Named(field_defs) = &struct_def.fields {
3271 for field in field_defs {
3272 let default_val = if let Some(default_expr) = &field.default {
3273 self.evaluate(default_expr)?
3274 } else {
3275 Value::Null
3277 };
3278 fields.insert(field.name.name.clone(), default_val);
3279 }
3280 }
3281 return Ok(Value::Struct {
3282 name: type_name.to_string(),
3283 fields: Rc::new(RefCell::new(fields)),
3284 });
3285 }
3286 }
3287
3288 if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(&qualified_name).cloned() {
3290 let arg_values: Vec<Value> = args
3291 .iter()
3292 .map(|a| self.evaluate(a))
3293 .collect::<Result<_, _>>()?;
3294
3295 if arg_values.len() != arity {
3296 return Err(RuntimeError::new(format!(
3297 "{} expects {} arguments, got {}",
3298 qualified_name, arity, arg_values.len()
3299 )));
3300 }
3301
3302 if arity == 0 {
3303 return Ok(Value::Variant {
3304 enum_name,
3305 variant_name,
3306 fields: None,
3307 });
3308 } else {
3309 if enum_name == "Item" {
3310 crate::sigil_debug!("DEBUG creating Item::{} variant with {} fields", variant_name, arg_values.len());
3311 }
3312 return Ok(Value::Variant {
3313 enum_name,
3314 variant_name,
3315 fields: Some(Rc::new(arg_values)),
3316 });
3317 }
3318 }
3319
3320 let segments: Vec<&str> = path.segments.iter().map(|s| s.ident.name.as_str()).collect();
3322 match segments.as_slice() {
3323 ["Map", "new"] | ["HashMap", "new"] => {
3324 return Ok(Value::Struct {
3326 name: "Map".to_string(),
3327 fields: Rc::new(RefCell::new(HashMap::new())),
3328 });
3329 }
3330 ["String", "new"] => {
3331 return Ok(Value::String(Rc::new(String::new())));
3332 }
3333 ["Vec", "new"] | ["Array", "new"] => {
3334 return Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))));
3335 }
3336 ["Box", "new"] => {
3337 if args.len() == 1 {
3339 return self.evaluate(&args[0]);
3340 }
3341 return Err(RuntimeError::new("Box::new expects 1 argument"));
3342 }
3343 ["char", "from_u32"] => {
3344 if args.len() == 1 {
3346 let arg = self.evaluate(&args[0])?;
3347 let code = match arg {
3348 Value::Int(i) => i as u32,
3349 _ => return Err(RuntimeError::new("char::from_u32 expects u32")),
3350 };
3351 if let Some(c) = char::from_u32(code) {
3352 return Ok(Value::Variant {
3354 enum_name: "Option".to_string(),
3355 variant_name: "Some".to_string(),
3356 fields: Some(Rc::new(vec![Value::Char(c)])),
3357 });
3358 } else {
3359 return Ok(Value::Variant {
3361 enum_name: "Option".to_string(),
3362 variant_name: "None".to_string(),
3363 fields: None,
3364 });
3365 }
3366 }
3367 return Err(RuntimeError::new("char::from_u32 expects 1 argument"));
3368 }
3369 ["parking_lot", "Mutex", "new"] | ["std", "sync", "Mutex", "new"] | ["Mutex", "new"] => {
3371 if args.len() == 1 {
3372 let inner = self.evaluate(&args[0])?;
3373 return Ok(Value::Struct {
3374 name: "Mutex".to_string(),
3375 fields: Rc::new(RefCell::new(HashMap::from([
3376 ("__inner__".to_string(), inner),
3377 ]))),
3378 });
3379 }
3380 return Err(RuntimeError::new("Mutex::new expects 1 argument"));
3381 }
3382 ["parking_lot", "RwLock", "new"] | ["std", "sync", "RwLock", "new"] | ["RwLock", "new"] => {
3384 if args.len() == 1 {
3385 let inner = self.evaluate(&args[0])?;
3386 return Ok(Value::Struct {
3387 name: "RwLock".to_string(),
3388 fields: Rc::new(RefCell::new(HashMap::from([
3389 ("__inner__".to_string(), inner),
3390 ]))),
3391 });
3392 }
3393 return Err(RuntimeError::new("RwLock::new expects 1 argument"));
3394 }
3395 ["std", "sync", "Arc", "new"] | ["Arc", "new"] => {
3397 if args.len() == 1 {
3398 let inner = self.evaluate(&args[0])?;
3399 return Ok(Value::Ref(Rc::new(RefCell::new(inner))));
3400 }
3401 return Err(RuntimeError::new("Arc::new expects 1 argument"));
3402 }
3403 ["std", "sync", "atomic", "AtomicU64", "new"] | ["AtomicU64", "new"] => {
3405 if args.len() == 1 {
3406 let inner = self.evaluate(&args[0])?;
3407 return Ok(Value::Struct {
3408 name: "AtomicU64".to_string(),
3409 fields: Rc::new(RefCell::new(HashMap::from([
3410 ("__value__".to_string(), inner),
3411 ]))),
3412 });
3413 }
3414 return Err(RuntimeError::new("AtomicU64::new expects 1 argument"));
3415 }
3416 ["std", "sync", "atomic", "AtomicUsize", "new"] | ["AtomicUsize", "new"] => {
3417 if args.len() == 1 {
3418 let inner = self.evaluate(&args[0])?;
3419 return Ok(Value::Struct {
3420 name: "AtomicUsize".to_string(),
3421 fields: Rc::new(RefCell::new(HashMap::from([
3422 ("__value__".to_string(), inner),
3423 ]))),
3424 });
3425 }
3426 return Err(RuntimeError::new("AtomicUsize::new expects 1 argument"));
3427 }
3428 ["std", "sync", "atomic", "AtomicBool", "new"] | ["AtomicBool", "new"] => {
3429 if args.len() == 1 {
3430 let inner = self.evaluate(&args[0])?;
3431 return Ok(Value::Struct {
3432 name: "AtomicBool".to_string(),
3433 fields: Rc::new(RefCell::new(HashMap::from([
3434 ("__value__".to_string(), inner),
3435 ]))),
3436 });
3437 }
3438 return Err(RuntimeError::new("AtomicBool::new expects 1 argument"));
3439 }
3440 _ => {}
3441 }
3442 }
3443
3444 let type_name_for_self = if let Expr::Path(path) = func_expr {
3446 if path.segments.len() >= 2 {
3447 let first = &path.segments[0].ident.name;
3449 if self.types.contains_key(first) {
3451 Some(first.clone())
3452 } else {
3453 None
3454 }
3455 } else {
3456 None
3457 }
3458 } else {
3459 None
3460 };
3461
3462 let func = self.evaluate(func_expr)?;
3463
3464 let mut mut_ref_sync: Vec<(String, Rc<RefCell<Value>>)> = Vec::new();
3467
3468 let mut arg_values: Vec<Value> = Vec::new();
3469 for arg in args.iter() {
3470 let val = self.evaluate(arg)?;
3471
3472 if let Expr::Unary { op: crate::ast::UnaryOp::RefMut, expr } = arg {
3474 if let Expr::Path(path) = expr.as_ref() {
3475 if path.segments.len() == 1 {
3476 let var_name = path.segments[0].ident.name.clone();
3477 if let Value::Ref(r) = &val {
3478 mut_ref_sync.push((var_name, r.clone()));
3479 }
3480 }
3481 }
3482 }
3483
3484 arg_values.push(val);
3485 }
3486
3487 let old_self_type = self.current_self_type.clone();
3490 if let Some(type_name) = type_name_for_self {
3491 self.current_self_type = Some(type_name);
3492 }
3493
3494 let result = match func {
3495 Value::Function(f) => self.call_function(&f, arg_values),
3496 Value::BuiltIn(b) => self.call_builtin(&b, arg_values),
3497 Value::Struct { ref name, .. } if name.starts_with("__constructor__") => {
3499 let actual_type = name.strip_prefix("__constructor__").unwrap();
3500 Ok(Value::Struct {
3502 name: actual_type.to_string(),
3503 fields: Rc::new(RefCell::new(HashMap::new())),
3504 })
3505 }
3506 _ => {
3507 crate::sigil_debug!("DEBUG Cannot call non-function: {:?}, expr: {:?}", func, func_expr);
3508 Err(RuntimeError::new("Cannot call non-function"))
3509 }
3510 };
3511
3512 for (var_name, ref_val) in mut_ref_sync {
3515 let current_value = ref_val.borrow().clone();
3516 let _ = self.environment.borrow_mut().set(&var_name, current_value);
3517 }
3518
3519 self.current_self_type = old_self_type;
3521
3522 result
3523 }
3524
3525 pub fn call_function(
3526 &mut self,
3527 func: &Function,
3528 args: Vec<Value>,
3529 ) -> Result<Value, RuntimeError> {
3530 if func.name.as_ref().map_or(false, |n| n.contains("read_source") || n.contains("parse_file") || n.contains("load_from_file") || n.contains("read_to_string")) {
3532 crate::sigil_debug!("DEBUG call_function: name={:?}, params={:?}", func.name, func.params);
3533 for (i, arg) in args.iter().enumerate() {
3534 crate::sigil_debug!(" arg[{}] = {:?}", i, arg);
3535 }
3536 }
3537 if args.len() != func.params.len() {
3538 return Err(RuntimeError::new(format!(
3539 "Expected {} arguments, got {} (func={:?}, params={:?})",
3540 func.params.len(),
3541 args.len(),
3542 func.name,
3543 func.params
3544 )));
3545 }
3546
3547 if func.params.iter().any(|p| p == "name") {
3549 for arg in &args {
3550 let unwrapped = Self::unwrap_all(arg);
3551 if let Value::String(s) = &unwrapped {
3552 if s.len() <= 10 {
3553 crate::sigil_debug!("DEBUG call_function(name='{}')", s);
3554 }
3555 }
3556 }
3557 }
3558
3559 let env = Rc::new(RefCell::new(Environment::with_parent(func.closure.clone())));
3561
3562 for (param, value) in func.params.iter().zip(args) {
3564 if param == "path" {
3566 crate::sigil_debug!("DEBUG call_function func={:?} binding param 'path' = {:?}", func.name, value);
3567 }
3568 env.borrow_mut().define(param.clone(), value);
3569 }
3570
3571 let prev_env = self.environment.clone();
3573 self.environment = env;
3574
3575 let result = match self.evaluate(&func.body) {
3576 Ok(val) => Ok(val),
3577 Err(e) if e.message == "return" => {
3578 Ok(self.return_value.take().unwrap_or(Value::Null))
3580 }
3581 Err(e) => Err(e),
3582 };
3583
3584 self.environment = prev_env;
3585 result
3586 }
3587
3588 fn call_builtin(
3589 &mut self,
3590 builtin: &BuiltInFn,
3591 args: Vec<Value>,
3592 ) -> Result<Value, RuntimeError> {
3593 if let Some(arity) = builtin.arity {
3594 if args.len() != arity {
3595 return Err(RuntimeError::new(format!(
3596 "{}() expects {} arguments, got {}",
3597 builtin.name,
3598 arity,
3599 args.len()
3600 )));
3601 }
3602 }
3603 (builtin.func)(self, args)
3604 }
3605
3606 pub fn await_value(&mut self, value: Value) -> Result<Value, RuntimeError> {
3608 match value {
3609 Value::Future(fut) => {
3610 let mut fut_inner = fut.borrow_mut();
3611 self.poll_future(&mut fut_inner)
3612 }
3613 other => Ok(other),
3615 }
3616 }
3617
3618 fn unwrap_result_or_option(
3622 &self,
3623 value: Value,
3624 propagate_errors: bool,
3625 panic_on_error: bool,
3626 ) -> Result<Value, RuntimeError> {
3627 let (is_ok_or_some, is_err, is_none, inner_val) = match &value {
3629 Value::Struct { name, fields } if name == "Ok" || name == "Some" => {
3630 let borrowed = fields.borrow();
3631 let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
3632 (true, false, false, inner)
3633 }
3634 Value::Struct { name, fields } if name == "Err" => {
3635 let borrowed = fields.borrow();
3636 let inner = borrowed.get("0").or(borrowed.get("value")).cloned();
3637 (false, true, false, inner)
3638 }
3639 Value::Struct { name, .. } if name == "None" => (false, false, true, None),
3640 _ => return Ok(value),
3641 };
3642
3643 if is_ok_or_some {
3644 Ok(inner_val.unwrap_or(value))
3645 } else if is_err {
3646 let msg = format!("Error: {:?}", inner_val);
3647 if panic_on_error {
3648 panic!("{}", msg);
3649 } else if propagate_errors {
3650 Err(RuntimeError::new(msg))
3651 } else {
3652 Ok(inner_val.unwrap_or(value))
3653 }
3654 } else if is_none {
3655 if panic_on_error {
3656 panic!("Unwrapped None");
3657 } else if propagate_errors {
3658 Err(RuntimeError::new("Unwrapped None".to_string()))
3659 } else {
3660 Ok(value)
3661 }
3662 } else {
3663 Ok(value)
3664 }
3665 }
3666
3667 fn poll_future(&mut self, fut: &mut FutureInner) -> Result<Value, RuntimeError> {
3669 match &fut.state {
3671 FutureState::Ready(v) => return Ok((**v).clone()),
3672 FutureState::Failed(e) => return Err(RuntimeError::new(e.clone())),
3673 _ => {}
3674 }
3675
3676 if let Some(complete_at) = fut.complete_at {
3678 if std::time::Instant::now() >= complete_at {
3679 fut.state = FutureState::Ready(Box::new(Value::Null));
3680 return Ok(Value::Null);
3681 } else {
3682 let remaining = complete_at - std::time::Instant::now();
3684 std::thread::sleep(remaining);
3685 fut.state = FutureState::Ready(Box::new(Value::Null));
3686 return Ok(Value::Null);
3687 }
3688 }
3689
3690 if let Some(computation) = fut.computation.take() {
3692 fut.state = FutureState::Running;
3693
3694 match computation {
3695 FutureComputation::Immediate(v) => {
3696 fut.state = FutureState::Ready(v.clone());
3697 Ok((*v).clone())
3698 }
3699 FutureComputation::Timer(duration) => {
3700 std::thread::sleep(duration);
3702 fut.state = FutureState::Ready(Box::new(Value::Null));
3703 Ok(Value::Null)
3704 }
3705 FutureComputation::Lazy { func, args } => {
3706 match self.call_function(&func, args) {
3708 Ok(result) => {
3709 fut.state = FutureState::Ready(Box::new(result.clone()));
3710 Ok(result)
3711 }
3712 Err(e) => {
3713 fut.state = FutureState::Failed(e.message.clone());
3714 Err(e)
3715 }
3716 }
3717 }
3718 FutureComputation::Join(futures) => {
3719 let mut results = Vec::new();
3721 for f in futures {
3722 let mut f_inner = f.borrow_mut();
3723 results.push(self.poll_future(&mut f_inner)?);
3724 }
3725 let result = Value::Array(Rc::new(RefCell::new(results)));
3726 fut.state = FutureState::Ready(Box::new(result.clone()));
3727 Ok(result)
3728 }
3729 FutureComputation::Race(futures) => {
3730 for f in futures {
3733 let f_inner = f.borrow_mut();
3734 if matches!(f_inner.state, FutureState::Ready(_)) {
3735 if let FutureState::Ready(v) = &f_inner.state {
3736 fut.state = FutureState::Ready(v.clone());
3737 return Ok((**v).clone());
3738 }
3739 }
3740 }
3741 Err(RuntimeError::new("No futures ready in race"))
3743 }
3744 }
3745 } else {
3746 match &fut.state {
3748 FutureState::Ready(v) => Ok((**v).clone()),
3749 FutureState::Failed(e) => Err(RuntimeError::new(e.clone())),
3750 _ => Err(RuntimeError::new("Future has no computation")),
3751 }
3752 }
3753 }
3754
3755 pub fn make_future_immediate(&self, value: Value) -> Value {
3757 Value::Future(Rc::new(RefCell::new(FutureInner {
3758 state: FutureState::Ready(Box::new(value)),
3759 computation: None,
3760 complete_at: None,
3761 })))
3762 }
3763
3764 pub fn make_future_lazy(&self, func: Rc<Function>, args: Vec<Value>) -> Value {
3766 Value::Future(Rc::new(RefCell::new(FutureInner {
3767 state: FutureState::Pending,
3768 computation: Some(FutureComputation::Lazy { func, args }),
3769 complete_at: None,
3770 })))
3771 }
3772
3773 pub fn make_future_timer(&self, duration: std::time::Duration) -> Value {
3775 Value::Future(Rc::new(RefCell::new(FutureInner {
3776 state: FutureState::Pending,
3777 computation: Some(FutureComputation::Timer(duration)),
3778 complete_at: Some(std::time::Instant::now() + duration),
3779 })))
3780 }
3781
3782 fn eval_array(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
3783 let values: Vec<Value> = elements
3784 .iter()
3785 .map(|e| self.evaluate(e))
3786 .collect::<Result<_, _>>()?;
3787 Ok(Value::Array(Rc::new(RefCell::new(values))))
3788 }
3789
3790 fn eval_tuple(&mut self, elements: &[Expr]) -> Result<Value, RuntimeError> {
3791 let values: Vec<Value> = elements
3792 .iter()
3793 .map(|e| self.evaluate(e))
3794 .collect::<Result<_, _>>()?;
3795 Ok(Value::Tuple(Rc::new(values)))
3796 }
3797
3798 fn eval_block(&mut self, block: &Block) -> Result<Value, RuntimeError> {
3799 let env = Rc::new(RefCell::new(Environment::with_parent(
3800 self.environment.clone(),
3801 )));
3802 let prev_env = self.environment.clone();
3803 self.environment = env;
3804
3805 let mut result = Value::Null;
3806
3807 for stmt in &block.stmts {
3808 match stmt {
3809 Stmt::Let { pattern, init, .. } => {
3810 let value = match init {
3811 Some(expr) => self.evaluate(expr)?,
3812 None => Value::Null,
3813 };
3814 self.bind_pattern(pattern, value)?;
3815 }
3816 Stmt::LetElse { pattern, init, else_branch, .. } => {
3817 let value = self.evaluate(init)?;
3818 if self.bind_pattern(pattern, value.clone()).is_err() {
3820 return self.evaluate(else_branch);
3821 }
3822 }
3823 Stmt::Expr(expr) => {
3824 result = self.evaluate(expr)?;
3825 }
3826 Stmt::Semi(expr) => {
3827 self.evaluate(expr)?;
3828 result = Value::Null;
3829 }
3830 Stmt::Item(item) => {
3831 self.execute_item(item)?;
3832 }
3833 }
3834 }
3835
3836 if let Some(expr) = &block.expr {
3837 result = self.evaluate(expr)?;
3838 }
3839
3840 let values_to_drop: Vec<(String, Value)> = self.environment
3843 .borrow()
3844 .values
3845 .iter()
3846 .filter_map(|(name, value)| {
3847 if let Value::Struct { name: struct_name, .. } = value {
3848 if self.drop_types.contains(struct_name) {
3849 return Some((name.clone(), value.clone()));
3850 }
3851 }
3852 None
3853 })
3854 .collect();
3855
3856 for (_var_name, value) in values_to_drop {
3858 if let Value::Struct { name: struct_name, .. } = &value {
3859 let drop_fn_name = format!("{}·drop", struct_name);
3860 let drop_fn = self.globals.borrow().get(&drop_fn_name).map(|v| v.clone());
3862 if let Some(Value::Function(f)) = drop_fn {
3863 let _ = self.call_function(&f, vec![value.clone()]);
3865 }
3866 }
3867 }
3868
3869 self.environment = prev_env;
3870 Ok(result)
3871 }
3872
3873 fn bind_pattern(&mut self, pattern: &Pattern, value: Value) -> Result<(), RuntimeError> {
3874 match pattern {
3875 Pattern::Ident { name, .. } => {
3876 if name.name != "_" {
3878 if name.name == "path" {
3880 crate::sigil_debug!("DEBUG bind_pattern: binding 'path' = {:?}", value);
3881 }
3882 self.environment
3883 .borrow_mut()
3884 .define(name.name.clone(), value);
3885 }
3886 Ok(())
3887 }
3888 Pattern::Tuple(patterns) => {
3889 let unwrapped = Self::unwrap_all(&value);
3891 crate::sigil_debug!("DEBUG bind_pattern Tuple: patterns.len()={}, value type={:?}",
3892 patterns.len(), std::mem::discriminant(&unwrapped));
3893 match unwrapped {
3894 Value::Tuple(values) => {
3895 if patterns.len() != values.len() {
3896 return Err(RuntimeError::new("Tuple pattern size mismatch"));
3897 }
3898 for (i, (p, v)) in patterns.iter().zip(values.iter()).enumerate() {
3899 crate::sigil_debug!("DEBUG binding tuple element {}: {:?} = {}", i, p, self.format_value(v));
3900 self.bind_pattern(p, v.clone())?;
3901 }
3902 Ok(())
3903 }
3904 Value::Null => {
3905 Ok(())
3907 }
3908 Value::Array(arr) if arr.borrow().len() == patterns.len() => {
3909 let vals = arr.borrow();
3911 for (p, v) in patterns.iter().zip(vals.iter()) {
3912 self.bind_pattern(p, v.clone())?;
3913 }
3914 Ok(())
3915 }
3916 _ => Err(RuntimeError::new("Expected tuple"))
3917 }
3918 }
3919 Pattern::Wildcard => Ok(()),
3920 Pattern::Struct { path, fields, .. } => {
3921 let unwrapped = Self::unwrap_all(&value);
3923 match &unwrapped {
3925 Value::Struct { fields: struct_fields, .. } => {
3926 for field_pat in fields {
3927 let field_name = &field_pat.name.name;
3928 let field_val = struct_fields.borrow().get(field_name).cloned().unwrap_or(Value::Null);
3930 if let Some(pat) = &field_pat.pattern {
3931 self.bind_pattern(pat, field_val)?;
3932 } else {
3933 self.environment.borrow_mut().define(field_name.clone(), field_val);
3935 }
3936 }
3937 Ok(())
3938 }
3939 Value::Variant { enum_name, variant_name, fields: variant_fields } => {
3940 let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
3942 if pattern_variant == variant_name || path.segments.iter().any(|s| s.ident.name == *variant_name) {
3943 if let Some(inner_fields) = variant_fields {
3946 if inner_fields.len() == 1 {
3947 if let Value::Struct { fields: inner_struct, .. } = &inner_fields[0] {
3949 for field_pat in fields {
3950 let field_name = &field_pat.name.name;
3951 let field_val = inner_struct.borrow().get(field_name).cloned().unwrap_or(Value::Null);
3953 if let Some(pat) = &field_pat.pattern {
3954 self.bind_pattern(pat, field_val)?;
3955 } else {
3956 self.environment.borrow_mut().define(field_name.clone(), field_val);
3957 }
3958 }
3959 return Ok(());
3960 }
3961 }
3962 for field_pat in fields {
3965 let field_name = &field_pat.name.name;
3966 let field_val = inner_fields.iter().find_map(|f| {
3970 if let Value::Struct { fields: fs, .. } = f {
3971 fs.borrow().get(field_name).cloned()
3972 } else {
3973 None
3974 }
3975 });
3976 if let Some(val) = field_val {
3977 if let Some(pat) = &field_pat.pattern {
3978 self.bind_pattern(pat, val)?;
3979 } else {
3980 self.environment.borrow_mut().define(field_name.clone(), val);
3981 }
3982 }
3983 }
3984 }
3985 Ok(())
3986 } else {
3987 crate::sigil_debug!("DEBUG variant name mismatch: pattern={}, actual={}", pattern_variant, variant_name);
3988 Err(RuntimeError::new(format!(
3989 "Variant name mismatch: expected {} but got {}::{}",
3990 pattern_variant, enum_name, variant_name
3991 )))
3992 }
3993 }
3994 _ => {
3995 crate::sigil_debug!("DEBUG struct pattern bind: expected struct/variant but got {:?}", std::mem::discriminant(&unwrapped));
3996 Err(RuntimeError::new("Expected struct or variant value for struct pattern"))
3997 }
3998 }
3999 }
4000 Pattern::Path(_path) => {
4001 Ok(())
4004 }
4005 Pattern::TupleStruct { path, fields } => {
4006 let unwrapped = Self::unwrap_all(&value);
4009 let path_str = path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::");
4010 crate::sigil_debug!("DEBUG bind_pattern TupleStruct: path={}, value type={:?}",
4011 path_str,
4012 std::mem::discriminant(&unwrapped));
4013 if let Value::Variant { variant_name, fields: variant_fields, enum_name } = &unwrapped {
4014 crate::sigil_debug!("DEBUG Variant {}::{}, fields={}", enum_name, variant_name,
4015 if variant_fields.is_some() { format!("Some(len={})", variant_fields.as_ref().unwrap().len()) } else { "None".to_string() });
4016 let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4017 if pattern_variant == variant_name {
4018 if let Some(inner_fields) = variant_fields {
4020 if fields.len() == 1 && inner_fields.len() == 1 {
4021 self.bind_pattern(&fields[0], inner_fields[0].clone())?;
4022 } else {
4023 for (pat, val) in fields.iter().zip(inner_fields.iter()) {
4024 self.bind_pattern(pat, val.clone())?;
4025 }
4026 }
4027 } else if !fields.is_empty() {
4028 crate::sigil_debug!("DEBUG TupleStruct: pattern expects {} fields but variant has none", fields.len());
4030 }
4031 }
4032 Ok(())
4033 } else {
4034 if let Value::Tuple(tuple_vals) = &value {
4036 for (pat, val) in fields.iter().zip(tuple_vals.iter()) {
4037 self.bind_pattern(pat, val.clone())?;
4038 }
4039 Ok(())
4040 } else {
4041 Err(RuntimeError::new("Expected variant or tuple for tuple struct pattern"))
4042 }
4043 }
4044 }
4045 Pattern::Literal(_) => {
4046 Ok(())
4048 }
4049 Pattern::Rest => {
4050 Ok(())
4052 }
4053 Pattern::Range { .. } => {
4054 Ok(())
4056 }
4057 Pattern::Or(patterns) => {
4058 for p in patterns {
4060 if self.pattern_matches(p, &value)? {
4061 return self.bind_pattern(p, value.clone());
4062 }
4063 }
4064 Err(RuntimeError::new("Or pattern didn't match any alternative"))
4066 }
4067 _ => Err(RuntimeError::new(format!("Unsupported pattern: {:?}", pattern))),
4068 }
4069 }
4070
4071 fn eval_if(
4072 &mut self,
4073 condition: &Expr,
4074 then_branch: &Block,
4075 else_branch: &Option<Box<Expr>>,
4076 ) -> Result<Value, RuntimeError> {
4077 let cond = self.evaluate(condition)?;
4078 if self.is_truthy(&cond) {
4079 self.eval_block(then_branch)
4080 } else if let Some(else_expr) = else_branch {
4081 self.evaluate(else_expr)
4082 } else {
4083 Ok(Value::Null)
4084 }
4085 }
4086
4087 fn eval_match(&mut self, expr: &Expr, arms: &[MatchArm]) -> Result<Value, RuntimeError> {
4088 let value = self.evaluate(expr)?;
4089
4090 let unwrapped = Self::unwrap_all(&value);
4092 if let Value::String(s) = &unwrapped {
4093 if s.len() <= 10 {
4094 crate::sigil_debug!("DEBUG eval_match: string='{}', arms={}", s, arms.len());
4095 }
4096 }
4097
4098 for arm in arms {
4099 if self.pattern_matches(&arm.pattern, &value)? {
4100 let env = Rc::new(RefCell::new(Environment::with_parent(
4102 self.environment.clone(),
4103 )));
4104 let prev_env = self.environment.clone();
4105 self.environment = env;
4106
4107 if let Err(e) = self.bind_pattern(&arm.pattern, value.clone()) {
4110 self.environment = prev_env;
4111 return Err(e);
4112 }
4113
4114 if let Some(guard) = &arm.guard {
4116 let guard_val = self.evaluate(guard)?;
4117 if !self.is_truthy(&guard_val) {
4118 self.environment = prev_env;
4120 continue;
4121 }
4122 }
4123
4124 let result = self.evaluate(&arm.body);
4126
4127 self.environment = prev_env;
4128 return result;
4129 }
4130 }
4131
4132 crate::sigil_debug!("DEBUG No matching pattern for value: {} (discriminant: {:?})",
4134 self.format_value(&value), std::mem::discriminant(&value));
4135 for (i, arm) in arms.iter().enumerate() {
4137 crate::sigil_debug!("DEBUG arm {}: {:?}", i, arm.pattern);
4138 }
4139 Err(RuntimeError::new(format!("No matching pattern for {}", self.format_value(&value))))
4140 }
4141
4142 fn pattern_matches(&mut self, pattern: &Pattern, value: &Value) -> Result<bool, RuntimeError> {
4143 let value = Self::unwrap_all(value);
4145
4146 if let Value::String(s) = &value {
4148 if **s == "fn" {
4149 crate::sigil_debug!("DEBUG pattern_matches: value='fn', pattern={:?}", pattern);
4150 }
4151 }
4152
4153 match (pattern, &value) {
4154 (Pattern::Wildcard, _) => Ok(true),
4155 (Pattern::Ident { evidentiality: Some(Evidentiality::Uncertain), name, .. }, val) => {
4157 let matches = match val {
4159 Value::Null => false,
4160 Value::Variant { variant_name, .. } if variant_name == "None" => false,
4161 _ => true,
4162 };
4163 crate::sigil_debug!("DEBUG pattern_matches ?{}: value={} => {}", name.name, self.format_value(val), matches);
4164 Ok(matches)
4165 }
4166 (Pattern::Ident { .. }, _) => Ok(true),
4167 (Pattern::Literal(lit), val) => {
4168 let lit_val = self.eval_literal(lit)?;
4169 let result = self.values_equal(&lit_val, val);
4170 if matches!(lit, Literal::Null) || matches!(val, Value::Null) {
4172 crate::sigil_debug!("DEBUG literal pattern: lit={:?}, lit_val={}, val={}, result={}",
4173 lit, self.format_value(&lit_val), self.format_value(val), result);
4174 }
4175 Ok(result)
4176 }
4177 (Pattern::Tuple(patterns), Value::Tuple(values)) => {
4178 if patterns.len() != values.len() {
4179 return Ok(false);
4180 }
4181 for (p, v) in patterns.iter().zip(values.iter()) {
4182 if !self.pattern_matches(p, v)? {
4183 return Ok(false);
4184 }
4185 }
4186 Ok(true)
4187 }
4188 (Pattern::Path(path), Value::Variant { variant_name, fields, .. }) => {
4190 let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4191 Ok(pattern_variant == variant_name && fields.is_none())
4193 }
4194 (Pattern::TupleStruct { path, fields: pat_fields }, Value::Variant { variant_name, fields, .. }) => {
4196 let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4197 if pattern_variant != variant_name {
4198 return Ok(false);
4199 }
4200 if let Some(variant_fields) = fields {
4202 if pat_fields.len() != variant_fields.len() {
4203 return Ok(false);
4204 }
4205 for (p, v) in pat_fields.iter().zip(variant_fields.iter()) {
4206 if !self.pattern_matches(p, v)? {
4207 return Ok(false);
4208 }
4209 }
4210 Ok(true)
4211 } else {
4212 Ok(pat_fields.is_empty())
4214 }
4215 }
4216 (Pattern::Struct { path, fields: pat_fields, rest }, Value::Struct { name: struct_name, fields: struct_fields }) => {
4218 let pattern_name = path.segments.iter().map(|s| s.ident.name.as_str()).collect::<Vec<_>>().join("::");
4219 if pattern_name != *struct_name {
4220 return Ok(false);
4221 }
4222 let borrowed = struct_fields.borrow();
4224 for field_pat in pat_fields {
4225 let field_name = &field_pat.name.name;
4226 if let Some(field_val) = borrowed.get(field_name) {
4227 if let Some(sub_pat) = &field_pat.pattern {
4228 if !self.pattern_matches(sub_pat, field_val)? {
4229 return Ok(false);
4230 }
4231 }
4232 } else if !rest {
4234 return Ok(false);
4236 }
4237 }
4238 Ok(true)
4239 }
4240 (Pattern::Struct { path, fields: pat_fields, rest }, Value::Variant { variant_name, fields: variant_fields, .. }) => {
4242 let pattern_variant = path.segments.last().map(|s| s.ident.name.as_str()).unwrap_or("");
4243 if pattern_variant != variant_name {
4244 return Ok(false);
4245 }
4246 if let Some(inner_fields) = variant_fields {
4248 if inner_fields.len() == 1 {
4249 if let Value::Struct { fields: inner_struct, .. } = &inner_fields[0] {
4250 let borrowed = inner_struct.borrow();
4251 for field_pat in pat_fields {
4252 let field_name = &field_pat.name.name;
4253 if let Some(field_val) = borrowed.get(field_name) {
4254 if let Some(sub_pat) = &field_pat.pattern {
4255 if !self.pattern_matches(sub_pat, field_val)? {
4256 return Ok(false);
4257 }
4258 }
4259 } else if !rest {
4260 return Ok(false);
4261 }
4262 }
4263 return Ok(true);
4264 }
4265 }
4266 }
4267 Ok(pat_fields.is_empty() || *rest)
4269 }
4270 (Pattern::Or(patterns), val) => {
4272 for p in patterns {
4273 if self.pattern_matches(p, val)? {
4274 return Ok(true);
4275 }
4276 }
4277 Ok(false)
4278 }
4279 (Pattern::Rest, _) => Ok(true),
4281 (Pattern::Range { start, end, inclusive }, val) => {
4283 let extract_char = |pat: &Option<Box<Pattern>>| -> Option<char> {
4285 match pat {
4286 Some(p) => match p.as_ref() {
4287 Pattern::Literal(Literal::Char(c)) => Some(*c),
4288 _ => None,
4289 },
4290 None => None,
4291 }
4292 };
4293 let extract_int = |pat: &Option<Box<Pattern>>| -> Option<i64> {
4295 match pat {
4296 Some(p) => match p.as_ref() {
4297 Pattern::Literal(Literal::Int { value, .. }) => value.parse().ok(),
4298 _ => None,
4299 },
4300 None => None,
4301 }
4302 };
4303
4304 match val {
4305 Value::Char(c) => {
4306 let start_val = extract_char(start);
4307 let end_val = extract_char(end);
4308 let in_range = match (start_val, end_val, *inclusive) {
4309 (Some(s), Some(e), true) => *c >= s && *c <= e,
4310 (Some(s), Some(e), false) => *c >= s && *c < e,
4311 (Some(s), None, _) => *c >= s,
4312 (None, Some(e), true) => *c <= e,
4313 (None, Some(e), false) => *c < e,
4314 (None, None, _) => true,
4315 };
4316 Ok(in_range)
4317 }
4318 Value::Int(i) => {
4319 let start_val = extract_int(start);
4320 let end_val = extract_int(end);
4321 let in_range = match (start_val, end_val, *inclusive) {
4322 (Some(s), Some(e), true) => *i >= s && *i <= e,
4323 (Some(s), Some(e), false) => *i >= s && *i < e,
4324 (Some(s), None, _) => *i >= s,
4325 (None, Some(e), true) => *i <= e,
4326 (None, Some(e), false) => *i < e,
4327 (None, None, _) => true,
4328 };
4329 Ok(in_range)
4330 }
4331 _ => Ok(false),
4332 }
4333 }
4334 (Pattern::Literal(Literal::String(s)), Value::String(vs)) => {
4336 Ok(s == vs.as_str())
4337 }
4338 (Pattern::Literal(Literal::Char(c)), Value::Char(vc)) => {
4339 Ok(c == vc)
4340 }
4341 _ => Ok(false),
4342 }
4343 }
4344
4345 fn values_equal(&self, a: &Value, b: &Value) -> bool {
4346 let a_unwrapped = match a {
4348 Value::Ref(r) => r.borrow().clone(),
4349 _ => a.clone(),
4350 };
4351 let b_unwrapped = match b {
4352 Value::Ref(r) => r.borrow().clone(),
4353 _ => b.clone(),
4354 };
4355 match (&a_unwrapped, &b_unwrapped) {
4356 (Value::Null, Value::Null) => true,
4357 (Value::Bool(a), Value::Bool(b)) => a == b,
4358 (Value::Int(a), Value::Int(b)) => a == b,
4359 (Value::Float(a), Value::Float(b)) => (a - b).abs() < f64::EPSILON,
4360 (Value::String(a), Value::String(b)) => {
4361 let result = **a == **b;
4362 if a.len() <= 5 && b.len() <= 5 {
4364 crate::sigil_debug!("DEBUG values_equal: '{}' == '{}' -> {}", a, b, result);
4365 }
4366 result
4367 }
4368 (Value::Char(a), Value::Char(b)) => a == b,
4369 _ => false,
4370 }
4371 }
4372
4373 fn eval_for(
4374 &mut self,
4375 pattern: &Pattern,
4376 iter: &Expr,
4377 body: &Block,
4378 ) -> Result<Value, RuntimeError> {
4379 let iterable_raw = self.evaluate(iter)?;
4380 let iterable = Self::unwrap_all(&iterable_raw);
4381 let items = match iterable {
4382 Value::Array(arr) => arr.borrow().clone(),
4383 Value::Tuple(t) => (*t).clone(),
4384 Value::String(s) => s.chars().map(Value::Char).collect(),
4385 Value::Map(m) => {
4386 m.borrow()
4388 .iter()
4389 .map(|(k, v)| {
4390 Value::Tuple(Rc::new(vec![
4391 Value::String(Rc::new(k.clone())),
4392 v.clone(),
4393 ]))
4394 })
4395 .collect()
4396 }
4397 Value::Variant { fields: Some(f), .. } => (*f).clone(),
4398 _ => return Err(RuntimeError::new(format!("Cannot iterate over non-iterable: {:?}", iterable_raw))),
4399 };
4400
4401 let mut result = Value::Null;
4402 for item in items {
4403 let env = Rc::new(RefCell::new(Environment::with_parent(
4404 self.environment.clone(),
4405 )));
4406 let prev_env = self.environment.clone();
4407 self.environment = env;
4408
4409 self.bind_pattern(pattern, item)?;
4410
4411 match self.eval_block(body) {
4412 Ok(val) => result = val,
4413 Err(e) if e.message == "break" => {
4414 self.environment = prev_env;
4415 break;
4416 }
4417 Err(e) if e.message == "continue" => {
4418 self.environment = prev_env;
4419 continue;
4420 }
4421 Err(e) => {
4422 self.environment = prev_env;
4423 return Err(e);
4424 }
4425 }
4426
4427 self.environment = prev_env;
4428 }
4429
4430 Ok(result)
4431 }
4432
4433 fn eval_while(&mut self, condition: &Expr, body: &Block) -> Result<Value, RuntimeError> {
4434 let mut result = Value::Null;
4435 loop {
4436 let cond = self.evaluate(condition)?;
4437 if !self.is_truthy(&cond) {
4438 break;
4439 }
4440
4441 match self.eval_block(body) {
4442 Ok(val) => result = val,
4443 Err(e) if e.message == "break" => break,
4444 Err(e) if e.message == "continue" => continue,
4445 Err(e) => return Err(e),
4446 }
4447 }
4448 Ok(result)
4449 }
4450
4451 fn eval_loop(&mut self, body: &Block) -> Result<Value, RuntimeError> {
4452 loop {
4453 match self.eval_block(body) {
4454 Ok(_) => {}
4455 Err(e) if e.message == "break" => break,
4456 Err(e) if e.message == "continue" => continue,
4457 Err(e) => return Err(e),
4458 }
4459 }
4460 Ok(Value::Null)
4461 }
4462
4463 fn eval_return(&mut self, value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
4464 let val = match value {
4465 Some(expr) => self.evaluate(expr)?,
4466 None => Value::Null,
4467 };
4468 self.return_value = Some(val);
4470 Err(RuntimeError::new("return"))
4471 }
4472
4473 fn eval_break(&mut self, _value: &Option<Box<Expr>>) -> Result<Value, RuntimeError> {
4474 Err(RuntimeError::new("break"))
4476 }
4477
4478 fn eval_index(&mut self, expr: &Expr, index: &Expr) -> Result<Value, RuntimeError> {
4479 let collection = self.evaluate(expr)?;
4480
4481 let collection = match collection {
4483 Value::Ref(r) => r.borrow().clone(),
4484 other => other,
4485 };
4486
4487 if let Expr::Range { start, end, inclusive } = index {
4489 let start_val = match start {
4490 Some(e) => match self.evaluate(e)? {
4491 Value::Int(n) => n as usize,
4492 _ => return Err(RuntimeError::new("Slice start must be an integer")),
4493 },
4494 None => 0,
4495 };
4496
4497 return match &collection {
4498 Value::Array(arr) => {
4499 let arr = arr.borrow();
4500 let len = arr.len();
4501 let end_val = match end {
4502 Some(e) => match self.evaluate(e)? {
4503 Value::Int(n) => {
4504 let n = n as usize;
4505 if *inclusive { n + 1 } else { n }
4506 },
4507 _ => return Err(RuntimeError::new("Slice end must be an integer")),
4508 },
4509 None => len, };
4511 let end_val = end_val.min(len);
4512 let start_val = start_val.min(len);
4513 let sliced: Vec<Value> = arr[start_val..end_val].to_vec();
4514 Ok(Value::Array(Rc::new(RefCell::new(sliced))))
4515 }
4516 Value::String(s) => {
4517 let len = s.len();
4518 let end_val = match end {
4519 Some(e) => match self.evaluate(e)? {
4520 Value::Int(n) => {
4521 let n = n as usize;
4522 if *inclusive { n + 1 } else { n }
4523 },
4524 _ => return Err(RuntimeError::new("Slice end must be an integer")),
4525 },
4526 None => len, };
4528 let end_val = end_val.min(len);
4529 let start_val = start_val.min(len);
4530 let sliced = &s[start_val..end_val];
4532 Ok(Value::String(Rc::new(sliced.to_string())))
4533 }
4534 _ => Err(RuntimeError::new("Cannot slice this type")),
4535 };
4536 }
4537
4538 let idx = self.evaluate(index)?;
4539
4540 match (collection, idx) {
4541 (Value::Array(arr), Value::Int(i)) => {
4542 let arr = arr.borrow();
4543 let i = if i < 0 { arr.len() as i64 + i } else { i } as usize;
4544 let result = arr.get(i)
4545 .cloned()
4546 .ok_or_else(|| RuntimeError::new("Index out of bounds"));
4547 if let Ok(ref v) = result {
4548 crate::sigil_debug!("DEBUG eval_index: arr[{}] = {:?}", i, std::mem::discriminant(v));
4549 }
4550 result
4551 }
4552 (Value::Tuple(t), Value::Int(i)) => {
4553 let i = if i < 0 { t.len() as i64 + i } else { i } as usize;
4554 t.get(i)
4555 .cloned()
4556 .ok_or_else(|| RuntimeError::new("Index out of bounds"))
4557 }
4558 (Value::String(s), Value::Int(i)) => {
4559 let i = if i < 0 { s.len() as i64 + i } else { i } as usize;
4560 s.chars()
4561 .nth(i)
4562 .map(Value::Char)
4563 .ok_or_else(|| RuntimeError::new("Index out of bounds"))
4564 }
4565 (Value::Array(arr), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
4567 let arr = arr.borrow();
4568 let start = match &range_tuple[0] {
4569 Value::Int(n) => *n as usize,
4570 _ => return Err(RuntimeError::new("Range start must be integer")),
4571 };
4572 let end = match &range_tuple[1] {
4573 Value::Null => arr.len(), Value::Int(n) => *n as usize,
4575 _ => return Err(RuntimeError::new("Range end must be integer or None")),
4576 };
4577 let start = start.min(arr.len());
4578 let end = end.min(arr.len());
4579 let sliced: Vec<Value> = arr[start..end].to_vec();
4580 Ok(Value::Array(Rc::new(RefCell::new(sliced))))
4581 }
4582 (Value::String(s), Value::Tuple(range_tuple)) if range_tuple.len() == 2 => {
4583 let start = match &range_tuple[0] {
4584 Value::Int(n) => *n as usize,
4585 _ => return Err(RuntimeError::new("Range start must be integer")),
4586 };
4587 let end = match &range_tuple[1] {
4588 Value::Null => s.len(), Value::Int(n) => *n as usize,
4590 _ => return Err(RuntimeError::new("Range end must be integer or None")),
4591 };
4592 let start = start.min(s.len());
4593 let end = end.min(s.len());
4594 let sliced = &s[start..end];
4595 Ok(Value::String(Rc::new(sliced.to_string())))
4596 }
4597 (coll, idx) => {
4598 crate::sigil_debug!("DEBUG Cannot index: collection={:?}, index={:?}",
4599 std::mem::discriminant(&coll), std::mem::discriminant(&idx));
4600 Err(RuntimeError::new("Cannot index"))
4601 }
4602 }
4603 }
4604
4605 fn eval_field(&mut self, expr: &Expr, field: &Ident) -> Result<Value, RuntimeError> {
4606 if field.name == "items" {
4607 crate::sigil_debug!("DEBUG eval_field: accessing .items on expr={:?}", expr);
4608 }
4609 if field.name == "evidence" {
4611 crate::sigil_debug!("DEBUG eval_field: accessing .evidence");
4612 }
4613 let value = self.evaluate(expr)?;
4614 if field.name == "items" {
4615 crate::sigil_debug!("DEBUG eval_field: .items receiver value={:?}", std::mem::discriminant(&value));
4616 }
4617 if field.name == "evidence" {
4618 crate::sigil_debug!("DEBUG eval_field: .evidence receiver value type={:?}", std::mem::discriminant(&value));
4619 }
4620 fn get_field(val: &Value, field_name: &str) -> Result<Value, RuntimeError> {
4622 if field_name == "evidence" {
4624 crate::sigil_debug!("DEBUG get_field 'evidence' on value type: {:?}", std::mem::discriminant(val));
4625 }
4626 match val {
4627 Value::Struct { name, fields } => {
4628 let field_val = fields.borrow().get(field_name).cloned();
4629 if field_val.is_none() && field_name == "path" {
4630 crate::sigil_debug!("DEBUG Unknown field 'path': struct={}, available={:?}", name, fields.borrow().keys().collect::<Vec<_>>());
4631 }
4632 if field_name == "evidence" || name.contains("IrPattern") {
4634 crate::sigil_debug!("DEBUG get_field on Struct: name={}, field={}, available={:?}, found={}",
4635 name, field_name, fields.borrow().keys().collect::<Vec<_>>(), field_val.is_some());
4636 }
4637 match field_val {
4639 Some(v) => Ok(v),
4640 None => {
4641 crate::sigil_warn!("WARN: Unknown field '{}' on '{}' - returning null", field_name, name);
4642 Ok(Value::Null)
4643 }
4644 }
4645 }
4646 Value::Tuple(t) => {
4647 let idx: usize = field_name
4649 .parse()
4650 .map_err(|_| RuntimeError::new("Invalid tuple index"))?;
4651 t.get(idx)
4652 .cloned()
4653 .ok_or_else(|| RuntimeError::new("Tuple index out of bounds"))
4654 }
4655 Value::Ref(r) => {
4656 get_field(&r.borrow(), field_name)
4658 }
4659 Value::Evidential { value, .. } => {
4660 get_field(value, field_name)
4662 }
4663 Value::Affective { value, .. } => {
4664 get_field(value, field_name)
4666 }
4667 Value::Variant { fields: variant_fields, .. } => {
4668 if let Some(inner_fields) = variant_fields {
4671 for f in inner_fields.iter() {
4673 if let Value::Struct { fields: struct_fields, .. } = f {
4674 if let Some(field_val) = struct_fields.borrow().get(field_name).cloned() {
4675 return Ok(field_val);
4676 }
4677 }
4678 }
4679 Ok(Value::Null)
4681 } else {
4682 Ok(Value::Null)
4684 }
4685 }
4686 other => {
4687 crate::sigil_warn!("WARN: Cannot access field '{}' on non-struct - returning null", field_name);
4689 Ok(Value::Null)
4690 }
4691 }
4692 }
4693 get_field(&value, &field.name)
4694 }
4695
4696 fn extract_root_var(expr: &Expr) -> Option<String> {
4698 match expr {
4699 Expr::Path(path) if path.segments.len() == 1 => {
4700 Some(path.segments[0].ident.name.clone())
4701 }
4702 Expr::MethodCall { receiver, .. } => {
4703 Self::extract_root_var(receiver)
4704 }
4705 _ => None,
4706 }
4707 }
4708
4709 fn eval_method_call(
4710 &mut self,
4711 receiver: &Expr,
4712 method: &Ident,
4713 args: &[Expr],
4714 ) -> Result<Value, RuntimeError> {
4715 if (method.name == "push" || method.name == "push_str") && args.len() == 1 {
4717 let recv_val = self.evaluate(receiver)?;
4718 let recv_unwrapped = Self::unwrap_all(&recv_val);
4719 if let Value::String(s) = &recv_unwrapped {
4720 let arg = self.evaluate(&args[0])?;
4721 let arg_unwrapped = Self::unwrap_all(&arg);
4722 let new_s = match arg_unwrapped {
4723 Value::Char(c) => {
4724 let mut new_str = (**s).clone();
4725 new_str.push(c);
4726 new_str
4727 }
4728 Value::String(ref add_s) => {
4729 let mut new_str = (**s).clone();
4730 new_str.push_str(add_s);
4731 new_str
4732 }
4733 _ => return Err(RuntimeError::new("push expects char or string argument")),
4734 };
4735 let new_val = Value::String(Rc::new(new_s));
4736
4737 if let Some(root_var) = Self::extract_root_var(receiver) {
4739 self.environment.borrow_mut().set(&root_var, new_val.clone())?;
4740 return Ok(new_val);
4742 }
4743
4744 if let Expr::Field { expr: base_expr, field: field_ident } = receiver {
4746 let base = self.evaluate(base_expr)?;
4747 if let Value::Struct { fields, .. } = base {
4748 fields.borrow_mut().insert(field_ident.name.clone(), new_val.clone());
4749 return Ok(new_val);
4751 }
4752 }
4753 return Ok(new_val);
4755 }
4756 }
4757
4758 let recv_raw = self.evaluate(receiver)?;
4759 let recv = Self::unwrap_value(&recv_raw).clone();
4761
4762 static METHOD_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0);
4764 let count = METHOD_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
4765 if count < 500 {
4766 let recv_type = match &recv {
4767 Value::Struct { name, .. } => format!("Struct({})", name),
4768 Value::String(s) => format!("String('{}')", if s.len() <= 20 { s.as_str() } else { "<long>" }),
4769 Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
4770 other => format!("{:?}", std::mem::discriminant(other)),
4771 };
4772 if recv_type.contains("Lexer") || method.name.contains("keyword") || method.name.contains("lex") {
4773 crate::sigil_debug!("DEBUG method #{}: {}.{}()", count, recv_type, method.name);
4774 }
4775 }
4776 let arg_values: Vec<Value> = args
4777 .iter()
4778 .map(|a| self.evaluate(a))
4779 .collect::<Result<_, _>>()?;
4780
4781 if method.name == "cloned" || method.name == "clone" {
4783 let recv_type = match &recv {
4784 Value::Struct { name, .. } => format!("Struct({})", name),
4785 Value::Variant { enum_name, variant_name, .. } => format!("Variant({}::{})", enum_name, variant_name),
4786 Value::String(_) => "String".to_string(),
4787 Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
4788 Value::Null => "Null".to_string(),
4789 other => format!("{:?}", std::mem::discriminant(other)),
4790 };
4791 crate::sigil_debug!("DEBUG {}: recv_type={}", method.name, recv_type);
4792 }
4793
4794 if method.name == "as_str" {
4796 let recv_unwrapped = Self::unwrap_all(&recv);
4797 if let Value::String(s) = &recv_unwrapped {
4798 crate::sigil_debug!("DEBUG as_str CALL: recv='{}' len={}", s, s.len());
4799 } else {
4800 crate::sigil_debug!("DEBUG as_str CALL: recv={:?} (not string)", recv_unwrapped);
4801 }
4802 }
4803
4804 if method.name == "keyword_or_ident" {
4806 let recv_type = match &recv {
4807 Value::Struct { name, .. } => format!("Struct({})", name),
4808 Value::String(_) => "String".to_string(),
4809 Value::Ref(r) => format!("Ref({})", match &*r.borrow() {
4810 Value::Struct { name, .. } => format!("Struct({})", name),
4811 other => format!("{:?}", std::mem::discriminant(other)),
4812 }),
4813 other => format!("{:?}", std::mem::discriminant(other)),
4814 };
4815 crate::sigil_debug!("DEBUG keyword_or_ident: recv_type={}", recv_type);
4816 }
4817
4818 for arg in &arg_values {
4820 let unwrapped = Self::unwrap_all(arg);
4821 if let Value::String(s) = &unwrapped {
4822 if **s == "fn" {
4823 let recv_type = match &recv {
4824 Value::Struct { name, .. } => format!("Struct({})", name),
4825 Value::String(_) => "String".to_string(),
4826 Value::Ref(_) => "Ref".to_string(),
4827 other => format!("{:?}", std::mem::discriminant(other)),
4828 };
4829 crate::sigil_debug!("DEBUG method call with 'fn': method={}, recv_type={}", method.name, recv_type);
4830 }
4831 }
4832 }
4833
4834 match (&recv, method.name.as_str()) {
4836 (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
4837 (Value::Array(arr), "push") => {
4838 if arg_values.len() != 1 {
4839 return Err(RuntimeError::new("push expects 1 argument"));
4840 }
4841 arr.borrow_mut().push(arg_values[0].clone());
4842 Ok(Value::Null)
4843 }
4844 (Value::Array(arr), "pop") => arr
4845 .borrow_mut()
4846 .pop()
4847 .ok_or_else(|| RuntimeError::new("pop on empty array")),
4848 (Value::Array(arr), "extend") => {
4849 if arg_values.len() != 1 {
4850 return Err(RuntimeError::new("extend expects 1 argument"));
4851 }
4852 match &arg_values[0] {
4853 Value::Array(other) => {
4854 arr.borrow_mut().extend(other.borrow().iter().cloned());
4855 Ok(Value::Null)
4856 }
4857 _ => Err(RuntimeError::new("extend expects array argument")),
4858 }
4859 }
4860 (Value::Array(arr), "reverse") => {
4861 let mut v = arr.borrow().clone();
4862 v.reverse();
4863 Ok(Value::Array(Rc::new(RefCell::new(v))))
4864 }
4865 (Value::Array(arr), "skip") => {
4866 let n = match arg_values.first() {
4867 Some(Value::Int(i)) => *i as usize,
4868 _ => 1,
4869 };
4870 let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
4871 Ok(Value::Array(Rc::new(RefCell::new(v))))
4872 }
4873 (Value::Array(arr), "take") => {
4874 let n = match arg_values.first() {
4875 Some(Value::Int(i)) => *i as usize,
4876 _ => 1,
4877 };
4878 let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
4879 Ok(Value::Array(Rc::new(RefCell::new(v))))
4880 }
4881 (Value::Array(arr), "step_by") => {
4882 let n = match arg_values.first() {
4883 Some(Value::Int(i)) if *i > 0 => *i as usize,
4884 _ => 1,
4885 };
4886 let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
4887 Ok(Value::Array(Rc::new(RefCell::new(v))))
4888 }
4889 (Value::Array(arr), "contains") => {
4890 if arg_values.len() != 1 {
4891 return Err(RuntimeError::new("contains expects 1 argument"));
4892 }
4893 let target = &arg_values[0];
4894 let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
4895 Ok(Value::Bool(found))
4896 }
4897 (Value::Tuple(t), "to_string") | (Value::Tuple(t), "string") => {
4899 let s: Vec<String> = t.iter().map(|v| format!("{}", v)).collect();
4900 Ok(Value::String(Rc::new(format!("({})", s.join(", ")))))
4901 }
4902 (Value::Tuple(t), "len") => Ok(Value::Int(t.len() as i64)),
4903 (Value::Tuple(t), "first") => t.first().cloned().ok_or_else(|| RuntimeError::new("empty tuple")),
4904 (Value::Tuple(t), "last") => t.last().cloned().ok_or_else(|| RuntimeError::new("empty tuple")),
4905 (Value::Tuple(t), "get") => {
4906 let idx = match arg_values.first() {
4907 Some(Value::Int(i)) => *i as usize,
4908 _ => return Err(RuntimeError::new("get expects integer index")),
4909 };
4910 t.get(idx).cloned().ok_or_else(|| RuntimeError::new("tuple index out of bounds"))
4911 }
4912 (Value::Array(arr), "first") | (Value::Array(arr), "next") => Ok(arr
4913 .borrow()
4914 .first()
4915 .cloned()
4916 .unwrap_or(Value::Null)),
4917 (Value::Array(arr), "last") => arr
4918 .borrow()
4919 .last()
4920 .cloned()
4921 .ok_or_else(|| RuntimeError::new("empty array")),
4922 (Value::Array(arr), "iter") | (Value::Array(arr), "into_iter") => {
4923 Ok(Value::Array(arr.clone()))
4925 }
4926 (Value::Array(arr), "map") => {
4927 if arg_values.len() != 1 {
4929 return Err(RuntimeError::new("map expects 1 argument (closure)"));
4930 }
4931 match &arg_values[0] {
4932 Value::Function(f) => {
4933 let mut results = Vec::new();
4934 for val in arr.borrow().iter() {
4935 let result = self.call_function(f, vec![val.clone()])?;
4936 results.push(result);
4937 }
4938 Ok(Value::Array(Rc::new(RefCell::new(results))))
4939 }
4940 _ => Err(RuntimeError::new("map expects closure argument")),
4941 }
4942 }
4943 (Value::Array(arr), "filter") => {
4944 if arg_values.len() != 1 {
4946 return Err(RuntimeError::new("filter expects 1 argument (closure)"));
4947 }
4948 match &arg_values[0] {
4949 Value::Function(f) => {
4950 let mut results = Vec::new();
4951 for val in arr.borrow().iter() {
4952 let keep = self.call_function(f, vec![val.clone()])?;
4953 if matches!(keep, Value::Bool(true)) {
4954 results.push(val.clone());
4955 }
4956 }
4957 Ok(Value::Array(Rc::new(RefCell::new(results))))
4958 }
4959 _ => Err(RuntimeError::new("filter expects closure argument")),
4960 }
4961 }
4962 (Value::Array(arr), "any") => {
4963 if arg_values.len() != 1 {
4965 return Err(RuntimeError::new("any expects 1 argument (closure)"));
4966 }
4967 match &arg_values[0] {
4968 Value::Function(f) => {
4969 for val in arr.borrow().iter() {
4970 let result = self.call_function(f, vec![val.clone()])?;
4971 if matches!(result, Value::Bool(true)) {
4972 return Ok(Value::Bool(true));
4973 }
4974 }
4975 Ok(Value::Bool(false))
4976 }
4977 _ => Err(RuntimeError::new("any expects closure argument")),
4978 }
4979 }
4980 (Value::Array(arr), "all") => {
4981 if arg_values.len() != 1 {
4983 return Err(RuntimeError::new("all expects 1 argument (closure)"));
4984 }
4985 match &arg_values[0] {
4986 Value::Function(f) => {
4987 for val in arr.borrow().iter() {
4988 let result = self.call_function(f, vec![val.clone()])?;
4989 if !matches!(result, Value::Bool(true)) {
4990 return Ok(Value::Bool(false));
4991 }
4992 }
4993 Ok(Value::Bool(true))
4994 }
4995 _ => Err(RuntimeError::new("all expects closure argument")),
4996 }
4997 }
4998 (Value::Array(arr), "find") => {
4999 if arg_values.len() != 1 {
5001 return Err(RuntimeError::new("find expects 1 argument (closure)"));
5002 }
5003 match &arg_values[0] {
5004 Value::Function(f) => {
5005 for val in arr.borrow().iter() {
5006 let result = self.call_function(f, vec![val.clone()])?;
5007 if matches!(result, Value::Bool(true)) {
5008 return Ok(Value::Variant {
5009 enum_name: "Option".to_string(),
5010 variant_name: "Some".to_string(),
5011 fields: Some(Rc::new(vec![val.clone()])),
5012 });
5013 }
5014 }
5015 Ok(Value::Variant {
5016 enum_name: "Option".to_string(),
5017 variant_name: "None".to_string(),
5018 fields: None,
5019 })
5020 }
5021 _ => Err(RuntimeError::new("find expects closure argument")),
5022 }
5023 }
5024 (Value::Array(arr), "enumerate") => {
5025 let enumerated: Vec<Value> = arr
5027 .borrow()
5028 .iter()
5029 .enumerate()
5030 .map(|(i, v)| Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()])))
5031 .collect();
5032 Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
5033 }
5034 (Value::Array(arr), "zip") => {
5035 if arg_values.len() != 1 {
5037 return Err(RuntimeError::new("zip expects 1 argument"));
5038 }
5039 match &arg_values[0] {
5040 Value::Array(other) => {
5041 let a = arr.borrow();
5042 let b = other.borrow();
5043 let zipped: Vec<Value> = a.iter()
5044 .zip(b.iter())
5045 .map(|(x, y)| Value::Tuple(Rc::new(vec![x.clone(), y.clone()])))
5046 .collect();
5047 Ok(Value::Array(Rc::new(RefCell::new(zipped))))
5048 }
5049 _ => Err(RuntimeError::new("zip expects array argument")),
5050 }
5051 }
5052 (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5053 (Value::String(s), "chars") => {
5054 let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5055 Ok(Value::Array(Rc::new(RefCell::new(chars))))
5056 }
5057 (Value::String(s), "contains") => {
5058 if arg_values.len() != 1 {
5059 return Err(RuntimeError::new("contains expects 1 argument"));
5060 }
5061 match &arg_values[0] {
5062 Value::String(sub) => Ok(Value::Bool(s.contains(sub.as_str()))),
5063 Value::Char(c) => Ok(Value::Bool(s.contains(*c))),
5064 Value::Ref(inner) => {
5065 if let Value::String(sub) = &*inner.borrow() {
5066 Ok(Value::Bool(s.contains(sub.as_str())))
5067 } else {
5068 Err(RuntimeError::new("contains expects string or char"))
5069 }
5070 }
5071 _ => Err(RuntimeError::new("contains expects string or char")),
5072 }
5073 }
5074 (Value::String(s), "as_str") => {
5075 if s.len() <= 10 { crate::sigil_debug!("DEBUG as_str: '{}'", s); }
5076 Ok(Value::String(s.clone()))
5077 }
5078 (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
5079 (Value::String(s), "into") => Ok(Value::String(s.clone())), (Value::String(s), "starts_with") => {
5081 if arg_values.len() != 1 {
5082 return Err(RuntimeError::new("starts_with expects 1 argument"));
5083 }
5084 match &arg_values[0] {
5085 Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
5086 _ => Err(RuntimeError::new("starts_with expects string")),
5087 }
5088 }
5089 (Value::String(s), "ends_with") => {
5090 if arg_values.len() != 1 {
5091 return Err(RuntimeError::new("ends_with expects 1 argument"));
5092 }
5093 match &arg_values[0] {
5094 Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
5095 _ => Err(RuntimeError::new("ends_with expects string")),
5096 }
5097 }
5098 (Value::String(s), "strip_prefix") => {
5099 if arg_values.len() != 1 {
5100 return Err(RuntimeError::new("strip_prefix expects 1 argument"));
5101 }
5102 match &arg_values[0] {
5103 Value::String(prefix) => {
5104 match s.strip_prefix(prefix.as_str()) {
5105 Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5106 None => Ok(Value::Null),
5107 }
5108 }
5109 _ => Err(RuntimeError::new("strip_prefix expects string")),
5110 }
5111 }
5112 (Value::String(s), "strip_suffix") => {
5113 if arg_values.len() != 1 {
5114 return Err(RuntimeError::new("strip_suffix expects 1 argument"));
5115 }
5116 match &arg_values[0] {
5117 Value::String(suffix) => {
5118 match s.strip_suffix(suffix.as_str()) {
5119 Some(stripped) => Ok(Value::String(Rc::new(stripped.to_string()))),
5120 None => Ok(Value::Null),
5121 }
5122 }
5123 _ => Err(RuntimeError::new("strip_suffix expects string")),
5124 }
5125 }
5126 (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5127 (Value::String(s), "find") => {
5128 if arg_values.len() != 1 {
5129 return Err(RuntimeError::new("find expects 1 argument"));
5130 }
5131 match &arg_values[0] {
5132 Value::Char(c) => {
5133 match s.find(*c) {
5134 Some(idx) => Ok(Value::Variant {
5135 enum_name: "Option".to_string(),
5136 variant_name: "Some".to_string(),
5137 fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5138 }),
5139 None => Ok(Value::Variant {
5140 enum_name: "Option".to_string(),
5141 variant_name: "None".to_string(),
5142 fields: None,
5143 }),
5144 }
5145 }
5146 Value::String(pattern) => {
5147 match s.find(pattern.as_str()) {
5148 Some(idx) => Ok(Value::Variant {
5149 enum_name: "Option".to_string(),
5150 variant_name: "Some".to_string(),
5151 fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5152 }),
5153 None => Ok(Value::Variant {
5154 enum_name: "Option".to_string(),
5155 variant_name: "None".to_string(),
5156 fields: None,
5157 }),
5158 }
5159 }
5160 Value::Function(f) => {
5161 for (idx, c) in s.chars().enumerate() {
5162 let result = self.call_function(f, vec![Value::Char(c)])?;
5163 if let Value::Bool(true) = result {
5164 return Ok(Value::Variant {
5165 enum_name: "Option".to_string(),
5166 variant_name: "Some".to_string(),
5167 fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5168 });
5169 }
5170 }
5171 Ok(Value::Variant {
5172 enum_name: "Option".to_string(),
5173 variant_name: "None".to_string(),
5174 fields: None,
5175 })
5176 }
5177 _ => Err(RuntimeError::new("find expects a char, string, or closure")),
5178 }
5179 }
5180 (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
5181 (Value::String(s), "concat") => {
5182 if arg_values.len() != 1 {
5183 return Err(RuntimeError::new("concat expects 1 argument"));
5184 }
5185 match &arg_values[0] {
5186 Value::String(other) => {
5187 let mut result = (**s).clone();
5188 result.push_str(other);
5189 Ok(Value::String(Rc::new(result)))
5190 }
5191 _ => Err(RuntimeError::new("concat expects string argument")),
5192 }
5193 }
5194 (Value::String(s), "as_ptr") => {
5195 Ok(Value::String(s.clone()))
5197 }
5198 (Value::String(_), "is_null") => Ok(Value::Bool(false)),
5199 (Value::Null, "is_null") => Ok(Value::Bool(true)),
5200 (Value::String(s), "char_at") => {
5201 if arg_values.len() != 1 {
5202 return Err(RuntimeError::new("char_at expects 1 argument"));
5203 }
5204 let idx = match &arg_values[0] {
5205 Value::Int(i) => *i as usize,
5206 _ => return Err(RuntimeError::new("char_at expects integer index")),
5207 };
5208 if idx < s.len() {
5211 let remaining = &s[idx..];
5213 match remaining.chars().next() {
5214 Some(c) => Ok(Value::Char(c)),
5215 None => Ok(Value::Null),
5216 }
5217 } else {
5218 Ok(Value::Null) }
5220 }
5221 (Value::String(s), "chars") => {
5222 let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5223 Ok(Value::Array(Rc::new(RefCell::new(chars))))
5224 }
5225 (Value::String(s), "bytes") => {
5226 let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
5227 Ok(Value::Array(Rc::new(RefCell::new(bytes))))
5228 }
5229 (Value::String(s), "split") => {
5230 if arg_values.len() != 1 {
5231 return Err(RuntimeError::new("split expects 1 argument"));
5232 }
5233 match &arg_values[0] {
5234 Value::String(sep) => {
5235 let parts: Vec<Value> = s.split(sep.as_str())
5236 .map(|p| Value::String(Rc::new(p.to_string())))
5237 .collect();
5238 Ok(Value::Array(Rc::new(RefCell::new(parts))))
5239 }
5240 Value::Char(sep) => {
5241 let parts: Vec<Value> = s.split(*sep)
5242 .map(|p| Value::String(Rc::new(p.to_string())))
5243 .collect();
5244 Ok(Value::Array(Rc::new(RefCell::new(parts))))
5245 }
5246 _ => Err(RuntimeError::new("split expects string or char separator")),
5247 }
5248 }
5249 (Value::Char(c), "len_utf8") => Ok(Value::Int(c.len_utf8() as i64)),
5251 (Value::Char(c), "is_alphabetic") => Ok(Value::Bool(c.is_alphabetic())),
5252 (Value::Char(c), "is_alphanumeric") => Ok(Value::Bool(c.is_alphanumeric())),
5253 (Value::Char(c), "is_ascii_alphanumeric") => Ok(Value::Bool(c.is_ascii_alphanumeric())),
5254 (Value::Char(c), "is_ascii_alphabetic") => Ok(Value::Bool(c.is_ascii_alphabetic())),
5255 (Value::Char(c), "is_ascii_digit") => Ok(Value::Bool(c.is_ascii_digit())),
5256 (Value::Char(c), "is_ascii_hexdigit") => Ok(Value::Bool(c.is_ascii_hexdigit())),
5257 (Value::Char(c), "is_ascii") => Ok(Value::Bool(c.is_ascii())),
5258 (Value::Char(c), "is_digit") => {
5259 let radix = if arg_values.is_empty() { 10 } else {
5260 match &arg_values[0] {
5261 Value::Int(n) => *n as u32,
5262 _ => 10,
5263 }
5264 };
5265 Ok(Value::Bool(c.is_digit(radix)))
5266 }
5267 (Value::Char(c), "is_numeric") => Ok(Value::Bool(c.is_numeric())),
5268 (Value::Char(c), "is_whitespace") => Ok(Value::Bool(c.is_whitespace())),
5269 (Value::Char(c), "is_uppercase") => Ok(Value::Bool(c.is_uppercase())),
5270 (Value::Char(c), "is_lowercase") => Ok(Value::Bool(c.is_lowercase())),
5271 (Value::Char(c), "to_uppercase") => {
5272 let upper: String = c.to_uppercase().collect();
5273 Ok(Value::String(Rc::new(upper)))
5274 }
5275 (Value::Char(c), "to_lowercase") => {
5276 let lower: String = c.to_lowercase().collect();
5277 Ok(Value::String(Rc::new(lower)))
5278 }
5279 (Value::Char(c), "to_string") => Ok(Value::String(Rc::new(c.to_string()))),
5280 (Value::Char(c), "to_digit") => {
5281 let radix = if arg_values.is_empty() { 10 } else {
5282 match &arg_values[0] {
5283 Value::Int(n) => *n as u32,
5284 _ => 10,
5285 }
5286 };
5287 match c.to_digit(radix) {
5288 Some(d) => Ok(Value::Int(d as i64)),
5289 None => Ok(Value::Null),
5290 }
5291 }
5292 (Value::Char(c), "to_ascii_uppercase") => Ok(Value::Char(c.to_ascii_uppercase())),
5293 (Value::Char(c), "to_ascii_lowercase") => Ok(Value::Char(c.to_ascii_lowercase())),
5294 (Value::Char(c), "clone") => Ok(Value::Char(*c)),
5295 (Value::String(s), "upper") | (Value::String(s), "uppercase") | (Value::String(s), "to_uppercase") => {
5296 Ok(Value::String(Rc::new(s.to_uppercase())))
5297 }
5298 (Value::String(s), "lower") | (Value::String(s), "lowercase") | (Value::String(s), "to_lowercase") => {
5299 Ok(Value::String(Rc::new(s.to_lowercase())))
5300 }
5301 (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
5302 (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
5303 (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
5304 (Value::String(s), "exists") => Ok(Value::Bool(std::path::Path::new(s.as_str()).exists())),
5306 (Value::String(s), "is_dir") => Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir())),
5307 (Value::String(s), "is_file") => Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file())),
5308 (Value::String(s), "join") => {
5309 if arg_values.len() != 1 {
5311 return Err(RuntimeError::new(&format!("join expects 1 argument, got {}", arg_values.len())));
5312 }
5313 let other = match &arg_values[0] {
5314 Value::String(s2) => s2.as_str().to_string(),
5315 other => return Err(RuntimeError::new(&format!("join expects String argument, got {:?}", other))),
5316 };
5317 let path = std::path::Path::new(s.as_str()).join(&other);
5318 Ok(Value::String(Rc::new(path.to_string_lossy().to_string())))
5319 }
5320 (Value::String(s), "parent") => {
5321 let path = std::path::Path::new(s.as_str());
5323 match path.parent() {
5324 Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
5325 None => Ok(Value::Null),
5326 }
5327 }
5328 (Value::String(s), "file_name") => {
5329 let path = std::path::Path::new(s.as_str());
5331 match path.file_name() {
5332 Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5333 None => Ok(Value::Null),
5334 }
5335 }
5336 (Value::String(s), "extension") => {
5337 let path = std::path::Path::new(s.as_str());
5339 match path.extension() {
5340 Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5341 None => Ok(Value::Null),
5342 }
5343 }
5344 (Value::String(_), "and_then") | (Value::String(_), "or_else") => {
5346 Ok(recv.clone())
5348 }
5349 (Value::String(s), "first") => s
5350 .chars()
5351 .next()
5352 .map(Value::Char)
5353 .ok_or_else(|| RuntimeError::new("empty string")),
5354 (Value::String(s), "last") => s
5355 .chars()
5356 .last()
5357 .map(Value::Char)
5358 .ok_or_else(|| RuntimeError::new("empty string")),
5359 (Value::Array(arr), "is_empty") => Ok(Value::Bool(arr.borrow().is_empty())),
5360 (Value::Array(arr), "clone") => Ok(Value::Array(Rc::new(RefCell::new(arr.borrow().clone())))),
5361 (Value::Array(arr), "collect") => {
5362 Ok(Value::Array(arr.clone()))
5365 }
5366 (Value::Array(arr), "join") => {
5367 let separator = if arg_values.is_empty() {
5368 String::new()
5369 } else {
5370 match &arg_values[0] {
5371 Value::String(s) => (**s).clone(),
5372 _ => return Err(RuntimeError::new("join separator must be string")),
5373 }
5374 };
5375 let parts: Vec<String> = arr.borrow().iter()
5376 .map(|v| self.format_value(v))
5377 .collect();
5378 Ok(Value::String(Rc::new(parts.join(&separator))))
5379 }
5380 (Value::Map(m), "insert") => {
5382 if arg_values.len() != 2 {
5383 return Err(RuntimeError::new("insert expects 2 arguments"));
5384 }
5385 let key = match &arg_values[0] {
5386 Value::String(s) => (**s).clone(),
5387 _ => format!("{}", arg_values[0]),
5388 };
5389 m.borrow_mut().insert(key, arg_values[1].clone());
5390 Ok(Value::Null)
5391 }
5392 (Value::Map(m), "get") => {
5393 if arg_values.len() != 1 {
5394 return Err(RuntimeError::new("get expects 1 argument"));
5395 }
5396 let key = match &arg_values[0] {
5397 Value::String(s) => (**s).clone(),
5398 _ => format!("{}", arg_values[0]),
5399 };
5400 Ok(m.borrow().get(&key).cloned().unwrap_or(Value::Null))
5401 }
5402 (Value::Map(m), "contains_key") => {
5403 if arg_values.len() != 1 {
5404 return Err(RuntimeError::new("contains_key expects 1 argument"));
5405 }
5406 let key = match &arg_values[0] {
5407 Value::String(s) => (**s).clone(),
5408 _ => format!("{}", arg_values[0]),
5409 };
5410 Ok(Value::Bool(m.borrow().contains_key(&key)))
5411 }
5412 (Value::Map(m), "len") => Ok(Value::Int(m.borrow().len() as i64)),
5413 (Value::Map(m), "is_empty") => Ok(Value::Bool(m.borrow().is_empty())),
5414 (Value::Map(m), "keys") => {
5415 let keys: Vec<Value> = m.borrow().keys()
5416 .map(|k| Value::String(Rc::new(k.clone())))
5417 .collect();
5418 Ok(Value::Array(Rc::new(RefCell::new(keys))))
5419 }
5420 (Value::Map(m), "values") => {
5421 let values: Vec<Value> = m.borrow().values().cloned().collect();
5422 Ok(Value::Array(Rc::new(RefCell::new(values))))
5423 }
5424 (Value::Ref(r), "cloned") => {
5426 Ok(r.borrow().clone())
5428 }
5429 (Value::Ref(r), "borrow") => {
5430 Ok(recv.clone())
5432 }
5433 (Value::Ref(r), "borrow_mut") => {
5434 Ok(recv.clone())
5436 }
5437 (Value::Ref(r), _) => {
5439 let inner = r.borrow().clone();
5441 if let Value::Struct { name, fields } = &inner {
5442 let qualified_name = format!("{}·{}", name, method.name);
5444 let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5445 if let Some(func) = func {
5446 if let Value::Function(f) = func {
5447 let old_self_type = self.current_self_type.take();
5449 self.current_self_type = Some(name.clone());
5450
5451 let mut all_args = vec![recv.clone()];
5453 all_args.extend(arg_values.clone());
5454 let result = self.call_function(&f, all_args);
5455
5456 self.current_self_type = old_self_type;
5458 return result;
5459 } else if let Value::BuiltIn(b) = func {
5460 let mut all_args = vec![recv.clone()];
5461 all_args.extend(arg_values.clone());
5462 return (b.func)(self, all_args);
5463 }
5464 }
5465
5466 if name == "Self" {
5468 let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
5469
5470 for (type_name, type_def) in &self.types {
5472 if let TypeDef::Struct(struct_def) = type_def {
5473 let def_fields: Vec<String> = match &struct_def.fields {
5474 crate::ast::StructFields::Named(fs) => fs.iter().map(|f| f.name.name.clone()).collect(),
5475 _ => continue,
5476 };
5477
5478 let matches = field_names.iter().all(|f| def_fields.contains(f));
5480 if matches {
5481 let qualified_name = format!("{}·{}", type_name, method.name);
5482 let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
5483 if let Some(func) = func {
5484 if let Value::Function(f) = func {
5485 let old_self_type = self.current_self_type.take();
5487 self.current_self_type = Some(type_name.clone());
5488
5489 let mut all_args = vec![recv.clone()];
5490 all_args.extend(arg_values.clone());
5491 let result = self.call_function(&f, all_args);
5492
5493 self.current_self_type = old_self_type;
5495 return result;
5496 } else if let Value::BuiltIn(b) = func {
5497 let mut all_args = vec![recv.clone()];
5498 all_args.extend(arg_values.clone());
5499 return (b.func)(self, all_args);
5500 }
5501 }
5502 }
5503 }
5504 }
5505 }
5506
5507 if name == "PathBuf" || name == "Path" {
5509 if let Some(Value::String(path)) = fields.borrow().get("path").cloned() {
5510 match method.name.as_str() {
5511 "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5512 "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5513 "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5514 "join" => {
5515 if let Some(Value::String(other)) = arg_values.first() {
5516 let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5517 let mut new_fields = std::collections::HashMap::new();
5518 new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5519 return Ok(Value::Struct {
5520 name: "PathBuf".to_string(),
5521 fields: Rc::new(RefCell::new(new_fields)),
5522 });
5523 }
5524 return Err(RuntimeError::new("join requires string argument"));
5525 }
5526 "parent" => {
5527 let p = std::path::Path::new(path.as_str());
5528 return match p.parent() {
5529 Some(par) => {
5530 let mut new_fields = std::collections::HashMap::new();
5531 new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5532 Ok(Value::Struct {
5533 name: "PathBuf".to_string(),
5534 fields: Rc::new(RefCell::new(new_fields)),
5535 })
5536 }
5537 None => Ok(Value::Null),
5538 };
5539 }
5540 "file_name" => {
5541 let p = std::path::Path::new(path.as_str());
5542 return match p.file_name() {
5543 Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5544 None => Ok(Value::Null),
5545 };
5546 }
5547 "extension" => {
5548 let p = std::path::Path::new(path.as_str());
5549 return match p.extension() {
5550 Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5551 None => Ok(Value::Null),
5552 };
5553 }
5554 "to_string" | "display" | "to_str" => {
5555 return Ok(Value::String(path.clone()));
5556 }
5557 _ => {}
5558 }
5559 }
5560 }
5561
5562 crate::sigil_warn!("WARN: Unknown method '{}' on '&{}' - returning null", method.name, name);
5564 return Ok(Value::Null);
5565 }
5566 if let Value::String(s) = &inner {
5569 match method.name.as_str() {
5570 "to_string" => return Ok(Value::String(s.clone())),
5571 "len" => return Ok(Value::Int(s.len() as i64)),
5572 "is_empty" => return Ok(Value::Bool(s.is_empty())),
5573 "as_str" => return Ok(Value::String(s.clone())),
5574 "starts_with" => {
5575 let prefix = match arg_values.first() {
5576 Some(Value::String(p)) => p.as_str(),
5577 Some(Value::Char(c)) => return Ok(Value::Bool(s.starts_with(*c))),
5578 _ => return Err(RuntimeError::new("starts_with expects string or char")),
5579 };
5580 return Ok(Value::Bool(s.starts_with(prefix)));
5581 }
5582 "ends_with" => {
5583 let suffix = match arg_values.first() {
5584 Some(Value::String(p)) => p.as_str(),
5585 Some(Value::Char(c)) => return Ok(Value::Bool(s.ends_with(*c))),
5586 _ => return Err(RuntimeError::new("ends_with expects string or char")),
5587 };
5588 return Ok(Value::Bool(s.ends_with(suffix)));
5589 }
5590 "contains" => {
5591 let substr = match arg_values.first() {
5592 Some(Value::String(p)) => p.as_str(),
5593 Some(Value::Char(c)) => return Ok(Value::Bool(s.contains(*c))),
5594 _ => return Err(RuntimeError::new("contains expects string or char")),
5595 };
5596 return Ok(Value::Bool(s.contains(substr)));
5597 }
5598 "trim" => return Ok(Value::String(Rc::new(s.trim().to_string()))),
5599 "to_lowercase" => return Ok(Value::String(Rc::new(s.to_lowercase()))),
5600 "to_uppercase" => return Ok(Value::String(Rc::new(s.to_uppercase()))),
5601 "chars" => {
5602 let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5603 return Ok(Value::Array(Rc::new(RefCell::new(chars))));
5604 }
5605 "split" => {
5606 let delim = match arg_values.first() {
5607 Some(Value::String(d)) => d.as_str().to_string(),
5608 Some(Value::Char(c)) => c.to_string(),
5609 _ => " ".to_string(),
5610 };
5611 let parts: Vec<Value> = s.split(&delim)
5612 .map(|p| Value::String(Rc::new(p.to_string())))
5613 .collect();
5614 return Ok(Value::Array(Rc::new(RefCell::new(parts))));
5615 }
5616 "replace" => {
5617 if arg_values.len() != 2 {
5618 return Err(RuntimeError::new("replace expects 2 arguments"));
5619 }
5620 let from = match &arg_values[0] {
5621 Value::String(f) => f.as_str().to_string(),
5622 Value::Char(c) => c.to_string(),
5623 _ => return Err(RuntimeError::new("replace expects strings")),
5624 };
5625 let to = match &arg_values[1] {
5626 Value::String(t) => t.as_str().to_string(),
5627 Value::Char(c) => c.to_string(),
5628 _ => return Err(RuntimeError::new("replace expects strings")),
5629 };
5630 return Ok(Value::String(Rc::new(s.replace(&from, &to))));
5631 }
5632 _ => {}
5633 }
5634 }
5635 if let Value::Array(arr) = &inner {
5637 match method.name.as_str() {
5638 "len" => return Ok(Value::Int(arr.borrow().len() as i64)),
5639 "is_empty" => return Ok(Value::Bool(arr.borrow().is_empty())),
5640 "push" => {
5641 if arg_values.len() != 1 {
5642 return Err(RuntimeError::new("push expects 1 argument"));
5643 }
5644 arr.borrow_mut().push(arg_values[0].clone());
5645 return Ok(Value::Null);
5646 }
5647 "pop" => {
5648 return arr.borrow_mut().pop()
5649 .ok_or_else(|| RuntimeError::new("pop on empty array"));
5650 }
5651 "contains" => {
5652 if arg_values.len() != 1 {
5653 return Err(RuntimeError::new("contains expects 1 argument"));
5654 }
5655 let target = &arg_values[0];
5656 let found = arr.borrow().iter().any(|v| self.values_equal(v, target));
5657 return Ok(Value::Bool(found));
5658 }
5659 "first" | "next" => {
5660 return Ok(arr.borrow().first().cloned().unwrap_or(Value::Null));
5661 }
5662 "last" => {
5663 return arr.borrow().last().cloned()
5664 .ok_or_else(|| RuntimeError::new("empty array"));
5665 }
5666 "iter" | "into_iter" => {
5667 return Ok(Value::Array(arr.clone()));
5668 }
5669 "reverse" => {
5670 let mut v = arr.borrow().clone();
5671 v.reverse();
5672 return Ok(Value::Array(Rc::new(RefCell::new(v))));
5673 }
5674 "skip" => {
5675 let n = match arg_values.first() {
5676 Some(Value::Int(i)) => *i as usize,
5677 _ => 1,
5678 };
5679 let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
5680 return Ok(Value::Array(Rc::new(RefCell::new(v))));
5681 }
5682 "take" => {
5683 let n = match arg_values.first() {
5684 Some(Value::Int(i)) => *i as usize,
5685 _ => 1,
5686 };
5687 let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
5688 return Ok(Value::Array(Rc::new(RefCell::new(v))));
5689 }
5690 "get" => {
5691 let idx = match arg_values.first() {
5692 Some(Value::Int(i)) => *i as usize,
5693 _ => return Err(RuntimeError::new("get expects integer index")),
5694 };
5695 return Ok(arr.borrow().get(idx).cloned().unwrap_or(Value::Null));
5696 }
5697 _ => {}
5698 }
5699 }
5700 if method.name == "clone" {
5702 crate::sigil_debug!("DEBUG clone: recv_type=Ref({:?})", std::mem::discriminant(&inner));
5703 return Ok(inner.clone());
5704 }
5705 if method.name == "into" {
5707 return Ok(inner.clone());
5708 }
5709 if method.name == "to_string" {
5711 return Ok(Value::String(Rc::new(format!("{}", inner))));
5712 }
5713 if let Value::Struct { name, fields, .. } = &inner {
5715 if name == "PathBuf" || name == "Path" {
5716 let borrowed = fields.borrow();
5717 if let Some(Value::String(path)) = borrowed.get("path") {
5718 match method.name.as_str() {
5719 "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5720 "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5721 "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5722 "join" => {
5723 if let Some(Value::String(other)) = arg_values.first() {
5724 let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5725 let mut new_fields = std::collections::HashMap::new();
5726 new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5727 return Ok(Value::Struct {
5728 name: "PathBuf".to_string(),
5729 fields: Rc::new(RefCell::new(new_fields)),
5730 });
5731 }
5732 return Err(RuntimeError::new("join requires string argument"));
5733 }
5734 "parent" => {
5735 let p = std::path::Path::new(path.as_str());
5736 return match p.parent() {
5737 Some(par) => {
5738 let mut new_fields = std::collections::HashMap::new();
5739 new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5740 Ok(Value::Struct {
5741 name: "PathBuf".to_string(),
5742 fields: Rc::new(RefCell::new(new_fields)),
5743 })
5744 }
5745 None => Ok(Value::Null),
5746 };
5747 }
5748 "file_name" => {
5749 let p = std::path::Path::new(path.as_str());
5750 return match p.file_name() {
5751 Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5752 None => Ok(Value::Null),
5753 };
5754 }
5755 "extension" => {
5756 let p = std::path::Path::new(path.as_str());
5757 return match p.extension() {
5758 Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5759 None => Ok(Value::Null),
5760 };
5761 }
5762 "to_string" | "display" => {
5763 return Ok(Value::String(path.clone()));
5764 }
5765 _ => {}
5766 }
5767 }
5768 }
5769 }
5770 if let Value::String(s) = &inner {
5772 match method.name.as_str() {
5773 "exists" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).exists())),
5774 "is_dir" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_dir())),
5775 "is_file" => return Ok(Value::Bool(std::path::Path::new(s.as_str()).is_file())),
5776 "join" => {
5777 if let Some(Value::String(other)) = arg_values.first() {
5778 let path = std::path::Path::new(s.as_str()).join(other.as_str());
5779 return Ok(Value::String(Rc::new(path.to_string_lossy().to_string())));
5780 }
5781 return Err(RuntimeError::new("join requires string argument"));
5782 }
5783 "parent" => {
5784 let path = std::path::Path::new(s.as_str());
5785 return match path.parent() {
5786 Some(p) => Ok(Value::String(Rc::new(p.to_string_lossy().to_string()))),
5787 None => Ok(Value::Null),
5788 };
5789 }
5790 "file_name" => {
5791 let path = std::path::Path::new(s.as_str());
5792 return match path.file_name() {
5793 Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5794 None => Ok(Value::Null),
5795 };
5796 }
5797 "extension" => {
5798 let path = std::path::Path::new(s.as_str());
5799 return match path.extension() {
5800 Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5801 None => Ok(Value::Null),
5802 };
5803 }
5804 _ => {}
5805 }
5806 }
5807 if let Value::String(_) = inner {
5810 let recv_unwrapped = inner.clone();
5813 match (&recv_unwrapped, method.name.as_str()) {
5814 (Value::String(s), "find") => {
5815 if arg_values.len() != 1 {
5816 return Err(RuntimeError::new("find expects 1 argument"));
5817 }
5818 match &arg_values[0] {
5819 Value::Char(c) => {
5820 return match s.find(*c) {
5821 Some(idx) => Ok(Value::Variant {
5822 enum_name: "Option".to_string(),
5823 variant_name: "Some".to_string(),
5824 fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5825 }),
5826 None => Ok(Value::Variant {
5827 enum_name: "Option".to_string(),
5828 variant_name: "None".to_string(),
5829 fields: None,
5830 }),
5831 }
5832 }
5833 Value::String(pattern) => {
5834 return match s.find(pattern.as_str()) {
5835 Some(idx) => Ok(Value::Variant {
5836 enum_name: "Option".to_string(),
5837 variant_name: "Some".to_string(),
5838 fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5839 }),
5840 None => Ok(Value::Variant {
5841 enum_name: "Option".to_string(),
5842 variant_name: "None".to_string(),
5843 fields: None,
5844 }),
5845 }
5846 }
5847 Value::Function(f) => {
5848 for (idx, c) in s.chars().enumerate() {
5849 let result = self.call_function(f, vec![Value::Char(c)])?;
5850 if let Value::Bool(true) = result {
5851 return Ok(Value::Variant {
5852 enum_name: "Option".to_string(),
5853 variant_name: "Some".to_string(),
5854 fields: Some(Rc::new(vec![Value::Int(idx as i64)])),
5855 });
5856 }
5857 }
5858 return Ok(Value::Variant {
5859 enum_name: "Option".to_string(),
5860 variant_name: "None".to_string(),
5861 fields: None,
5862 })
5863 }
5864 _ => return Err(RuntimeError::new("find expects a char, string, or closure")),
5865 }
5866 }
5867 (Value::String(s), "trim") => return Ok(Value::String(Rc::new(s.trim().to_string()))),
5868 (Value::String(s), "is_empty") => return Ok(Value::Bool(s.is_empty())),
5869 (Value::String(s), "len") => return Ok(Value::Int(s.len() as i64)),
5870 (Value::String(s), "to_string") => return Ok(Value::String(s.clone())),
5871 (Value::String(s), "chars") => {
5872 let chars: Vec<Value> = s.chars().map(Value::Char).collect();
5873 return Ok(Value::Array(Rc::new(RefCell::new(chars))))
5874 }
5875 (Value::String(s), "starts_with") => {
5876 if let Some(Value::String(prefix)) = arg_values.first() {
5877 return Ok(Value::Bool(s.starts_with(prefix.as_str())));
5878 }
5879 return Err(RuntimeError::new("starts_with expects string argument"));
5880 }
5881 _ => {}
5882 }
5883 }
5884 Err(RuntimeError::new(format!(
5885 "Cannot call method {} on Ref to non-struct",
5886 method.name
5887 )))
5888 }
5889 (Value::Struct { name, fields }, _) => {
5891 if method.name == "clone" {
5893 return Ok(recv.clone());
5895 }
5896 if name == "PathBuf" || name == "Path" {
5898 let borrowed = fields.borrow();
5899 if let Some(Value::String(path)) = borrowed.get("path") {
5900 match method.name.as_str() {
5901 "exists" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).exists())),
5902 "is_dir" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_dir())),
5903 "is_file" => return Ok(Value::Bool(std::path::Path::new(path.as_str()).is_file())),
5904 "join" => {
5905 if let Some(Value::String(other)) = arg_values.first() {
5906 let new_path = std::path::Path::new(path.as_str()).join(other.as_str());
5907 let mut new_fields = std::collections::HashMap::new();
5908 new_fields.insert("path".to_string(), Value::String(Rc::new(new_path.to_string_lossy().to_string())));
5909 return Ok(Value::Struct {
5910 name: "PathBuf".to_string(),
5911 fields: Rc::new(RefCell::new(new_fields)),
5912 });
5913 }
5914 return Err(RuntimeError::new("join requires string argument"));
5915 }
5916 "parent" => {
5917 let p = std::path::Path::new(path.as_str());
5918 return match p.parent() {
5919 Some(par) => {
5920 let mut new_fields = std::collections::HashMap::new();
5921 new_fields.insert("path".to_string(), Value::String(Rc::new(par.to_string_lossy().to_string())));
5922 Ok(Value::Struct {
5923 name: "PathBuf".to_string(),
5924 fields: Rc::new(RefCell::new(new_fields)),
5925 })
5926 }
5927 None => Ok(Value::Null),
5928 };
5929 }
5930 "file_name" => {
5931 let p = std::path::Path::new(path.as_str());
5932 return match p.file_name() {
5933 Some(n) => Ok(Value::String(Rc::new(n.to_string_lossy().to_string()))),
5934 None => Ok(Value::Null),
5935 };
5936 }
5937 "extension" => {
5938 let p = std::path::Path::new(path.as_str());
5939 return match p.extension() {
5940 Some(e) => Ok(Value::String(Rc::new(e.to_string_lossy().to_string()))),
5941 None => Ok(Value::Null),
5942 };
5943 }
5944 "to_string" | "display" => {
5945 return Ok(Value::String(path.clone()));
5946 }
5947 _ => {}
5948 }
5949 }
5950 }
5951 if name == "Rc" {
5953 let borrowed = fields.borrow();
5954 if let Some(value) = borrowed.get("_value") {
5955 match method.name.as_str() {
5956 "clone" => {
5957 let mut new_fields = HashMap::new();
5959 new_fields.insert("_value".to_string(), value.clone());
5960 return Ok(Value::Struct {
5961 name: "Rc".to_string(),
5962 fields: Rc::new(RefCell::new(new_fields)),
5963 });
5964 }
5965 _ => {}
5966 }
5967 }
5968 }
5969 if name == "Cell" {
5971 match method.name.as_str() {
5972 "get" => {
5973 let borrowed = fields.borrow();
5974 if let Some(value) = borrowed.get("_value") {
5975 return Ok(value.clone());
5976 }
5977 return Err(RuntimeError::new("Cell has no value"));
5978 }
5979 "set" => {
5980 if arg_values.len() != 1 {
5981 return Err(RuntimeError::new("set expects 1 argument"));
5982 }
5983 fields.borrow_mut().insert("_value".to_string(), arg_values[0].clone());
5984 return Ok(Value::Null);
5985 }
5986 _ => {}
5987 }
5988 }
5989 if name == "Duration" {
5991 let borrowed = fields.borrow();
5992 let secs = match borrowed.get("secs") {
5993 Some(Value::Int(s)) => *s,
5994 _ => 0,
5995 };
5996 let nanos = match borrowed.get("nanos") {
5997 Some(Value::Int(n)) => *n,
5998 _ => 0,
5999 };
6000 match method.name.as_str() {
6001 "as_secs" => return Ok(Value::Int(secs)),
6002 "as_millis" => return Ok(Value::Int(secs * 1000 + nanos / 1_000_000)),
6003 "as_micros" => return Ok(Value::Int(secs * 1_000_000 + nanos / 1000)),
6004 "as_nanos" => return Ok(Value::Int(secs * 1_000_000_000 + nanos)),
6005 "subsec_nanos" => return Ok(Value::Int(nanos)),
6006 "subsec_millis" => return Ok(Value::Int(nanos / 1_000_000)),
6007 "is_zero" => return Ok(Value::Bool(secs == 0 && nanos == 0)),
6008 _ => {}
6009 }
6010 }
6011 if name == "Mutex" {
6013 match method.name.as_str() {
6014 "lock" => {
6015 let borrowed = fields.borrow();
6018 if let Some(inner) = borrowed.get("__inner__") {
6019 return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6021 }
6022 return Err(RuntimeError::new("Mutex has no inner value"));
6023 }
6024 "try_lock" => {
6025 let borrowed = fields.borrow();
6027 if let Some(inner) = borrowed.get("__inner__") {
6028 let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6029 return Ok(Value::Variant {
6030 enum_name: "Option".to_string(),
6031 variant_name: "Some".to_string(),
6032 fields: Some(Rc::new(vec![guard])),
6033 });
6034 }
6035 return Ok(Value::Variant {
6036 enum_name: "Option".to_string(),
6037 variant_name: "None".to_string(),
6038 fields: None,
6039 });
6040 }
6041 "into_inner" => {
6042 let borrowed = fields.borrow();
6044 if let Some(inner) = borrowed.get("__inner__") {
6045 return Ok(inner.clone());
6046 }
6047 return Err(RuntimeError::new("Mutex has no inner value"));
6048 }
6049 "get_mut" => {
6050 let borrowed = fields.borrow();
6052 if let Some(inner) = borrowed.get("__inner__") {
6053 return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6054 }
6055 return Err(RuntimeError::new("Mutex has no inner value"));
6056 }
6057 _ => {}
6058 }
6059 }
6060 if name == "RwLock" {
6062 match method.name.as_str() {
6063 "read" => {
6064 let borrowed = fields.borrow();
6066 if let Some(inner) = borrowed.get("__inner__") {
6067 return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6068 }
6069 return Err(RuntimeError::new("RwLock has no inner value"));
6070 }
6071 "write" => {
6072 let borrowed = fields.borrow();
6074 if let Some(inner) = borrowed.get("__inner__") {
6075 return Ok(Value::Ref(Rc::new(RefCell::new(inner.clone()))));
6076 }
6077 return Err(RuntimeError::new("RwLock has no inner value"));
6078 }
6079 "try_read" => {
6080 let borrowed = fields.borrow();
6081 if let Some(inner) = borrowed.get("__inner__") {
6082 let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6083 return Ok(Value::Variant {
6084 enum_name: "Option".to_string(),
6085 variant_name: "Some".to_string(),
6086 fields: Some(Rc::new(vec![guard])),
6087 });
6088 }
6089 return Ok(Value::Variant {
6090 enum_name: "Option".to_string(),
6091 variant_name: "None".to_string(),
6092 fields: None,
6093 });
6094 }
6095 "try_write" => {
6096 let borrowed = fields.borrow();
6097 if let Some(inner) = borrowed.get("__inner__") {
6098 let guard = Value::Ref(Rc::new(RefCell::new(inner.clone())));
6099 return Ok(Value::Variant {
6100 enum_name: "Option".to_string(),
6101 variant_name: "Some".to_string(),
6102 fields: Some(Rc::new(vec![guard])),
6103 });
6104 }
6105 return Ok(Value::Variant {
6106 enum_name: "Option".to_string(),
6107 variant_name: "None".to_string(),
6108 fields: None,
6109 });
6110 }
6111 "into_inner" => {
6112 let borrowed = fields.borrow();
6113 if let Some(inner) = borrowed.get("__inner__") {
6114 return Ok(inner.clone());
6115 }
6116 return Err(RuntimeError::new("RwLock has no inner value"));
6117 }
6118 _ => {}
6119 }
6120 }
6121 if name == "AtomicU64" || name == "AtomicUsize" || name == "AtomicI64" || name == "AtomicIsize" {
6123 match method.name.as_str() {
6124 "load" => {
6125 let borrowed = fields.borrow();
6127 if let Some(val) = borrowed.get("__value__") {
6128 return Ok(val.clone());
6129 }
6130 return Ok(Value::Int(0));
6131 }
6132 "store" => {
6133 if let Some(new_val) = arg_values.first() {
6135 fields.borrow_mut().insert("__value__".to_string(), new_val.clone());
6136 return Ok(Value::Null);
6137 }
6138 return Err(RuntimeError::new("store requires a value"));
6139 }
6140 "fetch_add" => {
6141 if let Some(Value::Int(n)) = arg_values.first() {
6143 let mut borrowed = fields.borrow_mut();
6144 let old = match borrowed.get("__value__") {
6145 Some(Value::Int(v)) => *v,
6146 _ => 0,
6147 };
6148 borrowed.insert("__value__".to_string(), Value::Int(old + n));
6149 return Ok(Value::Int(old));
6150 }
6151 return Err(RuntimeError::new("fetch_add requires integer"));
6152 }
6153 "fetch_sub" => {
6154 if let Some(Value::Int(n)) = arg_values.first() {
6155 let mut borrowed = fields.borrow_mut();
6156 let old = match borrowed.get("__value__") {
6157 Some(Value::Int(v)) => *v,
6158 _ => 0,
6159 };
6160 borrowed.insert("__value__".to_string(), Value::Int(old - n));
6161 return Ok(Value::Int(old));
6162 }
6163 return Err(RuntimeError::new("fetch_sub requires integer"));
6164 }
6165 "swap" => {
6166 if let Some(new_val) = arg_values.first() {
6167 let mut borrowed = fields.borrow_mut();
6168 let old = borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
6169 borrowed.insert("__value__".to_string(), new_val.clone());
6170 return Ok(old);
6171 }
6172 return Err(RuntimeError::new("swap requires a value"));
6173 }
6174 "compare_exchange" | "compare_and_swap" => {
6175 if arg_values.len() >= 2 {
6177 let current = &arg_values[0];
6178 let new_val = &arg_values[1];
6179 let mut borrowed = fields.borrow_mut();
6180 let actual = borrowed.get("__value__").cloned().unwrap_or(Value::Int(0));
6181 if self.values_equal(&actual, current) {
6182 borrowed.insert("__value__".to_string(), new_val.clone());
6183 return Ok(Value::Variant {
6184 enum_name: "Result".to_string(),
6185 variant_name: "Ok".to_string(),
6186 fields: Some(Rc::new(vec![actual])),
6187 });
6188 } else {
6189 return Ok(Value::Variant {
6190 enum_name: "Result".to_string(),
6191 variant_name: "Err".to_string(),
6192 fields: Some(Rc::new(vec![actual])),
6193 });
6194 }
6195 }
6196 return Err(RuntimeError::new("compare_exchange requires two arguments"));
6197 }
6198 _ => {}
6199 }
6200 }
6201 if name == "AtomicBool" {
6203 match method.name.as_str() {
6204 "load" => {
6205 let borrowed = fields.borrow();
6206 if let Some(val) = borrowed.get("__value__") {
6207 return Ok(val.clone());
6208 }
6209 return Ok(Value::Bool(false));
6210 }
6211 "store" => {
6212 if let Some(new_val) = arg_values.first() {
6213 fields.borrow_mut().insert("__value__".to_string(), new_val.clone());
6214 return Ok(Value::Null);
6215 }
6216 return Err(RuntimeError::new("store requires a value"));
6217 }
6218 "swap" => {
6219 if let Some(new_val) = arg_values.first() {
6220 let mut borrowed = fields.borrow_mut();
6221 let old = borrowed.get("__value__").cloned().unwrap_or(Value::Bool(false));
6222 borrowed.insert("__value__".to_string(), new_val.clone());
6223 return Ok(old);
6224 }
6225 return Err(RuntimeError::new("swap requires a value"));
6226 }
6227 "fetch_and" => {
6228 if let Some(Value::Bool(b)) = arg_values.first() {
6229 let mut borrowed = fields.borrow_mut();
6230 let old = match borrowed.get("__value__") {
6231 Some(Value::Bool(v)) => *v,
6232 _ => false,
6233 };
6234 borrowed.insert("__value__".to_string(), Value::Bool(old && *b));
6235 return Ok(Value::Bool(old));
6236 }
6237 return Err(RuntimeError::new("fetch_and requires boolean"));
6238 }
6239 "fetch_or" => {
6240 if let Some(Value::Bool(b)) = arg_values.first() {
6241 let mut borrowed = fields.borrow_mut();
6242 let old = match borrowed.get("__value__") {
6243 Some(Value::Bool(v)) => *v,
6244 _ => false,
6245 };
6246 borrowed.insert("__value__".to_string(), Value::Bool(old || *b));
6247 return Ok(Value::Bool(old));
6248 }
6249 return Err(RuntimeError::new("fetch_or requires boolean"));
6250 }
6251 _ => {}
6252 }
6253 }
6254 if method.name == "to_string" {
6255 let field_str = fields.borrow().iter()
6257 .map(|(k, v)| format!("{}: {}", k, v))
6258 .collect::<Vec<_>>()
6259 .join(", ");
6260 return Ok(Value::String(Rc::new(format!("{} {{ {} }}", name, field_str))));
6261 }
6262
6263 if name.starts_with("Pattern::") {
6265 match method.name.as_str() {
6266 "evidentiality" => {
6267 if let Some(ev) = fields.borrow().get("evidentiality") {
6269 return Ok(ev.clone());
6270 }
6271 return Ok(Value::Null);
6272 }
6273 "name" | "binding_name" => {
6274 if let Some(n) = fields.borrow().get("name") {
6276 let result = match &n {
6279 Value::Struct { fields: inner_fields, .. } => {
6280 if let Some(inner_name) = inner_fields.borrow().get("name") {
6281 crate::sigil_debug!("DEBUG binding_name: returning inner name {} from {}", inner_name, name);
6282 inner_name.clone()
6283 } else {
6284 crate::sigil_debug!("DEBUG binding_name: returning struct {} from {}", n, name);
6285 n.clone()
6286 }
6287 }
6288 _ => {
6289 crate::sigil_debug!("DEBUG binding_name: returning {} from {}", n, name);
6290 n.clone()
6291 }
6292 };
6293 return Ok(result);
6294 }
6295 crate::sigil_debug!("DEBUG binding_name: 'name' field not found in {}, fields: {:?}", name, fields.borrow().keys().collect::<Vec<_>>());
6296 return Ok(Value::Null);
6298 }
6299 "mutable" => {
6300 if let Some(m) = fields.borrow().get("mutable") {
6302 return Ok(m.clone());
6303 }
6304 return Ok(Value::Bool(false));
6305 }
6306 "is_ident" => {
6307 return Ok(Value::Bool(name == "Pattern::Ident"));
6308 }
6309 "is_wildcard" => {
6310 return Ok(Value::Bool(name == "Pattern::Wildcard"));
6311 }
6312 "clone" => {
6313 return Ok(recv.clone());
6314 }
6315 _ => {}
6316 }
6317 }
6318
6319 if name == "PathBuf" || name == "Path" {
6321 match method.name.as_str() {
6322 "exists" => {
6323 let path = match fields.borrow().get("path") {
6325 Some(Value::String(s)) => s.to_string(),
6326 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6327 };
6328 return Ok(Value::Bool(std::path::Path::new(&path).exists()));
6329 }
6330 "is_dir" => {
6331 let path = match fields.borrow().get("path") {
6332 Some(Value::String(s)) => s.to_string(),
6333 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6334 };
6335 return Ok(Value::Bool(std::path::Path::new(&path).is_dir()));
6336 }
6337 "is_file" => {
6338 let path = match fields.borrow().get("path") {
6339 Some(Value::String(s)) => s.to_string(),
6340 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6341 };
6342 return Ok(Value::Bool(std::path::Path::new(&path).is_file()));
6343 }
6344 "extension" => {
6345 let path = match fields.borrow().get("path") {
6346 Some(Value::String(s)) => s.to_string(),
6347 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6348 };
6349 match std::path::Path::new(&path).extension() {
6350 Some(ext) => {
6351 let ext_str = ext.to_string_lossy().to_string();
6353 let mut ext_fields = HashMap::new();
6354 ext_fields.insert("value".to_string(), Value::String(Rc::new(ext_str)));
6355 return Ok(Value::Variant {
6356 enum_name: "Option".to_string(),
6357 variant_name: "Some".to_string(),
6358 fields: Some(Rc::new(vec![Value::Struct {
6359 name: "OsStr".to_string(),
6360 fields: Rc::new(RefCell::new(ext_fields)),
6361 }])),
6362 });
6363 }
6364 None => {
6365 return Ok(Value::Variant {
6366 enum_name: "Option".to_string(),
6367 variant_name: "None".to_string(),
6368 fields: None,
6369 });
6370 }
6371 }
6372 }
6373 "file_name" => {
6374 let path = match fields.borrow().get("path") {
6375 Some(Value::String(s)) => s.to_string(),
6376 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6377 };
6378 match std::path::Path::new(&path).file_name() {
6379 Some(fname) => {
6380 let fname_str = fname.to_string_lossy().to_string();
6381 let mut fname_fields = HashMap::new();
6382 fname_fields.insert("value".to_string(), Value::String(Rc::new(fname_str)));
6383 return Ok(Value::Variant {
6384 enum_name: "Option".to_string(),
6385 variant_name: "Some".to_string(),
6386 fields: Some(Rc::new(vec![Value::Struct {
6387 name: "OsStr".to_string(),
6388 fields: Rc::new(RefCell::new(fname_fields)),
6389 }])),
6390 });
6391 }
6392 None => {
6393 return Ok(Value::Variant {
6394 enum_name: "Option".to_string(),
6395 variant_name: "None".to_string(),
6396 fields: None,
6397 });
6398 }
6399 }
6400 }
6401 "parent" => {
6402 let path = match fields.borrow().get("path") {
6403 Some(Value::String(s)) => s.to_string(),
6404 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6405 };
6406 match std::path::Path::new(&path).parent() {
6407 Some(parent) => {
6408 let mut parent_fields = HashMap::new();
6409 parent_fields.insert("path".to_string(), Value::String(Rc::new(parent.to_string_lossy().to_string())));
6410 return Ok(Value::Variant {
6411 enum_name: "Option".to_string(),
6412 variant_name: "Some".to_string(),
6413 fields: Some(Rc::new(vec![Value::Struct {
6414 name: "Path".to_string(),
6415 fields: Rc::new(RefCell::new(parent_fields)),
6416 }])),
6417 });
6418 }
6419 None => {
6420 return Ok(Value::Variant {
6421 enum_name: "Option".to_string(),
6422 variant_name: "None".to_string(),
6423 fields: None,
6424 });
6425 }
6426 }
6427 }
6428 "to_str" => {
6429 let path = match fields.borrow().get("path") {
6431 Some(Value::String(s)) => s.clone(),
6432 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6433 };
6434 return Ok(Value::Variant {
6436 enum_name: "Option".to_string(),
6437 variant_name: "Some".to_string(),
6438 fields: Some(Rc::new(vec![Value::String(path)])),
6439 });
6440 }
6441 "to_string_lossy" => {
6442 let path = match fields.borrow().get("path") {
6443 Some(Value::String(s)) => s.clone(),
6444 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6445 };
6446 return Ok(Value::String(path));
6447 }
6448 "join" => {
6449 if arg_values.is_empty() {
6451 return Err(RuntimeError::new("join expects 1 argument"));
6452 }
6453 let base = match fields.borrow().get("path") {
6454 Some(Value::String(s)) => s.to_string(),
6455 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6456 };
6457 let component = match &arg_values[0] {
6458 Value::String(s) => s.to_string(),
6459 Value::Struct { name: n, fields: f } if n == "PathBuf" || n == "Path" => {
6460 match f.borrow().get("path") {
6461 Some(Value::String(s)) => s.to_string(),
6462 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6463 }
6464 }
6465 _ => return Err(RuntimeError::new("join expects string or PathBuf")),
6466 };
6467 let joined = std::path::Path::new(&base).join(&component);
6468 let mut new_fields = HashMap::new();
6469 new_fields.insert("path".to_string(), Value::String(Rc::new(joined.to_string_lossy().to_string())));
6470 return Ok(Value::Struct {
6471 name: "PathBuf".to_string(),
6472 fields: Rc::new(RefCell::new(new_fields)),
6473 });
6474 }
6475 "display" => {
6476 let path = match fields.borrow().get("path") {
6477 Some(Value::String(s)) => s.clone(),
6478 _ => return Err(RuntimeError::new("PathBuf has no path field")),
6479 };
6480 return Ok(Value::String(path));
6481 }
6482 "to_path_buf" => {
6483 return Ok(recv.clone());
6485 }
6486 _ => {}
6487 }
6488 }
6489
6490 if name == "OsStr" {
6492 match method.name.as_str() {
6493 "to_str" => {
6494 let val = match fields.borrow().get("value") {
6495 Some(Value::String(s)) => s.clone(),
6496 _ => return Err(RuntimeError::new("OsStr has no value field")),
6497 };
6498 return Ok(Value::Variant {
6499 enum_name: "Option".to_string(),
6500 variant_name: "Some".to_string(),
6501 fields: Some(Rc::new(vec![Value::String(val)])),
6502 });
6503 }
6504 "to_string_lossy" => {
6505 let val = match fields.borrow().get("value") {
6506 Some(Value::String(s)) => s.clone(),
6507 _ => return Err(RuntimeError::new("OsStr has no value field")),
6508 };
6509 return Ok(Value::String(val));
6510 }
6511 "to_lowercase" => {
6512 let val = match fields.borrow().get("value") {
6513 Some(Value::String(s)) => s.to_lowercase(),
6514 _ => return Err(RuntimeError::new("OsStr has no value field")),
6515 };
6516 return Ok(Value::String(Rc::new(val)));
6517 }
6518 "as_str" => {
6519 let val = match fields.borrow().get("value") {
6520 Some(Value::String(s)) => s.clone(),
6521 _ => return Err(RuntimeError::new("OsStr has no value field")),
6522 };
6523 return Ok(Value::String(val));
6524 }
6525 _ => {}
6526 }
6527 }
6528
6529 if name == "DirEntry" {
6531 match method.name.as_str() {
6532 "path" => {
6533 let path = match fields.borrow().get("path") {
6534 Some(Value::String(s)) => s.clone(),
6535 _ => return Err(RuntimeError::new("DirEntry has no path field")),
6536 };
6537 let mut path_fields = HashMap::new();
6538 path_fields.insert("path".to_string(), Value::String(path));
6539 return Ok(Value::Struct {
6540 name: "PathBuf".to_string(),
6541 fields: Rc::new(RefCell::new(path_fields)),
6542 });
6543 }
6544 "file_name" => {
6545 let path = match fields.borrow().get("path") {
6546 Some(Value::String(s)) => s.to_string(),
6547 _ => return Err(RuntimeError::new("DirEntry has no path field")),
6548 };
6549 let fname = std::path::Path::new(&path)
6550 .file_name()
6551 .map(|f| f.to_string_lossy().to_string())
6552 .unwrap_or_default();
6553 let mut fname_fields = HashMap::new();
6554 fname_fields.insert("value".to_string(), Value::String(Rc::new(fname)));
6555 return Ok(Value::Struct {
6556 name: "OsStr".to_string(),
6557 fields: Rc::new(RefCell::new(fname_fields)),
6558 });
6559 }
6560 _ => {}
6561 }
6562 }
6563
6564 if name == "Map" {
6566 match method.name.as_str() {
6567 "get" => {
6568 if arg_values.len() != 1 {
6570 return Err(RuntimeError::new("Map.get expects 1 argument"));
6571 }
6572 let key = match &arg_values[0] {
6573 Value::String(s) => s.to_string(),
6574 Value::Int(n) => n.to_string(),
6575 other => format!("{:?}", other),
6576 };
6577 if let Some(val) = fields.borrow().get(&key) {
6578 return Ok(val.clone());
6579 }
6580 return Ok(Value::Null);
6581 }
6582 "insert" => {
6583 if arg_values.len() != 2 {
6585 return Err(RuntimeError::new("Map.insert expects 2 arguments"));
6586 }
6587 let key = match &arg_values[0] {
6588 Value::String(s) => s.to_string(),
6589 Value::Int(n) => n.to_string(),
6590 other => format!("{:?}", other),
6591 };
6592 crate::sigil_debug!("DEBUG Map.insert: key='{}', value={}", key, arg_values[1]);
6593 fields.borrow_mut().insert(key, arg_values[1].clone());
6594 return Ok(Value::Null);
6595 }
6596 "contains_key" => {
6597 if arg_values.len() != 1 {
6598 return Err(RuntimeError::new("Map.contains_key expects 1 argument"));
6599 }
6600 let key = match &arg_values[0] {
6601 Value::String(s) => s.to_string(),
6602 Value::Int(n) => n.to_string(),
6603 other => format!("{:?}", other),
6604 };
6605 return Ok(Value::Bool(fields.borrow().contains_key(&key)));
6606 }
6607 "len" => {
6608 return Ok(Value::Int(fields.borrow().len() as i64));
6609 }
6610 "is_empty" => {
6611 return Ok(Value::Bool(fields.borrow().is_empty()));
6612 }
6613 "keys" => {
6614 let keys: Vec<Value> = fields.borrow()
6615 .keys()
6616 .map(|k| Value::String(Rc::new(k.clone())))
6617 .collect();
6618 return Ok(Value::Array(Rc::new(RefCell::new(keys))));
6619 }
6620 "values" => {
6621 let vals: Vec<Value> = fields.borrow()
6622 .values()
6623 .cloned()
6624 .collect();
6625 return Ok(Value::Array(Rc::new(RefCell::new(vals))));
6626 }
6627 "clone" => {
6628 return Ok(recv.clone());
6629 }
6630 _ => {}
6631 }
6632 }
6633
6634 let qualified_name = format!("{}·{}", name, method.name);
6635
6636 if name == "Parser" && (method.name == "parse_file" || method.name == "read_source") {
6638 crate::sigil_debug!("DEBUG Parser method call: {}", qualified_name);
6639 for (i, arg) in arg_values.iter().enumerate() {
6640 crate::sigil_debug!(" arg_value[{}] = {:?}", i, arg);
6641 }
6642 }
6643
6644 if name == "Lexer" {
6646 if method.name == "lex_ident_or_keyword" {
6648 for (i, arg) in arg_values.iter().enumerate() {
6649 let unwrapped = Self::unwrap_all(arg);
6650 if let Value::Char(c) = &unwrapped {
6651 crate::sigil_debug!("DEBUG Lexer·lex_ident_or_keyword arg[{}]='{}'", i, c);
6652 }
6653 }
6654 }
6655 crate::sigil_debug!("DEBUG Lexer method call: {}", qualified_name);
6656 }
6657 for arg in &arg_values {
6659 let unwrapped = Self::unwrap_all(arg);
6660 if let Value::String(s) = &unwrapped {
6661 if **s == "fn" {
6662 crate::sigil_debug!("DEBUG struct method with 'fn': {} recv_name={}", method.name, name);
6663 }
6664 }
6665 }
6666
6667 let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
6668 if let Some(func) = func {
6669 if let Value::Function(f) = func {
6670 let old_self_type = self.current_self_type.take();
6672 self.current_self_type = Some(name.clone());
6673
6674 let mut all_args = vec![recv.clone()];
6676 all_args.extend(arg_values.clone());
6677 let result = self.call_function(&f, all_args);
6678
6679 self.current_self_type = old_self_type;
6681 return result;
6682 } else if let Value::BuiltIn(b) = func {
6683 let mut all_args = vec![recv.clone()];
6684 all_args.extend(arg_values.clone());
6685 return (b.func)(self, all_args);
6686 }
6687 }
6688
6689 if name == "Self" {
6691 let field_names: Vec<String> = fields.borrow().keys().cloned().collect();
6693
6694 for (type_name, type_def) in &self.types {
6696 if let TypeDef::Struct(struct_def) = type_def {
6697 let def_fields: Vec<String> = match &struct_def.fields {
6699 crate::ast::StructFields::Named(fs) => fs.iter().map(|f| f.name.name.clone()).collect(),
6700 _ => continue,
6701 };
6702
6703 let matches = field_names.iter().all(|f| def_fields.contains(f));
6705 if matches {
6706 let qualified_name = format!("{}·{}", type_name, method.name);
6707 let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
6708 if let Some(func) = func {
6709 if let Value::Function(f) = func {
6710 let old_self_type = self.current_self_type.take();
6712 self.current_self_type = Some(type_name.clone());
6713
6714 let mut all_args = vec![recv.clone()];
6715 all_args.extend(arg_values.clone());
6716 let result = self.call_function(&f, all_args);
6717
6718 self.current_self_type = old_self_type;
6720 return result;
6721 } else if let Value::BuiltIn(b) = func {
6722 let mut all_args = vec![recv.clone()];
6723 all_args.extend(arg_values.clone());
6724 return (b.func)(self, all_args);
6725 }
6726 }
6727 }
6728 }
6729 }
6730 }
6731
6732 crate::sigil_warn!("WARN: Unknown method '{}' on '{}' - returning null", method.name, name);
6735 Ok(Value::Null)
6736 }
6737 (Value::Variant { enum_name, variant_name, fields }, _) => {
6739 if enum_name == "Option" {
6741 match method.name.as_str() {
6742 "cloned" => {
6743 return Ok(recv.clone());
6746 }
6747 "is_some" => {
6748 return Ok(Value::Bool(variant_name == "Some"));
6749 }
6750 "is_none" => {
6751 return Ok(Value::Bool(variant_name == "None"));
6752 }
6753 "unwrap" => {
6754 crate::sigil_debug!("DEBUG Option.unwrap: variant={}, fields={:?}", variant_name, fields);
6755 if variant_name == "Some" {
6756 if let Some(f) = fields {
6757 let result = f.first().cloned().unwrap_or(Value::Null);
6758 crate::sigil_debug!("DEBUG Option.unwrap: returning {:?}", result);
6759 return Ok(result);
6760 }
6761 }
6762 return Err(RuntimeError::new("unwrap on None"));
6763 }
6764 "unwrap_or" => {
6765 if variant_name == "Some" {
6766 if let Some(f) = fields {
6767 return Ok(f.first().cloned().unwrap_or(Value::Null));
6768 }
6769 }
6770 return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
6771 }
6772 "map" => {
6773 if variant_name == "Some" {
6775 if let Some(f) = fields {
6776 if let Some(inner) = f.first() {
6777 if let Some(Value::Function(func)) = arg_values.first() {
6778 let result = self.call_function(func, vec![inner.clone()])?;
6779 return Ok(Value::Variant {
6780 enum_name: "Option".to_string(),
6781 variant_name: "Some".to_string(),
6782 fields: Some(Rc::new(vec![result])),
6783 });
6784 }
6785 }
6786 }
6787 }
6788 return Ok(Value::Variant {
6789 enum_name: "Option".to_string(),
6790 variant_name: "None".to_string(),
6791 fields: None,
6792 });
6793 }
6794 "and_then" => {
6795 crate::sigil_debug!("DEBUG and_then: variant={}, has_fields={}, arg_count={}", variant_name, fields.is_some(), arg_values.len());
6797 if let Some(arg) = arg_values.first() {
6798 crate::sigil_debug!("DEBUG and_then: arg type = {:?}", std::mem::discriminant(arg));
6799 }
6800 if variant_name == "Some" {
6801 if let Some(f) = fields {
6802 if let Some(inner) = f.first() {
6803 crate::sigil_debug!("DEBUG and_then: inner = {:?}", inner);
6804 if let Some(Value::Function(func)) = arg_values.first() {
6805 let result = self.call_function(func, vec![inner.clone()])?;
6806 crate::sigil_debug!("DEBUG and_then: result = {:?}", result);
6807 return Ok(result);
6809 } else {
6810 crate::sigil_debug!("DEBUG and_then: arg is not a Function!");
6811 }
6812 }
6813 }
6814 }
6815 return Ok(Value::Variant {
6817 enum_name: "Option".to_string(),
6818 variant_name: "None".to_string(),
6819 fields: None,
6820 });
6821 }
6822 "or_else" => {
6823 if variant_name == "Some" {
6825 return Ok(recv.clone());
6827 }
6828 if let Some(Value::Function(func)) = arg_values.first() {
6830 return self.call_function(func, vec![]);
6831 }
6832 return Ok(recv.clone());
6833 }
6834 "ok_or" | "ok_or_else" => {
6835 if variant_name == "Some" {
6837 if let Some(f) = fields {
6838 if let Some(inner) = f.first() {
6839 return Ok(Value::Variant {
6840 enum_name: "Result".to_string(),
6841 variant_name: "Ok".to_string(),
6842 fields: Some(Rc::new(vec![inner.clone()])),
6843 });
6844 }
6845 }
6846 }
6847 let err_val = arg_values.first().cloned().unwrap_or(Value::String(Rc::new("None".to_string())));
6849 return Ok(Value::Variant {
6850 enum_name: "Result".to_string(),
6851 variant_name: "Err".to_string(),
6852 fields: Some(Rc::new(vec![err_val])),
6853 });
6854 }
6855 _ => {}
6856 }
6857 }
6858 if enum_name == "Result" {
6860 match method.name.as_str() {
6861 "is_ok" => {
6862 return Ok(Value::Bool(variant_name == "Ok"));
6863 }
6864 "is_err" => {
6865 return Ok(Value::Bool(variant_name == "Err"));
6866 }
6867 "ok" => {
6868 if variant_name == "Ok" {
6871 let inner = fields.as_ref()
6872 .and_then(|f| f.first().cloned())
6873 .unwrap_or(Value::Null);
6874 return Ok(Value::Variant {
6875 enum_name: "Option".to_string(),
6876 variant_name: "Some".to_string(),
6877 fields: Some(Rc::new(vec![inner])),
6878 });
6879 }
6880 return Ok(Value::Variant {
6881 enum_name: "Option".to_string(),
6882 variant_name: "None".to_string(),
6883 fields: None,
6884 });
6885 }
6886 "err" => {
6887 if variant_name == "Err" {
6890 let inner = fields.as_ref()
6891 .and_then(|f| f.first().cloned())
6892 .unwrap_or(Value::Null);
6893 return Ok(Value::Variant {
6894 enum_name: "Option".to_string(),
6895 variant_name: "Some".to_string(),
6896 fields: Some(Rc::new(vec![inner])),
6897 });
6898 }
6899 return Ok(Value::Variant {
6900 enum_name: "Option".to_string(),
6901 variant_name: "None".to_string(),
6902 fields: None,
6903 });
6904 }
6905 "unwrap" => {
6906 if variant_name == "Ok" {
6907 if let Some(f) = fields {
6908 return Ok(f.first().cloned().unwrap_or(Value::Null));
6909 }
6910 }
6911 return Err(RuntimeError::new("unwrap on Err"));
6912 }
6913 "unwrap_or" => {
6914 if variant_name == "Ok" {
6915 if let Some(f) = fields {
6916 return Ok(f.first().cloned().unwrap_or(Value::Null));
6917 }
6918 }
6919 return Ok(arg_values.first().cloned().unwrap_or(Value::Null));
6920 }
6921 "map" => {
6922 if variant_name == "Ok" {
6924 if let Some(Value::Function(f)) = arg_values.first() {
6925 let inner = fields.as_ref()
6926 .and_then(|f| f.first().cloned())
6927 .unwrap_or(Value::Null);
6928 let result = self.call_function(f, vec![inner])?;
6929 return Ok(Value::Variant {
6930 enum_name: "Result".to_string(),
6931 variant_name: "Ok".to_string(),
6932 fields: Some(Rc::new(vec![result])),
6933 });
6934 }
6935 }
6936 return Ok(recv.clone());
6938 }
6939 "map_err" => {
6940 if variant_name == "Err" {
6942 if let Some(Value::Function(f)) = arg_values.first() {
6943 let inner = fields.as_ref()
6944 .and_then(|f| f.first().cloned())
6945 .unwrap_or(Value::Null);
6946 let result = self.call_function(f, vec![inner])?;
6947 return Ok(Value::Variant {
6948 enum_name: "Result".to_string(),
6949 variant_name: "Err".to_string(),
6950 fields: Some(Rc::new(vec![result])),
6951 });
6952 }
6953 }
6954 return Ok(recv.clone());
6956 }
6957 "and_then" => {
6958 if variant_name == "Ok" {
6960 if let Some(Value::Function(f)) = arg_values.first() {
6961 let inner = fields.as_ref()
6962 .and_then(|f| f.first().cloned())
6963 .unwrap_or(Value::Null);
6964 return self.call_function(f, vec![inner]);
6965 }
6966 }
6967 return Ok(recv.clone());
6969 }
6970 _ => {}
6971 }
6972 }
6973 crate::sigil_debug!("DEBUG variant method call: enum_name={}, variant_name={}, method={}", enum_name, variant_name, method.name);
6975
6976 if enum_name == "Type" {
6978 match method.name.as_str() {
6979 "is_never" => {
6980 return Ok(Value::Bool(variant_name == "Never"));
6982 }
6983 "to_string" => {
6984 let type_str = match variant_name.as_str() {
6986 "Bool" => "bool".to_string(),
6987 "Int" => "i64".to_string(),
6988 "Float" => "f64".to_string(),
6989 "Str" => "str".to_string(),
6990 "Char" => "char".to_string(),
6991 "Unit" => "()".to_string(),
6992 "Never" => "!".to_string(),
6993 "Error" => "<error>".to_string(),
6994 other => format!("Type::{}", other),
6995 };
6996 return Ok(Value::String(Rc::new(type_str)));
6997 }
6998 _ => {}
6999 }
7000 }
7001
7002 if enum_name == "Pattern" {
7003 match method.name.as_str() {
7004 "evidentiality" => {
7005 if variant_name == "Ident" {
7007 if let Some(f) = fields {
7008 for field_val in f.iter() {
7011 if let Value::Struct { fields: inner, .. } = field_val {
7012 if let Some(ev) = inner.borrow().get("evidentiality") {
7013 return Ok(ev.clone());
7014 }
7015 }
7016 }
7017 if f.len() > 2 {
7019 return Ok(f[2].clone());
7020 }
7021 }
7022 }
7023 return Ok(Value::Null);
7025 }
7026 "name" => {
7027 if variant_name == "Ident" {
7029 if let Some(f) = fields {
7030 for field_val in f.iter() {
7031 if let Value::Struct { fields: inner, .. } = field_val {
7032 if let Some(n) = inner.borrow().get("name") {
7033 return Ok(n.clone());
7034 }
7035 }
7036 }
7037 if let Some(n) = f.first() {
7039 return Ok(n.clone());
7040 }
7041 }
7042 }
7043 return Ok(Value::Null);
7044 }
7045 "mutable" => {
7046 if variant_name == "Ident" {
7048 if let Some(f) = fields {
7049 for field_val in f.iter() {
7050 if let Value::Struct { fields: inner, .. } = field_val {
7051 if let Some(m) = inner.borrow().get("mutable") {
7052 return Ok(m.clone());
7053 }
7054 }
7055 }
7056 if f.len() > 1 {
7058 return Ok(f[1].clone());
7059 }
7060 }
7061 }
7062 return Ok(Value::Bool(false));
7063 }
7064 _ => {}
7065 }
7066 }
7067 if method.name == "clone" {
7069 return Ok(recv.clone());
7070 }
7071
7072 let qualified_name = format!("{}·{}", enum_name, method.name);
7073 let func = self.globals.borrow().get(&qualified_name).map(|v| v.clone());
7074 if let Some(func) = func {
7075 if let Value::Function(f) = func {
7076 let mut all_args = vec![recv.clone()];
7077 all_args.extend(arg_values.clone());
7078 return self.call_function(&f, all_args);
7079 } else if let Value::BuiltIn(b) = func {
7080 let mut all_args = vec![recv.clone()];
7081 all_args.extend(arg_values.clone());
7082 return (b.func)(self, all_args);
7083 }
7084 }
7085 crate::sigil_warn!("WARN: Unknown method '{}' on enum '{}' - returning null", method.name, enum_name);
7087 Ok(Value::Null)
7088 }
7089 (Value::Null, "len_utf8") => Ok(Value::Int(0)),
7091 (Value::Null, "is_ascii") => Ok(Value::Bool(false)),
7092 (Value::Null, "is_alphabetic") => Ok(Value::Bool(false)),
7093 (Value::Null, "is_alphanumeric") => Ok(Value::Bool(false)),
7094 (Value::Null, "is_numeric") | (Value::Null, "is_digit") => Ok(Value::Bool(false)),
7095 (Value::Null, "is_whitespace") => Ok(Value::Bool(false)),
7096 (Value::Null, "is_uppercase") => Ok(Value::Bool(false)),
7097 (Value::Null, "is_lowercase") => Ok(Value::Bool(false)),
7098 (Value::Null, "len") => Ok(Value::Int(0)),
7099 (Value::Null, "is_empty") => Ok(Value::Bool(true)),
7100 (Value::Null, "to_string") => Ok(Value::String(Rc::new("".to_string()))),
7101 (Value::Null, "clone") => Ok(Value::Null),
7102 (Value::Null, "is_some") => Ok(Value::Bool(false)),
7103 (Value::Null, "is_none") => Ok(Value::Bool(true)),
7104 (Value::Null, "unwrap_or") => {
7105 if arg_values.is_empty() {
7106 Ok(Value::Null)
7107 } else {
7108 Ok(arg_values[0].clone())
7109 }
7110 }
7111 (Value::Char(c), "unwrap_or") => Ok(Value::Char(*c)),
7113 (Value::Int(n), "unwrap_or") => Ok(Value::Int(*n)),
7114 (Value::Float(n), "unwrap_or") => Ok(Value::Float(*n)),
7115 (Value::String(s), "unwrap_or") => Ok(Value::String(s.clone())),
7116 (Value::Bool(b), "unwrap_or") => Ok(Value::Bool(*b)),
7117 (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
7119 Ok(Value::String(Rc::new(n.to_string())))
7120 }
7121 (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
7122 (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
7123 (Value::Int(n), "duration_since") => {
7124 let other_ns = match arg_values.first() {
7127 Some(Value::Int(i)) => *i,
7128 Some(Value::Struct { fields, .. }) => {
7129 let borrowed = fields.borrow();
7130 let secs = match borrowed.get("secs") {
7131 Some(Value::Int(s)) => *s,
7132 _ => 0,
7133 };
7134 let nanos = match borrowed.get("nanos") {
7135 Some(Value::Int(n)) => *n,
7136 _ => 0,
7137 };
7138 secs * 1_000_000_000 + nanos
7139 }
7140 _ => 0,
7141 };
7142 let diff_ns = n - other_ns;
7143 let mut fields = std::collections::HashMap::new();
7144 fields.insert("secs".to_string(), Value::Int(diff_ns / 1_000_000_000));
7145 fields.insert("nanos".to_string(), Value::Int(diff_ns % 1_000_000_000));
7146 Ok(Value::Variant {
7147 enum_name: "Result".to_string(),
7148 variant_name: "Ok".to_string(),
7149 fields: Some(Rc::new(vec![Value::Struct {
7150 name: "Duration".to_string(),
7151 fields: Rc::new(RefCell::new(fields)),
7152 }])),
7153 })
7154 }
7155 (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
7157 Ok(Value::String(Rc::new(n.to_string())))
7158 }
7159 (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
7160 (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
7161 (Value::Bool(b), "to_string") | (Value::Bool(b), "string") => {
7163 Ok(Value::String(Rc::new(b.to_string())))
7164 }
7165 (Value::Char(c), "to_string") | (Value::Char(c), "string") => {
7167 Ok(Value::String(Rc::new(c.to_string())))
7168 }
7169 _ => {
7170 let recv_type = match &recv {
7172 Value::String(s) => format!("String(len={})", s.len()),
7173 Value::Array(arr) => format!("Array(len={})", arr.borrow().len()),
7174 Value::Struct { name, .. } => format!("Struct({})", name),
7175 Value::Variant { enum_name, variant_name, .. } => format!("Variant({}::{})", enum_name, variant_name),
7176 Value::Ref(r) => format!("Ref({:?})", std::mem::discriminant(&*r.borrow())),
7177 Value::Null => "Null".to_string(),
7178 other => format!("{:?}", std::mem::discriminant(other)),
7179 };
7180 crate::sigil_warn!("WARN: Unknown method '{}' on recv_type={} - returning null", method.name, recv_type);
7181 Ok(Value::Null)
7183 }
7184 }
7185 }
7186
7187 fn eval_incorporation(
7190 &mut self,
7191 segments: &[IncorporationSegment],
7192 ) -> Result<Value, RuntimeError> {
7193 if segments.is_empty() {
7194 return Err(RuntimeError::new("empty incorporation chain"));
7195 }
7196
7197 let first = &segments[0];
7199 let mut value = if let Some(args) = &first.args {
7200 let arg_values: Vec<Value> = args
7202 .iter()
7203 .map(|a| self.evaluate(a))
7204 .collect::<Result<_, _>>()?;
7205 self.call_function_by_name(&first.name.name, arg_values)?
7206 } else {
7207 self.environment
7209 .borrow()
7210 .get(&first.name.name)
7211 .ok_or_else(|| RuntimeError::new(format!("undefined: {}", first.name.name)))?
7212 };
7213
7214 for segment in segments.iter().skip(1) {
7216 let arg_values: Vec<Value> = segment
7217 .args
7218 .as_ref()
7219 .map(|args| {
7220 args.iter()
7221 .map(|a| self.evaluate(a))
7222 .collect::<Result<Vec<_>, _>>()
7223 })
7224 .transpose()?
7225 .unwrap_or_default();
7226
7227 value = self.call_incorporation_method(&value, &segment.name.name, arg_values)?;
7229 }
7230
7231 Ok(value)
7232 }
7233
7234 fn call_incorporation_method(
7237 &mut self,
7238 receiver: &Value,
7239 method_name: &str,
7240 args: Vec<Value>,
7241 ) -> Result<Value, RuntimeError> {
7242 match (receiver, method_name) {
7244 (Value::String(s), "len") => Ok(Value::Int(s.len() as i64)),
7246 (Value::String(s), "upper") | (Value::String(s), "uppercase") | (Value::String(s), "to_uppercase") => {
7247 Ok(Value::String(Rc::new(s.to_uppercase())))
7248 }
7249 (Value::String(s), "lower") | (Value::String(s), "lowercase") | (Value::String(s), "to_lowercase") => {
7250 Ok(Value::String(Rc::new(s.to_lowercase())))
7251 }
7252 (Value::String(s), "trim") => Ok(Value::String(Rc::new(s.trim().to_string()))),
7253 (Value::String(s), "chars") => {
7254 let chars: Vec<Value> = s
7255 .chars()
7256 .map(|c| Value::String(Rc::new(c.to_string())))
7257 .collect();
7258 Ok(Value::Array(Rc::new(RefCell::new(chars))))
7259 }
7260 (Value::String(s), "lines") => {
7261 let lines: Vec<Value> = s
7262 .lines()
7263 .map(|l| Value::String(Rc::new(l.to_string())))
7264 .collect();
7265 Ok(Value::Array(Rc::new(RefCell::new(lines))))
7266 }
7267 (Value::String(s), "bytes") => {
7268 let bytes: Vec<Value> = s.bytes().map(|b| Value::Int(b as i64)).collect();
7269 Ok(Value::Array(Rc::new(RefCell::new(bytes))))
7270 }
7271 (Value::String(s), "parse_int") | (Value::String(s), "to_int") => s
7272 .parse::<i64>()
7273 .map(Value::Int)
7274 .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as int", s))),
7275 (Value::String(s), "parse_float") | (Value::String(s), "to_float") => s
7276 .parse::<f64>()
7277 .map(Value::Float)
7278 .map_err(|_| RuntimeError::new(format!("cannot parse '{}' as float", s))),
7279 (Value::String(s), "as_str") => {
7280 if s.len() <= 10 { crate::sigil_debug!("DEBUG as_str: '{}'", s); }
7281 Ok(Value::String(s.clone()))
7282 }
7283 (Value::String(s), "to_string") => Ok(Value::String(s.clone())),
7284 (Value::String(s), "starts_with") => {
7285 if args.len() != 1 {
7286 return Err(RuntimeError::new("starts_with expects 1 argument"));
7287 }
7288 match &args[0] {
7289 Value::String(prefix) => Ok(Value::Bool(s.starts_with(prefix.as_str()))),
7290 _ => Err(RuntimeError::new("starts_with expects string")),
7291 }
7292 }
7293 (Value::String(s), "ends_with") => {
7294 if args.len() != 1 {
7295 return Err(RuntimeError::new("ends_with expects 1 argument"));
7296 }
7297 match &args[0] {
7298 Value::String(suffix) => Ok(Value::Bool(s.ends_with(suffix.as_str()))),
7299 _ => Err(RuntimeError::new("ends_with expects string")),
7300 }
7301 }
7302 (Value::String(s), "is_empty") => Ok(Value::Bool(s.is_empty())),
7303 (Value::String(s), "clone") => Ok(Value::String(Rc::new((**s).clone()))),
7304 (Value::String(s), "first") => s
7305 .chars()
7306 .next()
7307 .map(Value::Char)
7308 .ok_or_else(|| RuntimeError::new("empty string")),
7309 (Value::String(s), "last") => s
7310 .chars()
7311 .last()
7312 .map(Value::Char)
7313 .ok_or_else(|| RuntimeError::new("empty string")),
7314
7315 (Value::Array(arr), "len") => Ok(Value::Int(arr.borrow().len() as i64)),
7317 (Value::Array(arr), "first") | (Value::Array(arr), "next") => Ok(arr
7318 .borrow()
7319 .first()
7320 .cloned()
7321 .unwrap_or(Value::Null)),
7322 (Value::Array(arr), "last") => arr
7323 .borrow()
7324 .last()
7325 .cloned()
7326 .ok_or_else(|| RuntimeError::new("empty array")),
7327 (Value::Array(arr), "reverse") | (Value::Array(arr), "rev") => {
7328 let mut v = arr.borrow().clone();
7329 v.reverse();
7330 Ok(Value::Array(Rc::new(RefCell::new(v))))
7331 }
7332 (Value::Array(arr), "join") => {
7333 let sep = args
7334 .first()
7335 .map(|v| match v {
7336 Value::String(s) => s.to_string(),
7337 _ => "".to_string(),
7338 })
7339 .unwrap_or_default();
7340 let joined = arr
7341 .borrow()
7342 .iter()
7343 .map(|v| format!("{}", v))
7344 .collect::<Vec<_>>()
7345 .join(&sep);
7346 Ok(Value::String(Rc::new(joined)))
7347 }
7348 (Value::Array(arr), "sum") => {
7349 let mut sum = 0i64;
7350 for v in arr.borrow().iter() {
7351 match v {
7352 Value::Int(i) => sum += i,
7353 Value::Float(f) => return Ok(Value::Float(sum as f64 + f)),
7354 _ => {}
7355 }
7356 }
7357 Ok(Value::Int(sum))
7358 }
7359 (Value::Array(arr), "skip") => {
7360 let n = match args.first() {
7361 Some(Value::Int(i)) => *i as usize,
7362 _ => 1,
7363 };
7364 let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
7365 Ok(Value::Array(Rc::new(RefCell::new(v))))
7366 }
7367 (Value::Array(arr), "take") => {
7368 let n = match args.first() {
7369 Some(Value::Int(i)) => *i as usize,
7370 _ => 1,
7371 };
7372 let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
7373 Ok(Value::Array(Rc::new(RefCell::new(v))))
7374 }
7375 (Value::Array(arr), "step_by") => {
7376 let n = match args.first() {
7377 Some(Value::Int(i)) if *i > 0 => *i as usize,
7378 _ => 1,
7379 };
7380 let v: Vec<Value> = arr.borrow().iter().step_by(n).cloned().collect();
7381 Ok(Value::Array(Rc::new(RefCell::new(v))))
7382 }
7383
7384 (Value::Int(n), "abs") => Ok(Value::Int(n.abs())),
7386 (Value::Float(n), "abs") => Ok(Value::Float(n.abs())),
7387 (Value::Int(n), "to_string") | (Value::Int(n), "string") => {
7388 Ok(Value::String(Rc::new(n.to_string())))
7389 }
7390 (Value::Float(n), "to_string") | (Value::Float(n), "string") => {
7391 Ok(Value::String(Rc::new(n.to_string())))
7392 }
7393 (Value::Int(n), "to_float") | (Value::Int(n), "float") => Ok(Value::Float(*n as f64)),
7394 (Value::Float(n), "to_int") | (Value::Float(n), "int") => Ok(Value::Int(*n as i64)),
7395
7396 (Value::Map(map), field) => map
7398 .borrow()
7399 .get(field)
7400 .cloned()
7401 .ok_or_else(|| RuntimeError::new(format!("no field '{}' in map", field))),
7402 (Value::Struct { fields, .. }, field) => fields
7403 .borrow()
7404 .get(field)
7405 .cloned()
7406 .ok_or_else(|| RuntimeError::new(format!("no field '{}' in struct", field))),
7407
7408 _ => {
7410 let mut all_args = vec![receiver.clone()];
7411 all_args.extend(args);
7412 self.call_function_by_name(method_name, all_args)
7413 }
7414 }
7415 }
7416
7417 pub fn call_function_by_name(
7419 &mut self,
7420 name: &str,
7421 args: Vec<Value>,
7422 ) -> Result<Value, RuntimeError> {
7423 let func_value = self.environment.borrow().get(name);
7425
7426 match func_value {
7427 Some(Value::Function(f)) => self.call_function(&f, args),
7428 Some(Value::BuiltIn(b)) => self.call_builtin(&b, args),
7429 Some(_) => Err(RuntimeError::new(format!("{} is not a function", name))),
7430 None => {
7431 if let Some((enum_name, variant_name, arity)) = self.variant_constructors.get(name).cloned() {
7433 if arity == 0 && args.is_empty() {
7434 return Ok(Value::Variant {
7435 enum_name,
7436 variant_name,
7437 fields: None,
7438 });
7439 } else if args.len() == arity {
7440 return Ok(Value::Variant {
7441 enum_name,
7442 variant_name,
7443 fields: Some(Rc::new(args)),
7444 });
7445 } else {
7446 return Err(RuntimeError::new(format!(
7447 "{} expects {} arguments, got {}",
7448 name, arity, args.len()
7449 )));
7450 }
7451 }
7452 Err(RuntimeError::new(format!("undefined function: {}", name)))
7453 }
7454 }
7455 }
7456
7457 fn eval_pipe(&mut self, expr: &Expr, operations: &[PipeOp]) -> Result<Value, RuntimeError> {
7458 let mut value = self.evaluate(expr)?;
7459
7460 for op in operations {
7461 value = self.apply_pipe_op(value, op)?;
7462 }
7463
7464 Ok(value)
7465 }
7466
7467 fn apply_pipe_op(&mut self, value: Value, op: &PipeOp) -> Result<Value, RuntimeError> {
7468 let value = Self::unwrap_all(&value);
7470
7471 match op {
7472 PipeOp::Transform(body) => {
7473 let (param_pattern, inner_body) = match body.as_ref() {
7476 Expr::Closure { params, body, .. } => {
7477 let pattern = params.first().map(|p| p.pattern.clone());
7478 (pattern, body.as_ref())
7479 }
7480 _ => (None, body.as_ref()),
7481 };
7482
7483 match value {
7484 Value::Array(arr) => {
7485 let results: Vec<Value> = arr
7486 .borrow()
7487 .iter()
7488 .map(|item| {
7489 if let Some(ref pattern) = param_pattern {
7491 self.bind_pattern(pattern, item.clone())?;
7492 } else {
7493 self.environment
7494 .borrow_mut()
7495 .define("_".to_string(), item.clone());
7496 }
7497 self.evaluate(inner_body)
7498 })
7499 .collect::<Result<_, _>>()?;
7500 Ok(Value::Array(Rc::new(RefCell::new(results))))
7501 }
7502 single => {
7503 if let Some(ref pattern) = param_pattern {
7504 self.bind_pattern(pattern, single)?;
7505 } else {
7506 self.environment
7507 .borrow_mut()
7508 .define("_".to_string(), single);
7509 }
7510 self.evaluate(inner_body)
7511 }
7512 }
7513 }
7514 PipeOp::Filter(predicate) => {
7515 let (param_pattern, inner_pred) = match predicate.as_ref() {
7518 Expr::Closure { params, body, .. } => {
7519 let pattern = params.first().map(|p| p.pattern.clone());
7520 (pattern, body.as_ref())
7521 }
7522 _ => (None, predicate.as_ref()),
7523 };
7524
7525 match value {
7526 Value::Array(arr) => {
7527 let results: Vec<Value> = arr
7528 .borrow()
7529 .iter()
7530 .filter_map(|item| {
7531 if let Some(ref pattern) = param_pattern {
7533 if let Err(e) = self.bind_pattern(pattern, item.clone()) {
7534 return Some(Err(e));
7535 }
7536 } else {
7537 self.environment
7538 .borrow_mut()
7539 .define("_".to_string(), item.clone());
7540 }
7541 match self.evaluate(inner_pred) {
7542 Ok(v) if self.is_truthy(&v) => Some(Ok(item.clone())),
7543 Ok(_) => None,
7544 Err(e) => Some(Err(e)),
7545 }
7546 })
7547 .collect::<Result<_, _>>()?;
7548 Ok(Value::Array(Rc::new(RefCell::new(results))))
7549 }
7550 _ => Err(RuntimeError::new("Filter requires array")),
7551 }
7552 }
7553 PipeOp::Sort(field) => {
7554 match value {
7556 Value::Array(arr) => {
7557 let mut v = arr.borrow().clone();
7558 v.sort_by(|a, b| self.compare_values(a, b, field));
7559 Ok(Value::Array(Rc::new(RefCell::new(v))))
7560 }
7561 _ => Err(RuntimeError::new("Sort requires array")),
7562 }
7563 }
7564 PipeOp::Reduce(body) => {
7565 match value {
7567 Value::Array(arr) => {
7568 let arr = arr.borrow();
7569 if arr.is_empty() {
7570 return Err(RuntimeError::new("Cannot reduce empty array"));
7571 }
7572 let mut acc = arr[0].clone();
7573 for item in arr.iter().skip(1) {
7574 self.environment.borrow_mut().define("acc".to_string(), acc);
7575 self.environment
7576 .borrow_mut()
7577 .define("_".to_string(), item.clone());
7578 acc = self.evaluate(body)?;
7579 }
7580 Ok(acc)
7581 }
7582 _ => Err(RuntimeError::new("Reduce requires array")),
7583 }
7584 }
7585 PipeOp::ReduceSum => {
7586 self.sum_values(value)
7588 }
7589 PipeOp::ReduceProd => {
7590 self.product_values(value)
7592 }
7593 PipeOp::ReduceMin => {
7594 self.min_values(value)
7596 }
7597 PipeOp::ReduceMax => {
7598 self.max_values(value)
7600 }
7601 PipeOp::ReduceConcat => {
7602 self.concat_values(value)
7604 }
7605 PipeOp::ReduceAll => {
7606 self.all_values(value)
7608 }
7609 PipeOp::ReduceAny => {
7610 self.any_values(value)
7612 }
7613 PipeOp::Match(arms) => {
7614 for arm in arms {
7616 if self.pattern_matches(&arm.pattern, &value)? {
7617 let prev_env = self.environment.clone();
7619 self.environment =
7620 Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
7621
7622 self.bind_pattern(&arm.pattern, value.clone())?;
7624
7625 self.environment
7627 .borrow_mut()
7628 .define("_".to_string(), value.clone());
7629
7630 let guard_passes = if let Some(guard) = &arm.guard {
7632 matches!(self.evaluate(guard)?, Value::Bool(true))
7633 } else {
7634 true
7635 };
7636
7637 if guard_passes {
7638 let result = self.evaluate(&arm.body)?;
7639 self.environment = prev_env;
7640 return Ok(result);
7641 }
7642
7643 self.environment = prev_env;
7645 }
7646 }
7647 Err(RuntimeError::new("No pattern matched in pipe match"))
7648 }
7649 PipeOp::TryMap(mapper) => {
7650 match &value {
7652 Value::Struct { name, fields } if name == "Ok" || name.ends_with("::Ok") => {
7654 let fields = fields.borrow();
7656 fields
7657 .get("0")
7658 .or_else(|| fields.get("value"))
7659 .cloned()
7660 .ok_or_else(|| RuntimeError::new("Ok variant has no value"))
7661 }
7662 Value::Struct { name, fields } if name == "Err" || name.ends_with("::Err") => {
7663 let fields = fields.borrow();
7665 let err_val = fields
7666 .get("0")
7667 .or_else(|| fields.get("error"))
7668 .cloned()
7669 .unwrap_or(Value::Null);
7670 if let Some(mapper_expr) = mapper {
7671 let prev_env = self.environment.clone();
7673 self.environment =
7674 Rc::new(RefCell::new(Environment::with_parent(prev_env.clone())));
7675 self.environment
7676 .borrow_mut()
7677 .define("_".to_string(), err_val);
7678 let mapped = self.evaluate(mapper_expr)?;
7679 self.environment = prev_env;
7680 Err(RuntimeError::new(format!("Error: {:?}", mapped)))
7681 } else {
7682 Err(RuntimeError::new(format!("Error: {:?}", err_val)))
7683 }
7684 }
7685 Value::Struct { name, fields }
7687 if name == "Some" || name.ends_with("::Some") =>
7688 {
7689 let fields = fields.borrow();
7690 fields
7691 .get("0")
7692 .or_else(|| fields.get("value"))
7693 .cloned()
7694 .ok_or_else(|| RuntimeError::new("Some variant has no value"))
7695 }
7696 Value::Struct { name, .. } if name == "None" || name.ends_with("::None") => {
7697 Err(RuntimeError::new("Unwrapped None value"))
7698 }
7699 Value::Null => Err(RuntimeError::new("Unwrapped null value")),
7700 _ => Ok(value),
7702 }
7703 }
7704 PipeOp::Call(callee) => {
7705 let callee_val = self.evaluate(callee)?;
7707 match callee_val {
7708 Value::Function(f) => {
7709 self.call_function(&f, vec![value])
7711 }
7712 Value::BuiltIn(b) => {
7713 self.call_builtin(&b, vec![value])
7715 }
7716 Value::Struct { .. } => {
7717 Ok(value)
7720 }
7721 _ => Err(RuntimeError::new(format!(
7722 "Cannot call non-function value in pipe: {:?}",
7723 callee_val
7724 ))),
7725 }
7726 }
7727 PipeOp::Method { name, type_args: _, args } => {
7728 let arg_values: Vec<Value> = args
7729 .iter()
7730 .map(|a| self.evaluate(a))
7731 .collect::<Result<_, _>>()?;
7732
7733 match name.name.as_str() {
7735 "collect" => Ok(value), "sum" | "Σ" => self.sum_values(value),
7737 "product" | "Π" => self.product_values(value),
7738 "len" => match &value {
7739 Value::Array(arr) => Ok(Value::Int(arr.borrow().len() as i64)),
7740 Value::String(s) => Ok(Value::Int(s.len() as i64)),
7741 _ => Err(RuntimeError::new("len requires array or string")),
7742 },
7743 "reverse" => match value {
7744 Value::Array(arr) => {
7745 let mut v = arr.borrow().clone();
7746 v.reverse();
7747 Ok(Value::Array(Rc::new(RefCell::new(v))))
7748 }
7749 _ => Err(RuntimeError::new("reverse requires array")),
7750 },
7751 "iter" | "into_iter" => {
7752 Ok(value)
7754 },
7755 "enumerate" => {
7756 match &value {
7758 Value::Array(arr) => {
7759 let enumerated: Vec<Value> = arr
7760 .borrow()
7761 .iter()
7762 .enumerate()
7763 .map(|(i, v)| {
7764 Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
7765 })
7766 .collect();
7767 Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
7768 }
7769 _ => Err(RuntimeError::new("enumerate requires array")),
7770 }
7771 },
7772 "first" => match &value {
7773 Value::Array(arr) => arr
7774 .borrow()
7775 .first()
7776 .cloned()
7777 .ok_or_else(|| RuntimeError::new("first on empty array")),
7778 _ => Err(RuntimeError::new("first requires array")),
7779 },
7780 "last" => match &value {
7781 Value::Array(arr) => arr
7782 .borrow()
7783 .last()
7784 .cloned()
7785 .ok_or_else(|| RuntimeError::new("last on empty array")),
7786 _ => Err(RuntimeError::new("last requires array")),
7787 },
7788 "take" => {
7789 if arg_values.len() != 1 {
7790 return Err(RuntimeError::new("take requires 1 argument"));
7791 }
7792 let n = match &arg_values[0] {
7793 Value::Int(n) => *n as usize,
7794 _ => return Err(RuntimeError::new("take requires integer")),
7795 };
7796 match value {
7797 Value::Array(arr) => {
7798 let v: Vec<Value> = arr.borrow().iter().take(n).cloned().collect();
7799 Ok(Value::Array(Rc::new(RefCell::new(v))))
7800 }
7801 _ => Err(RuntimeError::new("take requires array")),
7802 }
7803 }
7804 "skip" => {
7805 if arg_values.len() != 1 {
7806 return Err(RuntimeError::new("skip requires 1 argument"));
7807 }
7808 let n = match &arg_values[0] {
7809 Value::Int(n) => *n as usize,
7810 _ => return Err(RuntimeError::new("skip requires integer")),
7811 };
7812 match value {
7813 Value::Array(arr) => {
7814 let v: Vec<Value> = arr.borrow().iter().skip(n).cloned().collect();
7815 Ok(Value::Array(Rc::new(RefCell::new(v))))
7816 }
7817 _ => Err(RuntimeError::new("skip requires array")),
7818 }
7819 }
7820 "join" => {
7821 let separator = if arg_values.is_empty() {
7823 String::new()
7824 } else {
7825 match &arg_values[0] {
7826 Value::String(s) => (**s).clone(),
7827 _ => return Err(RuntimeError::new("join separator must be string")),
7828 }
7829 };
7830 match value {
7831 Value::Array(arr) => {
7832 let parts: Vec<String> = arr.borrow().iter()
7833 .map(|v| format!("{}", Self::unwrap_all(v)))
7834 .collect();
7835 Ok(Value::String(Rc::new(parts.join(&separator))))
7836 }
7837 _ => Err(RuntimeError::new("join requires array")),
7838 }
7839 }
7840 "all" => {
7841 match value {
7843 Value::Array(arr) => {
7844 for item in arr.borrow().iter() {
7845 if !self.is_truthy(item) {
7846 return Ok(Value::Bool(false));
7847 }
7848 }
7849 Ok(Value::Bool(true))
7850 }
7851 _ => Err(RuntimeError::new("all requires array")),
7852 }
7853 }
7854 "any" => {
7855 match value {
7857 Value::Array(arr) => {
7858 for item in arr.borrow().iter() {
7859 if self.is_truthy(item) {
7860 return Ok(Value::Bool(true));
7861 }
7862 }
7863 Ok(Value::Bool(false))
7864 }
7865 _ => Err(RuntimeError::new("any requires array")),
7866 }
7867 }
7868 "map" => {
7869 if arg_values.len() != 1 {
7871 return Err(RuntimeError::new("map expects 1 argument (closure)"));
7872 }
7873 match (&value, &arg_values[0]) {
7874 (Value::Array(arr), Value::Function(f)) => {
7875 let mut results = Vec::new();
7876 for val in arr.borrow().iter() {
7877 let result = self.call_function(f, vec![val.clone()])?;
7878 results.push(result);
7879 }
7880 Ok(Value::Array(Rc::new(RefCell::new(results))))
7881 }
7882 (Value::Array(_), _) => Err(RuntimeError::new("map expects closure argument")),
7883 _ => Err(RuntimeError::new("map requires array")),
7884 }
7885 }
7886 "filter" => {
7887 if arg_values.len() != 1 {
7889 return Err(RuntimeError::new("filter expects 1 argument (closure)"));
7890 }
7891 match (&value, &arg_values[0]) {
7892 (Value::Array(arr), Value::Function(f)) => {
7893 let mut results = Vec::new();
7894 for val in arr.borrow().iter() {
7895 let keep = self.call_function(f, vec![val.clone()])?;
7896 if matches!(keep, Value::Bool(true)) {
7897 results.push(val.clone());
7898 }
7899 }
7900 Ok(Value::Array(Rc::new(RefCell::new(results))))
7901 }
7902 (Value::Array(_), _) => Err(RuntimeError::new("filter expects closure argument")),
7903 _ => Err(RuntimeError::new("filter requires array")),
7904 }
7905 }
7906 "fold" => {
7907 if arg_values.len() != 2 {
7909 return Err(RuntimeError::new("fold expects 2 arguments (init, closure)"));
7910 }
7911 match (&value, &arg_values[1]) {
7912 (Value::Array(arr), Value::Function(f)) => {
7913 let mut acc = arg_values[0].clone();
7914 for val in arr.borrow().iter() {
7915 acc = self.call_function(f, vec![acc, val.clone()])?;
7916 }
7917 Ok(acc)
7918 }
7919 (Value::Array(_), _) => Err(RuntimeError::new("fold expects closure as second argument")),
7920 _ => Err(RuntimeError::new("fold requires array")),
7921 }
7922 }
7923 _ => Err(RuntimeError::new(format!(
7924 "Unknown pipe method: {}",
7925 name.name
7926 ))),
7927 }
7928 }
7929 PipeOp::Await => {
7930 self.await_value(value)
7932 }
7933 PipeOp::First => {
7935 match &value {
7937 Value::Array(arr) => arr
7938 .borrow()
7939 .first()
7940 .cloned()
7941 .ok_or_else(|| RuntimeError::new("first (α) on empty array")),
7942 Value::Tuple(t) => t
7943 .first()
7944 .cloned()
7945 .ok_or_else(|| RuntimeError::new("first (α) on empty tuple")),
7946 _ => Err(RuntimeError::new("first (α) requires array or tuple")),
7947 }
7948 }
7949 PipeOp::Last => {
7950 match &value {
7952 Value::Array(arr) => arr
7953 .borrow()
7954 .last()
7955 .cloned()
7956 .ok_or_else(|| RuntimeError::new("last (ω) on empty array")),
7957 Value::Tuple(t) => t
7958 .last()
7959 .cloned()
7960 .ok_or_else(|| RuntimeError::new("last (ω) on empty tuple")),
7961 _ => Err(RuntimeError::new("last (ω) requires array or tuple")),
7962 }
7963 }
7964 PipeOp::Middle => {
7965 match &value {
7967 Value::Array(arr) => {
7968 let arr = arr.borrow();
7969 if arr.is_empty() {
7970 return Err(RuntimeError::new("middle (μ) on empty array"));
7971 }
7972 let mid = arr.len() / 2;
7973 Ok(arr[mid].clone())
7974 }
7975 Value::Tuple(t) => {
7976 if t.is_empty() {
7977 return Err(RuntimeError::new("middle (μ) on empty tuple"));
7978 }
7979 let mid = t.len() / 2;
7980 Ok(t[mid].clone())
7981 }
7982 _ => Err(RuntimeError::new("middle (μ) requires array or tuple")),
7983 }
7984 }
7985 PipeOp::Choice => {
7986 use std::time::{SystemTime, UNIX_EPOCH};
7988 match &value {
7989 Value::Array(arr) => {
7990 let arr = arr.borrow();
7991 if arr.is_empty() {
7992 return Err(RuntimeError::new("choice (χ) on empty array"));
7993 }
7994 let seed = SystemTime::now()
7995 .duration_since(UNIX_EPOCH)
7996 .unwrap_or(std::time::Duration::ZERO)
7997 .as_nanos() as u64;
7998 let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
7999 as usize
8000 % arr.len();
8001 Ok(arr[idx].clone())
8002 }
8003 Value::Tuple(t) => {
8004 if t.is_empty() {
8005 return Err(RuntimeError::new("choice (χ) on empty tuple"));
8006 }
8007 let seed = SystemTime::now()
8008 .duration_since(UNIX_EPOCH)
8009 .unwrap_or(std::time::Duration::ZERO)
8010 .as_nanos() as u64;
8011 let idx = ((seed.wrapping_mul(1103515245).wrapping_add(12345)) >> 16)
8012 as usize
8013 % t.len();
8014 Ok(t[idx].clone())
8015 }
8016 _ => Err(RuntimeError::new("choice (χ) requires array or tuple")),
8017 }
8018 }
8019 PipeOp::Nth(index_expr) => {
8020 let index = match self.evaluate(index_expr)? {
8022 Value::Int(n) => n,
8023 _ => return Err(RuntimeError::new("nth (ν) index must be integer")),
8024 };
8025 match &value {
8026 Value::Array(arr) => {
8027 let arr = arr.borrow();
8028 if index < 0 || index as usize >= arr.len() {
8029 return Err(RuntimeError::new("nth (ν) index out of bounds"));
8030 }
8031 Ok(arr[index as usize].clone())
8032 }
8033 Value::Tuple(t) => {
8034 if index < 0 || index as usize >= t.len() {
8035 return Err(RuntimeError::new("nth (ν) index out of bounds"));
8036 }
8037 Ok(t[index as usize].clone())
8038 }
8039 _ => Err(RuntimeError::new("nth (ν) requires array or tuple")),
8040 }
8041 }
8042 PipeOp::Next => {
8043 match &value {
8046 Value::Array(arr) => arr
8047 .borrow()
8048 .first()
8049 .cloned()
8050 .ok_or_else(|| RuntimeError::new("next (ξ) on empty array")),
8051 Value::Tuple(t) => t
8052 .first()
8053 .cloned()
8054 .ok_or_else(|| RuntimeError::new("next (ξ) on empty tuple")),
8055 _ => Err(RuntimeError::new("next (ξ) requires array or tuple")),
8056 }
8057 }
8058 PipeOp::Named { prefix, body } => {
8059 let method_name = prefix
8061 .iter()
8062 .map(|i| i.name.as_str())
8063 .collect::<Vec<_>>()
8064 .join("·");
8065 match method_name.as_str() {
8066 "map" => {
8067 if let Some(body) = body {
8068 match value {
8069 Value::Array(arr) => {
8070 let results: Vec<Value> = arr
8071 .borrow()
8072 .iter()
8073 .map(|item| {
8074 self.environment
8075 .borrow_mut()
8076 .define("_".to_string(), item.clone());
8077 self.evaluate(body)
8078 })
8079 .collect::<Result<_, _>>()?;
8080 Ok(Value::Array(Rc::new(RefCell::new(results))))
8081 }
8082 _ => Err(RuntimeError::new("map requires array")),
8083 }
8084 } else {
8085 Ok(value)
8086 }
8087 }
8088 "filter" => {
8089 if let Some(body) = body {
8090 match value {
8091 Value::Array(arr) => {
8092 let results: Vec<Value> = arr
8093 .borrow()
8094 .iter()
8095 .filter_map(|item| {
8096 self.environment
8097 .borrow_mut()
8098 .define("_".to_string(), item.clone());
8099 match self.evaluate(body) {
8100 Ok(v) if self.is_truthy(&v) => {
8101 Some(Ok(item.clone()))
8102 }
8103 Ok(_) => None,
8104 Err(e) => Some(Err(e)),
8105 }
8106 })
8107 .collect::<Result<_, _>>()?;
8108 Ok(Value::Array(Rc::new(RefCell::new(results))))
8109 }
8110 _ => Err(RuntimeError::new("filter requires array")),
8111 }
8112 } else {
8113 Ok(value)
8114 }
8115 }
8116 "all" => {
8117 if let Some(body) = body {
8118 match value {
8119 Value::Array(arr) => {
8120 for item in arr.borrow().iter() {
8121 self.environment
8122 .borrow_mut()
8123 .define("_".to_string(), item.clone());
8124 let result = self.evaluate(body)?;
8125 if !self.is_truthy(&result) {
8126 return Ok(Value::Bool(false));
8127 }
8128 }
8129 Ok(Value::Bool(true))
8130 }
8131 _ => Err(RuntimeError::new("all requires array")),
8132 }
8133 } else {
8134 match value {
8136 Value::Array(arr) => {
8137 for item in arr.borrow().iter() {
8138 if !self.is_truthy(item) {
8139 return Ok(Value::Bool(false));
8140 }
8141 }
8142 Ok(Value::Bool(true))
8143 }
8144 _ => Err(RuntimeError::new("all requires array")),
8145 }
8146 }
8147 }
8148 "any" => {
8149 if let Some(body) = body {
8150 match value {
8151 Value::Array(arr) => {
8152 for item in arr.borrow().iter() {
8153 self.environment
8154 .borrow_mut()
8155 .define("_".to_string(), item.clone());
8156 let result = self.evaluate(body)?;
8157 if self.is_truthy(&result) {
8158 return Ok(Value::Bool(true));
8159 }
8160 }
8161 Ok(Value::Bool(false))
8162 }
8163 _ => Err(RuntimeError::new("any requires array")),
8164 }
8165 } else {
8166 match value {
8168 Value::Array(arr) => {
8169 for item in arr.borrow().iter() {
8170 if self.is_truthy(item) {
8171 return Ok(Value::Bool(true));
8172 }
8173 }
8174 Ok(Value::Bool(false))
8175 }
8176 _ => Err(RuntimeError::new("any requires array")),
8177 }
8178 }
8179 }
8180 _ => Err(RuntimeError::new(format!(
8181 "Unknown named morpheme: {}",
8182 method_name
8183 ))),
8184 }
8185 }
8186 PipeOp::Parallel(inner_op) => {
8187 match value {
8190 Value::Array(arr) => {
8191 use std::sync::{Arc, Mutex};
8192
8193 let arr_ref = arr.borrow();
8194 let len = arr_ref.len();
8195 if len == 0 {
8196 return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8197 }
8198
8199 match inner_op.as_ref() {
8201 PipeOp::Transform(body) => {
8202 let num_threads = std::thread::available_parallelism()
8204 .map(|p| p.get())
8205 .unwrap_or(4)
8206 .min(len);
8207
8208 let _chunk_size = (len + num_threads - 1) / num_threads;
8210 let _results = Arc::new(Mutex::new(vec![Value::Null; len]));
8211 let items: Vec<Value> = arr_ref.clone();
8212 drop(arr_ref);
8213
8214 let _body_str = format!("{:?}", body);
8216
8217 let mut result_vec = Vec::with_capacity(len);
8221 for item in items.iter() {
8222 self.environment
8223 .borrow_mut()
8224 .define("_".to_string(), item.clone());
8225 result_vec.push(self.evaluate(body)?);
8226 }
8227 Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
8228 }
8229 PipeOp::Filter(predicate) => {
8230 let items: Vec<Value> = arr_ref.clone();
8232 drop(arr_ref);
8233
8234 let mut result_vec = Vec::new();
8235 for item in items.iter() {
8236 self.environment
8237 .borrow_mut()
8238 .define("_".to_string(), item.clone());
8239 let pred_result = self.evaluate(predicate)?;
8240 if self.is_truthy(&pred_result) {
8241 result_vec.push(item.clone());
8242 }
8243 }
8244 Ok(Value::Array(Rc::new(RefCell::new(result_vec))))
8245 }
8246 _ => {
8247 drop(arr_ref);
8249 self.apply_pipe_op(Value::Array(arr), inner_op)
8250 }
8251 }
8252 }
8253 _ => {
8254 self.apply_pipe_op(value, inner_op)
8256 }
8257 }
8258 }
8259 PipeOp::Gpu(inner_op) => {
8260 match value {
8267 Value::Array(arr) => {
8268 #[cfg(debug_assertions)]
8271 eprintln!(
8272 "[GPU] Would execute {:?} on GPU, falling back to CPU",
8273 inner_op
8274 );
8275
8276 self.apply_pipe_op(Value::Array(arr), inner_op)
8277 }
8278 _ => self.apply_pipe_op(value, inner_op),
8279 }
8280 }
8281
8282 PipeOp::Send(data_expr) => {
8288 let data = self.evaluate(data_expr)?;
8291
8292 let response = self.protocol_send(&value, &data)?;
8295
8296 Ok(self.wrap_reported(response))
8298 }
8299
8300 PipeOp::Recv => {
8301 let response = self.protocol_recv(&value)?;
8306
8307 Ok(self.wrap_reported(response))
8309 }
8310
8311 PipeOp::Stream(handler_expr) => {
8312 let handler = self.evaluate(handler_expr)?;
8314
8315 let stream = self.protocol_stream(&value, &handler)?;
8318 Ok(stream)
8319 }
8320
8321 PipeOp::Connect(config_expr) => {
8322 let config = match config_expr {
8324 Some(expr) => Some(self.evaluate(expr)?),
8325 None => None,
8326 };
8327
8328 let connection = self.protocol_connect(&value, config.as_ref())?;
8330 Ok(connection)
8331 }
8332
8333 PipeOp::Close => {
8334 self.protocol_close(&value)?;
8336 Ok(Value::Null)
8337 }
8338
8339 PipeOp::Header {
8340 name,
8341 value: value_expr,
8342 } => {
8343 let header_name = self.evaluate(name)?;
8345 let header_value = self.evaluate(value_expr)?;
8346
8347 self.protocol_add_header(value, &header_name, &header_value)
8349 }
8350
8351 PipeOp::Body(data_expr) => {
8352 let body_data = self.evaluate(data_expr)?;
8354
8355 self.protocol_set_body(value, &body_data)
8357 }
8358
8359 PipeOp::Timeout(ms_expr) => {
8360 let ms = self.evaluate(ms_expr)?;
8362
8363 self.protocol_set_timeout(value, &ms)
8365 }
8366
8367 PipeOp::Retry { count, strategy } => {
8368 let retry_count = self.evaluate(count)?;
8370 let retry_strategy = match strategy {
8371 Some(s) => Some(self.evaluate(s)?),
8372 None => None,
8373 };
8374
8375 self.protocol_set_retry(value, &retry_count, retry_strategy.as_ref())
8377 }
8378
8379 PipeOp::Validate {
8383 predicate,
8384 target_evidence,
8385 } => {
8386 let predicate_result = match predicate.as_ref() {
8389 Expr::Closure { params, body, .. } => {
8390 if let Some(param) = params.first() {
8391 let param_name = match ¶m.pattern {
8392 Pattern::Ident { name, .. } => name.name.clone(),
8393 _ => "it".to_string(),
8394 };
8395 self.environment
8396 .borrow_mut()
8397 .define(param_name, value.clone());
8398 }
8399 self.evaluate(body)?
8400 }
8401 _ => self.evaluate(predicate)?,
8402 };
8403
8404 match predicate_result {
8406 Value::Bool(true) => {
8407 let target_ev = match target_evidence {
8409 Evidentiality::Known => Evidence::Known,
8410 Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8411 Evidentiality::Reported => Evidence::Reported,
8412 Evidentiality::Paradox => Evidence::Paradox,
8413 };
8414 let inner = match value {
8415 Value::Evidential { value: v, .. } => *v,
8416 v => v,
8417 };
8418 Ok(Value::Evidential {
8419 value: Box::new(inner),
8420 evidence: target_ev,
8421 })
8422 }
8423 Value::Bool(false) => Err(RuntimeError::new(
8424 "validation failed: predicate returned false",
8425 )),
8426 _ => Err(RuntimeError::new("validation predicate must return bool")),
8427 }
8428 }
8429
8430 PipeOp::Assume {
8431 reason,
8432 target_evidence,
8433 } => {
8434 let reason_str: Rc<String> = if let Some(r) = reason {
8436 match self.evaluate(r)? {
8437 Value::String(s) => s,
8438 _ => Rc::new("<no reason>".to_string()),
8439 }
8440 } else {
8441 Rc::new("<no reason>".to_string())
8442 };
8443
8444 #[cfg(debug_assertions)]
8446 eprintln!(
8447 "[AUDIT] Evidence assumption: {} - reason: {}",
8448 match target_evidence {
8449 Evidentiality::Known => "!",
8450 Evidentiality::Uncertain | Evidentiality::Predicted => "?",
8451 Evidentiality::Reported => "~",
8452 Evidentiality::Paradox => "‽",
8453 },
8454 reason_str
8455 );
8456
8457 let target_ev = match target_evidence {
8458 Evidentiality::Known => Evidence::Known,
8459 Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8460 Evidentiality::Reported => Evidence::Reported,
8461 Evidentiality::Paradox => Evidence::Paradox,
8462 };
8463
8464 let inner = match value {
8465 Value::Evidential { value: v, .. } => *v,
8466 v => v,
8467 };
8468
8469 Ok(Value::Evidential {
8470 value: Box::new(inner),
8471 evidence: target_ev,
8472 })
8473 }
8474
8475 PipeOp::AssertEvidence(expected) => {
8476 let actual_evidence = match &value {
8478 Value::Evidential { evidence, .. } => evidence.clone(),
8479 _ => Evidence::Known,
8480 };
8481
8482 let expected_ev = match expected {
8483 Evidentiality::Known => Evidence::Known,
8484 Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
8485 Evidentiality::Reported => Evidence::Reported,
8486 Evidentiality::Paradox => Evidence::Paradox,
8487 };
8488
8489 let satisfies = match (&actual_evidence, &expected_ev) {
8491 (Evidence::Known, _) => true,
8492 (
8493 Evidence::Uncertain,
8494 Evidence::Uncertain | Evidence::Reported | Evidence::Paradox,
8495 ) => true,
8496 (Evidence::Reported, Evidence::Reported | Evidence::Paradox) => true,
8497 (Evidence::Paradox, Evidence::Paradox) => true,
8498 _ => false,
8499 };
8500
8501 if satisfies {
8502 Ok(value)
8503 } else {
8504 Err(RuntimeError::new(format!(
8505 "evidence assertion failed: expected {:?}, found {:?}",
8506 expected_ev, actual_evidence
8507 )))
8508 }
8509 }
8510
8511 PipeOp::Also(func) => {
8515 match func.as_ref() {
8518 Expr::Closure { params, body, .. } => {
8519 if let Some(param) = params.first() {
8520 let param_name = match ¶m.pattern {
8521 Pattern::Ident { name, .. } => name.name.clone(),
8522 _ => "it".to_string(),
8523 };
8524 self.environment
8525 .borrow_mut()
8526 .define(param_name, value.clone());
8527 }
8528 let _ = self.evaluate(body);
8530 }
8531 _ => {
8532 let _ = self.evaluate(func);
8534 }
8535 }
8536 Ok(value)
8538 }
8539
8540 PipeOp::Apply(func) => {
8541 match func.as_ref() {
8544 Expr::Closure { params, body, .. } => {
8545 if let Some(param) = params.first() {
8546 let param_name = match ¶m.pattern {
8547 Pattern::Ident { name, .. } => name.name.clone(),
8548 _ => "it".to_string(),
8549 };
8550 self.environment
8551 .borrow_mut()
8552 .define(param_name, value.clone());
8553 }
8554 let _ = self.evaluate(body);
8556 }
8557 _ => {
8558 let _ = self.evaluate(func);
8559 }
8560 }
8561 Ok(value)
8563 }
8564
8565 PipeOp::TakeIf(predicate) => {
8566 let predicate_result = match predicate.as_ref() {
8568 Expr::Closure { params, body, .. } => {
8569 if let Some(param) = params.first() {
8570 let param_name = match ¶m.pattern {
8571 Pattern::Ident { name, .. } => name.name.clone(),
8572 _ => "it".to_string(),
8573 };
8574 self.environment
8575 .borrow_mut()
8576 .define(param_name, value.clone());
8577 }
8578 self.evaluate(body)?
8579 }
8580 _ => self.evaluate(predicate)?,
8581 };
8582
8583 match predicate_result {
8584 Value::Bool(true) => Ok(Value::Variant {
8585 enum_name: "Option".to_string(),
8586 variant_name: "Some".to_string(),
8587 fields: Some(Rc::new(vec![value])),
8588 }),
8589 Value::Bool(false) => Ok(Value::Variant {
8590 enum_name: "Option".to_string(),
8591 variant_name: "None".to_string(),
8592 fields: None,
8593 }),
8594 _ => Err(RuntimeError::new("take_if predicate must return bool")),
8595 }
8596 }
8597
8598 PipeOp::TakeUnless(predicate) => {
8599 let predicate_result = match predicate.as_ref() {
8601 Expr::Closure { params, body, .. } => {
8602 if let Some(param) = params.first() {
8603 let param_name = match ¶m.pattern {
8604 Pattern::Ident { name, .. } => name.name.clone(),
8605 _ => "it".to_string(),
8606 };
8607 self.environment
8608 .borrow_mut()
8609 .define(param_name, value.clone());
8610 }
8611 self.evaluate(body)?
8612 }
8613 _ => self.evaluate(predicate)?,
8614 };
8615
8616 match predicate_result {
8617 Value::Bool(false) => Ok(Value::Variant {
8618 enum_name: "Option".to_string(),
8619 variant_name: "Some".to_string(),
8620 fields: Some(Rc::new(vec![value])),
8621 }),
8622 Value::Bool(true) => Ok(Value::Variant {
8623 enum_name: "Option".to_string(),
8624 variant_name: "None".to_string(),
8625 fields: None,
8626 }),
8627 _ => Err(RuntimeError::new("take_unless predicate must return bool")),
8628 }
8629 }
8630
8631 PipeOp::Let(func) => {
8632 match func.as_ref() {
8634 Expr::Closure { params, body, .. } => {
8635 if let Some(param) = params.first() {
8636 let param_name = match ¶m.pattern {
8637 Pattern::Ident { name, .. } => name.name.clone(),
8638 _ => "it".to_string(),
8639 };
8640 self.environment
8641 .borrow_mut()
8642 .define(param_name, value.clone());
8643 }
8644 self.evaluate(body)
8645 }
8646 _ => self.evaluate(func),
8647 }
8648 }
8649
8650 PipeOp::All(pred) => {
8654 match value {
8656 Value::Array(arr) => {
8657 for elem in arr.borrow().iter() {
8658 self.environment
8659 .borrow_mut()
8660 .define("_".to_string(), elem.clone());
8661 let result = self.evaluate(pred)?;
8662 if !self.is_truthy(&result) {
8663 return Ok(Value::Bool(false));
8664 }
8665 }
8666 Ok(Value::Bool(true))
8667 }
8668 _ => Err(RuntimeError::new("All requires array")),
8669 }
8670 }
8671
8672 PipeOp::Any(pred) => {
8673 match value {
8675 Value::Array(arr) => {
8676 for elem in arr.borrow().iter() {
8677 self.environment
8678 .borrow_mut()
8679 .define("_".to_string(), elem.clone());
8680 let result = self.evaluate(pred)?;
8681 if self.is_truthy(&result) {
8682 return Ok(Value::Bool(true));
8683 }
8684 }
8685 Ok(Value::Bool(false))
8686 }
8687 _ => Err(RuntimeError::new("Any requires array")),
8688 }
8689 }
8690
8691 PipeOp::Compose(f) => {
8692 self.environment.borrow_mut().define("_".to_string(), value);
8694 self.evaluate(f)
8695 }
8696
8697 PipeOp::Zip(other_expr) => {
8698 let other = self.evaluate(other_expr)?;
8700 match (value, other) {
8701 (Value::Array(arr1), Value::Array(arr2)) => {
8702 let zipped: Vec<Value> = arr1
8703 .borrow()
8704 .iter()
8705 .zip(arr2.borrow().iter())
8706 .map(|(a, b)| Value::Tuple(Rc::new(vec![a.clone(), b.clone()])))
8707 .collect();
8708 Ok(Value::Array(Rc::new(RefCell::new(zipped))))
8709 }
8710 _ => Err(RuntimeError::new("Zip requires two arrays")),
8711 }
8712 }
8713
8714 PipeOp::Scan(f) => {
8715 match value {
8717 Value::Array(arr) => {
8718 let arr = arr.borrow();
8719 if arr.is_empty() {
8720 return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8721 }
8722 let mut results = vec![arr[0].clone()];
8723 let mut acc = arr[0].clone();
8724 for elem in arr.iter().skip(1) {
8725 self.environment
8726 .borrow_mut()
8727 .define("acc".to_string(), acc.clone());
8728 self.environment
8729 .borrow_mut()
8730 .define("_".to_string(), elem.clone());
8731 acc = self.evaluate(f)?;
8732 results.push(acc.clone());
8733 }
8734 Ok(Value::Array(Rc::new(RefCell::new(results))))
8735 }
8736 _ => Err(RuntimeError::new("Scan requires array")),
8737 }
8738 }
8739
8740 PipeOp::Diff => {
8741 match value {
8743 Value::Array(arr) => {
8744 let arr = arr.borrow();
8745 if arr.len() < 2 {
8746 return Ok(Value::Array(Rc::new(RefCell::new(vec![]))));
8747 }
8748 let mut diffs = Vec::new();
8749 for i in 1..arr.len() {
8750 let diff = self.subtract_values(&arr[i], &arr[i - 1])?;
8751 diffs.push(diff);
8752 }
8753 Ok(Value::Array(Rc::new(RefCell::new(diffs))))
8754 }
8755 _ => Err(RuntimeError::new("Diff requires array")),
8756 }
8757 }
8758
8759 PipeOp::Gradient(var_expr) => {
8760 let _ = var_expr;
8763 Ok(Value::Float(0.0)) }
8765
8766 PipeOp::SortAsc => {
8767 match value {
8769 Value::Array(arr) => {
8770 let mut v = arr.borrow().clone();
8771 v.sort_by(|a, b| self.compare_values(a, b, &None));
8772 Ok(Value::Array(Rc::new(RefCell::new(v))))
8773 }
8774 _ => Err(RuntimeError::new("SortAsc requires array")),
8775 }
8776 }
8777
8778 PipeOp::SortDesc => {
8779 match value {
8781 Value::Array(arr) => {
8782 let mut v = arr.borrow().clone();
8783 v.sort_by(|a, b| self.compare_values(b, a, &None));
8784 Ok(Value::Array(Rc::new(RefCell::new(v))))
8785 }
8786 _ => Err(RuntimeError::new("SortDesc requires array")),
8787 }
8788 }
8789
8790 PipeOp::Reverse => {
8791 match value {
8793 Value::Array(arr) => {
8794 let mut v = arr.borrow().clone();
8795 v.reverse();
8796 Ok(Value::Array(Rc::new(RefCell::new(v))))
8797 }
8798 _ => Err(RuntimeError::new("Reverse requires array")),
8799 }
8800 }
8801
8802 PipeOp::Cycle(n_expr) => {
8803 match value {
8805 Value::Array(arr) => {
8806 let n_val = self.evaluate(n_expr)?;
8807 let n = match n_val {
8808 Value::Int(i) => i as usize,
8809 _ => return Err(RuntimeError::new("Cycle count must be integer")),
8810 };
8811 let arr = arr.borrow();
8812 let cycled: Vec<Value> =
8813 arr.iter().cloned().cycle().take(arr.len() * n).collect();
8814 Ok(Value::Array(Rc::new(RefCell::new(cycled))))
8815 }
8816 _ => Err(RuntimeError::new("Cycle requires array")),
8817 }
8818 }
8819
8820 PipeOp::Windows(n_expr) => {
8821 match value {
8823 Value::Array(arr) => {
8824 let n_val = self.evaluate(n_expr)?;
8825 let n = match n_val {
8826 Value::Int(i) => i as usize,
8827 _ => return Err(RuntimeError::new("Window size must be integer")),
8828 };
8829 let arr = arr.borrow();
8830 let windows: Vec<Value> = arr
8831 .windows(n)
8832 .map(|w| Value::Array(Rc::new(RefCell::new(w.to_vec()))))
8833 .collect();
8834 Ok(Value::Array(Rc::new(RefCell::new(windows))))
8835 }
8836 _ => Err(RuntimeError::new("Windows requires array")),
8837 }
8838 }
8839
8840 PipeOp::Chunks(n_expr) => {
8841 match value {
8843 Value::Array(arr) => {
8844 let n_val = self.evaluate(n_expr)?;
8845 let n = match n_val {
8846 Value::Int(i) => i as usize,
8847 _ => return Err(RuntimeError::new("Chunk size must be integer")),
8848 };
8849 let arr = arr.borrow();
8850 let chunks: Vec<Value> = arr
8851 .chunks(n)
8852 .map(|c| Value::Array(Rc::new(RefCell::new(c.to_vec()))))
8853 .collect();
8854 Ok(Value::Array(Rc::new(RefCell::new(chunks))))
8855 }
8856 _ => Err(RuntimeError::new("Chunks requires array")),
8857 }
8858 }
8859
8860 PipeOp::Flatten => {
8861 match value {
8863 Value::Array(arr) => {
8864 let mut flat = Vec::new();
8865 for elem in arr.borrow().iter() {
8866 match elem {
8867 Value::Array(inner) => {
8868 flat.extend(inner.borrow().iter().cloned());
8869 }
8870 other => flat.push(other.clone()),
8871 }
8872 }
8873 Ok(Value::Array(Rc::new(RefCell::new(flat))))
8874 }
8875 _ => Err(RuntimeError::new("Flatten requires array")),
8876 }
8877 }
8878
8879 PipeOp::Unique => {
8880 match value {
8882 Value::Array(arr) => {
8883 let mut seen = std::collections::HashSet::new();
8884 let mut unique = Vec::new();
8885 for elem in arr.borrow().iter() {
8886 let key = format!("{:?}", elem);
8887 if seen.insert(key) {
8888 unique.push(elem.clone());
8889 }
8890 }
8891 Ok(Value::Array(Rc::new(RefCell::new(unique))))
8892 }
8893 _ => Err(RuntimeError::new("Unique requires array")),
8894 }
8895 }
8896
8897 PipeOp::Enumerate => {
8898 match value {
8900 Value::Array(arr) => {
8901 let enumerated: Vec<Value> = arr
8902 .borrow()
8903 .iter()
8904 .enumerate()
8905 .map(|(i, v)| {
8906 Value::Tuple(Rc::new(vec![Value::Int(i as i64), v.clone()]))
8907 })
8908 .collect();
8909 Ok(Value::Array(Rc::new(RefCell::new(enumerated))))
8910 }
8911 _ => Err(RuntimeError::new("Enumerate requires array")),
8912 }
8913 }
8914 }
8915 }
8916
8917 fn wrap_reported(&self, value: Value) -> Value {
8924 Value::Evidential {
8925 value: Box::new(value),
8926 evidence: Evidence::Reported,
8927 }
8928 }
8929
8930 fn protocol_send(&mut self, connection: &Value, data: &Value) -> Result<Value, RuntimeError> {
8932 match connection {
8934 Value::Map(obj) => {
8935 let obj = obj.borrow();
8936 if let Some(Value::String(protocol)) = obj.get("__protocol__") {
8937 match protocol.as_str() {
8938 "http" | "https" => {
8939 #[cfg(debug_assertions)]
8942 eprintln!("[HTTP] Would send request with body: {:?}", data);
8943 Ok(Value::Map(Rc::new(RefCell::new({
8944 let mut response = HashMap::new();
8945 response.insert("status".to_string(), Value::Int(200));
8946 response.insert("body".to_string(), data.clone());
8947 response.insert(
8948 "__protocol__".to_string(),
8949 Value::String(Rc::new("http_response".to_string())),
8950 );
8951 response
8952 }))))
8953 }
8954 "ws" | "wss" => {
8955 #[cfg(debug_assertions)]
8957 eprintln!("[WebSocket] Would send message: {:?}", data);
8958 Ok(Value::Bool(true)) }
8960 "grpc" => {
8961 #[cfg(debug_assertions)]
8963 eprintln!("[gRPC] Would send message: {:?}", data);
8964 Ok(Value::Map(Rc::new(RefCell::new({
8965 let mut response = HashMap::new();
8966 response.insert("status".to_string(), Value::Int(0)); response.insert("message".to_string(), data.clone());
8968 response.insert(
8969 "__protocol__".to_string(),
8970 Value::String(Rc::new("grpc_response".to_string())),
8971 );
8972 response
8973 }))))
8974 }
8975 "kafka" => {
8976 #[cfg(debug_assertions)]
8978 eprintln!("[Kafka] Would produce message: {:?}", data);
8979 Ok(Value::Map(Rc::new(RefCell::new({
8980 let mut result = HashMap::new();
8981 result.insert("partition".to_string(), Value::Int(0));
8982 result.insert("offset".to_string(), Value::Int(42));
8983 result
8984 }))))
8985 }
8986 _ => Err(RuntimeError::new(format!("Unknown protocol: {}", protocol))),
8987 }
8988 } else {
8989 Err(RuntimeError::new(
8990 "Connection object missing __protocol__ field",
8991 ))
8992 }
8993 }
8994 _ => Err(RuntimeError::new("send requires a connection object")),
8995 }
8996 }
8997
8998 fn protocol_recv(&mut self, connection: &Value) -> Result<Value, RuntimeError> {
9000 match connection {
9001 Value::Map(obj) => {
9002 let obj = obj.borrow();
9003 if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9004 match protocol.as_str() {
9005 "ws" | "wss" => {
9006 #[cfg(debug_assertions)]
9008 eprintln!("[WebSocket] Would receive message");
9009 Ok(Value::String(Rc::new("received message".to_string())))
9010 }
9011 "kafka" => {
9012 #[cfg(debug_assertions)]
9014 eprintln!("[Kafka] Would consume message");
9015 Ok(Value::Map(Rc::new(RefCell::new({
9016 let mut msg = HashMap::new();
9017 msg.insert("key".to_string(), Value::Null);
9018 msg.insert(
9019 "value".to_string(),
9020 Value::String(Rc::new("consumed message".to_string())),
9021 );
9022 msg.insert("partition".to_string(), Value::Int(0));
9023 msg.insert("offset".to_string(), Value::Int(100));
9024 msg
9025 }))))
9026 }
9027 "grpc" => {
9028 #[cfg(debug_assertions)]
9030 eprintln!("[gRPC] Would receive stream message");
9031 Ok(Value::Map(Rc::new(RefCell::new({
9032 let mut msg = HashMap::new();
9033 msg.insert(
9034 "data".to_string(),
9035 Value::String(Rc::new("stream data".to_string())),
9036 );
9037 msg
9038 }))))
9039 }
9040 _ => Err(RuntimeError::new(format!(
9041 "recv not supported for protocol: {}",
9042 protocol
9043 ))),
9044 }
9045 } else {
9046 Err(RuntimeError::new(
9047 "Connection object missing __protocol__ field",
9048 ))
9049 }
9050 }
9051 _ => Err(RuntimeError::new("recv requires a connection object")),
9052 }
9053 }
9054
9055 fn protocol_stream(
9057 &mut self,
9058 connection: &Value,
9059 _handler: &Value,
9060 ) -> Result<Value, RuntimeError> {
9061 match connection {
9063 Value::Map(obj) => {
9064 let obj = obj.borrow();
9065 if let Some(Value::String(protocol)) = obj.get("__protocol__") {
9066 #[cfg(debug_assertions)]
9067 eprintln!("[{}] Would create stream", protocol);
9068
9069 Ok(Value::Map(Rc::new(RefCell::new({
9071 let mut stream = HashMap::new();
9072 stream.insert(
9073 "__type__".to_string(),
9074 Value::String(Rc::new("Stream".to_string())),
9075 );
9076 stream.insert("__protocol__".to_string(), Value::String(protocol.clone()));
9077 stream.insert(
9078 "__evidentiality__".to_string(),
9079 Value::String(Rc::new("reported".to_string())),
9080 );
9081 stream
9082 }))))
9083 } else {
9084 Err(RuntimeError::new(
9085 "Connection object missing __protocol__ field",
9086 ))
9087 }
9088 }
9089 _ => Err(RuntimeError::new("stream requires a connection object")),
9090 }
9091 }
9092
9093 fn protocol_connect(
9095 &mut self,
9096 target: &Value,
9097 _config: Option<&Value>,
9098 ) -> Result<Value, RuntimeError> {
9099 match target {
9100 Value::String(url) => {
9101 let protocol = if url.starts_with("wss://") || url.starts_with("ws://") {
9103 if url.starts_with("wss://") {
9104 "wss"
9105 } else {
9106 "ws"
9107 }
9108 } else if url.starts_with("https://") || url.starts_with("http://") {
9109 if url.starts_with("https://") {
9110 "https"
9111 } else {
9112 "http"
9113 }
9114 } else if url.starts_with("grpc://") || url.starts_with("grpcs://") {
9115 "grpc"
9116 } else if url.starts_with("kafka://") {
9117 "kafka"
9118 } else if url.starts_with("amqp://") || url.starts_with("amqps://") {
9119 "amqp"
9120 } else {
9121 "unknown"
9122 };
9123
9124 #[cfg(debug_assertions)]
9125 eprintln!("[{}] Would connect to: {}", protocol, url);
9126
9127 Ok(Value::Map(Rc::new(RefCell::new({
9129 let mut conn = HashMap::new();
9130 conn.insert(
9131 "__protocol__".to_string(),
9132 Value::String(Rc::new(protocol.to_string())),
9133 );
9134 conn.insert("url".to_string(), Value::String(url.clone()));
9135 conn.insert("connected".to_string(), Value::Bool(true));
9136 conn
9137 }))))
9138 }
9139 Value::Map(obj) => {
9140 let mut conn = obj.borrow().clone();
9142 conn.insert("connected".to_string(), Value::Bool(true));
9143 Ok(Value::Map(Rc::new(RefCell::new(conn))))
9144 }
9145 _ => Err(RuntimeError::new(
9146 "connect requires URL string or config object",
9147 )),
9148 }
9149 }
9150
9151 fn protocol_close(&mut self, connection: &Value) -> Result<(), RuntimeError> {
9153 match connection {
9154 Value::Map(obj) => {
9155 let mut obj = obj.borrow_mut();
9156 if let Some(Value::String(protocol)) = obj.get("__protocol__").cloned() {
9157 #[cfg(debug_assertions)]
9158 eprintln!("[{}] Would close connection", protocol);
9159 obj.insert("connected".to_string(), Value::Bool(false));
9160 Ok(())
9161 } else {
9162 Err(RuntimeError::new(
9163 "Connection object missing __protocol__ field",
9164 ))
9165 }
9166 }
9167 _ => Err(RuntimeError::new("close requires a connection object")),
9168 }
9169 }
9170
9171 fn protocol_add_header(
9173 &mut self,
9174 mut request: Value,
9175 name: &Value,
9176 header_value: &Value,
9177 ) -> Result<Value, RuntimeError> {
9178 let name_str = match name {
9179 Value::String(s) => (**s).clone(),
9180 _ => return Err(RuntimeError::new("Header name must be a string")),
9181 };
9182 let value_str = match header_value {
9183 Value::String(s) => (**s).clone(),
9184 Value::Int(i) => i.to_string(),
9185 _ => return Err(RuntimeError::new("Header value must be string or int")),
9186 };
9187
9188 match &mut request {
9189 Value::Map(obj) => {
9190 let mut obj = obj.borrow_mut();
9191
9192 let headers = obj
9194 .entry("headers".to_string())
9195 .or_insert_with(|| Value::Map(Rc::new(RefCell::new(HashMap::new()))));
9196
9197 if let Value::Map(headers_obj) = headers {
9198 headers_obj
9199 .borrow_mut()
9200 .insert(name_str, Value::String(Rc::new(value_str)));
9201 }
9202 drop(obj);
9203 Ok(request)
9204 }
9205 _ => Err(RuntimeError::new("header requires a request object")),
9206 }
9207 }
9208
9209 fn protocol_set_body(
9211 &mut self,
9212 mut request: Value,
9213 body: &Value,
9214 ) -> Result<Value, RuntimeError> {
9215 match &mut request {
9216 Value::Map(obj) => {
9217 obj.borrow_mut().insert("body".to_string(), body.clone());
9218 Ok(request)
9219 }
9220 _ => Err(RuntimeError::new("body requires a request object")),
9221 }
9222 }
9223
9224 fn protocol_set_timeout(
9226 &mut self,
9227 mut request: Value,
9228 ms: &Value,
9229 ) -> Result<Value, RuntimeError> {
9230 let timeout_ms = match ms {
9231 Value::Int(n) => *n,
9232 Value::Float(f) => *f as i64,
9233 _ => return Err(RuntimeError::new("Timeout must be a number (milliseconds)")),
9234 };
9235
9236 match &mut request {
9237 Value::Map(obj) => {
9238 obj.borrow_mut()
9239 .insert("timeout_ms".to_string(), Value::Int(timeout_ms));
9240 Ok(request)
9241 }
9242 _ => Err(RuntimeError::new("timeout requires a request object")),
9243 }
9244 }
9245
9246 fn protocol_set_retry(
9248 &mut self,
9249 mut request: Value,
9250 count: &Value,
9251 strategy: Option<&Value>,
9252 ) -> Result<Value, RuntimeError> {
9253 let retry_count = match count {
9254 Value::Int(n) => *n,
9255 _ => return Err(RuntimeError::new("Retry count must be an integer")),
9256 };
9257
9258 match &mut request {
9259 Value::Map(obj) => {
9260 let mut obj = obj.borrow_mut();
9261 obj.insert("retry_count".to_string(), Value::Int(retry_count));
9262 if let Some(strat) = strategy {
9263 obj.insert("retry_strategy".to_string(), strat.clone());
9264 }
9265 drop(obj);
9266 Ok(request)
9267 }
9268 _ => Err(RuntimeError::new("retry requires a request object")),
9269 }
9270 }
9271
9272 fn sum_values(&self, value: Value) -> Result<Value, RuntimeError> {
9273 match value {
9274 Value::Array(arr) => {
9275 let arr = arr.borrow();
9276 if arr.is_empty() {
9277 return Ok(Value::Int(0));
9278 }
9279 let mut sum = match &arr[0] {
9280 Value::Int(_) => Value::Int(0),
9281 Value::Float(_) => Value::Float(0.0),
9282 _ => return Err(RuntimeError::new("Cannot sum non-numeric array")),
9283 };
9284 for item in arr.iter() {
9285 sum = match (&sum, item) {
9286 (Value::Int(a), Value::Int(b)) => Value::Int(a + b),
9287 (Value::Float(a), Value::Float(b)) => Value::Float(a + b),
9288 (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 + b),
9289 (Value::Float(a), Value::Int(b)) => Value::Float(a + *b as f64),
9290 _ => return Err(RuntimeError::new("Cannot sum non-numeric values")),
9291 };
9292 }
9293 Ok(sum)
9294 }
9295 _ => Err(RuntimeError::new("sum requires array")),
9296 }
9297 }
9298
9299 fn product_values(&self, value: Value) -> Result<Value, RuntimeError> {
9300 match value {
9301 Value::Array(arr) => {
9302 let arr = arr.borrow();
9303 if arr.is_empty() {
9304 return Ok(Value::Int(1));
9305 }
9306 let mut prod = match &arr[0] {
9307 Value::Int(_) => Value::Int(1),
9308 Value::Float(_) => Value::Float(1.0),
9309 _ => return Err(RuntimeError::new("Cannot multiply non-numeric array")),
9310 };
9311 for item in arr.iter() {
9312 prod = match (&prod, item) {
9313 (Value::Int(a), Value::Int(b)) => Value::Int(a * b),
9314 (Value::Float(a), Value::Float(b)) => Value::Float(a * b),
9315 (Value::Int(a), Value::Float(b)) => Value::Float(*a as f64 * b),
9316 (Value::Float(a), Value::Int(b)) => Value::Float(a * *b as f64),
9317 _ => return Err(RuntimeError::new("Cannot multiply non-numeric values")),
9318 };
9319 }
9320 Ok(prod)
9321 }
9322 _ => Err(RuntimeError::new("product requires array")),
9323 }
9324 }
9325
9326 fn min_values(&self, value: Value) -> Result<Value, RuntimeError> {
9327 match value {
9328 Value::Array(arr) => {
9329 let arr = arr.borrow();
9330 if arr.is_empty() {
9331 return Err(RuntimeError::new("Cannot find min of empty array"));
9332 }
9333 let mut min = arr[0].clone();
9334 for item in arr.iter().skip(1) {
9335 min = match (&min, item) {
9336 (Value::Int(a), Value::Int(b)) => {
9337 if *b < *a {
9338 Value::Int(*b)
9339 } else {
9340 Value::Int(*a)
9341 }
9342 }
9343 (Value::Float(a), Value::Float(b)) => {
9344 if *b < *a {
9345 Value::Float(*b)
9346 } else {
9347 Value::Float(*a)
9348 }
9349 }
9350 (Value::Int(a), Value::Float(b)) => {
9351 let af = *a as f64;
9352 if *b < af {
9353 Value::Float(*b)
9354 } else {
9355 Value::Float(af)
9356 }
9357 }
9358 (Value::Float(a), Value::Int(b)) => {
9359 let bf = *b as f64;
9360 if bf < *a {
9361 Value::Float(bf)
9362 } else {
9363 Value::Float(*a)
9364 }
9365 }
9366 _ => {
9367 return Err(RuntimeError::new("Cannot find min of non-numeric values"))
9368 }
9369 };
9370 }
9371 Ok(min)
9372 }
9373 _ => Err(RuntimeError::new("min requires array")),
9374 }
9375 }
9376
9377 fn max_values(&self, value: Value) -> Result<Value, RuntimeError> {
9378 match value {
9379 Value::Array(arr) => {
9380 let arr = arr.borrow();
9381 if arr.is_empty() {
9382 return Err(RuntimeError::new("Cannot find max of empty array"));
9383 }
9384 let mut max = arr[0].clone();
9385 for item in arr.iter().skip(1) {
9386 max = match (&max, item) {
9387 (Value::Int(a), Value::Int(b)) => {
9388 if *b > *a {
9389 Value::Int(*b)
9390 } else {
9391 Value::Int(*a)
9392 }
9393 }
9394 (Value::Float(a), Value::Float(b)) => {
9395 if *b > *a {
9396 Value::Float(*b)
9397 } else {
9398 Value::Float(*a)
9399 }
9400 }
9401 (Value::Int(a), Value::Float(b)) => {
9402 let af = *a as f64;
9403 if *b > af {
9404 Value::Float(*b)
9405 } else {
9406 Value::Float(af)
9407 }
9408 }
9409 (Value::Float(a), Value::Int(b)) => {
9410 let bf = *b as f64;
9411 if bf > *a {
9412 Value::Float(bf)
9413 } else {
9414 Value::Float(*a)
9415 }
9416 }
9417 _ => {
9418 return Err(RuntimeError::new("Cannot find max of non-numeric values"))
9419 }
9420 };
9421 }
9422 Ok(max)
9423 }
9424 _ => Err(RuntimeError::new("max requires array")),
9425 }
9426 }
9427
9428 fn concat_values(&self, value: Value) -> Result<Value, RuntimeError> {
9429 match value {
9430 Value::Array(arr) => {
9431 let arr = arr.borrow();
9432 if arr.is_empty() {
9433 return Ok(Value::String(Rc::new(String::new())));
9434 }
9435 match &arr[0] {
9437 Value::String(_) => {
9438 let mut result = String::new();
9439 for item in arr.iter() {
9440 if let Value::String(s) = item {
9441 result.push_str(s);
9442 } else {
9443 return Err(RuntimeError::new(
9444 "concat requires all elements to be strings",
9445 ));
9446 }
9447 }
9448 Ok(Value::String(Rc::new(result)))
9449 }
9450 Value::Array(_) => {
9451 let mut result = Vec::new();
9452 for item in arr.iter() {
9453 if let Value::Array(inner) = item {
9454 result.extend(inner.borrow().iter().cloned());
9455 } else {
9456 return Err(RuntimeError::new(
9457 "concat requires all elements to be arrays",
9458 ));
9459 }
9460 }
9461 Ok(Value::Array(Rc::new(RefCell::new(result))))
9462 }
9463 _ => Err(RuntimeError::new("concat requires strings or arrays")),
9464 }
9465 }
9466 _ => Err(RuntimeError::new("concat requires array")),
9467 }
9468 }
9469
9470 fn all_values(&self, value: Value) -> Result<Value, RuntimeError> {
9471 match value {
9472 Value::Array(arr) => {
9473 let arr = arr.borrow();
9474 for item in arr.iter() {
9475 match item {
9476 Value::Bool(b) => {
9477 if !*b {
9478 return Ok(Value::Bool(false));
9479 }
9480 }
9481 _ => return Err(RuntimeError::new("all requires array of booleans")),
9482 }
9483 }
9484 Ok(Value::Bool(true))
9485 }
9486 _ => Err(RuntimeError::new("all requires array")),
9487 }
9488 }
9489
9490 fn any_values(&self, value: Value) -> Result<Value, RuntimeError> {
9491 match value {
9492 Value::Array(arr) => {
9493 let arr = arr.borrow();
9494 for item in arr.iter() {
9495 match item {
9496 Value::Bool(b) => {
9497 if *b {
9498 return Ok(Value::Bool(true));
9499 }
9500 }
9501 _ => return Err(RuntimeError::new("any requires array of booleans")),
9502 }
9503 }
9504 Ok(Value::Bool(false))
9505 }
9506 _ => Err(RuntimeError::new("any requires array")),
9507 }
9508 }
9509
9510 fn compare_values(&self, a: &Value, b: &Value, _field: &Option<Ident>) -> std::cmp::Ordering {
9511 match (a, b) {
9513 (Value::Int(a), Value::Int(b)) => a.cmp(b),
9514 (Value::Float(a), Value::Float(b)) => {
9515 a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal)
9516 }
9517 (Value::String(a), Value::String(b)) => a.cmp(b),
9518 _ => std::cmp::Ordering::Equal,
9519 }
9520 }
9521
9522 fn subtract_values(&self, a: &Value, b: &Value) -> Result<Value, RuntimeError> {
9524 match (a, b) {
9525 (Value::Int(a), Value::Int(b)) => Ok(Value::Int(a - b)),
9526 (Value::Float(a), Value::Float(b)) => Ok(Value::Float(a - b)),
9527 (Value::Int(a), Value::Float(b)) => Ok(Value::Float(*a as f64 - b)),
9528 (Value::Float(a), Value::Int(b)) => Ok(Value::Float(a - *b as f64)),
9529 _ => Err(RuntimeError::new(format!(
9530 "Cannot subtract {:?} from {:?}",
9531 b, a
9532 ))),
9533 }
9534 }
9535
9536 fn eval_closure(
9537 &mut self,
9538 params: &[ClosureParam],
9539 body: &Expr,
9540 ) -> Result<Value, RuntimeError> {
9541 let param_names: Vec<String> = params
9542 .iter()
9543 .map(|p| match &p.pattern {
9544 Pattern::Ident { name, .. } => name.name.clone(),
9545 _ => "_".to_string(),
9546 })
9547 .collect();
9548
9549 Ok(Value::Function(Rc::new(Function {
9550 name: None,
9551 params: param_names,
9552 body: body.clone(),
9553 closure: self.environment.clone(),
9554 })))
9555 }
9556
9557 fn eval_struct_literal(
9558 &mut self,
9559 path: &TypePath,
9560 fields: &[FieldInit],
9561 rest: &Option<Box<Expr>>,
9562 ) -> Result<Value, RuntimeError> {
9563 let raw_name = path
9564 .segments
9565 .iter()
9566 .map(|s| s.ident.name.as_str())
9567 .collect::<Vec<_>>()
9568 .join("::");
9569
9570 let name = if raw_name == "Self" {
9572 if let Some(ref self_type) = self.current_self_type {
9573 self_type.clone()
9574 } else {
9575 raw_name
9577 }
9578 } else {
9579 raw_name
9580 };
9581
9582 let mut field_values = HashMap::new();
9583
9584 if let Some(rest_expr) = rest {
9586 let prev_self_type = self.current_self_type.clone();
9588 self.current_self_type = Some(name.clone());
9589
9590 let rest_value = self.evaluate(rest_expr)?;
9591
9592 self.current_self_type = prev_self_type;
9593
9594 if let Value::Struct { fields: rest_fields, .. } = rest_value {
9596 for (k, v) in rest_fields.borrow().iter() {
9597 field_values.insert(k.clone(), v.clone());
9598 }
9599 }
9600 }
9601
9602 for field in fields {
9604 let value = match &field.value {
9605 Some(expr) => self.evaluate(expr)?,
9606 None => self
9607 .environment
9608 .borrow()
9609 .get(&field.name.name)
9610 .ok_or_else(|| {
9611 RuntimeError::new(format!("Unknown variable: {}", field.name.name))
9612 })?,
9613 };
9614 field_values.insert(field.name.name.clone(), value);
9615 }
9616
9617 Ok(Value::Struct {
9618 name,
9619 fields: Rc::new(RefCell::new(field_values)),
9620 })
9621 }
9622
9623 fn extract_evidence(value: &Value) -> Option<Evidence> {
9625 match value {
9626 Value::Evidential { evidence, .. } => Some(*evidence),
9627 _ => None,
9628 }
9629 }
9630
9631 fn extract_affect(value: &Value) -> Option<&RuntimeAffect> {
9633 match value {
9634 Value::Affective { affect, .. } => Some(affect),
9635 _ => None,
9636 }
9637 }
9638
9639 fn affect_to_evidence(affect: &RuntimeAffect) -> Option<Evidence> {
9643 if affect.sarcasm {
9645 return Some(Evidence::Uncertain);
9646 }
9647
9648 match affect.confidence {
9650 Some(RuntimeConfidence::High) => Some(Evidence::Known),
9651 Some(RuntimeConfidence::Low) => Some(Evidence::Uncertain),
9652 Some(RuntimeConfidence::Medium) | None => None,
9653 }
9654 }
9655
9656 fn combine_evidence(a: Option<Evidence>, b: Option<Evidence>) -> Option<Evidence> {
9659 match (a, b) {
9660 (None, None) => None,
9661 (Some(e), None) | (None, Some(e)) => Some(e),
9662 (Some(a), Some(b)) => {
9663 let rank = |e: Evidence| match e {
9664 Evidence::Known => 0,
9665 Evidence::Uncertain => 1,
9666 Evidence::Reported => 2,
9667 Evidence::Paradox => 3,
9668 };
9669 if rank(a) >= rank(b) {
9670 Some(a)
9671 } else {
9672 Some(b)
9673 }
9674 }
9675 }
9676 }
9677
9678 fn unwrap_evidential(value: &Value) -> &Value {
9680 match value {
9681 Value::Evidential { value: inner, .. } => Self::unwrap_evidential(inner),
9682 _ => value,
9683 }
9684 }
9685
9686 fn unwrap_affective(value: &Value) -> &Value {
9688 match value {
9689 Value::Affective { value: inner, .. } => Self::unwrap_affective(inner),
9690 _ => value,
9691 }
9692 }
9693
9694 fn unwrap_value(value: &Value) -> &Value {
9696 match value {
9697 Value::Evidential { value: inner, .. } => Self::unwrap_value(inner),
9698 Value::Affective { value: inner, .. } => Self::unwrap_value(inner),
9699 _ => value,
9700 }
9701 }
9702
9703 fn unwrap_all(value: &Value) -> Value {
9705 match value {
9706 Value::Evidential { value: inner, .. } => Self::unwrap_all(inner),
9707 Value::Affective { value: inner, .. } => Self::unwrap_all(inner),
9708 Value::Ref(r) => Self::unwrap_all(&r.borrow()),
9709 _ => value.clone(),
9710 }
9711 }
9712
9713 fn eval_evidential(&mut self, expr: &Expr, ev: &Evidentiality) -> Result<Value, RuntimeError> {
9714 let value = self.evaluate(expr)?;
9715
9716 if *ev == Evidentiality::Known {
9721 return match value {
9722 Value::Null => Ok(Value::Null), Value::Evidential { value: inner, .. } => Ok(*inner), other => Ok(other), };
9726 }
9727
9728 let evidence = match ev {
9729 Evidentiality::Known => Evidence::Known, Evidentiality::Uncertain | Evidentiality::Predicted => Evidence::Uncertain,
9731 Evidentiality::Reported => Evidence::Reported,
9732 Evidentiality::Paradox => Evidence::Paradox,
9733 };
9734 Ok(Value::Evidential {
9735 value: Box::new(value),
9736 evidence,
9737 })
9738 }
9739
9740 fn eval_format_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
9742 let tokens = tokens.trim();
9747 if !tokens.starts_with('"') {
9748 return Ok(Value::String(Rc::new(tokens.to_string())));
9750 }
9751
9752 let mut in_escape = false;
9754 let mut format_end = 1;
9755 for (i, c) in tokens[1..].char_indices() {
9756 if in_escape {
9757 in_escape = false;
9758 } else if c == '\\' {
9759 in_escape = true;
9760 } else if c == '"' {
9761 format_end = i + 2; break;
9763 }
9764 }
9765
9766 let format_str = &tokens[1..format_end-1]; crate::sigil_debug!("DEBUG format_str: '{}'", format_str);
9768 let args_str = if format_end < tokens.len() {
9769 tokens[format_end..].trim_start_matches(',').trim()
9770 } else {
9771 ""
9772 };
9773
9774 let mut arg_values: Vec<String> = Vec::new();
9776 if !args_str.is_empty() {
9777 let mut depth = 0;
9779 let mut current_arg = String::new();
9780 for c in args_str.chars() {
9781 match c {
9782 '(' | '[' | '{' => {
9783 depth += 1;
9784 current_arg.push(c);
9785 }
9786 ')' | ']' | '}' => {
9787 depth -= 1;
9788 current_arg.push(c);
9789 }
9790 ',' if depth == 0 => {
9791 let arg = current_arg.trim().to_string();
9792 if !arg.is_empty() {
9793 let mut parser = crate::parser::Parser::new(&arg);
9795 match parser.parse_expr() {
9796 Ok(expr) => {
9797 match self.evaluate(&expr) {
9798 Ok(val) => arg_values.push(self.format_value(&val)),
9799 Err(_) => arg_values.push(arg),
9800 }
9801 }
9802 Err(_) => arg_values.push(arg),
9803 }
9804 }
9805 current_arg.clear();
9806 }
9807 _ => current_arg.push(c),
9808 }
9809 }
9810 let arg = current_arg.trim().to_string();
9812 if !arg.is_empty() {
9813 let mut parser = crate::parser::Parser::new(&arg);
9814 match parser.parse_expr() {
9815 Ok(expr) => {
9816 match self.evaluate(&expr) {
9817 Ok(val) => arg_values.push(self.format_value(&val)),
9818 Err(_) => arg_values.push(arg),
9819 }
9820 }
9821 Err(_) => arg_values.push(arg),
9822 }
9823 }
9824 }
9825
9826 let mut result = String::new();
9828 let mut arg_idx = 0;
9829 let mut chars = format_str.chars().peekable();
9830
9831 while let Some(c) = chars.next() {
9832 if c == '{' {
9833 if chars.peek() == Some(&'{') {
9834 chars.next();
9836 result.push('{');
9837 } else {
9838 let mut placeholder = String::new();
9840 while let Some(pc) = chars.next() {
9841 if pc == '}' {
9842 break;
9843 }
9844 placeholder.push(pc);
9845 }
9846 if arg_idx < arg_values.len() {
9848 result.push_str(&arg_values[arg_idx]);
9849 arg_idx += 1;
9850 } else {
9851 result.push_str(&format!("{{{}}}", placeholder));
9852 }
9853 }
9854 } else if c == '}' {
9855 if chars.peek() == Some(&'}') {
9856 chars.next();
9858 result.push('}');
9859 } else {
9860 result.push('}');
9861 }
9862 } else if c == '\\' {
9863 if let Some(next) = chars.next() {
9865 match next {
9866 'n' => result.push('\n'),
9867 't' => result.push('\t'),
9868 'r' => result.push('\r'),
9869 '\\' => result.push('\\'),
9870 '"' => result.push('"'),
9871 _ => {
9872 result.push('\\');
9873 result.push(next);
9874 }
9875 }
9876 }
9877 } else {
9878 result.push(c);
9879 }
9880 }
9881
9882 Ok(Value::String(Rc::new(result)))
9883 }
9884
9885 fn format_value(&self, value: &Value) -> String {
9887 match value {
9888 Value::String(s) => s.to_string(),
9889 Value::Int(n) => n.to_string(),
9890 Value::Float(f) => f.to_string(),
9891 Value::Bool(b) => b.to_string(),
9892 Value::Char(c) => c.to_string(),
9893 Value::Null => "null".to_string(),
9894 Value::Array(arr) => {
9895 let items: Vec<String> = arr.borrow().iter().map(|v| self.format_value(v)).collect();
9896 format!("[{}]", items.join(", "))
9897 }
9898 Value::Tuple(items) => {
9899 let formatted: Vec<String> = items.iter().map(|v| self.format_value(v)).collect();
9900 format!("({})", formatted.join(", "))
9901 }
9902 Value::Struct { name, fields } => {
9903 let field_strs: Vec<String> = fields.borrow().iter()
9904 .map(|(k, v)| format!("{}: {}", k, self.format_value(v)))
9905 .collect();
9906 format!("{} {{ {} }}", name, field_strs.join(", "))
9907 }
9908 Value::Variant { enum_name, variant_name, fields } => {
9909 match fields {
9910 Some(f) if !f.is_empty() => {
9911 let formatted: Vec<String> = f.iter().map(|v| self.format_value(v)).collect();
9912 format!("{}::{}({})", enum_name, variant_name, formatted.join(", "))
9913 }
9914 _ => format!("{}::{}", enum_name, variant_name),
9915 }
9916 }
9917 Value::Evidential { value: inner, evidence } => {
9918 format!("{:?}{}", evidence, self.format_value(inner))
9919 }
9920 Value::Ref(r) => self.format_value(&r.borrow()),
9921 _ => format!("{:?}", value),
9922 }
9923 }
9924
9925 fn eval_vec_macro(&mut self, tokens: &str) -> Result<Value, RuntimeError> {
9927 let mut elements = Vec::new();
9929 let mut depth = 0;
9930 let mut current = String::new();
9931
9932 for c in tokens.chars() {
9933 match c {
9934 '(' | '[' | '{' => {
9935 depth += 1;
9936 current.push(c);
9937 }
9938 ')' | ']' | '}' => {
9939 depth -= 1;
9940 current.push(c);
9941 }
9942 ',' if depth == 0 => {
9943 let elem = current.trim().to_string();
9944 if !elem.is_empty() {
9945 let mut parser = crate::parser::Parser::new(&elem);
9946 if let Ok(expr) = parser.parse_expr() {
9947 elements.push(self.evaluate(&expr)?);
9948 }
9949 }
9950 current.clear();
9951 }
9952 _ => current.push(c),
9953 }
9954 }
9955
9956 let elem = current.trim().to_string();
9958 if !elem.is_empty() {
9959 let mut parser = crate::parser::Parser::new(&elem);
9960 if let Ok(expr) = parser.parse_expr() {
9961 elements.push(self.evaluate(&expr)?);
9962 }
9963 }
9964
9965 Ok(Value::Array(Rc::new(RefCell::new(elements))))
9966 }
9967
9968 fn eval_range(
9969 &mut self,
9970 start: &Option<Box<Expr>>,
9971 end: &Option<Box<Expr>>,
9972 inclusive: bool,
9973 ) -> Result<Value, RuntimeError> {
9974 let start_val = match start {
9975 Some(e) => match self.evaluate(e)? {
9976 Value::Int(n) => n,
9977 _ => return Err(RuntimeError::new("Range requires integer bounds")),
9978 },
9979 None => 0,
9980 };
9981
9982 let end_val = match end {
9983 Some(e) => match self.evaluate(e)? {
9984 Value::Int(n) => n,
9985 _ => return Err(RuntimeError::new("Range requires integer bounds")),
9986 },
9987 None => {
9988 return Ok(Value::Tuple(Rc::new(vec![
9991 Value::Int(start_val),
9992 Value::Null, ])));
9994 }
9995 };
9996
9997 let values: Vec<Value> = if inclusive {
9998 (start_val..=end_val).map(Value::Int).collect()
9999 } else {
10000 (start_val..end_val).map(Value::Int).collect()
10001 };
10002
10003 Ok(Value::Array(Rc::new(RefCell::new(values))))
10004 }
10005
10006 fn is_truthy(&self, value: &Value) -> bool {
10007 match value {
10008 Value::Null => false,
10009 Value::Bool(b) => *b,
10010 Value::Int(n) => *n != 0,
10011 Value::Float(n) => *n != 0.0,
10012 Value::String(s) => !s.is_empty(),
10013 Value::Array(arr) => !arr.borrow().is_empty(),
10014 Value::Empty => false,
10015 Value::Evidential { value, .. } => self.is_truthy(value),
10016 _ => true,
10017 }
10018 }
10019}
10020
10021impl Default for Interpreter {
10022 fn default() -> Self {
10023 Self::new()
10024 }
10025}
10026
10027#[cfg(test)]
10028mod tests {
10029 use super::*;
10030 use crate::Parser;
10031
10032 fn run(source: &str) -> Result<Value, RuntimeError> {
10033 let mut parser = Parser::new(source);
10034 let file = parser
10035 .parse_file()
10036 .map_err(|e| RuntimeError::new(e.to_string()))?;
10037 let mut interp = Interpreter::new();
10038 interp.execute(&file)
10039 }
10040
10041 #[test]
10042 fn test_arithmetic() {
10043 assert!(matches!(
10044 run("fn main() { return 2 + 3; }"),
10045 Ok(Value::Int(5))
10046 ));
10047 assert!(matches!(
10048 run("fn main() { return 10 - 4; }"),
10049 Ok(Value::Int(6))
10050 ));
10051 assert!(matches!(
10052 run("fn main() { return 3 * 4; }"),
10053 Ok(Value::Int(12))
10054 ));
10055 assert!(matches!(
10056 run("fn main() { return 15 / 3; }"),
10057 Ok(Value::Int(5))
10058 ));
10059 assert!(matches!(
10060 run("fn main() { return 2 ** 10; }"),
10061 Ok(Value::Int(1024))
10062 ));
10063 }
10064
10065 #[test]
10066 fn test_variables() {
10067 assert!(matches!(
10068 run("fn main() { let x = 42; return x; }"),
10069 Ok(Value::Int(42))
10070 ));
10071 }
10072
10073 #[test]
10074 fn test_conditionals() {
10075 assert!(matches!(
10076 run("fn main() { if true { return 1; } else { return 2; } }"),
10077 Ok(Value::Int(1))
10078 ));
10079 assert!(matches!(
10080 run("fn main() { if false { return 1; } else { return 2; } }"),
10081 Ok(Value::Int(2))
10082 ));
10083 }
10084
10085 #[test]
10086 fn test_arrays() {
10087 assert!(matches!(
10088 run("fn main() { return [1, 2, 3][1]; }"),
10089 Ok(Value::Int(2))
10090 ));
10091 }
10092
10093 #[test]
10094 fn test_functions() {
10095 let result = run("
10096 fn double(x: i64) -> i64 { return x * 2; }
10097 fn main() { return double(21); }
10098 ");
10099 assert!(matches!(result, Ok(Value::Int(42))));
10100 }
10101
10102 #[test]
10103 fn test_pipe_transform() {
10104 let result = run("fn main() { return [1, 2, 3]|τ{_ * 2}|sum; }");
10105 assert!(matches!(result, Ok(Value::Int(12))));
10106 }
10107
10108 #[test]
10109 fn test_pipe_filter() {
10110 let result = run("fn main() { return [1, 2, 3, 4, 5]|φ{_ > 2}|sum; }");
10111 assert!(matches!(result, Ok(Value::Int(12)))); }
10113
10114 #[test]
10115 fn test_interpolation_evidentiality_propagation() {
10116 let result = run(r#"
10119 fn main() {
10120 let rep = reported(42);
10121
10122 // Interpolating a reported value should make the string reported
10123 let s = f"Value: {rep}";
10124 return s;
10125 }
10126 "#);
10127
10128 match result {
10129 Ok(Value::Evidential {
10130 evidence: Evidence::Reported,
10131 value,
10132 }) => {
10133 assert!(matches!(*value, Value::String(_)));
10135 }
10136 Ok(other) => panic!("Expected Evidential Reported, got {:?}", other),
10137 Err(e) => panic!("Error: {:?}", e),
10138 }
10139 }
10140
10141 #[test]
10142 fn test_interpolation_worst_evidence_wins() {
10143 let result = run(r#"
10145 fn main() {
10146 let k = known(1); // Known is best
10147 let u = uncertain(2); // Uncertain is worse
10148
10149 // Combining known and uncertain should yield uncertain
10150 let s = f"{k} and {u}";
10151 return s;
10152 }
10153 "#);
10154
10155 match result {
10156 Ok(Value::Evidential {
10157 evidence: Evidence::Uncertain,
10158 ..
10159 }) => (),
10160 Ok(other) => panic!("Expected Evidential Uncertain, got {:?}", other),
10161 Err(e) => panic!("Error: {:?}", e),
10162 }
10163 }
10164
10165 #[test]
10166 fn test_interpolation_no_evidential_plain_string() {
10167 let result = run(r#"
10169 fn main() {
10170 let x = 42;
10171 let s = f"Value: {x}";
10172 return s;
10173 }
10174 "#);
10175
10176 match result {
10177 Ok(Value::String(s)) => {
10178 assert_eq!(*s, "Value: 42");
10179 }
10180 Ok(other) => panic!("Expected plain String, got {:?}", other),
10181 Err(e) => panic!("Error: {:?}", e),
10182 }
10183 }
10184}