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