Skip to main content

solilang/interpreter/
value.rs

1//! Runtime values for the Solilang interpreter.
2
3use std::cell::RefCell;
4use std::collections::{HashMap, HashSet};
5use std::fmt;
6use std::hash::{Hash, Hasher};
7use std::rc::Rc;
8use std::sync::mpsc::Receiver;
9use std::sync::{Arc, Mutex};
10
11use ahash::RandomState as AHasher;
12use indexmap::IndexMap;
13use rust_decimal::prelude::ToPrimitive;
14use rust_decimal::Decimal;
15use serde::ser::{SerializeMap, SerializeSeq};
16
17use crate::ast::{Expr, FunctionDecl, MethodDecl, Parameter, Stmt, TypeAnnotation};
18use crate::interpreter::builtins::model::QueryBuilder;
19use crate::interpreter::environment::Environment;
20use crate::span::Span;
21use crate::vm::upvalue::VmClosure;
22
23/// A Decimal value wrapper for financial calculations.
24/// Uses rust_decimal for exact decimal arithmetic.
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct DecimalValue(pub Decimal, pub u32); // (value, precision)
27
28impl DecimalValue {
29    /// Create a new DecimalValue from a string representation
30    pub fn from_str(s: &str, precision: u32) -> Result<Self, String> {
31        let decimal: Decimal = s.parse().map_err(|_| format!("Invalid decimal: {}", s))?;
32        Ok(Self(decimal, precision))
33    }
34
35    /// Get the precision (number of decimal places)
36    pub fn precision(&self) -> u32 {
37        self.1
38    }
39
40    /// Get the underlying decimal value
41    pub fn value(&self) -> &Decimal {
42        &self.0
43    }
44
45    /// Convert to f64 (loss of precision)
46    pub fn to_f64(&self) -> f64 {
47        self.0.to_f64().unwrap_or(0.0)
48    }
49}
50
51impl std::fmt::Display for DecimalValue {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        write!(f, "{}", self.0)
54    }
55}
56
57impl Hash for DecimalValue {
58    fn hash<H: Hasher>(&self, state: &mut H) {
59        self.0.hash(state);
60    }
61}
62
63/// A hashable key type for use in IndexMap.
64/// This wraps primitive Value types that can be used as hash keys.
65#[derive(Debug, Clone, PartialEq, Eq)]
66pub enum HashKey {
67    Int(i64),
68    Decimal(DecimalValue), // Hashable Decimal
69    String(String),
70    Bool(bool),
71    Null,
72    Symbol(String),
73}
74
75impl Hash for HashKey {
76    fn hash<H: Hasher>(&self, state: &mut H) {
77        match self {
78            HashKey::Int(n) => {
79                0u8.hash(state);
80                n.hash(state);
81            }
82            HashKey::Decimal(d) => {
83                1u8.hash(state);
84                d.hash(state);
85            }
86            HashKey::String(s) => {
87                2u8.hash(state);
88                s.hash(state);
89            }
90            HashKey::Bool(b) => {
91                3u8.hash(state);
92                b.hash(state);
93            }
94            HashKey::Null => {
95                4u8.hash(state);
96            }
97            HashKey::Symbol(s) => {
98                5u8.hash(state);
99                s.hash(state);
100            }
101        }
102    }
103}
104
105/// Zero-allocation key for looking up string keys in IndexMap<HashKey, Value>.
106/// Hashes identically to HashKey::String, avoiding String clone for lookups.
107#[repr(transparent)]
108pub struct StrKey<'a>(pub &'a str);
109
110impl Hash for StrKey<'_> {
111    #[inline]
112    fn hash<H: Hasher>(&self, state: &mut H) {
113        2u8.hash(state); // Must match HashKey::String tag
114        self.0.hash(state);
115    }
116}
117
118impl indexmap::Equivalent<HashKey> for StrKey<'_> {
119    #[inline]
120    fn equivalent(&self, key: &HashKey) -> bool {
121        matches!(key, HashKey::String(s) if s.as_str() == self.0)
122    }
123}
124
125impl HashKey {
126    /// Convert a Value to a HashKey if possible.
127    pub fn from_value(value: &Value) -> Option<HashKey> {
128        match value {
129            Value::Int(n) => Some(HashKey::Int(*n)),
130            Value::Decimal(d) => Some(HashKey::Decimal(d.clone())),
131            Value::String(s) => Some(HashKey::String(s.clone())),
132            Value::Bool(b) => Some(HashKey::Bool(*b)),
133            Value::Null => Some(HashKey::Null),
134            Value::Symbol(s) => Some(HashKey::Symbol(s.clone())),
135            // Floats are not hashable due to NaN != NaN issues
136            _ => None,
137        }
138    }
139
140    /// Convert back to a Value.
141    pub fn to_value(&self) -> Value {
142        match self {
143            HashKey::Int(n) => Value::Int(*n),
144            HashKey::Decimal(d) => Value::Decimal(d.clone()),
145            HashKey::String(s) => Value::String(s.clone()),
146            HashKey::Bool(b) => Value::Bool(*b),
147            HashKey::Null => Value::Null,
148            HashKey::Symbol(s) => Value::Symbol(s.clone()),
149        }
150    }
151
152    #[inline]
153    pub fn display_len(&self) -> usize {
154        match self {
155            HashKey::Int(n) => n.to_string().len(),
156            HashKey::Decimal(d) => d.to_string().len(),
157            HashKey::String(s) => s.len() + 2,
158            HashKey::Bool(b) => {
159                if *b {
160                    4
161                } else {
162                    5
163                }
164            }
165            HashKey::Null => 4,
166            HashKey::Symbol(s) => s.len() + 1,
167        }
168    }
169
170    #[inline]
171    pub fn write_key_to_string(&self, s: &mut String) {
172        match self {
173            HashKey::Int(n) => s.push_str(&n.to_string()),
174            HashKey::Decimal(d) => s.push_str(&d.to_string()),
175            HashKey::String(st) => {
176                s.push('"');
177                s.push_str(st);
178                s.push('"');
179            }
180            HashKey::Bool(b) => s.push_str(if *b { "true" } else { "false" }),
181            HashKey::Null => s.push_str("null"),
182            HashKey::Symbol(sym) => {
183                s.push(':');
184                s.push_str(sym);
185            }
186        }
187    }
188}
189
190impl std::fmt::Display for HashKey {
191    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
192        match self {
193            HashKey::Int(n) => write!(f, "{}", n),
194            HashKey::Decimal(d) => write!(f, "{}", d),
195            HashKey::String(s) => write!(f, "{}", s),
196            HashKey::Bool(b) => write!(f, "{}", b),
197            HashKey::Null => write!(f, "null"),
198            HashKey::Symbol(s) => write!(f, ":{}", s),
199        }
200    }
201}
202
203/// Helper function to create a hash Value from string key-value pairs.
204/// This is a convenience function for creating hashes in builtin functions.
205pub fn hash_from_pairs<I>(pairs: I) -> Value
206where
207    I: IntoIterator<Item = (String, Value)>,
208{
209    let map: HashPairs = pairs
210        .into_iter()
211        .map(|(k, v)| (HashKey::String(k), v))
212        .collect();
213    Value::Hash(Rc::new(RefCell::new(map)))
214}
215
216/// Helper function to create an empty hash Value.
217pub fn empty_hash() -> Value {
218    Value::Hash(Rc::new(RefCell::new(HashPairs::default())))
219}
220
221/// Type alias for hash map storage — uses ahash for 3-5x faster hashing than SipHash.
222pub type HashPairs = IndexMap<HashKey, Value, AHasher>;
223
224/// A runtime value in Solilang.
225#[derive(Debug, Clone)]
226pub enum Value {
227    /// Integer value
228    Int(i64),
229    /// Floating point value
230    Float(f64),
231    /// Decimal value (exact arithmetic for financial calculations)
232    Decimal(DecimalValue),
233    /// String value
234    String(String),
235    /// Symbol value (:name)
236    Symbol(String),
237    /// Boolean value
238    Bool(bool),
239    /// Null value
240    Null,
241    /// Array value
242    Array(Rc<RefCell<Vec<Value>>>),
243    /// Hash/Map value (ordered, O(1) lookup using IndexMap with ahash)
244    Hash(Rc<RefCell<HashPairs>>),
245    /// Function value (closure)
246    Function(Rc<Function>),
247    /// Native/builtin function
248    NativeFunction(NativeFunction),
249    /// Class definition
250    Class(Rc<Class>),
251    /// Class instance
252    Instance(Rc<RefCell<Instance>>),
253    /// Future value (async result that auto-resolves when used)
254    Future(Arc<Mutex<FutureState>>),
255    /// Method on a value (array/hash) - captures receiver and method name
256    Method(ValueMethod),
257    /// Breakpoint marker - triggers debug mode when encountered
258    Breakpoint,
259    /// Query builder for chainable database queries
260    QueryBuilder(Rc<RefCell<QueryBuilder>>),
261    /// Super reference - used for super.method() calls, carries the superclass
262    Super(Rc<Class>),
263    /// VM bytecode closure (used by the bytecode VM)
264    VmClosure(Rc<VmClosure>),
265    /// Image value (holds DynamicImage and metadata)
266    Image(Rc<RefCell<crate::interpreter::builtins::image::ImageData>>),
267}
268
269/// The type of HTTP future result
270#[derive(Clone)]
271pub enum HttpFutureKind {
272    /// Returns body as string
273    String,
274    /// Returns parsed JSON
275    Json,
276    /// Returns full response hash (status, headers, body)
277    FullResponse,
278    /// Returns SystemResult (for System.run())
279    SystemResult,
280}
281
282/// State of a Future value
283pub enum FutureState {
284    /// Waiting for result - holds receiver for raw String data and the kind
285    Pending {
286        receiver: Receiver<Result<String, String>>,
287        kind: HttpFutureKind,
288    },
289    /// Result is ready
290    Resolved(Value),
291    /// Error occurred
292    Error(String),
293}
294
295impl std::fmt::Debug for FutureState {
296    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
297        match self {
298            FutureState::Pending { .. } => write!(f, "FutureState::Pending"),
299            FutureState::Resolved(v) => write!(f, "FutureState::Resolved({:?})", v),
300            FutureState::Error(e) => write!(f, "FutureState::Error({:?})", e),
301        }
302    }
303}
304
305impl std::fmt::Debug for HttpFutureKind {
306    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
307        match self {
308            HttpFutureKind::String => write!(f, "String"),
309            HttpFutureKind::Json => write!(f, "Json"),
310            HttpFutureKind::FullResponse => write!(f, "FullResponse"),
311            HttpFutureKind::SystemResult => write!(f, "SystemResult"),
312        }
313    }
314}
315
316impl Value {
317    pub fn type_name(&self) -> String {
318        match self {
319            Value::Int(_) => "int".to_string(),
320            Value::Float(_) => "float".to_string(),
321            Value::Decimal(_) => "decimal".to_string(),
322            Value::String(_) => "string".to_string(),
323            Value::Symbol(_) => "symbol".to_string(),
324            Value::Bool(_) => "bool".to_string(),
325            Value::Null => "null".to_string(),
326            Value::Array(_) => "array".to_string(),
327            Value::Hash(_) => "hash".to_string(),
328            Value::Function(_) => "Function".to_string(),
329            Value::NativeFunction(_) => "Function".to_string(),
330            Value::Class(_) => "Class".to_string(),
331            Value::Instance(i) => i.borrow().class.name.clone(),
332            Value::Future(_) => "Future".to_string(),
333            Value::Method(_) => "Method".to_string(),
334            Value::Breakpoint => "Breakpoint".to_string(),
335            Value::QueryBuilder(_) => "QueryBuilder".to_string(),
336            Value::Super(_) => "Super".to_string(),
337            Value::VmClosure(_) => "Function".to_string(),
338            Value::Image(_) => "Image".to_string(),
339        }
340    }
341
342    /// Resolve a Future value, blocking until the result is ready.
343    /// For non-Future values, returns the value unchanged.
344    pub fn resolve(self) -> Result<Value, String> {
345        match self {
346            Value::Future(state) => {
347                let mut guard = state.lock().map_err(|_| "Future lock poisoned")?;
348                match std::mem::replace(
349                    &mut *guard,
350                    FutureState::Error("Future already consumed".into()),
351                ) {
352                    FutureState::Pending { receiver, kind } => {
353                        match receiver.recv() {
354                            Ok(Ok(raw_data)) => {
355                                // Convert raw string data to Value based on kind
356                                let value = convert_future_result(&raw_data, &kind)?;
357                                *guard = FutureState::Resolved(value.clone());
358                                Ok(value)
359                            }
360                            Ok(Err(e)) => {
361                                *guard = FutureState::Error(e.clone());
362                                Err(e)
363                            }
364                            Err(_) => Err("Future channel closed".into()),
365                        }
366                    }
367                    FutureState::Resolved(value) => {
368                        *guard = FutureState::Resolved(value.clone());
369                        Ok(value)
370                    }
371                    FutureState::Error(e) => {
372                        *guard = FutureState::Error(e.clone());
373                        Err(e)
374                    }
375                }
376            }
377            other => Ok(other),
378        }
379    }
380
381    /// Check if this value is a Future
382    pub fn is_future(&self) -> bool {
383        matches!(self, Value::Future(_))
384    }
385
386    pub fn is_truthy(&self) -> bool {
387        match self {
388            Value::Bool(b) => *b,
389            Value::Null => false,
390            Value::Int(0) => false,
391            Value::Decimal(_) => true,
392            Value::String(s) if s.is_empty() => false,
393            Value::Array(arr) if arr.borrow().is_empty() => false,
394            Value::Hash(hash) if hash.borrow().is_empty() => false,
395            Value::Future(_) => true,
396            Value::VmClosure(_) => true,
397            _ => true,
398        }
399    }
400
401    /// Check if this value can be used as a hash key (must be comparable).
402    /// Note: Floats are excluded because NaN != NaN breaks hash map invariants.
403    pub fn is_hashable(&self) -> bool {
404        matches!(
405            self,
406            Value::Int(_)
407                | Value::Decimal(_)
408                | Value::String(_)
409                | Value::Symbol(_)
410                | Value::Bool(_)
411                | Value::Null
412        )
413    }
414
415    /// Convert this value to a HashKey if possible.
416    pub fn to_hash_key(&self) -> Option<HashKey> {
417        HashKey::from_value(self)
418    }
419
420    /// Value equality for hash key comparison (legacy method, kept for compatibility).
421    pub fn hash_eq(&self, other: &Self) -> bool {
422        match (self, other) {
423            (Value::Int(a), Value::Int(b)) => a == b,
424            (Value::Float(a), Value::Float(b)) => a == b,
425            (Value::Decimal(a), Value::Decimal(b)) => a == b,
426            (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
427            (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
428            (Value::String(a), Value::String(b)) => a == b,
429            (Value::Bool(a), Value::Bool(b)) => a == b,
430            (Value::Null, Value::Null) => true,
431            _ => false,
432        }
433    }
434
435    #[inline]
436    pub fn display_len(&self) -> usize {
437        match self {
438            Value::Int(n) => n.to_string().len(),
439            Value::Float(n) => n.to_string().len(),
440            Value::Decimal(d) => d.to_string().len(),
441            Value::String(s) => s.len(),
442            Value::Symbol(s) => s.len() + 1,
443            Value::Bool(b) => {
444                if *b {
445                    4
446                } else {
447                    5
448                }
449            }
450            Value::Null => 4,
451            Value::Array(arr) => {
452                let arr = arr.borrow();
453                if arr.is_empty() {
454                    return 2;
455                }
456                let mut len = 1;
457                for (i, v) in arr.iter().enumerate() {
458                    len += v.display_len();
459                    if i > 0 {
460                        len += 2;
461                    }
462                }
463                len + 1
464            }
465            Value::Hash(hash) => {
466                let hash = hash.borrow();
467                if hash.is_empty() {
468                    return 2;
469                }
470                let mut len = 1;
471                for (i, (k, v)) in hash.iter().enumerate() {
472                    len += k.to_value().display_len();
473                    len += 4;
474                    len += v.display_len();
475                    if i > 0 {
476                        len += 2;
477                    }
478                }
479                len + 1
480            }
481            Value::Function(func) => func.name.len() + 5,
482            Value::NativeFunction(func) => func.name.len() + 13,
483            Value::Class(class) => class.name.len() + 8,
484            Value::Instance(inst) => {
485                let inst = inst.borrow();
486                inst.class.name.len() + 15
487            }
488            Value::Future(_) => 7,
489            Value::Method(_) => 8,
490            Value::Breakpoint => 10,
491            Value::QueryBuilder(_) => 13,
492            Value::Super(_) => 7,
493            Value::VmClosure(func) => func.proto.name.len() + 5,
494            Value::Image(_) => 7,
495        }
496    }
497
498    #[inline]
499    pub fn write_to_string(&self, s: &mut String) {
500        match self {
501            Value::Int(n) => s.push_str(&n.to_string()),
502            Value::Float(n) => s.push_str(&n.to_string()),
503            Value::Decimal(d) => s.push_str(&d.to_string()),
504            Value::String(st) => s.push_str(st),
505            Value::Symbol(sym) => {
506                s.push(':');
507                s.push_str(sym);
508            }
509            Value::Bool(b) => s.push_str(if *b { "true" } else { "false" }),
510            Value::Null => s.push_str("null"),
511            Value::Array(arr) => {
512                s.push('[');
513                let arr = arr.borrow();
514                for (i, v) in arr.iter().enumerate() {
515                    if i > 0 {
516                        s.push_str(", ");
517                    }
518                    v.write_to_string(s);
519                }
520                s.push(']');
521            }
522            Value::Hash(hash) => {
523                s.push('{');
524                let hash = hash.borrow();
525                for (i, (k, v)) in hash.iter().enumerate() {
526                    if i > 0 {
527                        s.push_str(", ");
528                    }
529                    k.to_value().write_to_string(s);
530                    s.push_str(" => ");
531                    v.write_to_string(s);
532                }
533                s.push('}');
534            }
535            Value::Function(func) => {
536                s.push_str("<fn ");
537                s.push_str(&func.name);
538                s.push('>');
539            }
540            Value::NativeFunction(func) => {
541                s.push_str("<native fn ");
542                s.push_str(&func.name);
543                s.push('>');
544            }
545            Value::Class(class) => {
546                s.push_str("<class ");
547                s.push_str(&class.name);
548                s.push('>');
549            }
550            Value::Instance(inst) => {
551                let inst = inst.borrow();
552                s.push('<');
553                s.push_str(&inst.class.name);
554                s.push_str(" instance>");
555            }
556            Value::Future(_) => s.push_str("<Future>"),
557            Value::Method(_) => s.push_str("<Method>"),
558            Value::Breakpoint => s.push_str("<Breakpoint>"),
559            Value::QueryBuilder(_) => s.push_str("<QueryBuilder>"),
560            Value::Super(_) => s.push_str("<Super>"),
561            Value::VmClosure(func) => {
562                s.push_str("<fn ");
563                s.push_str(&func.proto.name);
564                s.push('>');
565            }
566            Value::Image(_) => s.push_str("<Image>"),
567        }
568    }
569}
570
571impl PartialEq for Value {
572    fn eq(&self, other: &Self) -> bool {
573        match (self, other) {
574            (Value::Int(a), Value::Int(b)) => a == b,
575            (Value::Float(a), Value::Float(b)) => a == b,
576            (Value::Decimal(a), Value::Decimal(b)) => a == b,
577            (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
578            (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
579            (Value::String(a), Value::String(b)) => a == b,
580            (Value::Symbol(a), Value::Symbol(b)) => a == b,
581            (Value::Bool(a), Value::Bool(b)) => a == b,
582            (Value::Null, Value::Null) => true,
583            (Value::Array(a), Value::Array(b)) => {
584                // Use structural equality for arrays
585                let a_ref = a.borrow();
586                let b_ref = b.borrow();
587                if a_ref.len() != b_ref.len() {
588                    return false;
589                }
590                a_ref.iter().zip(b_ref.iter()).all(|(x, y)| x == y)
591            }
592            (Value::Hash(a), Value::Hash(b)) => {
593                // Use structural equality for hashes (O(n) with IndexMap)
594                let a_ref = a.borrow();
595                let b_ref = b.borrow();
596                if a_ref.len() != b_ref.len() {
597                    return false;
598                }
599                // Check that all key-value pairs in a exist in b with same values
600                a_ref.iter().all(|(k, v_a)| b_ref.get(k) == Some(v_a))
601            }
602            (Value::Instance(a), Value::Instance(b)) => Rc::ptr_eq(a, b),
603            (Value::Method(a), Value::Method(b)) => {
604                *a.receiver == *b.receiver && a.method_name == b.method_name
605            }
606            _ => false,
607        }
608    }
609}
610
611impl fmt::Display for Value {
612    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
613        match self {
614            Value::Int(n) => write!(f, "{}", n),
615            Value::Float(n) => write!(f, "{}", n),
616            Value::Decimal(d) => write!(f, "{}", d),
617            Value::String(s) => write!(f, "{}", s),
618            Value::Symbol(s) => write!(f, ":{}", s),
619            Value::Bool(b) => write!(f, "{}", b),
620            Value::Null => write!(f, "null"),
621            Value::Array(arr) => {
622                write!(f, "[")?;
623                let arr = arr.borrow();
624                for (i, val) in arr.iter().enumerate() {
625                    if i > 0 {
626                        write!(f, ", ")?;
627                    }
628                    write!(f, "{}", val)?;
629                }
630                write!(f, "]")
631            }
632            Value::Hash(hash) => {
633                write!(f, "{{")?;
634                let hash = hash.borrow();
635                for (i, (key, val)) in hash.iter().enumerate() {
636                    if i > 0 {
637                        write!(f, ", ")?;
638                    }
639                    write!(f, "{} => {}", key.to_value(), val)?;
640                }
641                write!(f, "}}")
642            }
643            Value::Function(func) => write!(f, "<fn {}>", func.name),
644            Value::NativeFunction(func) => write!(f, "<native fn {}>", func.name),
645            Value::Class(class) => write!(f, "<class {}>", class.name),
646            Value::Instance(inst) => {
647                let inst_ref = inst.borrow();
648                if inst_ref.fields.is_empty() {
649                    write!(f, "<{} instance>", inst_ref.class.name)
650                } else {
651                    write!(f, "<{}", inst_ref.class.name)?;
652                    let mut first = true;
653                    for (k, v) in inst_ref.fields.iter() {
654                        // Hide _errors when empty
655                        if k == "_errors" {
656                            if let Value::Array(arr) = v {
657                                if arr.borrow().is_empty() {
658                                    continue;
659                                }
660                            }
661                        }
662                        if first {
663                            write!(f, " ")?;
664                            first = false;
665                        } else {
666                            write!(f, ",\n ")?;
667                        }
668                        match v {
669                            Value::String(s) => write!(f, "{}: \"{}\"", k, s)?,
670                            _ => write!(f, "{}: {}", k, v)?,
671                        }
672                    }
673                    write!(f, ">")
674                }
675            }
676            Value::Future(state) => {
677                // Auto-resolve the future when displaying
678                let guard = state.lock().unwrap();
679                match &*guard {
680                    FutureState::Pending { .. } => write!(f, "<pending future>"),
681                    FutureState::Resolved(val) => write!(f, "{}", val),
682                    FutureState::Error(e) => write!(f, "<error: {}>", e),
683                }
684            }
685            Value::Method(method) => write!(
686                f,
687                "<method {}.{}>",
688                method.receiver.type_name(),
689                method.method_name
690            ),
691            Value::Breakpoint => write!(f, "<breakpoint>"),
692            Value::QueryBuilder(qb) => {
693                let qb = qb.borrow();
694                if qb.filter.is_some() {
695                    write!(f, "<QueryBuilder for {} with filter>", qb.class_name)
696                } else {
697                    write!(f, "<QueryBuilder for {}>", qb.class_name)
698                }
699            }
700            Value::Super(class) => write!(f, "<super of {}>", class.name),
701            Value::VmClosure(c) => write!(f, "<fn {}>", c.proto.name),
702            Value::Image(_) => write!(f, "<Image>"),
703        }
704    }
705}
706
707/// A user-defined function.
708#[derive(Debug, Clone)]
709pub struct Function {
710    pub name: String,
711    pub params: Vec<Parameter>,
712    pub body: Vec<Stmt>,
713    pub closure: Rc<RefCell<Environment>>,
714    pub is_method: bool,
715    pub span: Option<Span>,
716    pub source_path: Option<String>,
717    /// The superclass of the class where this method was defined.
718    /// Used for super calls to resolve to the correct parent class.
719    pub defining_superclass: Option<Rc<Class>>,
720    /// The declared return type annotation, if any.
721    /// Used for runtime return type enforcement.
722    pub return_type: Option<TypeAnnotation>,
723}
724
725impl Default for Function {
726    fn default() -> Self {
727        Self {
728            name: String::new(),
729            params: Vec::new(),
730            body: Vec::new(),
731            closure: Rc::new(RefCell::new(Environment::new())),
732            is_method: false,
733            span: None,
734            source_path: None,
735            defining_superclass: None,
736            return_type: None,
737        }
738    }
739}
740
741impl Function {
742    pub fn from_decl(
743        decl: &FunctionDecl,
744        closure: Rc<RefCell<Environment>>,
745        source_path: Option<String>,
746    ) -> Self {
747        Self {
748            name: decl.name.clone(),
749            params: decl.params.clone(),
750            body: decl.body.clone(),
751            closure,
752            is_method: false,
753            span: Some(decl.span),
754            source_path,
755            defining_superclass: None,
756            return_type: decl.return_type.clone(),
757        }
758    }
759
760    pub fn from_method(
761        decl: &MethodDecl,
762        closure: Rc<RefCell<Environment>>,
763        source_path: Option<String>,
764    ) -> Self {
765        Self {
766            name: decl.name.clone(),
767            params: decl.params.clone(),
768            body: decl.body.clone(),
769            closure,
770            is_method: true,
771            span: Some(decl.span),
772            source_path,
773            defining_superclass: None,
774            return_type: decl.return_type.clone(),
775        }
776    }
777
778    pub fn arity(&self) -> usize {
779        // Return the number of required parameters (params without defaults)
780        self.params
781            .iter()
782            .filter(|p| p.default_value.is_none())
783            .count()
784    }
785
786    /// Full arity including optional parameters
787    pub fn full_arity(&self) -> usize {
788        self.params.len()
789    }
790
791    /// Check if a parameter at index has a default value
792    pub fn param_has_default(&self, index: usize) -> bool {
793        self.params
794            .get(index)
795            .map(|p| p.default_value.is_some())
796            .unwrap_or(false)
797    }
798
799    /// Get the default value expression for a parameter at index
800    pub fn param_default_value(&self, index: usize) -> Option<&Expr> {
801        self.params
802            .get(index)
803            .and_then(|p| p.default_value.as_ref())
804    }
805}
806
807/// A native/builtin function.
808#[derive(Clone)]
809pub struct NativeFunction {
810    pub name: String,
811    pub arity: Option<usize>, // None means variadic
812    pub func: Rc<dyn Fn(Vec<Value>) -> Result<Value, String>>,
813}
814
815impl NativeFunction {
816    pub fn new<F>(name: impl Into<String>, arity: Option<usize>, func: F) -> Self
817    where
818        F: Fn(Vec<Value>) -> Result<Value, String> + 'static,
819    {
820        Self {
821            name: name.into(),
822            arity,
823            func: Rc::new(func),
824        }
825    }
826}
827
828impl fmt::Debug for NativeFunction {
829    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830        write!(f, "NativeFunction({})", self.name)
831    }
832}
833
834/// A method on a value (array/hash) that captures the receiver and method name.
835/// This allows calling methods like `.map()`, `.filter()`, `.each()` on values.
836#[derive(Clone)]
837pub struct ValueMethod {
838    pub receiver: Box<Value>,
839    pub method_name: String,
840}
841
842impl fmt::Debug for ValueMethod {
843    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
844        write!(
845            f,
846            "<method {}.{}>",
847            self.receiver.type_name(),
848            self.method_name
849        )
850    }
851}
852
853/// Kinds of value methods for arrays
854#[derive(Clone, Copy, Debug)]
855pub enum ArrayMethodKind {
856    Map,
857    Filter,
858    Each,
859}
860
861/// A class definition.
862#[derive(Debug, Clone)]
863pub struct Class {
864    pub name: String,
865    pub superclass: Option<Rc<Class>>,
866    /// Instance methods - using RefCell for interior mutability to support define_method
867    pub methods: Rc<RefCell<HashMap<String, Rc<Function>>>>,
868    pub static_methods: HashMap<String, Rc<Function>>,
869    pub native_static_methods: HashMap<String, Rc<NativeFunction>>,
870    pub native_methods: HashMap<String, Rc<NativeFunction>>,
871    pub static_fields: Rc<RefCell<HashMap<String, Value>>>,
872    pub fields: HashMap<String, Option<Expr>>,
873    pub constructor: Option<Rc<Function>>,
874    /// Nested classes defined within this class - using RefCell for interior mutability
875    pub nested_classes: Rc<RefCell<HashMap<String, Rc<Class>>>>,
876    /// Instance field names declared as `const` (immutable after initialization).
877    pub const_fields: HashSet<String>,
878    /// Static field names declared as `const` (immutable after initialization).
879    pub static_const_fields: HashSet<String>,
880    /// Flattened method cache for O(1) lookups including inherited methods.
881    /// This is computed lazily on first access and includes all methods from the inheritance chain.
882    /// NOTE: Should not be manually set; use Class::new() constructor instead.
883    pub all_methods_cache: RefCell<Option<HashMap<String, Rc<Function>>>>,
884    /// Flattened native method cache for O(1) lookups.
885    /// NOTE: Should not be manually set; use Class::new() constructor instead.
886    pub all_native_methods_cache: RefCell<Option<HashMap<String, Rc<NativeFunction>>>>,
887}
888
889impl Default for Class {
890    fn default() -> Self {
891        Self {
892            name: String::new(),
893            superclass: None,
894            methods: Rc::new(RefCell::new(HashMap::new())),
895            static_methods: HashMap::new(),
896            native_static_methods: HashMap::new(),
897            native_methods: HashMap::new(),
898            static_fields: Rc::new(RefCell::new(HashMap::new())),
899            fields: HashMap::new(),
900            constructor: None,
901            nested_classes: Rc::new(RefCell::new(HashMap::new())),
902            const_fields: HashSet::new(),
903            static_const_fields: HashSet::new(),
904            all_methods_cache: RefCell::new(None),
905            all_native_methods_cache: RefCell::new(None),
906        }
907    }
908}
909
910impl Class {
911    /// Create a new class with all fields initialized, including caches.
912    #[allow(clippy::too_many_arguments)]
913    pub fn new(
914        name: String,
915        superclass: Option<Rc<Class>>,
916        methods: HashMap<String, Rc<Function>>,
917        static_methods: HashMap<String, Rc<Function>>,
918        native_static_methods: HashMap<String, Rc<NativeFunction>>,
919        native_methods: HashMap<String, Rc<NativeFunction>>,
920        static_fields: Rc<RefCell<HashMap<String, Value>>>,
921        fields: HashMap<String, Option<Expr>>,
922        constructor: Option<Rc<Function>>,
923        nested_classes: Rc<RefCell<HashMap<String, Rc<Class>>>>,
924    ) -> Self {
925        Self {
926            name,
927            superclass,
928            methods: Rc::new(RefCell::new(methods)),
929            static_methods,
930            native_static_methods,
931            native_methods,
932            static_fields,
933            fields,
934            constructor,
935            nested_classes,
936            const_fields: HashSet::new(),
937            static_const_fields: HashSet::new(),
938            all_methods_cache: RefCell::new(None),
939            all_native_methods_cache: RefCell::new(None),
940        }
941    }
942
943    /// Find a constructor in this class or its superclass chain.
944    pub fn find_constructor(&self) -> Option<Rc<Function>> {
945        if let Some(ref ctor) = self.constructor {
946            return Some(ctor.clone());
947        }
948        if let Some(ref superclass) = self.superclass {
949            return superclass.find_constructor();
950        }
951        None
952    }
953
954    /// Build the flattened method cache if not already built.
955    fn ensure_methods_cached(&self) {
956        // Fast path: check if already cached without borrowing mutably
957        if self.all_methods_cache.borrow().is_some() {
958            return;
959        }
960
961        // Build flattened method map
962        let mut all_methods = HashMap::new();
963
964        // First, get methods from superclass (if any)
965        if let Some(ref superclass) = self.superclass {
966            superclass.ensure_methods_cached();
967            if let Some(ref parent_cache) = *superclass.all_methods_cache.borrow() {
968                all_methods.extend(parent_cache.iter().map(|(k, v)| (k.clone(), v.clone())));
969            }
970        }
971
972        // Then, override with methods from this class
973        for (k, v) in self.methods.borrow().iter() {
974            all_methods.insert(k.clone(), v.clone());
975        }
976
977        // Store in cache
978        *self.all_methods_cache.borrow_mut() = Some(all_methods);
979    }
980
981    /// Build the flattened native method cache if not already built.
982    fn ensure_native_methods_cached(&self) {
983        // Fast path: check if already cached without borrowing mutably
984        if self.all_native_methods_cache.borrow().is_some() {
985            return;
986        }
987
988        // Build flattened native method map
989        let mut all_native_methods = HashMap::new();
990
991        // First, get native methods from superclass (if any)
992        if let Some(ref superclass) = self.superclass {
993            superclass.ensure_native_methods_cached();
994            if let Some(ref parent_cache) = *superclass.all_native_methods_cache.borrow() {
995                all_native_methods.extend(parent_cache.iter().map(|(k, v)| (k.clone(), v.clone())));
996            }
997        }
998
999        // Then, override with native methods from this class
1000        all_native_methods.extend(self.native_methods.clone());
1001
1002        // Store in cache
1003        *self.all_native_methods_cache.borrow_mut() = Some(all_native_methods);
1004    }
1005
1006    pub fn find_method(&self, name: &str) -> Option<Rc<Function>> {
1007        // Ensure cache is built, then do O(1) lookup
1008        self.ensure_methods_cached();
1009        self.all_methods_cache
1010            .borrow()
1011            .as_ref()
1012            .and_then(|cache| cache.get(name).cloned())
1013    }
1014
1015    pub fn find_native_method(&self, name: &str) -> Option<Rc<NativeFunction>> {
1016        // Ensure cache is built, then do O(1) lookup
1017        self.ensure_native_methods_cached();
1018        self.all_native_methods_cache
1019            .borrow()
1020            .as_ref()
1021            .and_then(|cache| cache.get(name).cloned())
1022    }
1023
1024    /// Find a static method in this class or its superclass chain.
1025    pub fn find_static_method(&self, name: &str) -> Option<Rc<Function>> {
1026        if let Some(method) = self.static_methods.get(name) {
1027            return Some(method.clone());
1028        }
1029        if let Some(ref superclass) = self.superclass {
1030            return superclass.find_static_method(name);
1031        }
1032        None
1033    }
1034
1035    /// Find a native static method in this class or its superclass chain.
1036    pub fn find_native_static_method(&self, name: &str) -> Option<Rc<NativeFunction>> {
1037        if let Some(method) = self.native_static_methods.get(name) {
1038            return Some(method.clone());
1039        }
1040        if let Some(ref superclass) = self.superclass {
1041            return superclass.find_native_static_method(name);
1042        }
1043        None
1044    }
1045
1046    /// Check if this class is a subclass of Model (directly or indirectly).
1047    pub fn is_model_subclass(&self) -> bool {
1048        if self.name == "Model" {
1049            return true;
1050        }
1051        if let Some(ref superclass) = self.superclass {
1052            return superclass.is_model_subclass();
1053        }
1054        false
1055    }
1056}
1057
1058/// A class instance.
1059#[derive(Debug, Clone)]
1060pub struct Instance {
1061    pub class: Rc<Class>,
1062    pub fields: HashMap<String, Value>,
1063}
1064
1065impl Instance {
1066    pub fn new(class: Rc<Class>) -> Self {
1067        Self {
1068            class,
1069            fields: HashMap::new(),
1070        }
1071    }
1072
1073    pub fn get(&self, name: &str) -> Option<Value> {
1074        self.fields.get(name).cloned()
1075    }
1076
1077    pub fn set(&mut self, name: String, value: Value) {
1078        self.fields.insert(name, value);
1079    }
1080
1081    pub fn get_method(&self, name: &str) -> Option<Value> {
1082        // Check instance fields first
1083        if let Some(value) = self.fields.get(name) {
1084            return Some(value.clone());
1085        }
1086        // Then check class methods - convert Rc<Function> to Value::Function
1087        if let Some(func) = self.class.methods.borrow().get(name) {
1088            return Some(Value::Function(func.clone()));
1089        }
1090        None
1091    }
1092}
1093
1094/// Convert raw HTTP response data to a Value based on the future kind.
1095/// For FullResponse, the raw_data is a JSON-encoded response object.
1096fn convert_future_result(raw_data: &str, kind: &HttpFutureKind) -> Result<Value, String> {
1097    match kind {
1098        HttpFutureKind::String => Ok(Value::String(raw_data.to_string())),
1099        HttpFutureKind::Json => {
1100            // Parse JSON string into Value
1101            match serde_json::from_str::<serde_json::Value>(raw_data) {
1102                Ok(json) => json_to_value(json),
1103                Err(e) => Err(format!("Failed to parse JSON: {}", e)),
1104            }
1105        }
1106        HttpFutureKind::FullResponse => {
1107            // Parse the JSON-encoded full response
1108            match serde_json::from_str::<serde_json::Value>(raw_data) {
1109                Ok(json) => json_to_value(json),
1110                Err(e) => Err(format!("Failed to parse response: {}", e)),
1111            }
1112        }
1113        HttpFutureKind::SystemResult => {
1114            // Parse JSON: {"stdout": "...", "stderr": "...", "exit_code": N}
1115            #[derive(serde::Deserialize)]
1116            struct SystemResultJson {
1117                stdout: String,
1118                stderr: String,
1119                exit_code: i32,
1120            }
1121            match serde_json::from_str::<SystemResultJson>(raw_data) {
1122                Ok(data) => {
1123                    // Create a simple hash with the result data using IndexMap
1124                    let mut hash: HashPairs = HashPairs::default();
1125                    hash.insert(
1126                        HashKey::String("stdout".to_string()),
1127                        Value::String(data.stdout),
1128                    );
1129                    hash.insert(
1130                        HashKey::String("stderr".to_string()),
1131                        Value::String(data.stderr),
1132                    );
1133                    hash.insert(
1134                        HashKey::String("exit_code".to_string()),
1135                        Value::Int(data.exit_code as i64),
1136                    );
1137                    Ok(Value::Hash(Rc::new(RefCell::new(hash))))
1138                }
1139                Err(e) => Err(format!("Failed to parse SystemResult: {}", e)),
1140            }
1141        }
1142    }
1143}
1144
1145/// Convert a serde_json::Value to a Soli Value (consuming — moves strings instead of cloning).
1146pub fn json_to_value(json: serde_json::Value) -> Result<Value, String> {
1147    match json {
1148        serde_json::Value::Null => Ok(Value::Null),
1149        serde_json::Value::Bool(b) => Ok(Value::Bool(b)),
1150        serde_json::Value::Number(n) => {
1151            if let Some(i) = n.as_i64() {
1152                Ok(Value::Int(i))
1153            } else if let Some(f) = n.as_f64() {
1154                Ok(Value::Float(f))
1155            } else {
1156                Err("Invalid JSON number".to_string())
1157            }
1158        }
1159        serde_json::Value::String(s) => {
1160            // Try to parse as decimal first
1161            if let Ok(d) = s.parse::<Decimal>() {
1162                let precision = s.split('.').nth(1).map(|p| p.len() as u32).unwrap_or(0);
1163                Ok(Value::Decimal(DecimalValue(d, precision)))
1164            } else {
1165                Ok(Value::String(s))
1166            }
1167        }
1168        serde_json::Value::Array(arr) => {
1169            let len = arr.len();
1170            let mut items = Vec::with_capacity(len);
1171            for v in arr {
1172                items.push(json_to_value(v)?);
1173            }
1174            Ok(Value::Array(Rc::new(RefCell::new(items))))
1175        }
1176        serde_json::Value::Object(obj) => {
1177            let len = obj.len();
1178            let mut map = HashPairs::with_capacity_and_hasher(len, AHasher::default());
1179            for (k, v) in obj {
1180                map.insert(HashKey::String(k), json_to_value(v)?);
1181            }
1182            Ok(Value::Hash(Rc::new(RefCell::new(map))))
1183        }
1184    }
1185}
1186
1187/// Convert a serde_json::Value reference to a Soli Value (clones strings).
1188pub fn json_to_value_ref(json: &serde_json::Value) -> Result<Value, String> {
1189    match json {
1190        serde_json::Value::Null => Ok(Value::Null),
1191        serde_json::Value::Bool(b) => Ok(Value::Bool(*b)),
1192        serde_json::Value::Number(n) => {
1193            if let Some(i) = n.as_i64() {
1194                Ok(Value::Int(i))
1195            } else if let Some(f) = n.as_f64() {
1196                Ok(Value::Float(f))
1197            } else {
1198                Err("Invalid JSON number".to_string())
1199            }
1200        }
1201        serde_json::Value::String(s) => {
1202            // Try to parse as decimal first
1203            if let Ok(d) = s.parse::<Decimal>() {
1204                let precision = s.split('.').nth(1).map(|p| p.len() as u32).unwrap_or(0);
1205                Ok(Value::Decimal(DecimalValue(d, precision)))
1206            } else {
1207                Ok(Value::String(s.clone()))
1208            }
1209        }
1210        serde_json::Value::Array(arr) => {
1211            let len = arr.len();
1212            let mut items = Vec::with_capacity(len);
1213            for v in arr {
1214                items.push(json_to_value_ref(v)?);
1215            }
1216            Ok(Value::Array(Rc::new(RefCell::new(items))))
1217        }
1218        serde_json::Value::Object(obj) => {
1219            let len = obj.len();
1220            let mut map = HashPairs::with_capacity_and_hasher(len, AHasher::default());
1221            for (k, v) in obj {
1222                map.insert(HashKey::String(k.clone()), json_to_value_ref(v)?);
1223            }
1224            Ok(Value::Hash(Rc::new(RefCell::new(map))))
1225        }
1226    }
1227}
1228
1229/// Convert a Soli Value to serde_json::Value.
1230pub fn value_to_json(value: &Value) -> Result<serde_json::Value, String> {
1231    match value {
1232        Value::Int(n) => Ok(serde_json::Value::Number(serde_json::Number::from(*n))),
1233        Value::Float(f) => Ok(serde_json::Value::Number(
1234            serde_json::Number::from_f64(*f).ok_or_else(|| "Invalid float".to_string())?,
1235        )),
1236        Value::Decimal(d) => Ok(serde_json::Value::String(d.to_string())),
1237        Value::String(s) => Ok(serde_json::Value::String(s.clone())),
1238        Value::Bool(b) => Ok(serde_json::Value::Bool(*b)),
1239        Value::Null => Ok(serde_json::Value::Null),
1240        Value::Array(arr) => {
1241            let borrow = arr.borrow();
1242            let len = borrow.len();
1243            let mut vec = Vec::with_capacity(len);
1244            for v in borrow.iter() {
1245                vec.push(value_to_json(v)?);
1246            }
1247            Ok(serde_json::Value::Array(vec))
1248        }
1249        Value::Hash(hash) => {
1250            let borrow = hash.borrow();
1251            let len = borrow.len();
1252            let mut map = serde_json::Map::with_capacity(len);
1253            for (k, v) in borrow.iter() {
1254                if let HashKey::String(key) = k {
1255                    map.insert(key.clone(), value_to_json(v)?);
1256                }
1257            }
1258            Ok(serde_json::Value::Object(map))
1259        }
1260        Value::Instance(inst) => {
1261            let borrow = inst.borrow();
1262            let len = borrow.fields.len();
1263            let mut map = serde_json::Map::with_capacity(len);
1264            for (k, v) in borrow.fields.iter() {
1265                map.insert(k.clone(), value_to_json(v)?);
1266            }
1267            Ok(serde_json::Value::Object(map))
1268        }
1269        _ => Err(format!("Cannot convert {} to JSON", value.type_name())),
1270    }
1271}
1272
1273/// Implement serde::Serialize for Value to leverage serde_json's optimized writer.
1274impl serde::Serialize for Value {
1275    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1276        match self {
1277            Value::Null => serializer.serialize_unit(),
1278            Value::Bool(b) => serializer.serialize_bool(*b),
1279            Value::Int(n) => serializer.serialize_i64(*n),
1280            Value::Float(f) => serializer.serialize_f64(*f),
1281            Value::Decimal(d) => serializer.serialize_str(&d.to_string()),
1282            Value::String(s) => serializer.serialize_str(s),
1283            Value::Symbol(s) => serializer.serialize_str(s),
1284            Value::Array(arr) => {
1285                let borrow = arr.borrow();
1286                let mut seq = serializer.serialize_seq(Some(borrow.len()))?;
1287                for v in borrow.iter() {
1288                    seq.serialize_element(v)?;
1289                }
1290                seq.end()
1291            }
1292            Value::Hash(hash) => {
1293                let borrow = hash.borrow();
1294                let mut map = serializer.serialize_map(Some(borrow.len()))?;
1295                for (k, v) in borrow.iter() {
1296                    match k {
1297                        HashKey::String(key) | HashKey::Symbol(key) => {
1298                            map.serialize_entry(key, v)?;
1299                        }
1300                        _ => {}
1301                    }
1302                }
1303                map.end()
1304            }
1305            Value::Instance(inst) => {
1306                let borrow = inst.borrow();
1307                let mut map = serializer.serialize_map(Some(borrow.fields.len()))?;
1308                for (k, v) in borrow.fields.iter() {
1309                    map.serialize_entry(k, v)?;
1310                }
1311                map.end()
1312            }
1313            _ => Err(serde::ser::Error::custom(format!(
1314                "Cannot convert {} to JSON",
1315                self.type_name()
1316            ))),
1317        }
1318    }
1319}
1320
1321/// Serialize a Value to a JSON string using sonic-rs SIMD-accelerated writer.
1322#[inline]
1323pub fn stringify_to_string(value: &Value) -> Result<String, String> {
1324    let bytes = sonic_rs::to_vec(value).map_err(|e| e.to_string())?;
1325    // SAFETY: JSON serializers always produce valid UTF-8
1326    Ok(unsafe { String::from_utf8_unchecked(bytes) })
1327}
1328
1329/// Serialize an array slice to JSON without cloning into a Value.
1330#[inline]
1331pub fn stringify_array_to_string(items: &[Value]) -> Result<String, String> {
1332    let bytes = sonic_rs::to_vec(items).map_err(|e| e.to_string())?;
1333    Ok(unsafe { String::from_utf8_unchecked(bytes) })
1334}
1335
1336/// Wrapper for serializing hash entries (slice of key-value pairs) directly.
1337pub struct HashEntrySlice<'a>(pub &'a [(HashKey, Value)]);
1338
1339impl serde::Serialize for HashEntrySlice<'_> {
1340    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
1341        use serde::ser::SerializeMap;
1342        let mut map = serializer.serialize_map(Some(self.0.len()))?;
1343        for (k, v) in self.0 {
1344            if let HashKey::String(key) = k {
1345                map.serialize_entry(key, v)?;
1346            }
1347        }
1348        map.end()
1349    }
1350}
1351
1352/// Serialize hash entries to JSON without cloning into a Value.
1353#[inline]
1354pub fn stringify_hash_entries_to_string(entries: &[(HashKey, Value)]) -> Result<String, String> {
1355    let bytes = sonic_rs::to_vec(&HashEntrySlice(entries)).map_err(|e| e.to_string())?;
1356    Ok(unsafe { String::from_utf8_unchecked(bytes) })
1357}
1358
1359/// Fast i64 parsing — avoids the overhead of str::parse for the common case.
1360#[inline(always)]
1361fn fast_parse_i64(b: &[u8]) -> Value {
1362    let (neg, start) = if b[0] == b'-' { (true, 1) } else { (false, 0) };
1363    let mut n: i64 = 0;
1364    let mut i = start;
1365    while i < b.len() {
1366        let d = (b[i] - b'0') as i64;
1367        match n.checked_mul(10).and_then(|n| n.checked_add(d)) {
1368            Some(v) => n = v,
1369            None => {
1370                // Overflow — fall back to f64
1371                let s = unsafe { std::str::from_utf8_unchecked(b) };
1372                return Value::Float(s.parse::<f64>().unwrap_or(0.0));
1373            }
1374        }
1375        i += 1;
1376    }
1377    Value::Int(if neg { -n } else { n })
1378}
1379
1380/// Hand-rolled JSON parser — builds Value directly in one pass.
1381/// No serde, no intermediate tree, no trait dispatch overhead.
1382pub fn parse_json(s: &str) -> Result<Value, String> {
1383    let bytes = s.as_bytes();
1384    let mut pos = 0;
1385    let value = parse_value(bytes, &mut pos)?;
1386    skip_ws(bytes, &mut pos);
1387    if pos < bytes.len() {
1388        return Err(format!("Trailing content at position {}", pos));
1389    }
1390    Ok(value)
1391}
1392
1393/// Parse JSON from bytes.
1394pub fn parse_json_bytes(bytes: &[u8]) -> Result<Value, String> {
1395    let mut pos = 0;
1396    let value = parse_value(bytes, &mut pos)?;
1397    skip_ws(bytes, &mut pos);
1398    if pos < bytes.len() {
1399        return Err(format!("Trailing content at position {}", pos));
1400    }
1401    Ok(value)
1402}
1403
1404#[inline(always)]
1405fn skip_ws(b: &[u8], pos: &mut usize) {
1406    while *pos < b.len() {
1407        match b[*pos] {
1408            b' ' | b'\t' | b'\n' | b'\r' => *pos += 1,
1409            _ => break,
1410        }
1411    }
1412}
1413
1414#[inline(always)]
1415fn peek(b: &[u8], pos: &mut usize) -> Result<u8, String> {
1416    skip_ws(b, pos);
1417    if *pos < b.len() {
1418        Ok(b[*pos])
1419    } else {
1420        Err("Unexpected end of JSON".to_string())
1421    }
1422}
1423
1424fn parse_value(b: &[u8], pos: &mut usize) -> Result<Value, String> {
1425    match peek(b, pos)? {
1426        b'"' => parse_string(b, pos).map(Value::String),
1427        b'{' => parse_object(b, pos),
1428        b'[' => parse_array(b, pos),
1429        b't' => parse_literal(b, pos, b"true", Value::Bool(true)),
1430        b'f' => parse_literal(b, pos, b"false", Value::Bool(false)),
1431        b'n' => parse_literal(b, pos, b"null", Value::Null),
1432        b'-' | b'0'..=b'9' => parse_number(b, pos),
1433        c => Err(format!(
1434            "Unexpected character '{}' at position {}",
1435            c as char, *pos
1436        )),
1437    }
1438}
1439
1440#[inline]
1441fn parse_literal(
1442    b: &[u8],
1443    pos: &mut usize,
1444    expected: &[u8],
1445    value: Value,
1446) -> Result<Value, String> {
1447    if b[*pos..].starts_with(expected) {
1448        *pos += expected.len();
1449        Ok(value)
1450    } else {
1451        Err(format!("Invalid literal at position {}", *pos))
1452    }
1453}
1454
1455fn parse_number(b: &[u8], pos: &mut usize) -> Result<Value, String> {
1456    let start = *pos;
1457    let mut is_float = false;
1458
1459    if *pos < b.len() && b[*pos] == b'-' {
1460        *pos += 1;
1461    }
1462    if *pos >= b.len() || !b[*pos].is_ascii_digit() {
1463        return Err(format!("Invalid number at position {}", start));
1464    }
1465    if b[*pos] == b'0' {
1466        *pos += 1;
1467    } else {
1468        while *pos < b.len() && b[*pos].is_ascii_digit() {
1469            *pos += 1;
1470        }
1471    }
1472    if *pos < b.len() && b[*pos] == b'.' {
1473        is_float = true;
1474        *pos += 1;
1475        if *pos >= b.len() || !b[*pos].is_ascii_digit() {
1476            return Err(format!("Invalid number at position {}", start));
1477        }
1478        while *pos < b.len() && b[*pos].is_ascii_digit() {
1479            *pos += 1;
1480        }
1481    }
1482    if *pos < b.len() && (b[*pos] == b'e' || b[*pos] == b'E') {
1483        is_float = true;
1484        *pos += 1;
1485        if *pos < b.len() && (b[*pos] == b'+' || b[*pos] == b'-') {
1486            *pos += 1;
1487        }
1488        if *pos >= b.len() || !b[*pos].is_ascii_digit() {
1489            return Err(format!("Invalid number at position {}", start));
1490        }
1491        while *pos < b.len() && b[*pos].is_ascii_digit() {
1492            *pos += 1;
1493        }
1494    }
1495
1496    // SAFETY: We only advanced past ASCII digits, '.', 'e', 'E', '+', '-'
1497    let num_str = unsafe { std::str::from_utf8_unchecked(&b[start..*pos]) };
1498
1499    if is_float {
1500        num_str
1501            .parse::<f64>()
1502            .map(Value::Float)
1503            .map_err(|e| format!("Invalid float: {}", e))
1504    } else {
1505        // Fast path: hand-rolled i64 parse for common case
1506        Ok(fast_parse_i64(num_str.as_bytes()))
1507    }
1508}
1509
1510fn parse_string(b: &[u8], pos: &mut usize) -> Result<String, String> {
1511    *pos += 1; // skip opening '"'
1512    let start = *pos;
1513
1514    // Fast path: scan for end quote with no escapes using memchr-style scan
1515    while *pos < b.len() {
1516        let c = b[*pos];
1517        if c == b'"' {
1518            // No escapes found — direct allocation from slice
1519            let s = unsafe { String::from_utf8_unchecked(b[start..*pos].to_vec()) };
1520            *pos += 1;
1521            return Ok(s);
1522        }
1523        if c == b'\\' {
1524            break; // has escapes, use slow path
1525        }
1526        *pos += 1;
1527    }
1528
1529    // Slow path: build string with escape handling
1530    let mut result = String::from(unsafe { std::str::from_utf8_unchecked(&b[start..*pos]) });
1531    while *pos < b.len() {
1532        match b[*pos] {
1533            b'"' => {
1534                *pos += 1;
1535                return Ok(result);
1536            }
1537            b'\\' => {
1538                *pos += 1;
1539                if *pos >= b.len() {
1540                    return Err("Unterminated string escape".to_string());
1541                }
1542                match b[*pos] {
1543                    b'"' => result.push('"'),
1544                    b'\\' => result.push('\\'),
1545                    b'/' => result.push('/'),
1546                    b'n' => result.push('\n'),
1547                    b'r' => result.push('\r'),
1548                    b't' => result.push('\t'),
1549                    b'b' => result.push('\u{08}'),
1550                    b'f' => result.push('\u{0C}'),
1551                    b'u' => {
1552                        *pos += 1;
1553                        let cp = parse_hex4(b, pos)?;
1554                        if (0xD800..=0xDBFF).contains(&cp) {
1555                            // High surrogate — expect \uXXXX low surrogate
1556                            if *pos + 1 < b.len() && b[*pos] == b'\\' && b[*pos + 1] == b'u' {
1557                                *pos += 2;
1558                                let low = parse_hex4(b, pos)?;
1559                                if !(0xDC00..=0xDFFF).contains(&low) {
1560                                    return Err("Invalid surrogate pair".to_string());
1561                                }
1562                                let cp =
1563                                    0x10000 + ((cp as u32 - 0xD800) << 10) + (low as u32 - 0xDC00);
1564                                result.push(char::from_u32(cp).ok_or("Invalid Unicode")?);
1565                            } else {
1566                                return Err("Missing low surrogate".to_string());
1567                            }
1568                        } else {
1569                            result.push(
1570                                char::from_u32(cp as u32).ok_or("Invalid Unicode codepoint")?,
1571                            );
1572                        }
1573                        continue; // parse_hex4 already advanced pos
1574                    }
1575                    c => return Err(format!("Invalid escape \\{}", c as char)),
1576                }
1577                *pos += 1;
1578            }
1579            _ => {
1580                result.push(b[*pos] as char);
1581                *pos += 1;
1582            }
1583        }
1584    }
1585    Err("Unterminated string".to_string())
1586}
1587
1588#[inline]
1589fn parse_hex4(b: &[u8], pos: &mut usize) -> Result<u16, String> {
1590    if *pos + 4 > b.len() {
1591        return Err("Invalid \\u escape".to_string());
1592    }
1593    let hex = unsafe { std::str::from_utf8_unchecked(&b[*pos..*pos + 4]) };
1594    let val = u16::from_str_radix(hex, 16).map_err(|_| "Invalid hex in \\u escape".to_string())?;
1595    *pos += 4;
1596    Ok(val)
1597}
1598
1599fn parse_array(b: &[u8], pos: &mut usize) -> Result<Value, String> {
1600    *pos += 1; // skip '['
1601    if peek(b, pos)? == b']' {
1602        *pos += 1;
1603        return Ok(Value::Array(Rc::new(RefCell::new(Vec::new()))));
1604    }
1605    let mut items = Vec::with_capacity(8);
1606    loop {
1607        items.push(parse_value(b, pos)?);
1608        match peek(b, pos)? {
1609            b',' => *pos += 1,
1610            b']' => {
1611                *pos += 1;
1612                return Ok(Value::Array(Rc::new(RefCell::new(items))));
1613            }
1614            _ => return Err(format!("Expected ',' or ']' at position {}", *pos)),
1615        }
1616    }
1617}
1618
1619fn parse_object(b: &[u8], pos: &mut usize) -> Result<Value, String> {
1620    *pos += 1; // skip '{'
1621    if peek(b, pos)? == b'}' {
1622        *pos += 1;
1623        return Ok(Value::Hash(Rc::new(RefCell::new(HashPairs::with_hasher(
1624            AHasher::default(),
1625        )))));
1626    }
1627    // Pre-allocate for typical JSON objects (6 fields)
1628    let mut pairs = HashPairs::with_capacity_and_hasher(6, AHasher::default());
1629    loop {
1630        if peek(b, pos)? != b'"' {
1631            return Err(format!("Expected string key at position {}", *pos));
1632        }
1633        let key = parse_string(b, pos)?;
1634        if peek(b, pos)? != b':' {
1635            return Err(format!("Expected ':' at position {}", *pos));
1636        }
1637        *pos += 1;
1638        let value = parse_value(b, pos)?;
1639        pairs.insert(HashKey::String(key), value);
1640        match peek(b, pos)? {
1641            b',' => *pos += 1,
1642            b'}' => {
1643                *pos += 1;
1644                return Ok(Value::Hash(Rc::new(RefCell::new(pairs))));
1645            }
1646            _ => return Err(format!("Expected ',' or '}}' at position {}", *pos)),
1647        }
1648    }
1649}
1650
1651/// Unwrap a value, extracting the underlying value from class instances.
1652/// For String/Array/Hash class instances, returns the __value field.
1653/// For other values, returns the value as-is.
1654pub fn unwrap_value(value: &Value) -> Value {
1655    match value {
1656        Value::Instance(inst) => match inst.borrow().fields.get("__value").cloned() {
1657            Some(inner) => unwrap_value(&inner),
1658            _ => value.clone(),
1659        },
1660        _ => value.clone(),
1661    }
1662}
1663
1664use crate::ast::TypeKind;
1665
1666/// Check if a runtime value matches an expected type annotation.
1667/// Used for runtime return type enforcement.
1668pub fn value_matches_type(value: &Value, expected: &TypeAnnotation) -> bool {
1669    match &expected.kind {
1670        TypeKind::Named(name) => {
1671            let name_lower = name.to_lowercase();
1672            match name_lower.as_str() {
1673                "any" => true,
1674                "int" => matches!(value, Value::Int(_)),
1675                "float" => matches!(value, Value::Float(_)),
1676                "decimal" => matches!(value, Value::Decimal(_)),
1677                "string" => matches!(value, Value::String(_)),
1678                "bool" => matches!(value, Value::Bool(_)),
1679                "array" => matches!(value, Value::Array(_)),
1680                "hash" => matches!(value, Value::Hash(_)),
1681                "function" => matches!(value, Value::Function(_) | Value::NativeFunction(_)),
1682                "void" | "null" => matches!(value, Value::Null),
1683                // Class instance check
1684                _ => match value {
1685                    Value::Instance(inst) => inst.borrow().class.name == *name,
1686                    _ => false,
1687                },
1688            }
1689        }
1690        TypeKind::Void => matches!(value, Value::Null),
1691        TypeKind::Nullable(inner) => {
1692            matches!(value, Value::Null) || value_matches_type(value, inner)
1693        }
1694        TypeKind::Array(_) => matches!(value, Value::Array(_)),
1695        TypeKind::Hash { .. } => matches!(value, Value::Hash(_)),
1696        TypeKind::Function { .. } => {
1697            matches!(value, Value::Function(_) | Value::NativeFunction(_))
1698        }
1699    }
1700}
1701
1702#[cfg(test)]
1703mod decimal_tests {
1704    use super::*;
1705    use rust_decimal::Decimal;
1706    use std::str::FromStr;
1707
1708    #[test]
1709    fn test_decimal_value_creation() {
1710        let decimal = Decimal::from_str("19.99").unwrap();
1711        let decimal_value = DecimalValue(decimal, 2);
1712
1713        assert_eq!(decimal_value.precision(), 2);
1714        assert_eq!(decimal_value.to_string(), "19.99");
1715    }
1716
1717    #[test]
1718    fn test_decimal_value_from_str() {
1719        let result = DecimalValue::from_str("19.99", 2);
1720        assert!(result.is_ok());
1721        let decimal_value = result.unwrap();
1722        assert_eq!(decimal_value.precision(), 2);
1723        assert_eq!(decimal_value.to_string(), "19.99");
1724    }
1725
1726    #[test]
1727    fn test_decimal_value_from_str_invalid() {
1728        let result = DecimalValue::from_str("not_a_decimal", 2);
1729        assert!(result.is_err());
1730    }
1731
1732    #[test]
1733    fn test_decimal_value_to_f64() {
1734        let decimal = Decimal::from_str("19.99").unwrap();
1735        let decimal_value = DecimalValue(decimal, 2);
1736
1737        let f64_val = decimal_value.to_f64();
1738        assert!((f64_val - 19.99).abs() < 0.001);
1739    }
1740
1741    #[test]
1742    fn test_decimal_value_display() {
1743        let decimal = Decimal::from_str("123.45").unwrap();
1744        let decimal_value = DecimalValue(decimal, 2);
1745
1746        let display = format!("{}", decimal_value);
1747        assert_eq!(display, "123.45");
1748    }
1749
1750    #[test]
1751    fn test_decimal_value_clone() {
1752        let decimal = Decimal::from_str("99.99").unwrap();
1753        let original = DecimalValue(decimal, 2);
1754        let cloned = original.clone();
1755
1756        assert_eq!(original.to_string(), cloned.to_string());
1757        assert_eq!(original.precision(), cloned.precision());
1758    }
1759
1760    #[test]
1761    fn test_decimal_value_hash() {
1762        let decimal1 = Decimal::from_str("10.00").unwrap();
1763        let decimal2 = Decimal::from_str("10.00").unwrap();
1764        let decimal3 = Decimal::from_str("20.00").unwrap();
1765
1766        let dv1 = DecimalValue(decimal1, 2);
1767        let dv2 = DecimalValue(decimal2, 2);
1768        let dv3 = DecimalValue(decimal3, 2);
1769
1770        use std::collections::hash_map::DefaultHasher;
1771        use std::hash::Hash;
1772
1773        let mut hasher1 = DefaultHasher::new();
1774        dv1.hash(&mut hasher1);
1775        let hash1 = hasher1.finish();
1776
1777        let mut hasher2 = DefaultHasher::new();
1778        dv2.hash(&mut hasher2);
1779        let hash2 = hasher2.finish();
1780
1781        let mut hasher3 = DefaultHasher::new();
1782        dv3.hash(&mut hasher3);
1783        let hash3 = hasher3.finish();
1784
1785        assert_eq!(hash1, hash2);
1786        assert_ne!(hash1, hash3);
1787    }
1788
1789    #[test]
1790    fn test_hash_key_decimal() {
1791        let decimal = Decimal::from_str("19.99").unwrap();
1792        let decimal_value = DecimalValue(decimal, 2);
1793
1794        let hash_key = HashKey::Decimal(decimal_value.clone());
1795        let back_to_value = hash_key.to_value();
1796
1797        match back_to_value {
1798            Value::Decimal(dv) => {
1799                assert_eq!(dv.to_string(), decimal_value.to_string());
1800            }
1801            _ => panic!("Expected Decimal value"),
1802        }
1803    }
1804
1805    #[test]
1806    fn test_json_to_value_decimal_string() {
1807        let json = serde_json::Value::String("19.99".to_string());
1808        let result = json_to_value(json);
1809
1810        assert!(result.is_ok());
1811        let value = result.unwrap();
1812
1813        match value {
1814            Value::Decimal(dv) => {
1815                assert_eq!(dv.to_string(), "19.99");
1816            }
1817            _ => panic!("Expected Decimal value, got {:?}", value.type_name()),
1818        }
1819    }
1820
1821    #[test]
1822    fn test_json_to_value_decimal_string_precision() {
1823        let json = serde_json::Value::String("0.0675".to_string());
1824        let result = json_to_value(json);
1825
1826        assert!(result.is_ok());
1827        let value = result.unwrap();
1828
1829        match value {
1830            Value::Decimal(dv) => {
1831                assert_eq!(dv.precision(), 4);
1832                assert_eq!(dv.to_string(), "0.0675");
1833            }
1834            _ => panic!("Expected Decimal value"),
1835        }
1836    }
1837
1838    #[test]
1839    fn test_json_to_value_decimal_integer_string() {
1840        let json = serde_json::Value::String("100".to_string());
1841        let result = json_to_value(json);
1842
1843        assert!(result.is_ok());
1844        let value = result.unwrap();
1845
1846        match value {
1847            Value::Decimal(dv) => {
1848                assert_eq!(dv.precision(), 0);
1849                assert_eq!(dv.to_string(), "100");
1850            }
1851            _ => panic!("Expected Decimal value"),
1852        }
1853    }
1854
1855    #[test]
1856    fn test_value_to_json_decimal() {
1857        let decimal = Decimal::from_str("19.99").unwrap();
1858        let decimal_value = DecimalValue(decimal, 2);
1859        let value = Value::Decimal(decimal_value);
1860
1861        let result = value_to_json(&value);
1862
1863        assert!(result.is_ok());
1864        let json = result.unwrap();
1865
1866        match json {
1867            serde_json::Value::String(s) => {
1868                assert_eq!(s, "19.99");
1869            }
1870            _ => panic!("Expected JSON string"),
1871        }
1872    }
1873
1874    #[test]
1875    fn test_value_decimal_type_name() {
1876        let decimal = Decimal::from_str("19.99").unwrap();
1877        let decimal_value = DecimalValue(decimal, 2);
1878        let value = Value::Decimal(decimal_value);
1879
1880        assert_eq!(value.type_name(), "decimal");
1881    }
1882
1883    #[test]
1884    fn test_value_decimal_is_truthy() {
1885        let decimal = Decimal::from_str("0.00").unwrap();
1886        let decimal_value = DecimalValue(decimal, 2);
1887        let value = Value::Decimal(decimal_value);
1888
1889        assert!(value.is_truthy());
1890    }
1891
1892    #[test]
1893    fn test_value_decimal_is_hashable() {
1894        let decimal = Decimal::from_str("19.99").unwrap();
1895        let decimal_value = DecimalValue(decimal, 2);
1896        let value = Value::Decimal(decimal_value);
1897
1898        assert!(value.is_hashable());
1899    }
1900
1901    #[test]
1902    fn test_value_decimal_equality() {
1903        let decimal1 = Decimal::from_str("19.99").unwrap();
1904        let decimal2 = Decimal::from_str("19.99").unwrap();
1905        let decimal3 = Decimal::from_str("20.00").unwrap();
1906
1907        let value1 = Value::Decimal(DecimalValue(decimal1, 2));
1908        let value2 = Value::Decimal(DecimalValue(decimal2, 2));
1909        let value3 = Value::Decimal(DecimalValue(decimal3, 2));
1910
1911        assert_eq!(value1, value2);
1912        assert_ne!(value1, value3);
1913    }
1914
1915    #[test]
1916    fn test_value_decimal_partial_eq() {
1917        let decimal = Decimal::from_str("10.00").unwrap();
1918        let value = Value::Decimal(DecimalValue(decimal, 2));
1919
1920        assert!(value == Value::Decimal(DecimalValue(Decimal::from_str("10.00").unwrap(), 2)));
1921        assert!(value != Value::Decimal(DecimalValue(Decimal::from_str("20.00").unwrap(), 2)));
1922    }
1923
1924    #[test]
1925    fn test_decimal_precision_variations() {
1926        let test_cases = vec![
1927            ("0.1", 1),
1928            ("0.01", 2),
1929            ("0.001", 3),
1930            ("0.0001", 4),
1931            ("123.45", 2),
1932            ("1000", 0),
1933        ];
1934
1935        for (input, expected_precision) in test_cases {
1936            let json = serde_json::Value::String(input.to_string());
1937            let result = json_to_value(json);
1938
1939            assert!(result.is_ok(), "Failed for input: {}", input);
1940            let value = result.unwrap();
1941
1942            match value {
1943                Value::Decimal(dv) => {
1944                    assert_eq!(
1945                        dv.precision(),
1946                        expected_precision,
1947                        "Precision mismatch for input: {}",
1948                        input
1949                    );
1950                }
1951                _ => panic!("Expected Decimal value for input: {}", input),
1952            }
1953        }
1954    }
1955
1956    #[test]
1957    fn test_decimal_zero_values() {
1958        let zero_values = vec!["0", "0.0", "0.00", "0.000"];
1959
1960        for input in zero_values {
1961            let json = serde_json::Value::String(input.to_string());
1962            let result = json_to_value(json);
1963
1964            assert!(result.is_ok(), "Failed for zero input: {}", input);
1965            let value = result.unwrap();
1966
1967            match value {
1968                Value::Decimal(dv) => {
1969                    let dv_str = dv.to_string();
1970                    assert!(
1971                        dv_str == "0" || dv_str == "0.0" || dv_str == "0.00" || dv_str == "0.000",
1972                        "Unexpected zero format for input {}: got {}",
1973                        input,
1974                        dv_str
1975                    );
1976                }
1977                _ => panic!("Expected Decimal value for zero input: {}", input),
1978            }
1979        }
1980    }
1981
1982    #[test]
1983    fn test_decimal_negative_values() {
1984        let json = serde_json::Value::String("-19.99".to_string());
1985        let result = json_to_value(json);
1986
1987        assert!(result.is_ok());
1988        let value = result.unwrap();
1989
1990        match value {
1991            Value::Decimal(dv) => {
1992                assert_eq!(dv.to_string(), "-19.99");
1993            }
1994            _ => panic!("Expected Decimal value for negative input"),
1995        }
1996    }
1997
1998    #[test]
1999    fn test_decimal_large_values() {
2000        let json = serde_json::Value::String("9999999999.99".to_string());
2001        let result = json_to_value(json);
2002
2003        assert!(result.is_ok());
2004        let value = result.unwrap();
2005
2006        match value {
2007            Value::Decimal(dv) => {
2008                assert_eq!(dv.to_string(), "9999999999.99");
2009            }
2010            _ => panic!("Expected Decimal value for large input"),
2011        }
2012    }
2013
2014    #[test]
2015    fn test_decimal_in_array_json() {
2016        let json = serde_json::Value::Array(vec![
2017            serde_json::Value::String("10.00".to_string()),
2018            serde_json::Value::String("20.50".to_string()),
2019            serde_json::Value::String("30.75".to_string()),
2020        ]);
2021
2022        let result = json_to_value(json);
2023
2024        assert!(result.is_ok());
2025        let value = result.unwrap();
2026
2027        match value {
2028            Value::Array(arr_ref) => {
2029                let arr = arr_ref.borrow();
2030                assert_eq!(arr.len(), 3);
2031
2032                match &arr[0] {
2033                    Value::Decimal(dv) => assert_eq!(dv.to_string(), "10.00"),
2034                    _ => panic!("Expected Decimal in array"),
2035                }
2036            }
2037            _ => panic!("Expected Array value"),
2038        }
2039    }
2040
2041    #[test]
2042    fn test_decimal_in_hash_json() {
2043        let mut map = serde_json::Map::new();
2044        map.insert(
2045            "price".to_string(),
2046            serde_json::Value::String("19.99".to_string()),
2047        );
2048        map.insert(
2049            "name".to_string(),
2050            serde_json::Value::String("Widget".to_string()),
2051        );
2052        let json = serde_json::Value::Object(map);
2053
2054        let result = json_to_value(json);
2055
2056        assert!(result.is_ok());
2057        let value = result.unwrap();
2058
2059        match value {
2060            Value::Hash(hash_ref) => {
2061                let hash = hash_ref.borrow();
2062                let price_key = HashKey::String("price".to_string());
2063
2064                if let Some(price_value) = hash.get(&price_key) {
2065                    match price_value {
2066                        Value::Decimal(dv) => assert_eq!(dv.to_string(), "19.99"),
2067                        _ => panic!("Expected Decimal value for price"),
2068                    }
2069                } else {
2070                    panic!("Price key not found in hash");
2071                }
2072            }
2073            _ => panic!("Expected Hash value"),
2074        }
2075    }
2076}
2077
2078#[cfg(test)]
2079mod return_type_tests {
2080    use super::*;
2081    use crate::ast::{TypeAnnotation, TypeKind};
2082    use crate::span::Span;
2083
2084    fn make_type(kind: TypeKind) -> TypeAnnotation {
2085        TypeAnnotation::new(kind, Span::default())
2086    }
2087
2088    #[test]
2089    fn test_int_matches_int() {
2090        let value = Value::Int(42);
2091        let ty = make_type(TypeKind::Named("Int".to_string()));
2092        assert!(value_matches_type(&value, &ty));
2093    }
2094
2095    #[test]
2096    fn test_string_matches_string() {
2097        let value = Value::String("hello".to_string());
2098        let ty = make_type(TypeKind::Named("String".to_string()));
2099        assert!(value_matches_type(&value, &ty));
2100    }
2101
2102    #[test]
2103    fn test_int_does_not_match_string() {
2104        let value = Value::Int(42);
2105        let ty = make_type(TypeKind::Named("String".to_string()));
2106        assert!(!value_matches_type(&value, &ty));
2107    }
2108
2109    #[test]
2110    fn test_any_matches_everything() {
2111        let ty = make_type(TypeKind::Named("Any".to_string()));
2112        assert!(value_matches_type(&Value::Int(1), &ty));
2113        assert!(value_matches_type(&Value::String("x".to_string()), &ty));
2114        assert!(value_matches_type(&Value::Null, &ty));
2115        assert!(value_matches_type(&Value::Bool(true), &ty));
2116    }
2117
2118    #[test]
2119    fn test_nullable_accepts_null() {
2120        let inner = make_type(TypeKind::Named("Int".to_string()));
2121        let ty = make_type(TypeKind::Nullable(Box::new(inner)));
2122        assert!(value_matches_type(&Value::Null, &ty));
2123        assert!(value_matches_type(&Value::Int(42), &ty));
2124        assert!(!value_matches_type(&Value::String("x".to_string()), &ty));
2125    }
2126
2127    #[test]
2128    fn test_void_matches_null() {
2129        let ty = make_type(TypeKind::Void);
2130        assert!(value_matches_type(&Value::Null, &ty));
2131        assert!(!value_matches_type(&Value::Int(1), &ty));
2132    }
2133
2134    #[test]
2135    fn test_bool_matches_bool() {
2136        let ty = make_type(TypeKind::Named("Bool".to_string()));
2137        assert!(value_matches_type(&Value::Bool(true), &ty));
2138        assert!(value_matches_type(&Value::Bool(false), &ty));
2139        assert!(!value_matches_type(&Value::Int(1), &ty));
2140    }
2141
2142    #[test]
2143    #[allow(clippy::approx_constant)]
2144    fn test_float_matches_float() {
2145        let ty = make_type(TypeKind::Named("Float".to_string()));
2146        assert!(value_matches_type(&Value::Float(3.14), &ty));
2147        assert!(!value_matches_type(&Value::Int(3), &ty));
2148    }
2149
2150    #[test]
2151    fn test_array_type_matches_array() {
2152        let inner = make_type(TypeKind::Named("Int".to_string()));
2153        let ty = make_type(TypeKind::Array(Box::new(inner)));
2154        let arr = Value::Array(Rc::new(RefCell::new(vec![Value::Int(1)])));
2155        assert!(value_matches_type(&arr, &ty));
2156        assert!(!value_matches_type(&Value::Int(1), &ty));
2157    }
2158
2159    #[test]
2160    fn test_hash_type_matches_hash() {
2161        let key_ty = make_type(TypeKind::Named("String".to_string()));
2162        let val_ty = make_type(TypeKind::Named("Int".to_string()));
2163        let ty = make_type(TypeKind::Hash {
2164            key_type: Box::new(key_ty),
2165            value_type: Box::new(val_ty),
2166        });
2167        let hash = Value::Hash(Rc::new(RefCell::new(HashPairs::default())));
2168        assert!(value_matches_type(&hash, &ty));
2169        assert!(!value_matches_type(&Value::Int(1), &ty));
2170    }
2171
2172    #[test]
2173    fn test_case_insensitive_named_types() {
2174        // TypeKind uses "Int" but we should match case-insensitively
2175        let ty_lower = make_type(TypeKind::Named("int".to_string()));
2176        let ty_upper = make_type(TypeKind::Named("INT".to_string()));
2177        let ty_mixed = make_type(TypeKind::Named("Int".to_string()));
2178        let value = Value::Int(42);
2179        assert!(value_matches_type(&value, &ty_lower));
2180        assert!(value_matches_type(&value, &ty_upper));
2181        assert!(value_matches_type(&value, &ty_mixed));
2182    }
2183}