lust/bytecode/
value.rs

1use crate::ast::Type;
2use crate::jit;
3use crate::number::{
4    float_from_int, float_is_nan, float_to_hash_bits, int_from_float, int_from_usize, LustFloat,
5    LustInt,
6};
7use crate::vm::{pop_vm_ptr, push_vm_ptr, VM};
8use alloc::{
9    borrow::ToOwned,
10    format,
11    rc::{Rc, Weak},
12    string::{String, ToString},
13    vec,
14    vec::Vec,
15};
16use core::cell::RefCell;
17use core::fmt;
18use core::hash::{Hash, Hasher};
19use core::{ptr, slice, str};
20use hashbrown::HashMap;
21#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
22pub struct TaskHandle(pub u64);
23impl TaskHandle {
24    pub fn id(&self) -> u64 {
25        self.0
26    }
27}
28
29#[derive(Clone, Debug)]
30pub enum ValueKey {
31    Int(LustInt),
32    Float(LustFloat),
33    String(Rc<String>),
34    Bool(bool),
35}
36
37impl ValueKey {
38    pub fn from_value(value: &Value) -> Option<Self> {
39        match value {
40            Value::Int(i) => Some(ValueKey::Int(*i)),
41            Value::Float(f) => Some(ValueKey::Float(*f)),
42            Value::String(s) => Some(ValueKey::String(s.clone())),
43            Value::Bool(b) => Some(ValueKey::Bool(*b)),
44            _ => None,
45        }
46    }
47
48    pub fn string<S>(value: S) -> Self
49    where
50        S: Into<String>,
51    {
52        ValueKey::String(Rc::new(value.into()))
53    }
54
55    pub fn to_value(&self) -> Value {
56        match self {
57            ValueKey::Int(i) => Value::Int(*i),
58            ValueKey::Float(f) => Value::Float(*f),
59            ValueKey::String(s) => Value::String(s.clone()),
60            ValueKey::Bool(b) => Value::Bool(*b),
61        }
62    }
63}
64
65impl PartialEq for ValueKey {
66    fn eq(&self, other: &Self) -> bool {
67        match (self, other) {
68            (ValueKey::Int(a), ValueKey::Int(b)) => a == b,
69            (ValueKey::Float(a), ValueKey::Float(b)) => {
70                if float_is_nan(*a) && float_is_nan(*b) {
71                    true
72                } else {
73                    a == b
74                }
75            }
76
77            (ValueKey::String(a), ValueKey::String(b)) => a == b,
78            (ValueKey::Bool(a), ValueKey::Bool(b)) => a == b,
79            _ => false,
80        }
81    }
82}
83
84impl Eq for ValueKey {}
85impl Hash for ValueKey {
86    fn hash<H: Hasher>(&self, state: &mut H) {
87        match self {
88            ValueKey::Int(i) => {
89                0u8.hash(state);
90                i.hash(state);
91            }
92
93            ValueKey::Float(f) => {
94                1u8.hash(state);
95                if float_is_nan(*f) {
96                    u64::MAX.hash(state);
97                } else {
98                    float_to_hash_bits(*f).hash(state);
99                }
100            }
101
102            ValueKey::String(s) => {
103                2u8.hash(state);
104                s.hash(state);
105            }
106
107            ValueKey::Bool(b) => {
108                3u8.hash(state);
109                b.hash(state);
110            }
111        }
112    }
113}
114
115impl fmt::Display for ValueKey {
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        match self {
118            ValueKey::Int(i) => write!(f, "{}", i),
119            ValueKey::Float(fl) => write!(f, "{}", fl),
120            ValueKey::String(s) => write!(f, "{}", s),
121            ValueKey::Bool(b) => write!(f, "{}", b),
122        }
123    }
124}
125
126impl From<LustInt> for ValueKey {
127    fn from(value: LustInt) -> Self {
128        ValueKey::Int(value)
129    }
130}
131
132impl From<LustFloat> for ValueKey {
133    fn from(value: LustFloat) -> Self {
134        ValueKey::Float(value)
135    }
136}
137
138impl From<bool> for ValueKey {
139    fn from(value: bool) -> Self {
140        ValueKey::Bool(value)
141    }
142}
143
144impl From<String> for ValueKey {
145    fn from(value: String) -> Self {
146        ValueKey::String(Rc::new(value))
147    }
148}
149
150impl From<&str> for ValueKey {
151    fn from(value: &str) -> Self {
152        ValueKey::String(Rc::new(value.to_owned()))
153    }
154}
155
156impl From<Rc<String>> for ValueKey {
157    fn from(value: Rc<String>) -> Self {
158        ValueKey::String(value)
159    }
160}
161
162#[repr(u8)]
163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
164pub enum ValueTag {
165    Nil,
166    Bool,
167    Int,
168    Float,
169    String,
170    Array,
171    Tuple,
172    Map,
173    Table,
174    Struct,
175    Enum,
176    Function,
177    NativeFunction,
178    Closure,
179    Iterator,
180    Task,
181}
182
183impl ValueTag {
184    #[inline]
185    pub const fn as_u8(self) -> u8 {
186        self as u8
187    }
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
191pub enum FieldStorage {
192    Strong,
193    Weak,
194}
195
196#[derive(Debug)]
197pub struct StructLayout {
198    name: String,
199    field_names: Vec<Rc<String>>,
200    field_lookup_ptr: HashMap<usize, usize>,
201    field_lookup_str: HashMap<String, usize>,
202    field_storage: Vec<FieldStorage>,
203    field_types: Vec<Type>,
204    weak_targets: Vec<Option<Type>>,
205}
206
207impl StructLayout {
208    pub fn new(
209        name: String,
210        field_names: Vec<Rc<String>>,
211        field_storage: Vec<FieldStorage>,
212        field_types: Vec<Type>,
213        weak_targets: Vec<Option<Type>>,
214    ) -> Self {
215        debug_assert_eq!(
216            field_names.len(),
217            field_storage.len(),
218            "StructLayout::new expects field names and storage metadata to align"
219        );
220        debug_assert_eq!(
221            field_names.len(),
222            field_types.len(),
223            "StructLayout::new expects field names and type metadata to align"
224        );
225        debug_assert_eq!(
226            field_names.len(),
227            weak_targets.len(),
228            "StructLayout::new expects field names and weak target metadata to align"
229        );
230        let mut field_lookup_ptr = HashMap::with_capacity(field_names.len());
231        let mut field_lookup_str = HashMap::with_capacity(field_names.len());
232        for (index, field_name_rc) in field_names.iter().enumerate() {
233            let ptr = Rc::as_ptr(field_name_rc) as usize;
234            field_lookup_ptr.insert(ptr, index);
235            field_lookup_str.insert((**field_name_rc).clone(), index);
236        }
237
238        Self {
239            name,
240            field_names,
241            field_lookup_ptr,
242            field_lookup_str,
243            field_storage,
244            field_types,
245            weak_targets,
246        }
247    }
248
249    #[inline]
250    pub fn name(&self) -> &str {
251        &self.name
252    }
253
254    #[inline]
255    pub fn field_names(&self) -> &[Rc<String>] {
256        &self.field_names
257    }
258
259    #[inline]
260    pub fn index_of_rc(&self, key: &Rc<String>) -> Option<usize> {
261        let ptr = Rc::as_ptr(key) as usize;
262        self.field_lookup_ptr
263            .get(&ptr)
264            .copied()
265            .or_else(|| self.field_lookup_str.get(key.as_str()).copied())
266    }
267
268    #[inline]
269    pub fn index_of_str(&self, key: &str) -> Option<usize> {
270        self.field_lookup_str.get(key).copied()
271    }
272
273    #[inline]
274    pub fn field_storage(&self, index: usize) -> FieldStorage {
275        self.field_storage[index]
276    }
277
278    #[inline]
279    pub fn field_type(&self, index: usize) -> &Type {
280        &self.field_types[index]
281    }
282
283    #[inline]
284    pub fn weak_target(&self, index: usize) -> Option<&Type> {
285        self.weak_targets[index].as_ref()
286    }
287
288    #[inline]
289    pub fn is_weak(&self, index: usize) -> bool {
290        matches!(self.field_storage(index), FieldStorage::Weak)
291    }
292
293    pub fn canonicalize_field_value(&self, index: usize, value: Value) -> Result<Value, String> {
294        match self.field_storage(index) {
295            FieldStorage::Strong => Ok(value),
296            FieldStorage::Weak => self.canonicalize_weak_field(index, value),
297        }
298    }
299
300    pub fn materialize_field_value(&self, index: usize, value: Value) -> Value {
301        match self.field_storage(index) {
302            FieldStorage::Strong => value,
303            FieldStorage::Weak => self.materialize_weak_field(value),
304        }
305    }
306
307    fn canonicalize_weak_field(&self, index: usize, value: Value) -> Result<Value, String> {
308        let field_name = self.field_names[index].as_str();
309        match value {
310            Value::Enum {
311                enum_name,
312                variant,
313                values,
314            } if enum_name == "Option" => {
315                if variant == "Some" {
316                    if let Some(inner_values) = values {
317                        if let Some(inner) = inner_values.get(0) {
318                            let coerced = self.to_weak_struct(field_name, inner.clone())?;
319                            Ok(Value::enum_variant("Option", "Some", vec![coerced]))
320                        } else {
321                            Ok(Value::enum_unit("Option", "None"))
322                        }
323                    } else {
324                        Ok(Value::enum_unit("Option", "None"))
325                    }
326                } else if variant == "None" {
327                    Ok(Value::enum_unit("Option", "None"))
328                } else {
329                    Err(format!(
330                        "Struct '{}' field '{}' uses 'ref' and must store Option values; received variant '{}'",
331                        self.name, field_name, variant
332                    ))
333                }
334            }
335
336            Value::Nil => Ok(Value::enum_unit("Option", "None")),
337            other => {
338                let coerced = self.to_weak_struct(field_name, other)?;
339                Ok(Value::enum_variant("Option", "Some", vec![coerced]))
340            }
341        }
342    }
343
344    fn materialize_weak_field(&self, value: Value) -> Value {
345        match value {
346            Value::Enum {
347                enum_name,
348                variant,
349                values,
350            } if enum_name == "Option" => {
351                if variant == "Some" {
352                    if let Some(inner_values) = values {
353                        if let Some(inner) = inner_values.get(0) {
354                            match inner {
355                                Value::WeakStruct(ref weak) => {
356                                    if let Some(upgraded) = weak.upgrade() {
357                                        Value::enum_variant("Option", "Some", vec![upgraded])
358                                    } else {
359                                        Value::enum_unit("Option", "None")
360                                    }
361                                }
362
363                                _ => Value::enum_variant("Option", "Some", vec![inner.clone()]),
364                            }
365                        } else {
366                            Value::enum_unit("Option", "None")
367                        }
368                    } else {
369                        Value::enum_unit("Option", "None")
370                    }
371                } else {
372                    Value::enum_unit("Option", "None")
373                }
374            }
375
376            Value::Nil => Value::enum_unit("Option", "None"),
377            other => Value::enum_variant("Option", "Some", vec![other]),
378        }
379    }
380
381    fn to_weak_struct(&self, field_name: &str, value: Value) -> Result<Value, String> {
382        match value {
383            Value::Struct {
384                name,
385                layout,
386                fields,
387            } => Ok(Value::WeakStruct(WeakStructRef::new(name, layout, &fields))),
388            Value::WeakStruct(_) => Ok(value),
389            other => {
390                let ty = other.type_of();
391                Err(format!(
392                    "Struct '{}' field '{}' expects a struct reference but received value of type '{:?}'",
393                    self.name, field_name, ty
394                ))
395            }
396        }
397    }
398}
399
400#[repr(C, u8)]
401#[derive(Clone)]
402pub enum Value {
403    Nil,
404    Bool(bool),
405    Int(LustInt),
406    Float(LustFloat),
407    String(Rc<String>),
408    Array(Rc<RefCell<Vec<Value>>>),
409    Tuple(Rc<Vec<Value>>),
410    Map(Rc<RefCell<HashMap<ValueKey, Value>>>),
411    Table(Rc<RefCell<HashMap<ValueKey, Value>>>),
412    Struct {
413        name: String,
414        layout: Rc<StructLayout>,
415        fields: Rc<RefCell<Vec<Value>>>,
416    },
417    WeakStruct(WeakStructRef),
418    Enum {
419        enum_name: String,
420        variant: String,
421        values: Option<Rc<Vec<Value>>>,
422    },
423    Function(usize),
424    NativeFunction(NativeFn),
425    Closure {
426        function_idx: usize,
427        upvalues: Rc<Vec<Upvalue>>,
428    },
429    Iterator(Rc<RefCell<IteratorState>>),
430    Task(TaskHandle),
431}
432
433#[derive(Debug, Clone)]
434pub struct WeakStructRef {
435    name: String,
436    layout: Rc<StructLayout>,
437    fields: Weak<RefCell<Vec<Value>>>,
438}
439
440impl WeakStructRef {
441    pub fn new(name: String, layout: Rc<StructLayout>, fields: &Rc<RefCell<Vec<Value>>>) -> Self {
442        Self {
443            name,
444            layout,
445            fields: Rc::downgrade(fields),
446        }
447    }
448
449    pub fn upgrade(&self) -> Option<Value> {
450        self.fields.upgrade().map(|fields| Value::Struct {
451            name: self.name.clone(),
452            layout: self.layout.clone(),
453            fields,
454        })
455    }
456
457    pub fn struct_name(&self) -> &str {
458        &self.name
459    }
460}
461
462#[derive(Clone)]
463pub enum IteratorState {
464    Array {
465        items: Vec<Value>,
466        index: usize,
467    },
468    MapPairs {
469        items: Vec<(ValueKey, Value)>,
470        index: usize,
471    },
472    TablePairs {
473        items: Vec<(ValueKey, Value)>,
474        index: usize,
475    },
476}
477
478#[derive(Clone)]
479pub struct Upvalue {
480    value: Rc<RefCell<Value>>,
481}
482
483impl Upvalue {
484    pub fn new(value: Value) -> Self {
485        Self {
486            value: Rc::new(RefCell::new(value)),
487        }
488    }
489
490    pub fn get(&self) -> Value {
491        self.value.borrow().clone()
492    }
493
494    pub fn set(&self, value: Value) {
495        *self.value.borrow_mut() = value;
496    }
497}
498
499impl fmt::Debug for Upvalue {
500    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501        write!(f, "Upvalue({:?})", self.value.borrow())
502    }
503}
504
505#[derive(Debug, Clone)]
506pub enum NativeCallResult {
507    Return(Value),
508    Yield(Value),
509    Stop(Value),
510}
511
512impl From<Value> for NativeCallResult {
513    fn from(value: Value) -> Self {
514        NativeCallResult::Return(value)
515    }
516}
517
518pub type NativeFn = Rc<dyn Fn(&[Value]) -> Result<NativeCallResult, String>>;
519#[derive(Debug, Clone, Copy, PartialEq, Eq)]
520pub enum ValueType {
521    Nil,
522    Bool,
523    Int,
524    Float,
525    String,
526    Array,
527    Tuple,
528    Map,
529    Table,
530    Struct,
531    Enum,
532    Function,
533    NativeFunction,
534    Closure,
535    Iterator,
536    Task,
537}
538
539impl Value {
540    #[inline]
541    pub fn tag(&self) -> ValueTag {
542        match self {
543            Value::Nil => ValueTag::Nil,
544            Value::Bool(_) => ValueTag::Bool,
545            Value::Int(_) => ValueTag::Int,
546            Value::Float(_) => ValueTag::Float,
547            Value::String(_) => ValueTag::String,
548            Value::Array(_) => ValueTag::Array,
549            Value::Tuple(_) => ValueTag::Tuple,
550            Value::Map(_) => ValueTag::Map,
551            Value::Table(_) => ValueTag::Table,
552            Value::Struct { .. } | Value::WeakStruct(_) => ValueTag::Struct,
553            Value::Enum { .. } => ValueTag::Enum,
554            Value::Function(_) => ValueTag::Function,
555            Value::NativeFunction(_) => ValueTag::NativeFunction,
556            Value::Closure { .. } => ValueTag::Closure,
557            Value::Iterator(_) => ValueTag::Iterator,
558            Value::Task(_) => ValueTag::Task,
559        }
560    }
561
562    pub fn type_of(&self) -> ValueType {
563        match self {
564            Value::Nil => ValueType::Nil,
565            Value::Bool(_) => ValueType::Bool,
566            Value::Int(_) => ValueType::Int,
567            Value::Float(_) => ValueType::Float,
568            Value::String(_) => ValueType::String,
569            Value::Array(_) => ValueType::Array,
570            Value::Tuple(_) => ValueType::Tuple,
571            Value::Map(_) => ValueType::Map,
572            Value::Table(_) => ValueType::Table,
573            Value::Struct { .. } | Value::WeakStruct(_) => ValueType::Struct,
574            Value::Enum { .. } => ValueType::Enum,
575            Value::Function(_) => ValueType::Function,
576            Value::NativeFunction(_) => ValueType::NativeFunction,
577            Value::Closure { .. } => ValueType::Closure,
578            Value::Iterator(_) => ValueType::Iterator,
579            Value::Task(_) => ValueType::Task,
580        }
581    }
582
583    pub fn is_truthy(&self) -> bool {
584        !matches!(self, Value::Nil | Value::Bool(false))
585    }
586
587    pub fn to_bool(&self) -> bool {
588        self.is_truthy()
589    }
590
591    pub fn as_int(&self) -> Option<LustInt> {
592        match self {
593            Value::Int(i) => Some(*i),
594            Value::Float(f) => Some(int_from_float(*f)),
595            _ => None,
596        }
597    }
598
599    pub fn as_float(&self) -> Option<LustFloat> {
600        match self {
601            Value::Float(f) => Some(*f),
602            Value::Int(i) => Some(float_from_int(*i)),
603            _ => None,
604        }
605    }
606
607    pub fn as_string(&self) -> Option<&str> {
608        match self {
609            Value::String(s) => Some(s.as_str()),
610            _ => None,
611        }
612    }
613
614    pub fn as_string_rc(&self) -> Option<Rc<String>> {
615        match self {
616            Value::String(s) => Some(s.clone()),
617            _ => None,
618        }
619    }
620
621    pub fn as_task_handle(&self) -> Option<TaskHandle> {
622        match self {
623            Value::Task(handle) => Some(*handle),
624            _ => None,
625        }
626    }
627
628    pub fn as_array(&self) -> Option<Vec<Value>> {
629        match self {
630            Value::Array(arr) => Some(arr.borrow().clone()),
631            _ => None,
632        }
633    }
634
635    pub fn array_len(&self) -> Option<usize> {
636        match self {
637            Value::Array(arr) => Some(arr.borrow().len()),
638            _ => None,
639        }
640    }
641
642    pub fn array_get(&self, index: usize) -> Option<Value> {
643        match self {
644            Value::Array(arr) => arr.borrow().get(index).cloned(),
645            _ => None,
646        }
647    }
648
649    pub fn array_push(&self, value: Value) -> Result<(), String> {
650        match self {
651            Value::Array(arr) => {
652                arr.borrow_mut().push(value);
653                Ok(())
654            }
655
656            _ => Err("Cannot push to non-array".to_string()),
657        }
658    }
659
660    pub fn array_pop(&self) -> Result<Option<Value>, String> {
661        match self {
662            Value::Array(arr) => Ok(arr.borrow_mut().pop()),
663            _ => Err("Cannot pop from non-array".to_string()),
664        }
665    }
666
667    pub fn as_map(&self) -> Option<HashMap<ValueKey, Value>> {
668        match self {
669            Value::Map(map) => Some(map.borrow().clone()),
670            _ => None,
671        }
672    }
673
674    pub fn map_get(&self, key: &ValueKey) -> Option<Value> {
675        match self {
676            Value::Map(map) => map.borrow().get(key).cloned(),
677            _ => None,
678        }
679    }
680
681    pub fn map_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
682        match self {
683            Value::Map(map) => {
684                map.borrow_mut().insert(key, value);
685                Ok(())
686            }
687
688            _ => Err("Cannot set key on non-map".to_string()),
689        }
690    }
691
692    pub fn map_has(&self, key: &ValueKey) -> Option<bool> {
693        match self {
694            Value::Map(map) => Some(map.borrow().contains_key(key)),
695            _ => None,
696        }
697    }
698
699    pub fn map_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
700        match self {
701            Value::Map(map) => Ok(map.borrow_mut().remove(key)),
702            _ => Err("Cannot delete key from non-map".to_string()),
703        }
704    }
705
706    pub fn map_len(&self) -> Option<usize> {
707        match self {
708            Value::Map(map) => Some(map.borrow().len()),
709            _ => None,
710        }
711    }
712
713    pub fn as_table(&self) -> Option<HashMap<ValueKey, Value>> {
714        match self {
715            Value::Table(table) => Some(table.borrow().clone()),
716            _ => None,
717        }
718    }
719
720    pub fn table_get(&self, key: &ValueKey) -> Option<Value> {
721        match self {
722            Value::Table(table) => table.borrow().get(key).cloned(),
723            _ => None,
724        }
725    }
726
727    pub fn table_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
728        match self {
729            Value::Table(table) => {
730                table.borrow_mut().insert(key, value);
731                Ok(())
732            }
733
734            _ => Err("Cannot set key on non-table".to_string()),
735        }
736    }
737
738    pub fn table_has(&self, key: &ValueKey) -> Option<bool> {
739        match self {
740            Value::Table(table) => Some(table.borrow().contains_key(key)),
741            _ => None,
742        }
743    }
744
745    pub fn table_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
746        match self {
747            Value::Table(table) => Ok(table.borrow_mut().remove(key)),
748            _ => Err("Cannot delete key from non-table".to_string()),
749        }
750    }
751
752    pub fn table_len(&self) -> Option<usize> {
753        match self {
754            Value::Table(table) => Some(table.borrow().len()),
755            _ => None,
756        }
757    }
758
759    pub fn string(s: impl Into<String>) -> Self {
760        Value::String(Rc::new(s.into()))
761    }
762
763    pub fn array(values: Vec<Value>) -> Self {
764        Value::Array(Rc::new(RefCell::new(values)))
765    }
766
767    pub fn tuple(values: Vec<Value>) -> Self {
768        Value::Tuple(Rc::new(values))
769    }
770
771    pub fn tuple_len(&self) -> Option<usize> {
772        match self {
773            Value::Tuple(values) => Some(values.len()),
774            _ => None,
775        }
776    }
777
778    pub fn tuple_get(&self, index: usize) -> Option<Value> {
779        match self {
780            Value::Tuple(values) => values.get(index).cloned(),
781            _ => None,
782        }
783    }
784
785    pub fn map(entries: HashMap<ValueKey, Value>) -> Self {
786        Value::Map(Rc::new(RefCell::new(entries)))
787    }
788
789    pub fn table(entries: HashMap<ValueKey, Value>) -> Self {
790        Value::Table(Rc::new(RefCell::new(entries)))
791    }
792
793    pub fn task(handle: TaskHandle) -> Self {
794        Value::Task(handle)
795    }
796
797    pub fn struct_get_field_rc(&self, field: &Rc<String>) -> Option<Value> {
798        match self {
799            Value::Struct { layout, fields, .. } => layout
800                .index_of_rc(field)
801                .or_else(|| layout.index_of_str(field.as_str()))
802                .and_then(|idx| {
803                    fields
804                        .borrow()
805                        .get(idx)
806                        .cloned()
807                        .map(|value| layout.materialize_field_value(idx, value))
808                }),
809            _ => None,
810        }
811    }
812
813    pub fn struct_get_field(&self, field: &str) -> Option<Value> {
814        match self {
815            Value::Struct { layout, fields, .. } => layout.index_of_str(field).and_then(|idx| {
816                fields
817                    .borrow()
818                    .get(idx)
819                    .cloned()
820                    .map(|value| layout.materialize_field_value(idx, value))
821            }),
822            _ => None,
823        }
824    }
825
826    pub fn struct_get_field_indexed(&self, index: usize) -> Option<Value> {
827        match self {
828            Value::Struct { layout, fields, .. } => fields
829                .borrow()
830                .get(index)
831                .cloned()
832                .map(|value| layout.materialize_field_value(index, value)),
833            _ => None,
834        }
835    }
836
837    pub fn struct_set_field_rc(&self, field: &Rc<String>, value: Value) -> Result<(), String> {
838        match self {
839            Value::Struct { layout, .. } => {
840                if let Some(index) = layout
841                    .index_of_rc(field)
842                    .or_else(|| layout.index_of_str(field.as_str()))
843                {
844                    self.struct_set_field_indexed(index, value)
845                } else {
846                    Err(format!(
847                        "Struct '{}' has no field '{}'",
848                        layout.name(),
849                        field.as_str()
850                    ))
851                }
852            }
853
854            _ => Err("Attempted to set field on non-struct value".to_string()),
855        }
856    }
857
858    pub fn struct_set_field(&self, field: &str, value: Value) -> Result<(), String> {
859        match self {
860            Value::Struct { layout, .. } => {
861                if let Some(index) = layout.index_of_str(field) {
862                    self.struct_set_field_indexed(index, value)
863                } else {
864                    Err(format!(
865                        "Struct '{}' has no field '{}'",
866                        layout.name(),
867                        field
868                    ))
869                }
870            }
871
872            _ => Err("Attempted to set field on non-struct value".to_string()),
873        }
874    }
875
876    pub fn struct_set_field_indexed(&self, index: usize, value: Value) -> Result<(), String> {
877        match self {
878            Value::Struct {
879                name,
880                layout,
881                fields,
882            } => {
883                let mut borrowed = fields.borrow_mut();
884                if index < borrowed.len() {
885                    let canonical = layout.canonicalize_field_value(index, value)?;
886                    borrowed[index] = canonical;
887                    Ok(())
888                } else {
889                    Err(format!(
890                        "Struct '{}' field index {} out of bounds (len {})",
891                        name,
892                        index,
893                        borrowed.len()
894                    ))
895                }
896            }
897
898            _ => Err("Attempted to set field on non-struct value".to_string()),
899        }
900    }
901
902    pub fn enum_unit(enum_name: impl Into<String>, variant: impl Into<String>) -> Self {
903        Value::Enum {
904            enum_name: enum_name.into(),
905            variant: variant.into(),
906            values: None,
907        }
908    }
909
910    pub fn enum_variant(
911        enum_name: impl Into<String>,
912        variant: impl Into<String>,
913        values: Vec<Value>,
914    ) -> Self {
915        Value::Enum {
916            enum_name: enum_name.into(),
917            variant: variant.into(),
918            values: Some(Rc::new(values)),
919        }
920    }
921
922    pub fn as_enum(&self) -> Option<(&str, &str, Option<&[Value]>)> {
923        match self {
924            Value::Enum {
925                enum_name,
926                variant,
927                values,
928            } => Some((
929                enum_name.as_str(),
930                variant.as_str(),
931                values.as_ref().map(|v| v.as_slice()),
932            )),
933            _ => None,
934        }
935    }
936
937    pub fn is_enum_variant(&self, enum_name: &str, variant: &str) -> bool {
938        match self {
939            Value::Enum {
940                enum_name: en,
941                variant: v,
942                ..
943            } => (enum_name.is_empty() || en == enum_name) && v == variant,
944            _ => false,
945        }
946    }
947
948    pub fn some(value: Value) -> Self {
949        Value::enum_variant("Option", "Some", vec![value])
950    }
951
952    pub fn none() -> Self {
953        Value::enum_unit("Option", "None")
954    }
955
956    pub fn ok(value: Value) -> Self {
957        Value::enum_variant("Result", "Ok", vec![value])
958    }
959
960    pub fn err(error: Value) -> Self {
961        Value::enum_variant("Result", "Err", vec![error])
962    }
963
964    pub fn to_string(&self) -> String {
965        format!("{}", self)
966    }
967}
968
969impl fmt::Debug for Value {
970    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
971        match self {
972            Value::Nil => write!(f, "Nil"),
973            Value::Bool(b) => write!(f, "Bool({})", b),
974            Value::Int(i) => write!(f, "Int({})", i),
975            Value::Float(fl) => write!(f, "Float({})", fl),
976            Value::String(s) => write!(f, "String({:?})", s),
977            Value::Array(arr) => write!(f, "Array({:?})", arr.borrow()),
978            Value::Tuple(values) => write!(f, "Tuple({:?})", values),
979            Value::Map(map) => write!(f, "Map({:?})", map.borrow()),
980            Value::Table(table) => write!(f, "Table({:?})", table.borrow()),
981            Value::Struct {
982                name,
983                layout,
984                fields,
985            } => {
986                let borrowed = fields.borrow();
987                let mut display_fields = Vec::with_capacity(borrowed.len());
988                for (idx, field_name) in layout.field_names().iter().enumerate() {
989                    let value = borrowed.get(idx).cloned().unwrap_or(Value::Nil);
990                    display_fields.push((field_name.as_str().to_string(), value));
991                }
992
993                write!(
994                    f,
995                    "Struct {{ name: {:?}, fields: {:?} }}",
996                    name, display_fields
997                )
998            }
999
1000            Value::WeakStruct(weak) => {
1001                if let Some(upgraded) = weak.upgrade() {
1002                    write!(f, "WeakStruct({:?})", upgraded)
1003                } else {
1004                    write!(f, "WeakStruct(<dangling>)")
1005                }
1006            }
1007
1008            Value::Enum {
1009                enum_name,
1010                variant,
1011                values,
1012            } => {
1013                write!(
1014                    f,
1015                    "Enum {{ enum: {:?}, variant: {:?}, values: {:?} }}",
1016                    enum_name, variant, values
1017                )
1018            }
1019
1020            Value::Function(idx) => write!(f, "Function({})", idx),
1021            Value::NativeFunction(_) => write!(f, "NativeFunction(<fn>)"),
1022            Value::Closure {
1023                function_idx,
1024                upvalues,
1025            } => {
1026                write!(
1027                    f,
1028                    "Closure {{ function: {}, upvalues: {:?} }}",
1029                    function_idx, upvalues
1030                )
1031            }
1032
1033            Value::Iterator(_) => write!(f, "Iterator(<state>)"),
1034            Value::Task(handle) => write!(f, "Task({})", handle.0),
1035        }
1036    }
1037}
1038
1039impl fmt::Display for Value {
1040    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1041        match self {
1042            Value::Nil => write!(f, "nil"),
1043            Value::Bool(b) => write!(f, "{}", b),
1044            Value::Int(i) => write!(f, "{}", i),
1045            Value::Float(fl) => write!(f, "{}", fl),
1046            Value::String(s) => write!(f, "{}", s),
1047            Value::Array(arr) => {
1048                write!(f, "[")?;
1049                let borrowed = arr.borrow();
1050                for (i, val) in borrowed.iter().enumerate() {
1051                    if i > 0 {
1052                        write!(f, ", ")?;
1053                    }
1054
1055                    write!(f, "{}", val)?;
1056                }
1057
1058                write!(f, "]")
1059            }
1060
1061            Value::Tuple(values) => {
1062                write!(f, "(")?;
1063                for (i, val) in values.iter().enumerate() {
1064                    if i > 0 {
1065                        write!(f, ", ")?;
1066                    }
1067
1068                    write!(f, "{}", val)?;
1069                }
1070
1071                write!(f, ")")
1072            }
1073
1074            Value::Map(map) => {
1075                write!(f, "{{")?;
1076                let borrowed = map.borrow();
1077                for (i, (k, v)) in borrowed.iter().enumerate() {
1078                    if i > 0 {
1079                        write!(f, ", ")?;
1080                    }
1081
1082                    write!(f, "{}: {}", k, v)?;
1083                }
1084
1085                write!(f, "}}")
1086            }
1087
1088            Value::Table(table) => {
1089                write!(f, "{{")?;
1090                let borrowed = table.borrow();
1091                for (i, (k, v)) in borrowed.iter().enumerate() {
1092                    if i > 0 {
1093                        write!(f, ", ")?;
1094                    }
1095
1096                    write!(f, "{}: {}", k, v)?;
1097                }
1098
1099                write!(f, "}}")
1100            }
1101
1102            Value::Struct {
1103                name,
1104                layout,
1105                fields,
1106            } => {
1107                let borrowed = fields.borrow();
1108                write!(f, "{} {{", name)?;
1109                for (i, field_name) in layout.field_names().iter().enumerate() {
1110                    if i > 0 {
1111                        write!(f, ", ")?;
1112                    }
1113
1114                    let value = borrowed.get(i).unwrap_or(&Value::Nil);
1115                    write!(f, "{}: {}", field_name, value)?;
1116                }
1117
1118                write!(f, "}}")
1119            }
1120
1121            Value::WeakStruct(weak) => {
1122                if let Some(strong) = weak.upgrade() {
1123                    strong.fmt(f)
1124                } else {
1125                    write!(f, "nil")
1126                }
1127            }
1128
1129            Value::Enum {
1130                enum_name,
1131                variant,
1132                values,
1133            } => {
1134                write!(f, "{}.{}", enum_name, variant)?;
1135                if let Some(vals) = values {
1136                    write!(f, "(")?;
1137                    for (i, val) in vals.iter().enumerate() {
1138                        if i > 0 {
1139                            write!(f, ", ")?;
1140                        }
1141
1142                        write!(f, "{}", val)?;
1143                    }
1144
1145                    write!(f, ")")?;
1146                }
1147
1148                Ok(())
1149            }
1150
1151            Value::Function(idx) => write!(f, "<function@{}>", idx),
1152            Value::NativeFunction(_) => write!(f, "<native function>"),
1153            Value::Closure { function_idx, .. } => write!(f, "<closure@{}>", function_idx),
1154            Value::Iterator(_) => write!(f, "<iterator>"),
1155            Value::Task(handle) => write!(f, "<task {}>", handle.0),
1156        }
1157    }
1158}
1159
1160impl PartialEq for Value {
1161    fn eq(&self, other: &Self) -> bool {
1162        match (self, other) {
1163            (Value::Nil, Value::Nil) => true,
1164            (Value::Bool(a), Value::Bool(b)) => a == b,
1165            (Value::Int(a), Value::Int(b)) => a == b,
1166            (Value::Float(a), Value::Float(b)) => a == b,
1167            (Value::String(a), Value::String(b)) => a == b,
1168            (Value::Array(a), Value::Array(b)) => *a.borrow() == *b.borrow(),
1169            (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
1170            (Value::Map(a), Value::Map(b)) => *a.borrow() == *b.borrow(),
1171            (Value::Table(a), Value::Table(b)) => *a.borrow() == *b.borrow(),
1172            (
1173                Value::Struct {
1174                    name: n1,
1175                    layout: l1,
1176                    fields: f1,
1177                },
1178                Value::Struct {
1179                    name: n2,
1180                    layout: l2,
1181                    fields: f2,
1182                },
1183            ) => {
1184                if n1 != n2 {
1185                    return false;
1186                }
1187
1188                let borrowed_f1 = f1.borrow();
1189                let borrowed_f2 = f2.borrow();
1190                if borrowed_f1.len() != borrowed_f2.len() {
1191                    return false;
1192                }
1193
1194                if Rc::ptr_eq(l1, l2) {
1195                    return borrowed_f1
1196                        .iter()
1197                        .zip(borrowed_f2.iter())
1198                        .all(|(a, b)| a == b);
1199                }
1200
1201                l1.field_names()
1202                    .iter()
1203                    .enumerate()
1204                    .all(|(idx, field_name)| {
1205                        if let Some(other_idx) = l2.index_of_rc(field_name) {
1206                            borrowed_f1
1207                                .get(idx)
1208                                .zip(borrowed_f2.get(other_idx))
1209                                .map(|(a, b)| a == b)
1210                                .unwrap_or(false)
1211                        } else {
1212                            false
1213                        }
1214                    })
1215            }
1216
1217            (Value::WeakStruct(a), Value::WeakStruct(b)) => match (a.upgrade(), b.upgrade()) {
1218                (Some(left), Some(right)) => left == right,
1219                (None, None) => true,
1220                _ => false,
1221            },
1222            (Value::WeakStruct(a), other) => a
1223                .upgrade()
1224                .map(|upgraded| upgraded == *other)
1225                .unwrap_or(matches!(other, Value::Nil)),
1226            (value, Value::WeakStruct(b)) => b
1227                .upgrade()
1228                .map(|upgraded| *value == upgraded)
1229                .unwrap_or(matches!(value, Value::Nil)),
1230            (
1231                Value::Enum {
1232                    enum_name: e1,
1233                    variant: v1,
1234                    values: vals1,
1235                },
1236                Value::Enum {
1237                    enum_name: e2,
1238                    variant: v2,
1239                    values: vals2,
1240                },
1241            ) => e1 == e2 && v1 == v2 && vals1 == vals2,
1242            (Value::Function(a), Value::Function(b)) => a == b,
1243            (
1244                Value::Closure {
1245                    function_idx: f1,
1246                    upvalues: u1,
1247                },
1248                Value::Closure {
1249                    function_idx: f2,
1250                    upvalues: u2,
1251                },
1252            ) => f1 == f2 && Rc::ptr_eq(u1, u2),
1253            (Value::Iterator(_), Value::Iterator(_)) => false,
1254            (Value::Task(a), Value::Task(b)) => a == b,
1255            _ => false,
1256        }
1257    }
1258}
1259
1260#[cfg(feature = "std")]
1261#[no_mangle]
1262pub unsafe extern "C" fn jit_array_get_safe(
1263    array_value_ptr: *const Value,
1264    index: i64,
1265    out: *mut Value,
1266) -> u8 {
1267    if array_value_ptr.is_null() || out.is_null() {
1268        eprintln!("❌ jit_array_get_safe: null pointer detected!");
1269        return 0;
1270    }
1271
1272    let array_value = &*array_value_ptr;
1273    let arr = match array_value {
1274        Value::Array(arr) => arr,
1275        _ => {
1276            return 0;
1277        }
1278    };
1279    if index < 0 {
1280        return 0;
1281    }
1282
1283    let idx = index as usize;
1284    let borrowed = match arr.try_borrow() {
1285        Ok(b) => b,
1286        Err(_) => {
1287            return 0;
1288        }
1289    };
1290    if idx >= borrowed.len() {
1291        return 0;
1292    }
1293
1294    ptr::write(out, borrowed[idx].clone());
1295    1
1296}
1297
1298#[cfg(feature = "std")]
1299#[no_mangle]
1300pub unsafe extern "C" fn jit_array_len_safe(array_value_ptr: *const Value) -> i64 {
1301    if array_value_ptr.is_null() {
1302        return -1;
1303    }
1304
1305    let array_value = &*array_value_ptr;
1306    match array_value {
1307        Value::Array(arr) => match arr.try_borrow() {
1308            Ok(borrowed) => int_from_usize(borrowed.len()),
1309            Err(_) => -1,
1310        },
1311        _ => -1,
1312    }
1313}
1314
1315#[cfg(feature = "std")]
1316#[no_mangle]
1317pub unsafe extern "C" fn jit_concat_safe(
1318    left_value_ptr: *const Value,
1319    right_value_ptr: *const Value,
1320    out: *mut Value,
1321) -> u8 {
1322    if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1323        return 0;
1324    }
1325
1326    let left = &*left_value_ptr;
1327    let right = &*right_value_ptr;
1328    const NO_VM_ERROR: &str = "task API requires a running VM";
1329    let left_str = match VM::with_current(|vm| {
1330        let left_copy = left.clone();
1331        vm.value_to_string_for_concat(&left_copy)
1332            .map_err(|err| err.to_string())
1333    }) {
1334        Ok(rc) => rc,
1335        Err(err) if err == NO_VM_ERROR => Rc::new(left.to_string()),
1336        Err(_) => return 0,
1337    };
1338    let right_str = match VM::with_current(|vm| {
1339        let right_copy = right.clone();
1340        vm.value_to_string_for_concat(&right_copy)
1341            .map_err(|err| err.to_string())
1342    }) {
1343        Ok(rc) => rc,
1344        Err(err) if err == NO_VM_ERROR => Rc::new(right.to_string()),
1345        Err(_) => return 0,
1346    };
1347    let mut combined = String::with_capacity(left_str.len() + right_str.len());
1348    combined.push_str(left_str.as_ref());
1349    combined.push_str(right_str.as_ref());
1350    let result = Value::string(combined);
1351    ptr::write(out, result);
1352    1
1353}
1354
1355#[no_mangle]
1356pub unsafe extern "C" fn jit_guard_native_function(
1357    value_ptr: *const Value,
1358    expected_fn_ptr: *const (),
1359    register_index: u8,
1360) -> u8 {
1361    if value_ptr.is_null() || expected_fn_ptr.is_null() {
1362        jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1363        return 0;
1364    }
1365
1366    match &*value_ptr {
1367        Value::NativeFunction(func) => {
1368            let actual = Rc::as_ptr(func) as *const ();
1369            if actual == expected_fn_ptr {
1370                1
1371            } else {
1372                jit::log(|| {
1373                    format!(
1374                        "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1375                        register_index, actual, expected_fn_ptr
1376                    )
1377                });
1378                0
1379            }
1380        }
1381
1382        other => {
1383            jit::log(|| {
1384                format!(
1385                    "jit_guard_native_function: value not native in reg {} ({:?})",
1386                    register_index,
1387                    other.tag()
1388                )
1389            });
1390            0
1391        }
1392    }
1393}
1394
1395#[no_mangle]
1396pub unsafe extern "C" fn jit_call_native_safe(
1397    vm_ptr: *mut VM,
1398    callee_ptr: *const Value,
1399    expected_fn_ptr: *const (),
1400    args_ptr: *const Value,
1401    arg_count: u8,
1402    out: *mut Value,
1403) -> u8 {
1404    if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1405        jit::log(|| "jit_call_native_safe: null argument".to_string());
1406        return 0;
1407    }
1408
1409    let callee = &*callee_ptr;
1410    let native_fn = match callee {
1411        Value::NativeFunction(func) => func.clone(),
1412        other => {
1413            jit::log(|| {
1414                format!(
1415                    "jit_call_native_safe: callee not native ({:?})",
1416                    other.tag()
1417                )
1418            });
1419            return 0;
1420        }
1421    };
1422
1423    if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1424        jit::log(|| {
1425            format!(
1426                "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1427                Rc::as_ptr(&native_fn),
1428                expected_fn_ptr
1429            )
1430        });
1431        return 0;
1432    }
1433
1434    let mut args = Vec::with_capacity(arg_count as usize);
1435    if arg_count > 0 {
1436        if args_ptr.is_null() {
1437            jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1438            return 0;
1439        }
1440
1441        for i in 0..(arg_count as usize) {
1442            let arg = &*args_ptr.add(i);
1443            args.push(arg.clone());
1444        }
1445    }
1446
1447    push_vm_ptr(vm_ptr);
1448    let outcome = native_fn(&args);
1449    pop_vm_ptr();
1450
1451    let outcome = match outcome {
1452        Ok(result) => result,
1453        Err(err) => {
1454            jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1455            return 0;
1456        }
1457    };
1458
1459    match outcome {
1460        NativeCallResult::Return(value) => {
1461            ptr::write(out, value);
1462            1
1463        }
1464
1465        NativeCallResult::Yield(_) => {
1466            jit::log(|| "jit_call_native_safe: native attempted to yield".to_string());
1467            0
1468        }
1469
1470        NativeCallResult::Stop(_) => {
1471            jit::log(|| "jit_call_native_safe: native attempted to stop".to_string());
1472            0
1473        }
1474    }
1475}
1476
1477#[no_mangle]
1478pub unsafe extern "C" fn jit_call_method_safe(
1479    object_ptr: *const Value,
1480    method_name_ptr: *const u8,
1481    method_name_len: usize,
1482    args_ptr: *const Value,
1483    arg_count: u8,
1484    out: *mut Value,
1485) -> u8 {
1486    if object_ptr.is_null() || method_name_ptr.is_null() || out.is_null() {
1487        return 0;
1488    }
1489
1490    if arg_count > 0 && args_ptr.is_null() {
1491        return 0;
1492    }
1493
1494    let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
1495    let method_name = match str::from_utf8(method_name_slice) {
1496        Ok(s) => s,
1497        Err(_) => return 0,
1498    };
1499    let object = &*object_ptr;
1500    if matches!(object, Value::Struct { .. }) {
1501        return 0;
1502    }
1503
1504    let mut args = Vec::with_capacity(arg_count as usize);
1505    for i in 0..arg_count {
1506        let arg_ptr = args_ptr.add(i as usize);
1507        args.push((&*arg_ptr).clone());
1508    }
1509
1510    let result = match call_builtin_method_simple(object, method_name, args) {
1511        Ok(val) => val,
1512        Err(_) => return 0,
1513    };
1514    ptr::write(out, result);
1515    1
1516}
1517
1518fn call_builtin_method_simple(
1519    object: &Value,
1520    method_name: &str,
1521    args: Vec<Value>,
1522) -> Result<Value, String> {
1523    match object {
1524        Value::Struct { name, .. } => Err(format!(
1525            "User-defined methods on {} require deoptimization",
1526            name
1527        )),
1528        Value::Iterator(state_rc) => match method_name {
1529            "next" => {
1530                let mut state = state_rc.borrow_mut();
1531                match &mut *state {
1532                    IteratorState::Array { items, index } => {
1533                        if *index < items.len() {
1534                            let v = items[*index].clone();
1535                            *index += 1;
1536                            Ok(Value::some(v))
1537                        } else {
1538                            Ok(Value::none())
1539                        }
1540                    }
1541
1542                    IteratorState::MapPairs { items, index } => {
1543                        if *index < items.len() {
1544                            let (k, v) = items[*index].clone();
1545                            *index += 1;
1546                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
1547                        } else {
1548                            Ok(Value::none())
1549                        }
1550                    }
1551
1552                    IteratorState::TablePairs { items, index } => {
1553                        if *index < items.len() {
1554                            let (k, v) = items[*index].clone();
1555                            *index += 1;
1556                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
1557                        } else {
1558                            Ok(Value::none())
1559                        }
1560                    }
1561                }
1562            }
1563
1564            _ => Err(format!(
1565                "Iterator method '{}' not supported in JIT",
1566                method_name
1567            )),
1568        },
1569        Value::Enum {
1570            enum_name,
1571            variant,
1572            values,
1573        } if enum_name == "Option" => match method_name {
1574            "unwrap" => {
1575                if variant == "Some" {
1576                    if let Some(vals) = values {
1577                        if vals.len() == 1 {
1578                            Ok(vals[0].clone())
1579                        } else {
1580                            Err("Option::Some should have exactly 1 value".to_string())
1581                        }
1582                    } else {
1583                        Err("Option::Some should have a value".to_string())
1584                    }
1585                } else {
1586                    Err("Called unwrap() on Option::None".to_string())
1587                }
1588            }
1589
1590            _ => Err(format!(
1591                "Option method '{}' not supported in JIT",
1592                method_name
1593            )),
1594        },
1595        Value::Array(arr) => match method_name {
1596            "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
1597            "push" => {
1598                let value = args
1599                    .get(0)
1600                    .cloned()
1601                    .ok_or_else(|| "Array:push requires a value argument".to_string())?;
1602                arr.borrow_mut().push(value);
1603                Ok(Value::Nil)
1604            }
1605            "pop" => {
1606                let popped = arr.borrow_mut().pop();
1607                Ok(popped.map(Value::some).unwrap_or_else(Value::none))
1608            }
1609            "first" => {
1610                let borrowed = arr.borrow();
1611                Ok(borrowed
1612                    .first()
1613                    .cloned()
1614                    .map(Value::some)
1615                    .unwrap_or_else(Value::none))
1616            }
1617            "last" => {
1618                let borrowed = arr.borrow();
1619                Ok(borrowed
1620                    .last()
1621                    .cloned()
1622                    .map(Value::some)
1623                    .unwrap_or_else(Value::none))
1624            }
1625            "get" => {
1626                let index = args
1627                    .get(0)
1628                    .and_then(Value::as_int)
1629                    .ok_or_else(|| "Array:get requires an integer index".to_string())?;
1630                let borrowed = arr.borrow();
1631                Ok(borrowed
1632                    .get(index as usize)
1633                    .cloned()
1634                    .map(Value::some)
1635                    .unwrap_or_else(Value::none))
1636            }
1637            "iter" => {
1638                let items = arr.borrow().clone();
1639                let iter = IteratorState::Array { items, index: 0 };
1640                Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
1641            }
1642            _ => Err(format!(
1643                "Array method '{}' not supported in JIT",
1644                method_name
1645            )),
1646        },
1647        _ => Err(format!(
1648            "Method '{}' not supported in JIT (deoptimizing)",
1649            method_name
1650        )),
1651    }
1652}
1653
1654#[no_mangle]
1655pub unsafe extern "C" fn jit_get_field_safe(
1656    object_ptr: *const Value,
1657    field_name_ptr: *const u8,
1658    field_name_len: usize,
1659    out: *mut Value,
1660) -> u8 {
1661    if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
1662        return 0;
1663    }
1664
1665    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1666    let field_name = match str::from_utf8(field_name_slice) {
1667        Ok(s) => s,
1668        Err(_) => return 0,
1669    };
1670    let object = &*object_ptr;
1671    let field_value = match object {
1672        Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
1673            Some(idx) => match fields.borrow().get(idx) {
1674                Some(val) => val.clone(),
1675                None => return 0,
1676            },
1677            None => return 0,
1678        },
1679        _ => return 0,
1680    };
1681    ptr::write(out, field_value);
1682    1
1683}
1684
1685#[no_mangle]
1686pub unsafe extern "C" fn jit_set_field_safe(
1687    object_ptr: *const Value,
1688    field_name_ptr: *const u8,
1689    field_name_len: usize,
1690    value_ptr: *const Value,
1691) -> u8 {
1692    if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
1693        return 0;
1694    }
1695
1696    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1697    let field_name = match str::from_utf8(field_name_slice) {
1698        Ok(s) => s,
1699        Err(_) => return 0,
1700    };
1701    let object = &*object_ptr;
1702    let value = (&*value_ptr).clone();
1703    match object {
1704        Value::Struct { .. } => match object.struct_set_field(field_name, value) {
1705            Ok(()) => 1,
1706            Err(_) => 0,
1707        },
1708        Value::Map(map) => {
1709            use crate::bytecode::ValueKey;
1710            let key = ValueKey::String(Rc::new(field_name.to_string()));
1711            map.borrow_mut().insert(key, value);
1712            1
1713        }
1714
1715        _ => 0,
1716    }
1717}
1718
1719#[no_mangle]
1720pub unsafe extern "C" fn jit_get_field_indexed_safe(
1721    object_ptr: *const Value,
1722    field_index: usize,
1723    out: *mut Value,
1724) -> u8 {
1725    if object_ptr.is_null() || out.is_null() {
1726        return 0;
1727    }
1728
1729    let object = &*object_ptr;
1730    match object.struct_get_field_indexed(field_index) {
1731        Some(value) => {
1732            ptr::write(out, value);
1733            1
1734        }
1735
1736        None => 0,
1737    }
1738}
1739
1740#[no_mangle]
1741pub unsafe extern "C" fn jit_set_field_indexed_safe(
1742    object_ptr: *const Value,
1743    field_index: usize,
1744    value_ptr: *const Value,
1745) -> u8 {
1746    if object_ptr.is_null() || value_ptr.is_null() {
1747        return 0;
1748    }
1749
1750    let object = &*object_ptr;
1751    let value = (&*value_ptr).clone();
1752    match object.struct_set_field_indexed(field_index, value) {
1753        Ok(()) => 1,
1754        Err(_) => 0,
1755    }
1756}
1757
1758#[no_mangle]
1759pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
1760    object_ptr: *const Value,
1761    field_index: usize,
1762    out: *mut Value,
1763) -> u8 {
1764    if object_ptr.is_null() || out.is_null() {
1765        return 0;
1766    }
1767
1768    let object = &*object_ptr;
1769    let out_ref = &mut *out;
1770    match object {
1771        Value::Struct { layout, fields, .. } => {
1772            if layout.is_weak(field_index) {
1773                return 0;
1774            }
1775
1776            if let Ok(borrowed) = fields.try_borrow() {
1777                if let Some(Value::Int(val)) = borrowed.get(field_index) {
1778                    *out_ref = Value::Int(*val);
1779                    return 1;
1780                }
1781            }
1782
1783            0
1784        }
1785
1786        _ => 0,
1787    }
1788}
1789
1790#[no_mangle]
1791pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
1792    object_ptr: *const Value,
1793    field_index: usize,
1794    value_ptr: *const Value,
1795) -> u8 {
1796    if object_ptr.is_null() || value_ptr.is_null() {
1797        return 0;
1798    }
1799
1800    let object = &*object_ptr;
1801    let value = &*value_ptr;
1802    let new_value = match value {
1803        Value::Int(v) => *v,
1804        _ => return 0,
1805    };
1806    match object {
1807        Value::Struct { layout, fields, .. } => {
1808            if layout.is_weak(field_index) {
1809                return 0;
1810            }
1811
1812            if let Ok(mut borrowed) = fields.try_borrow_mut() {
1813                if field_index < borrowed.len() {
1814                    borrowed[field_index] = Value::Int(new_value);
1815                    return 1;
1816                }
1817            }
1818
1819            0
1820        }
1821
1822        _ => 0,
1823    }
1824}
1825
1826#[no_mangle]
1827pub unsafe extern "C" fn jit_new_struct_safe(
1828    struct_name_ptr: *const u8,
1829    struct_name_len: usize,
1830    field_names_ptr: *const *const u8,
1831    field_name_lens_ptr: *const usize,
1832    field_values_ptr: *const Value,
1833    field_count: usize,
1834    out: *mut Value,
1835) -> u8 {
1836    if struct_name_ptr.is_null() || out.is_null() {
1837        return 0;
1838    }
1839
1840    if field_count > 0
1841        && (field_names_ptr.is_null()
1842            || field_name_lens_ptr.is_null()
1843            || field_values_ptr.is_null())
1844    {
1845        return 0;
1846    }
1847
1848    let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
1849    let struct_name = match str::from_utf8(struct_name_slice) {
1850        Ok(s) => s.to_string(),
1851        Err(_) => return 0,
1852    };
1853    let mut fields = Vec::with_capacity(field_count);
1854    for i in 0..field_count {
1855        let field_name_ptr = *field_names_ptr.add(i);
1856        let field_name_len = *field_name_lens_ptr.add(i);
1857        let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1858        let field_name = match str::from_utf8(field_name_slice) {
1859            Ok(s) => Rc::new(s.to_string()),
1860            Err(_) => return 0,
1861        };
1862        let field_value_ptr = field_values_ptr.add(i);
1863        let field_value = (&*field_value_ptr).clone();
1864        fields.push((field_name, field_value));
1865    }
1866
1867    let struct_value = match crate::vm::VM::with_current(move |vm| {
1868        vm.instantiate_struct(&struct_name, fields)
1869            .map_err(|err| err.to_string())
1870    }) {
1871        Ok(value) => value,
1872        Err(_) => return 0,
1873    };
1874    ptr::write(out, struct_value);
1875    1
1876}
1877
1878#[no_mangle]
1879pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
1880    if src_ptr.is_null() || dest_ptr.is_null() {
1881        return 0;
1882    }
1883
1884    let src_value = &*src_ptr;
1885    let cloned_value = src_value.clone();
1886    ptr::write(dest_ptr, cloned_value);
1887    1
1888}