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        match self {
585            Value::Nil => false,
586            Value::Bool(false) => false,
587            Value::Enum {
588                enum_name, variant, ..
589            } if enum_name == "Option" && variant == "None" => false,
590            _ => true,
591        }
592    }
593
594    pub fn to_bool(&self) -> bool {
595        self.is_truthy()
596    }
597
598    pub fn as_int(&self) -> Option<LustInt> {
599        match self {
600            Value::Int(i) => Some(*i),
601            Value::Float(f) => Some(int_from_float(*f)),
602            _ => None,
603        }
604    }
605
606    pub fn as_float(&self) -> Option<LustFloat> {
607        match self {
608            Value::Float(f) => Some(*f),
609            Value::Int(i) => Some(float_from_int(*i)),
610            _ => None,
611        }
612    }
613
614    pub fn as_string(&self) -> Option<&str> {
615        match self {
616            Value::String(s) => Some(s.as_str()),
617            _ => None,
618        }
619    }
620
621    pub fn as_string_rc(&self) -> Option<Rc<String>> {
622        match self {
623            Value::String(s) => Some(s.clone()),
624            _ => None,
625        }
626    }
627
628    pub fn as_task_handle(&self) -> Option<TaskHandle> {
629        match self {
630            Value::Task(handle) => Some(*handle),
631            _ => None,
632        }
633    }
634
635    pub fn as_array(&self) -> Option<Vec<Value>> {
636        match self {
637            Value::Array(arr) => Some(arr.borrow().clone()),
638            _ => None,
639        }
640    }
641
642    pub fn array_len(&self) -> Option<usize> {
643        match self {
644            Value::Array(arr) => Some(arr.borrow().len()),
645            _ => None,
646        }
647    }
648
649    pub fn array_get(&self, index: usize) -> Option<Value> {
650        match self {
651            Value::Array(arr) => arr.borrow().get(index).cloned(),
652            _ => None,
653        }
654    }
655
656    pub fn array_push(&self, value: Value) -> Result<(), String> {
657        match self {
658            Value::Array(arr) => {
659                arr.borrow_mut().push(value);
660                Ok(())
661            }
662
663            _ => Err("Cannot push to non-array".to_string()),
664        }
665    }
666
667    pub fn array_pop(&self) -> Result<Option<Value>, String> {
668        match self {
669            Value::Array(arr) => Ok(arr.borrow_mut().pop()),
670            _ => Err("Cannot pop from non-array".to_string()),
671        }
672    }
673
674    pub fn as_map(&self) -> Option<HashMap<ValueKey, Value>> {
675        match self {
676            Value::Map(map) => Some(map.borrow().clone()),
677            _ => None,
678        }
679    }
680
681    pub fn map_get(&self, key: &ValueKey) -> Option<Value> {
682        match self {
683            Value::Map(map) => map.borrow().get(key).cloned(),
684            _ => None,
685        }
686    }
687
688    pub fn map_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
689        match self {
690            Value::Map(map) => {
691                map.borrow_mut().insert(key, value);
692                Ok(())
693            }
694
695            _ => Err("Cannot set key on non-map".to_string()),
696        }
697    }
698
699    pub fn map_has(&self, key: &ValueKey) -> Option<bool> {
700        match self {
701            Value::Map(map) => Some(map.borrow().contains_key(key)),
702            _ => None,
703        }
704    }
705
706    pub fn map_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
707        match self {
708            Value::Map(map) => Ok(map.borrow_mut().remove(key)),
709            _ => Err("Cannot delete key from non-map".to_string()),
710        }
711    }
712
713    pub fn map_len(&self) -> Option<usize> {
714        match self {
715            Value::Map(map) => Some(map.borrow().len()),
716            _ => None,
717        }
718    }
719
720    pub fn as_table(&self) -> Option<HashMap<ValueKey, Value>> {
721        match self {
722            Value::Table(table) => Some(table.borrow().clone()),
723            _ => None,
724        }
725    }
726
727    pub fn table_get(&self, key: &ValueKey) -> Option<Value> {
728        match self {
729            Value::Table(table) => table.borrow().get(key).cloned(),
730            _ => None,
731        }
732    }
733
734    pub fn table_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
735        match self {
736            Value::Table(table) => {
737                table.borrow_mut().insert(key, value);
738                Ok(())
739            }
740
741            _ => Err("Cannot set key on non-table".to_string()),
742        }
743    }
744
745    pub fn table_has(&self, key: &ValueKey) -> Option<bool> {
746        match self {
747            Value::Table(table) => Some(table.borrow().contains_key(key)),
748            _ => None,
749        }
750    }
751
752    pub fn table_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
753        match self {
754            Value::Table(table) => Ok(table.borrow_mut().remove(key)),
755            _ => Err("Cannot delete key from non-table".to_string()),
756        }
757    }
758
759    pub fn table_len(&self) -> Option<usize> {
760        match self {
761            Value::Table(table) => Some(table.borrow().len()),
762            _ => None,
763        }
764    }
765
766    pub fn string(s: impl Into<String>) -> Self {
767        Value::String(Rc::new(s.into()))
768    }
769
770    pub fn array(values: Vec<Value>) -> Self {
771        Value::Array(Rc::new(RefCell::new(values)))
772    }
773
774    pub fn tuple(values: Vec<Value>) -> Self {
775        Value::Tuple(Rc::new(values))
776    }
777
778    pub fn tuple_len(&self) -> Option<usize> {
779        match self {
780            Value::Tuple(values) => Some(values.len()),
781            _ => None,
782        }
783    }
784
785    pub fn tuple_get(&self, index: usize) -> Option<Value> {
786        match self {
787            Value::Tuple(values) => values.get(index).cloned(),
788            _ => None,
789        }
790    }
791
792    pub fn map(entries: HashMap<ValueKey, Value>) -> Self {
793        Value::Map(Rc::new(RefCell::new(entries)))
794    }
795
796    pub fn table(entries: HashMap<ValueKey, Value>) -> Self {
797        Value::Table(Rc::new(RefCell::new(entries)))
798    }
799
800    pub fn task(handle: TaskHandle) -> Self {
801        Value::Task(handle)
802    }
803
804    pub fn struct_get_field_rc(&self, field: &Rc<String>) -> Option<Value> {
805        match self {
806            Value::Struct { layout, fields, .. } => layout
807                .index_of_rc(field)
808                .or_else(|| layout.index_of_str(field.as_str()))
809                .and_then(|idx| {
810                    fields
811                        .borrow()
812                        .get(idx)
813                        .cloned()
814                        .map(|value| layout.materialize_field_value(idx, value))
815                }),
816            _ => None,
817        }
818    }
819
820    pub fn struct_get_field(&self, field: &str) -> Option<Value> {
821        match self {
822            Value::Struct { layout, fields, .. } => layout.index_of_str(field).and_then(|idx| {
823                fields
824                    .borrow()
825                    .get(idx)
826                    .cloned()
827                    .map(|value| layout.materialize_field_value(idx, value))
828            }),
829            _ => None,
830        }
831    }
832
833    pub fn struct_get_field_indexed(&self, index: usize) -> Option<Value> {
834        match self {
835            Value::Struct { layout, fields, .. } => fields
836                .borrow()
837                .get(index)
838                .cloned()
839                .map(|value| layout.materialize_field_value(index, value)),
840            _ => None,
841        }
842    }
843
844    pub fn struct_set_field_rc(&self, field: &Rc<String>, value: Value) -> Result<(), String> {
845        match self {
846            Value::Struct { layout, .. } => {
847                if let Some(index) = layout
848                    .index_of_rc(field)
849                    .or_else(|| layout.index_of_str(field.as_str()))
850                {
851                    self.struct_set_field_indexed(index, value)
852                } else {
853                    Err(format!(
854                        "Struct '{}' has no field '{}'",
855                        layout.name(),
856                        field.as_str()
857                    ))
858                }
859            }
860
861            _ => Err("Attempted to set field on non-struct value".to_string()),
862        }
863    }
864
865    pub fn struct_set_field(&self, field: &str, value: Value) -> Result<(), String> {
866        match self {
867            Value::Struct { layout, .. } => {
868                if let Some(index) = layout.index_of_str(field) {
869                    self.struct_set_field_indexed(index, value)
870                } else {
871                    Err(format!(
872                        "Struct '{}' has no field '{}'",
873                        layout.name(),
874                        field
875                    ))
876                }
877            }
878
879            _ => Err("Attempted to set field on non-struct value".to_string()),
880        }
881    }
882
883    pub fn struct_set_field_indexed(&self, index: usize, value: Value) -> Result<(), String> {
884        match self {
885            Value::Struct {
886                name,
887                layout,
888                fields,
889            } => {
890                let mut borrowed = fields.borrow_mut();
891                if index < borrowed.len() {
892                    let canonical = layout.canonicalize_field_value(index, value)?;
893                    borrowed[index] = canonical;
894                    Ok(())
895                } else {
896                    Err(format!(
897                        "Struct '{}' field index {} out of bounds (len {})",
898                        name,
899                        index,
900                        borrowed.len()
901                    ))
902                }
903            }
904
905            _ => Err("Attempted to set field on non-struct value".to_string()),
906        }
907    }
908
909    pub fn enum_unit(enum_name: impl Into<String>, variant: impl Into<String>) -> Self {
910        Value::Enum {
911            enum_name: enum_name.into(),
912            variant: variant.into(),
913            values: None,
914        }
915    }
916
917    pub fn enum_variant(
918        enum_name: impl Into<String>,
919        variant: impl Into<String>,
920        values: Vec<Value>,
921    ) -> Self {
922        Value::Enum {
923            enum_name: enum_name.into(),
924            variant: variant.into(),
925            values: Some(Rc::new(values)),
926        }
927    }
928
929    pub fn as_enum(&self) -> Option<(&str, &str, Option<&[Value]>)> {
930        match self {
931            Value::Enum {
932                enum_name,
933                variant,
934                values,
935            } => Some((
936                enum_name.as_str(),
937                variant.as_str(),
938                values.as_ref().map(|v| v.as_slice()),
939            )),
940            _ => None,
941        }
942    }
943
944    pub fn is_enum_variant(&self, enum_name: &str, variant: &str) -> bool {
945        match self {
946            Value::Enum {
947                enum_name: en,
948                variant: v,
949                ..
950            } => (enum_name.is_empty() || en == enum_name) && v == variant,
951            _ => false,
952        }
953    }
954
955    pub fn some(value: Value) -> Self {
956        Value::enum_variant("Option", "Some", vec![value])
957    }
958
959    pub fn none() -> Self {
960        Value::enum_unit("Option", "None")
961    }
962
963    pub fn ok(value: Value) -> Self {
964        Value::enum_variant("Result", "Ok", vec![value])
965    }
966
967    pub fn err(error: Value) -> Self {
968        Value::enum_variant("Result", "Err", vec![error])
969    }
970
971    pub fn to_string(&self) -> String {
972        format!("{}", self)
973    }
974}
975
976impl fmt::Debug for Value {
977    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
978        match self {
979            Value::Nil => write!(f, "Nil"),
980            Value::Bool(b) => write!(f, "Bool({})", b),
981            Value::Int(i) => write!(f, "Int({})", i),
982            Value::Float(fl) => write!(f, "Float({})", fl),
983            Value::String(s) => write!(f, "String({:?})", s),
984            Value::Array(arr) => write!(f, "Array({:?})", arr.borrow()),
985            Value::Tuple(values) => write!(f, "Tuple({:?})", values),
986            Value::Map(map) => write!(f, "Map({:?})", map.borrow()),
987            Value::Table(table) => write!(f, "Table({:?})", table.borrow()),
988            Value::Struct {
989                name,
990                layout,
991                fields,
992            } => {
993                let borrowed = fields.borrow();
994                let mut display_fields = Vec::with_capacity(borrowed.len());
995                for (idx, field_name) in layout.field_names().iter().enumerate() {
996                    let value = borrowed.get(idx).cloned().unwrap_or(Value::Nil);
997                    display_fields.push((field_name.as_str().to_string(), value));
998                }
999
1000                write!(
1001                    f,
1002                    "Struct {{ name: {:?}, fields: {:?} }}",
1003                    name, display_fields
1004                )
1005            }
1006
1007            Value::WeakStruct(weak) => {
1008                if let Some(upgraded) = weak.upgrade() {
1009                    write!(f, "WeakStruct({:?})", upgraded)
1010                } else {
1011                    write!(f, "WeakStruct(<dangling>)")
1012                }
1013            }
1014
1015            Value::Enum {
1016                enum_name,
1017                variant,
1018                values,
1019            } => {
1020                write!(
1021                    f,
1022                    "Enum {{ enum: {:?}, variant: {:?}, values: {:?} }}",
1023                    enum_name, variant, values
1024                )
1025            }
1026
1027            Value::Function(idx) => write!(f, "Function({})", idx),
1028            Value::NativeFunction(_) => write!(f, "NativeFunction(<fn>)"),
1029            Value::Closure {
1030                function_idx,
1031                upvalues,
1032            } => {
1033                write!(
1034                    f,
1035                    "Closure {{ function: {}, upvalues: {:?} }}",
1036                    function_idx, upvalues
1037                )
1038            }
1039
1040            Value::Iterator(_) => write!(f, "Iterator(<state>)"),
1041            Value::Task(handle) => write!(f, "Task({})", handle.0),
1042        }
1043    }
1044}
1045
1046impl fmt::Display for Value {
1047    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1048        match self {
1049            Value::Nil => write!(f, "nil"),
1050            Value::Bool(b) => write!(f, "{}", b),
1051            Value::Int(i) => write!(f, "{}", i),
1052            Value::Float(fl) => write!(f, "{}", fl),
1053            Value::String(s) => write!(f, "{}", s),
1054            Value::Array(arr) => {
1055                write!(f, "[")?;
1056                let borrowed = arr.borrow();
1057                for (i, val) in borrowed.iter().enumerate() {
1058                    if i > 0 {
1059                        write!(f, ", ")?;
1060                    }
1061
1062                    write!(f, "{}", val)?;
1063                }
1064
1065                write!(f, "]")
1066            }
1067
1068            Value::Tuple(values) => {
1069                write!(f, "(")?;
1070                for (i, val) in values.iter().enumerate() {
1071                    if i > 0 {
1072                        write!(f, ", ")?;
1073                    }
1074
1075                    write!(f, "{}", val)?;
1076                }
1077
1078                write!(f, ")")
1079            }
1080
1081            Value::Map(map) => {
1082                write!(f, "{{")?;
1083                let borrowed = map.borrow();
1084                for (i, (k, v)) in borrowed.iter().enumerate() {
1085                    if i > 0 {
1086                        write!(f, ", ")?;
1087                    }
1088
1089                    write!(f, "{}: {}", k, v)?;
1090                }
1091
1092                write!(f, "}}")
1093            }
1094
1095            Value::Table(table) => {
1096                write!(f, "{{")?;
1097                let borrowed = table.borrow();
1098                for (i, (k, v)) in borrowed.iter().enumerate() {
1099                    if i > 0 {
1100                        write!(f, ", ")?;
1101                    }
1102
1103                    write!(f, "{}: {}", k, v)?;
1104                }
1105
1106                write!(f, "}}")
1107            }
1108
1109            Value::Struct {
1110                name,
1111                layout,
1112                fields,
1113            } => {
1114                let borrowed = fields.borrow();
1115                write!(f, "{} {{", name)?;
1116                for (i, field_name) in layout.field_names().iter().enumerate() {
1117                    if i > 0 {
1118                        write!(f, ", ")?;
1119                    }
1120
1121                    let value = borrowed.get(i).unwrap_or(&Value::Nil);
1122                    write!(f, "{}: {}", field_name, value)?;
1123                }
1124
1125                write!(f, "}}")
1126            }
1127
1128            Value::WeakStruct(weak) => {
1129                if let Some(strong) = weak.upgrade() {
1130                    strong.fmt(f)
1131                } else {
1132                    write!(f, "nil")
1133                }
1134            }
1135
1136            Value::Enum {
1137                enum_name,
1138                variant,
1139                values,
1140            } => {
1141                write!(f, "{}.{}", enum_name, variant)?;
1142                if let Some(vals) = values {
1143                    write!(f, "(")?;
1144                    for (i, val) in vals.iter().enumerate() {
1145                        if i > 0 {
1146                            write!(f, ", ")?;
1147                        }
1148
1149                        write!(f, "{}", val)?;
1150                    }
1151
1152                    write!(f, ")")?;
1153                }
1154
1155                Ok(())
1156            }
1157
1158            Value::Function(idx) => write!(f, "<function@{}>", idx),
1159            Value::NativeFunction(_) => write!(f, "<native function>"),
1160            Value::Closure { function_idx, .. } => write!(f, "<closure@{}>", function_idx),
1161            Value::Iterator(_) => write!(f, "<iterator>"),
1162            Value::Task(handle) => write!(f, "<task {}>", handle.0),
1163        }
1164    }
1165}
1166
1167impl PartialEq for Value {
1168    fn eq(&self, other: &Self) -> bool {
1169        match (self, other) {
1170            (Value::Nil, Value::Nil) => true,
1171            (Value::Bool(a), Value::Bool(b)) => a == b,
1172            (Value::Int(a), Value::Int(b)) => a == b,
1173            (Value::Float(a), Value::Float(b)) => a == b,
1174            (Value::String(a), Value::String(b)) => a == b,
1175            (Value::Array(a), Value::Array(b)) => *a.borrow() == *b.borrow(),
1176            (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
1177            (Value::Map(a), Value::Map(b)) => *a.borrow() == *b.borrow(),
1178            (Value::Table(a), Value::Table(b)) => *a.borrow() == *b.borrow(),
1179            (
1180                Value::Struct {
1181                    name: n1,
1182                    layout: l1,
1183                    fields: f1,
1184                },
1185                Value::Struct {
1186                    name: n2,
1187                    layout: l2,
1188                    fields: f2,
1189                },
1190            ) => {
1191                if n1 != n2 {
1192                    return false;
1193                }
1194
1195                let borrowed_f1 = f1.borrow();
1196                let borrowed_f2 = f2.borrow();
1197                if borrowed_f1.len() != borrowed_f2.len() {
1198                    return false;
1199                }
1200
1201                if Rc::ptr_eq(l1, l2) {
1202                    return borrowed_f1
1203                        .iter()
1204                        .zip(borrowed_f2.iter())
1205                        .all(|(a, b)| a == b);
1206                }
1207
1208                l1.field_names()
1209                    .iter()
1210                    .enumerate()
1211                    .all(|(idx, field_name)| {
1212                        if let Some(other_idx) = l2.index_of_rc(field_name) {
1213                            borrowed_f1
1214                                .get(idx)
1215                                .zip(borrowed_f2.get(other_idx))
1216                                .map(|(a, b)| a == b)
1217                                .unwrap_or(false)
1218                        } else {
1219                            false
1220                        }
1221                    })
1222            }
1223
1224            (Value::WeakStruct(a), Value::WeakStruct(b)) => match (a.upgrade(), b.upgrade()) {
1225                (Some(left), Some(right)) => left == right,
1226                (None, None) => true,
1227                _ => false,
1228            },
1229            (Value::WeakStruct(a), other) => a
1230                .upgrade()
1231                .map(|upgraded| upgraded == *other)
1232                .unwrap_or(matches!(other, Value::Nil)),
1233            (value, Value::WeakStruct(b)) => b
1234                .upgrade()
1235                .map(|upgraded| *value == upgraded)
1236                .unwrap_or(matches!(value, Value::Nil)),
1237            (
1238                Value::Enum {
1239                    enum_name: e1,
1240                    variant: v1,
1241                    values: vals1,
1242                },
1243                Value::Enum {
1244                    enum_name: e2,
1245                    variant: v2,
1246                    values: vals2,
1247                },
1248            ) => e1 == e2 && v1 == v2 && vals1 == vals2,
1249            (Value::Function(a), Value::Function(b)) => a == b,
1250            (
1251                Value::Closure {
1252                    function_idx: f1,
1253                    upvalues: u1,
1254                },
1255                Value::Closure {
1256                    function_idx: f2,
1257                    upvalues: u2,
1258                },
1259            ) => f1 == f2 && Rc::ptr_eq(u1, u2),
1260            (Value::Iterator(_), Value::Iterator(_)) => false,
1261            (Value::Task(a), Value::Task(b)) => a == b,
1262            _ => false,
1263        }
1264    }
1265}
1266
1267#[cfg(feature = "std")]
1268#[no_mangle]
1269pub unsafe extern "C" fn jit_array_get_safe(
1270    array_value_ptr: *const Value,
1271    index: i64,
1272    out: *mut Value,
1273) -> u8 {
1274    if array_value_ptr.is_null() || out.is_null() {
1275        eprintln!("❌ jit_array_get_safe: null pointer detected!");
1276        return 0;
1277    }
1278
1279    let array_value = &*array_value_ptr;
1280    let arr = match array_value {
1281        Value::Array(arr) => arr,
1282        _ => {
1283            return 0;
1284        }
1285    };
1286    if index < 0 {
1287        return 0;
1288    }
1289
1290    let idx = index as usize;
1291    let borrowed = match arr.try_borrow() {
1292        Ok(b) => b,
1293        Err(_) => {
1294            return 0;
1295        }
1296    };
1297    if idx >= borrowed.len() {
1298        return 0;
1299    }
1300
1301    ptr::write(out, borrowed[idx].clone());
1302    1
1303}
1304
1305#[cfg(feature = "std")]
1306#[no_mangle]
1307pub unsafe extern "C" fn jit_array_len_safe(array_value_ptr: *const Value) -> i64 {
1308    if array_value_ptr.is_null() {
1309        return -1;
1310    }
1311
1312    let array_value = &*array_value_ptr;
1313    match array_value {
1314        Value::Array(arr) => match arr.try_borrow() {
1315            Ok(borrowed) => int_from_usize(borrowed.len()),
1316            Err(_) => -1,
1317        },
1318        _ => -1,
1319    }
1320}
1321
1322#[cfg(feature = "std")]
1323#[no_mangle]
1324pub unsafe extern "C" fn jit_concat_safe(
1325    left_value_ptr: *const Value,
1326    right_value_ptr: *const Value,
1327    out: *mut Value,
1328) -> u8 {
1329    if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1330        return 0;
1331    }
1332
1333    let left = &*left_value_ptr;
1334    let right = &*right_value_ptr;
1335    const NO_VM_ERROR: &str = "task API requires a running VM";
1336    let left_str = match VM::with_current(|vm| {
1337        let left_copy = left.clone();
1338        vm.value_to_string_for_concat(&left_copy)
1339            .map_err(|err| err.to_string())
1340    }) {
1341        Ok(rc) => rc,
1342        Err(err) if err == NO_VM_ERROR => Rc::new(left.to_string()),
1343        Err(_) => return 0,
1344    };
1345    let right_str = match VM::with_current(|vm| {
1346        let right_copy = right.clone();
1347        vm.value_to_string_for_concat(&right_copy)
1348            .map_err(|err| err.to_string())
1349    }) {
1350        Ok(rc) => rc,
1351        Err(err) if err == NO_VM_ERROR => Rc::new(right.to_string()),
1352        Err(_) => return 0,
1353    };
1354    let mut combined = String::with_capacity(left_str.len() + right_str.len());
1355    combined.push_str(left_str.as_ref());
1356    combined.push_str(right_str.as_ref());
1357    let result = Value::string(combined);
1358    ptr::write(out, result);
1359    1
1360}
1361
1362#[no_mangle]
1363pub unsafe extern "C" fn jit_guard_native_function(
1364    value_ptr: *const Value,
1365    expected_fn_ptr: *const (),
1366    register_index: u8,
1367) -> u8 {
1368    if value_ptr.is_null() || expected_fn_ptr.is_null() {
1369        jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1370        return 0;
1371    }
1372
1373    match &*value_ptr {
1374        Value::NativeFunction(func) => {
1375            let actual = Rc::as_ptr(func) as *const ();
1376            if actual == expected_fn_ptr {
1377                1
1378            } else {
1379                jit::log(|| {
1380                    format!(
1381                        "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1382                        register_index, actual, expected_fn_ptr
1383                    )
1384                });
1385                0
1386            }
1387        }
1388
1389        other => {
1390            jit::log(|| {
1391                format!(
1392                    "jit_guard_native_function: value not native in reg {} ({:?})",
1393                    register_index,
1394                    other.tag()
1395                )
1396            });
1397            0
1398        }
1399    }
1400}
1401
1402#[no_mangle]
1403pub unsafe extern "C" fn jit_call_native_safe(
1404    vm_ptr: *mut VM,
1405    callee_ptr: *const Value,
1406    expected_fn_ptr: *const (),
1407    args_ptr: *const Value,
1408    arg_count: u8,
1409    out: *mut Value,
1410) -> u8 {
1411    if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1412        jit::log(|| "jit_call_native_safe: null argument".to_string());
1413        return 0;
1414    }
1415
1416    let callee = &*callee_ptr;
1417    let native_fn = match callee {
1418        Value::NativeFunction(func) => func.clone(),
1419        other => {
1420            jit::log(|| {
1421                format!(
1422                    "jit_call_native_safe: callee not native ({:?})",
1423                    other.tag()
1424                )
1425            });
1426            return 0;
1427        }
1428    };
1429
1430    if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1431        jit::log(|| {
1432            format!(
1433                "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1434                Rc::as_ptr(&native_fn),
1435                expected_fn_ptr
1436            )
1437        });
1438        return 0;
1439    }
1440
1441    let mut args = Vec::with_capacity(arg_count as usize);
1442    if arg_count > 0 {
1443        if args_ptr.is_null() {
1444            jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1445            return 0;
1446        }
1447
1448        for i in 0..(arg_count as usize) {
1449            let arg = &*args_ptr.add(i);
1450            args.push(arg.clone());
1451        }
1452    }
1453
1454    push_vm_ptr(vm_ptr);
1455    let outcome = native_fn(&args);
1456    pop_vm_ptr();
1457
1458    let outcome = match outcome {
1459        Ok(result) => result,
1460        Err(err) => {
1461            jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1462            return 0;
1463        }
1464    };
1465
1466    match outcome {
1467        NativeCallResult::Return(value) => {
1468            ptr::write(out, value);
1469            1
1470        }
1471
1472        NativeCallResult::Yield(_) => {
1473            jit::log(|| "jit_call_native_safe: native attempted to yield".to_string());
1474            0
1475        }
1476
1477        NativeCallResult::Stop(_) => {
1478            jit::log(|| "jit_call_native_safe: native attempted to stop".to_string());
1479            0
1480        }
1481    }
1482}
1483
1484#[no_mangle]
1485pub unsafe extern "C" fn jit_call_method_safe(
1486    object_ptr: *const Value,
1487    method_name_ptr: *const u8,
1488    method_name_len: usize,
1489    args_ptr: *const Value,
1490    arg_count: u8,
1491    out: *mut Value,
1492) -> u8 {
1493    if object_ptr.is_null() || method_name_ptr.is_null() || out.is_null() {
1494        return 0;
1495    }
1496
1497    if arg_count > 0 && args_ptr.is_null() {
1498        return 0;
1499    }
1500
1501    let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
1502    let method_name = match str::from_utf8(method_name_slice) {
1503        Ok(s) => s,
1504        Err(_) => return 0,
1505    };
1506    let object = &*object_ptr;
1507    if matches!(object, Value::Struct { .. }) {
1508        return 0;
1509    }
1510
1511    let mut args = Vec::with_capacity(arg_count as usize);
1512    for i in 0..arg_count {
1513        let arg_ptr = args_ptr.add(i as usize);
1514        args.push((&*arg_ptr).clone());
1515    }
1516
1517    let result = match call_builtin_method_simple(object, method_name, args) {
1518        Ok(val) => val,
1519        Err(_) => return 0,
1520    };
1521    ptr::write(out, result);
1522    1
1523}
1524
1525fn call_builtin_method_simple(
1526    object: &Value,
1527    method_name: &str,
1528    args: Vec<Value>,
1529) -> Result<Value, String> {
1530    match object {
1531        Value::Struct { name, .. } => Err(format!(
1532            "User-defined methods on {} require deoptimization",
1533            name
1534        )),
1535        Value::Iterator(state_rc) => match method_name {
1536            "next" => {
1537                let mut state = state_rc.borrow_mut();
1538                match &mut *state {
1539                    IteratorState::Array { items, index } => {
1540                        if *index < items.len() {
1541                            let v = items[*index].clone();
1542                            *index += 1;
1543                            Ok(Value::some(v))
1544                        } else {
1545                            Ok(Value::none())
1546                        }
1547                    }
1548
1549                    IteratorState::MapPairs { items, index } => {
1550                        if *index < items.len() {
1551                            let (k, v) = items[*index].clone();
1552                            *index += 1;
1553                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
1554                        } else {
1555                            Ok(Value::none())
1556                        }
1557                    }
1558
1559                    IteratorState::TablePairs { items, index } => {
1560                        if *index < items.len() {
1561                            let (k, v) = items[*index].clone();
1562                            *index += 1;
1563                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
1564                        } else {
1565                            Ok(Value::none())
1566                        }
1567                    }
1568                }
1569            }
1570
1571            _ => Err(format!(
1572                "Iterator method '{}' not supported in JIT",
1573                method_name
1574            )),
1575        },
1576        Value::Enum {
1577            enum_name,
1578            variant,
1579            values,
1580        } if enum_name == "Option" => match method_name {
1581            "unwrap" => {
1582                if variant == "Some" {
1583                    if let Some(vals) = values {
1584                        if vals.len() == 1 {
1585                            Ok(vals[0].clone())
1586                        } else {
1587                            Err("Option::Some should have exactly 1 value".to_string())
1588                        }
1589                    } else {
1590                        Err("Option::Some should have a value".to_string())
1591                    }
1592                } else {
1593                    Err("Called unwrap() on Option::None".to_string())
1594                }
1595            }
1596
1597            _ => Err(format!(
1598                "Option method '{}' not supported in JIT",
1599                method_name
1600            )),
1601        },
1602        Value::Array(arr) => match method_name {
1603            "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
1604            "push" => {
1605                let value = args
1606                    .get(0)
1607                    .cloned()
1608                    .ok_or_else(|| "Array:push requires a value argument".to_string())?;
1609                arr.borrow_mut().push(value);
1610                Ok(Value::Nil)
1611            }
1612            "pop" => {
1613                let popped = arr.borrow_mut().pop();
1614                Ok(popped.map(Value::some).unwrap_or_else(Value::none))
1615            }
1616            "first" => {
1617                let borrowed = arr.borrow();
1618                Ok(borrowed
1619                    .first()
1620                    .cloned()
1621                    .map(Value::some)
1622                    .unwrap_or_else(Value::none))
1623            }
1624            "last" => {
1625                let borrowed = arr.borrow();
1626                Ok(borrowed
1627                    .last()
1628                    .cloned()
1629                    .map(Value::some)
1630                    .unwrap_or_else(Value::none))
1631            }
1632            "get" => {
1633                let index = args
1634                    .get(0)
1635                    .and_then(Value::as_int)
1636                    .ok_or_else(|| "Array:get requires an integer index".to_string())?;
1637                let borrowed = arr.borrow();
1638                Ok(borrowed
1639                    .get(index as usize)
1640                    .cloned()
1641                    .map(Value::some)
1642                    .unwrap_or_else(Value::none))
1643            }
1644            "iter" => {
1645                let items = arr.borrow().clone();
1646                let iter = IteratorState::Array { items, index: 0 };
1647                Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
1648            }
1649            _ => Err(format!(
1650                "Array method '{}' not supported in JIT",
1651                method_name
1652            )),
1653        },
1654        _ => Err(format!(
1655            "Method '{}' not supported in JIT (deoptimizing)",
1656            method_name
1657        )),
1658    }
1659}
1660
1661#[no_mangle]
1662pub unsafe extern "C" fn jit_get_field_safe(
1663    object_ptr: *const Value,
1664    field_name_ptr: *const u8,
1665    field_name_len: usize,
1666    out: *mut Value,
1667) -> u8 {
1668    if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
1669        return 0;
1670    }
1671
1672    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1673    let field_name = match str::from_utf8(field_name_slice) {
1674        Ok(s) => s,
1675        Err(_) => return 0,
1676    };
1677    let object = &*object_ptr;
1678    let field_value = match object {
1679        Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
1680            Some(idx) => match fields.borrow().get(idx) {
1681                Some(val) => val.clone(),
1682                None => return 0,
1683            },
1684            None => return 0,
1685        },
1686        _ => return 0,
1687    };
1688    ptr::write(out, field_value);
1689    1
1690}
1691
1692#[no_mangle]
1693pub unsafe extern "C" fn jit_set_field_safe(
1694    object_ptr: *const Value,
1695    field_name_ptr: *const u8,
1696    field_name_len: usize,
1697    value_ptr: *const Value,
1698) -> u8 {
1699    if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
1700        return 0;
1701    }
1702
1703    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1704    let field_name = match str::from_utf8(field_name_slice) {
1705        Ok(s) => s,
1706        Err(_) => return 0,
1707    };
1708    let object = &*object_ptr;
1709    let value = (&*value_ptr).clone();
1710    match object {
1711        Value::Struct { .. } => match object.struct_set_field(field_name, value) {
1712            Ok(()) => 1,
1713            Err(_) => 0,
1714        },
1715        Value::Map(map) => {
1716            use crate::bytecode::ValueKey;
1717            let key = ValueKey::String(Rc::new(field_name.to_string()));
1718            map.borrow_mut().insert(key, value);
1719            1
1720        }
1721
1722        _ => 0,
1723    }
1724}
1725
1726#[no_mangle]
1727pub unsafe extern "C" fn jit_get_field_indexed_safe(
1728    object_ptr: *const Value,
1729    field_index: usize,
1730    out: *mut Value,
1731) -> u8 {
1732    if object_ptr.is_null() || out.is_null() {
1733        return 0;
1734    }
1735
1736    let object = &*object_ptr;
1737    match object.struct_get_field_indexed(field_index) {
1738        Some(value) => {
1739            ptr::write(out, value);
1740            1
1741        }
1742
1743        None => 0,
1744    }
1745}
1746
1747#[no_mangle]
1748pub unsafe extern "C" fn jit_set_field_indexed_safe(
1749    object_ptr: *const Value,
1750    field_index: usize,
1751    value_ptr: *const Value,
1752) -> u8 {
1753    if object_ptr.is_null() || value_ptr.is_null() {
1754        return 0;
1755    }
1756
1757    let object = &*object_ptr;
1758    let value = (&*value_ptr).clone();
1759    match object.struct_set_field_indexed(field_index, value) {
1760        Ok(()) => 1,
1761        Err(_) => 0,
1762    }
1763}
1764
1765#[no_mangle]
1766pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
1767    object_ptr: *const Value,
1768    field_index: usize,
1769    out: *mut Value,
1770) -> u8 {
1771    if object_ptr.is_null() || out.is_null() {
1772        return 0;
1773    }
1774
1775    let object = &*object_ptr;
1776    let out_ref = &mut *out;
1777    match object {
1778        Value::Struct { layout, fields, .. } => {
1779            if layout.is_weak(field_index) {
1780                return 0;
1781            }
1782
1783            if let Ok(borrowed) = fields.try_borrow() {
1784                if let Some(Value::Int(val)) = borrowed.get(field_index) {
1785                    *out_ref = Value::Int(*val);
1786                    return 1;
1787                }
1788            }
1789
1790            0
1791        }
1792
1793        _ => 0,
1794    }
1795}
1796
1797#[no_mangle]
1798pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
1799    object_ptr: *const Value,
1800    field_index: usize,
1801    value_ptr: *const Value,
1802) -> u8 {
1803    if object_ptr.is_null() || value_ptr.is_null() {
1804        return 0;
1805    }
1806
1807    let object = &*object_ptr;
1808    let value = &*value_ptr;
1809    let new_value = match value {
1810        Value::Int(v) => *v,
1811        _ => return 0,
1812    };
1813    match object {
1814        Value::Struct { layout, fields, .. } => {
1815            if layout.is_weak(field_index) {
1816                return 0;
1817            }
1818
1819            if let Ok(mut borrowed) = fields.try_borrow_mut() {
1820                if field_index < borrowed.len() {
1821                    borrowed[field_index] = Value::Int(new_value);
1822                    return 1;
1823                }
1824            }
1825
1826            0
1827        }
1828
1829        _ => 0,
1830    }
1831}
1832
1833#[no_mangle]
1834pub unsafe extern "C" fn jit_new_struct_safe(
1835    struct_name_ptr: *const u8,
1836    struct_name_len: usize,
1837    field_names_ptr: *const *const u8,
1838    field_name_lens_ptr: *const usize,
1839    field_values_ptr: *const Value,
1840    field_count: usize,
1841    out: *mut Value,
1842) -> u8 {
1843    if struct_name_ptr.is_null() || out.is_null() {
1844        return 0;
1845    }
1846
1847    if field_count > 0
1848        && (field_names_ptr.is_null()
1849            || field_name_lens_ptr.is_null()
1850            || field_values_ptr.is_null())
1851    {
1852        return 0;
1853    }
1854
1855    let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
1856    let struct_name = match str::from_utf8(struct_name_slice) {
1857        Ok(s) => s.to_string(),
1858        Err(_) => return 0,
1859    };
1860    let mut fields = Vec::with_capacity(field_count);
1861    for i in 0..field_count {
1862        let field_name_ptr = *field_names_ptr.add(i);
1863        let field_name_len = *field_name_lens_ptr.add(i);
1864        let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1865        let field_name = match str::from_utf8(field_name_slice) {
1866            Ok(s) => Rc::new(s.to_string()),
1867            Err(_) => return 0,
1868        };
1869        let field_value_ptr = field_values_ptr.add(i);
1870        let field_value = (&*field_value_ptr).clone();
1871        fields.push((field_name, field_value));
1872    }
1873
1874    let struct_value = match crate::vm::VM::with_current(move |vm| {
1875        vm.instantiate_struct(&struct_name, fields)
1876            .map_err(|err| err.to_string())
1877    }) {
1878        Ok(value) => value,
1879        Err(_) => return 0,
1880    };
1881    ptr::write(out, struct_value);
1882    1
1883}
1884
1885#[no_mangle]
1886pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
1887    if src_ptr.is_null() || dest_ptr.is_null() {
1888        return 0;
1889    }
1890
1891    let src_value = &*src_ptr;
1892    let cloned_value = src_value.clone();
1893    ptr::write(dest_ptr, cloned_value);
1894    1
1895}