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::{DefaultHashBuilder, 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 struct ValueKey {
31    original: Value,
32    hashed: Value,
33}
34
35impl ValueKey {
36    pub fn from_value(value: &Value) -> Self {
37        ValueKey {
38            original: value.clone(),
39            hashed: value.clone(),
40        }
41    }
42
43    pub fn with_hashed(original: Value, hashed: Value) -> Self {
44        ValueKey { original, hashed }
45    }
46
47    pub fn string<S>(value: S) -> Self
48    where
49        S: Into<String>,
50    {
51        ValueKey::from(Value::String(Rc::new(value.into())))
52    }
53
54    pub fn to_value(&self) -> Value {
55        self.original.clone()
56    }
57}
58
59impl PartialEq for ValueKey {
60    fn eq(&self, other: &Self) -> bool {
61        value_key_eq(&self.hashed, &other.hashed)
62    }
63}
64
65impl Eq for ValueKey {}
66impl Hash for ValueKey {
67    fn hash<H: Hasher>(&self, state: &mut H) {
68        hash_value_for_key(&self.hashed, state);
69    }
70}
71
72impl fmt::Display for ValueKey {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        write!(f, "{}", self.original)
75    }
76}
77
78impl From<Value> for ValueKey {
79    fn from(value: Value) -> Self {
80        ValueKey {
81            original: value.clone(),
82            hashed: value,
83        }
84    }
85}
86
87impl From<LustInt> for ValueKey {
88    fn from(value: LustInt) -> Self {
89        ValueKey::from(Value::Int(value))
90    }
91}
92
93impl From<LustFloat> for ValueKey {
94    fn from(value: LustFloat) -> Self {
95        ValueKey::from(Value::Float(value))
96    }
97}
98
99impl From<bool> for ValueKey {
100    fn from(value: bool) -> Self {
101        ValueKey::from(Value::Bool(value))
102    }
103}
104
105impl From<String> for ValueKey {
106    fn from(value: String) -> Self {
107        ValueKey::from(Value::String(Rc::new(value)))
108    }
109}
110
111impl From<&str> for ValueKey {
112    fn from(value: &str) -> Self {
113        ValueKey::from(Value::String(Rc::new(value.to_owned())))
114    }
115}
116
117impl From<Rc<String>> for ValueKey {
118    fn from(value: Rc<String>) -> Self {
119        ValueKey::from(Value::String(value))
120    }
121}
122
123/// Helper function to unwrap LuaValue enums for key comparison
124fn unwrap_lua_value_for_key(value: &Value) -> Value {
125    if let Value::Enum {
126        enum_name,
127        variant,
128        values,
129    } = value
130    {
131        if enum_name == "LuaValue" {
132            return match variant.as_str() {
133                "Nil" => Value::Nil,
134                "Bool" => values
135                    .as_ref()
136                    .and_then(|v| v.get(0))
137                    .cloned()
138                    .unwrap_or(Value::Bool(false)),
139                "Int" | "Number" => values
140                    .as_ref()
141                    .and_then(|v| v.get(0))
142                    .cloned()
143                    .unwrap_or(Value::Int(0)),
144                "String" => values
145                    .as_ref()
146                    .and_then(|v| v.get(0))
147                    .cloned()
148                    .unwrap_or(Value::String(Rc::new(String::new()))),
149                "Table" => values
150                    .as_ref()
151                    .and_then(|v| v.get(0))
152                    .cloned()
153                    .unwrap_or(Value::Nil),
154                "Function" => values
155                    .as_ref()
156                    .and_then(|v| v.get(0))
157                    .cloned()
158                    .unwrap_or(Value::Nil),
159                _ => value.clone(),
160            };
161        }
162    }
163    value.clone()
164}
165
166fn value_key_eq(left: &Value, right: &Value) -> bool {
167    use Value::*;
168
169    // Check if either side is a LuaValue enum and unwrap if needed
170    let is_lua_value_left = matches!(left, Enum { enum_name, .. } if enum_name == "LuaValue");
171    let is_lua_value_right = matches!(right, Enum { enum_name, .. } if enum_name == "LuaValue");
172
173    // If either side is a LuaValue, unwrap both and compare
174    if is_lua_value_left || is_lua_value_right {
175        let unwrapped_left = unwrap_lua_value_for_key(left);
176        let unwrapped_right = unwrap_lua_value_for_key(right);
177        return value_key_eq(&unwrapped_left, &unwrapped_right);
178    }
179
180    match (left, right) {
181        (Nil, Nil) => true,
182        (Bool(a), Bool(b)) => a == b,
183        (Int(a), Int(b)) => a == b,
184        (Float(a), Float(b)) => {
185            if float_is_nan(*a) && float_is_nan(*b) {
186                true
187            } else {
188                a == b
189            }
190        }
191        (String(a), String(b)) => a == b,
192        (Array(a), Array(b)) => Rc::ptr_eq(a, b),
193        (Tuple(a), Tuple(b)) => Rc::ptr_eq(a, b),
194        (Map(a), Map(b)) => Rc::ptr_eq(a, b),
195        (Struct { fields: f1, .. }, Struct { fields: f2, .. }) => Rc::ptr_eq(f1, f2),
196        (WeakStruct(a), WeakStruct(b)) => Weak::ptr_eq(a.fields(), b.fields()),
197        (
198            Enum {
199                enum_name: n1,
200                variant: v1,
201                values: vals1,
202            },
203            Enum {
204                enum_name: n2,
205                variant: v2,
206                values: vals2,
207            },
208        ) => n1 == n2 && v1 == v2 && values_ptr_eq(vals1, vals2),
209        (Function(a), Function(b)) => a == b,
210        (NativeFunction(a), NativeFunction(b)) => Rc::ptr_eq(a, b),
211        (
212            Closure {
213                function_idx: f1,
214                upvalues: u1,
215            },
216            Closure {
217                function_idx: f2,
218                upvalues: u2,
219            },
220        ) => f1 == f2 && Rc::ptr_eq(u1, u2),
221        (Iterator(a), Iterator(b)) => Rc::ptr_eq(a, b),
222        (Task(a), Task(b)) => a == b,
223        _ => false,
224    }
225}
226
227fn hash_value_for_key<H: Hasher>(value: &Value, state: &mut H) {
228    use Value::*;
229
230    // Check if this is a LuaValue enum and unwrap it for consistent hashing
231    if matches!(value, Enum { enum_name, .. } if enum_name == "LuaValue") {
232        let unwrapped = unwrap_lua_value_for_key(value);
233        return hash_value_for_key(&unwrapped, state);
234    }
235
236    match value {
237        Nil => {
238            0u8.hash(state);
239        }
240        Bool(b) => {
241            1u8.hash(state);
242            b.hash(state);
243        }
244        Int(i) => {
245            2u8.hash(state);
246            i.hash(state);
247        }
248        Float(f) => {
249            3u8.hash(state);
250            if float_is_nan(*f) {
251                u64::MAX.hash(state);
252            } else {
253                float_to_hash_bits(*f).hash(state);
254            }
255        }
256        String(s) => {
257            4u8.hash(state);
258            s.hash(state);
259        }
260        Array(arr) => {
261            5u8.hash(state);
262            (Rc::as_ptr(arr) as usize).hash(state);
263        }
264        Tuple(tuple) => {
265            6u8.hash(state);
266            (Rc::as_ptr(tuple) as usize).hash(state);
267        }
268        Map(map) => {
269            7u8.hash(state);
270            (Rc::as_ptr(map) as usize).hash(state);
271        }
272        Struct { fields, .. } => {
273            8u8.hash(state);
274            (Rc::as_ptr(fields) as usize).hash(state);
275        }
276        WeakStruct(weak) => {
277            9u8.hash(state);
278            (weak.fields_ptr() as usize).hash(state);
279        }
280        Enum {
281            enum_name,
282            variant,
283            values,
284        } => {
285            10u8.hash(state);
286            enum_name.hash(state);
287            variant.hash(state);
288            values
289                .as_ref()
290                .map(|rc| Rc::as_ptr(rc) as usize)
291                .hash(state);
292        }
293        Function(idx) => {
294            11u8.hash(state);
295            idx.hash(state);
296        }
297        NativeFunction(func) => {
298            12u8.hash(state);
299            (Rc::as_ptr(func) as *const () as usize).hash(state);
300        }
301        Closure {
302            function_idx,
303            upvalues,
304        } => {
305            13u8.hash(state);
306            function_idx.hash(state);
307            (Rc::as_ptr(upvalues) as usize).hash(state);
308        }
309        Iterator(iter) => {
310            14u8.hash(state);
311            (Rc::as_ptr(iter) as usize).hash(state);
312        }
313        Task(handle) => {
314            15u8.hash(state);
315            handle.hash(state);
316        }
317    }
318}
319
320fn values_ptr_eq(left: &Option<Rc<Vec<Value>>>, right: &Option<Rc<Vec<Value>>>) -> bool {
321    match (left, right) {
322        (Some(a), Some(b)) => Rc::ptr_eq(a, b),
323        (None, None) => true,
324        _ => false,
325    }
326}
327
328pub type LustMap = HashMap<ValueKey, Value, DefaultHashBuilder>;
329
330#[repr(u8)]
331#[derive(Debug, Clone, Copy, PartialEq, Eq)]
332pub enum ValueTag {
333    Nil,
334    Bool,
335    Int,
336    Float,
337    String,
338    Array,
339    Tuple,
340    Map,
341    Struct,
342    Enum,
343    Function,
344    NativeFunction,
345    Closure,
346    Iterator,
347    Task,
348}
349
350impl ValueTag {
351    #[inline]
352    pub const fn as_u8(self) -> u8 {
353        self as u8
354    }
355}
356
357#[derive(Debug, Clone, Copy, PartialEq, Eq)]
358pub enum FieldStorage {
359    Strong,
360    Weak,
361}
362
363#[derive(Debug)]
364pub struct StructLayout {
365    name: String,
366    field_names: Vec<Rc<String>>,
367    field_lookup_ptr: HashMap<usize, usize>,
368    field_lookup_str: HashMap<String, usize>,
369    field_storage: Vec<FieldStorage>,
370    field_types: Vec<Type>,
371    weak_targets: Vec<Option<Type>>,
372}
373
374impl StructLayout {
375    pub fn new(
376        name: String,
377        field_names: Vec<Rc<String>>,
378        field_storage: Vec<FieldStorage>,
379        field_types: Vec<Type>,
380        weak_targets: Vec<Option<Type>>,
381    ) -> Self {
382        debug_assert_eq!(
383            field_names.len(),
384            field_storage.len(),
385            "StructLayout::new expects field names and storage metadata to align"
386        );
387        debug_assert_eq!(
388            field_names.len(),
389            field_types.len(),
390            "StructLayout::new expects field names and type metadata to align"
391        );
392        debug_assert_eq!(
393            field_names.len(),
394            weak_targets.len(),
395            "StructLayout::new expects field names and weak target metadata to align"
396        );
397        let mut field_lookup_ptr = HashMap::with_capacity(field_names.len());
398        let mut field_lookup_str = HashMap::with_capacity(field_names.len());
399        for (index, field_name_rc) in field_names.iter().enumerate() {
400            let ptr = Rc::as_ptr(field_name_rc) as usize;
401            field_lookup_ptr.insert(ptr, index);
402            field_lookup_str.insert((**field_name_rc).clone(), index);
403        }
404
405        Self {
406            name,
407            field_names,
408            field_lookup_ptr,
409            field_lookup_str,
410            field_storage,
411            field_types,
412            weak_targets,
413        }
414    }
415
416    #[inline]
417    pub fn name(&self) -> &str {
418        &self.name
419    }
420
421    #[inline]
422    pub fn field_names(&self) -> &[Rc<String>] {
423        &self.field_names
424    }
425
426    #[inline]
427    pub fn index_of_rc(&self, key: &Rc<String>) -> Option<usize> {
428        let ptr = Rc::as_ptr(key) as usize;
429        self.field_lookup_ptr
430            .get(&ptr)
431            .copied()
432            .or_else(|| self.field_lookup_str.get(key.as_str()).copied())
433    }
434
435    #[inline]
436    pub fn index_of_str(&self, key: &str) -> Option<usize> {
437        self.field_lookup_str.get(key).copied()
438    }
439
440    #[inline]
441    pub fn field_storage(&self, index: usize) -> FieldStorage {
442        self.field_storage[index]
443    }
444
445    #[inline]
446    pub fn field_type(&self, index: usize) -> &Type {
447        &self.field_types[index]
448    }
449
450    #[inline]
451    pub fn weak_target(&self, index: usize) -> Option<&Type> {
452        self.weak_targets[index].as_ref()
453    }
454
455    #[inline]
456    pub fn is_weak(&self, index: usize) -> bool {
457        matches!(self.field_storage(index), FieldStorage::Weak)
458    }
459
460    pub fn canonicalize_field_value(&self, index: usize, value: Value) -> Result<Value, String> {
461        match self.field_storage(index) {
462            FieldStorage::Strong => Ok(value),
463            FieldStorage::Weak => self.canonicalize_weak_field(index, value),
464        }
465    }
466
467    pub fn materialize_field_value(&self, index: usize, value: Value) -> Value {
468        match self.field_storage(index) {
469            FieldStorage::Strong => value,
470            FieldStorage::Weak => self.materialize_weak_field(value),
471        }
472    }
473
474    fn canonicalize_weak_field(&self, index: usize, value: Value) -> Result<Value, String> {
475        let field_name = self.field_names[index].as_str();
476        match value {
477            Value::Enum {
478                enum_name,
479                variant,
480                values,
481            } if enum_name == "Option" => {
482                if variant == "Some" {
483                    if let Some(inner_values) = values {
484                        if let Some(inner) = inner_values.get(0) {
485                            let coerced = self.to_weak_struct(field_name, inner.clone())?;
486                            Ok(Value::enum_variant("Option", "Some", vec![coerced]))
487                        } else {
488                            Ok(Value::enum_unit("Option", "None"))
489                        }
490                    } else {
491                        Ok(Value::enum_unit("Option", "None"))
492                    }
493                } else if variant == "None" {
494                    Ok(Value::enum_unit("Option", "None"))
495                } else {
496                    Err(format!(
497                        "Struct '{}' field '{}' uses 'ref' and must store Option values; received variant '{}'",
498                        self.name, field_name, variant
499                    ))
500                }
501            }
502
503            Value::Nil => Ok(Value::enum_unit("Option", "None")),
504            other => {
505                let coerced = self.to_weak_struct(field_name, other)?;
506                Ok(Value::enum_variant("Option", "Some", vec![coerced]))
507            }
508        }
509    }
510
511    fn materialize_weak_field(&self, value: Value) -> Value {
512        match value {
513            Value::Enum {
514                enum_name,
515                variant,
516                values,
517            } if enum_name == "Option" => {
518                if variant == "Some" {
519                    if let Some(inner_values) = values {
520                        if let Some(inner) = inner_values.get(0) {
521                            match inner {
522                                Value::WeakStruct(ref weak) => {
523                                    if let Some(upgraded) = weak.upgrade() {
524                                        Value::enum_variant("Option", "Some", vec![upgraded])
525                                    } else {
526                                        Value::enum_unit("Option", "None")
527                                    }
528                                }
529
530                                _ => Value::enum_variant("Option", "Some", vec![inner.clone()]),
531                            }
532                        } else {
533                            Value::enum_unit("Option", "None")
534                        }
535                    } else {
536                        Value::enum_unit("Option", "None")
537                    }
538                } else {
539                    Value::enum_unit("Option", "None")
540                }
541            }
542
543            Value::Nil => Value::enum_unit("Option", "None"),
544            other => Value::enum_variant("Option", "Some", vec![other]),
545        }
546    }
547
548    fn to_weak_struct(&self, field_name: &str, value: Value) -> Result<Value, String> {
549        match value {
550            Value::Struct {
551                name,
552                layout,
553                fields,
554            } => Ok(Value::WeakStruct(WeakStructRef::new(name, layout, &fields))),
555            Value::WeakStruct(_) => Ok(value),
556            other => {
557                let ty = other.type_of();
558                Err(format!(
559                    "Struct '{}' field '{}' expects a struct reference but received value of type '{:?}'",
560                    self.name, field_name, ty
561                ))
562            }
563        }
564    }
565}
566
567#[repr(C, u8)]
568#[derive(Clone)]
569pub enum Value {
570    Nil,
571    Bool(bool),
572    Int(LustInt),
573    Float(LustFloat),
574    String(Rc<String>),
575    Array(Rc<RefCell<Vec<Value>>>),
576    Tuple(Rc<Vec<Value>>),
577    Map(Rc<RefCell<LustMap>>),
578    Struct {
579        name: String,
580        layout: Rc<StructLayout>,
581        fields: Rc<RefCell<Vec<Value>>>,
582    },
583    WeakStruct(WeakStructRef),
584    Enum {
585        enum_name: String,
586        variant: String,
587        values: Option<Rc<Vec<Value>>>,
588    },
589    Function(usize),
590    NativeFunction(NativeFn),
591    Closure {
592        function_idx: usize,
593        upvalues: Rc<Vec<Upvalue>>,
594    },
595    Iterator(Rc<RefCell<IteratorState>>),
596    Task(TaskHandle),
597}
598
599#[derive(Debug, Clone)]
600pub struct WeakStructRef {
601    name: String,
602    layout: Rc<StructLayout>,
603    fields: Weak<RefCell<Vec<Value>>>,
604}
605
606impl WeakStructRef {
607    pub fn new(name: String, layout: Rc<StructLayout>, fields: &Rc<RefCell<Vec<Value>>>) -> Self {
608        Self {
609            name,
610            layout,
611            fields: Rc::downgrade(fields),
612        }
613    }
614
615    pub fn upgrade(&self) -> Option<Value> {
616        self.fields.upgrade().map(|fields| Value::Struct {
617            name: self.name.clone(),
618            layout: self.layout.clone(),
619            fields,
620        })
621    }
622
623    pub fn struct_name(&self) -> &str {
624        &self.name
625    }
626
627    pub(crate) fn fields(&self) -> &Weak<RefCell<Vec<Value>>> {
628        &self.fields
629    }
630
631    pub(crate) fn fields_ptr(&self) -> *const RefCell<Vec<Value>> {
632        self.fields.as_ptr()
633    }
634}
635
636#[derive(Clone)]
637pub enum IteratorState {
638    Array {
639        items: Vec<Value>,
640        index: usize,
641    },
642    MapPairs {
643        items: Vec<(ValueKey, Value)>,
644        index: usize,
645    },
646}
647
648#[derive(Clone)]
649pub struct Upvalue {
650    value: Rc<RefCell<Value>>,
651}
652
653impl Upvalue {
654    pub fn new(value: Value) -> Self {
655        Self {
656            value: Rc::new(RefCell::new(value)),
657        }
658    }
659
660    pub fn get(&self) -> Value {
661        self.value.borrow().clone()
662    }
663
664    pub fn set(&self, value: Value) {
665        *self.value.borrow_mut() = value;
666    }
667}
668
669impl fmt::Debug for Upvalue {
670    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
671        write!(f, "Upvalue({:?})", self.value.borrow())
672    }
673}
674
675#[derive(Debug, Clone)]
676pub enum NativeCallResult {
677    Return(Value),
678    Yield(Value),
679    Stop(Value),
680}
681
682impl From<Value> for NativeCallResult {
683    fn from(value: Value) -> Self {
684        NativeCallResult::Return(value)
685    }
686}
687
688pub type NativeFn = Rc<dyn Fn(&[Value]) -> Result<NativeCallResult, String>>;
689#[derive(Debug, Clone, Copy, PartialEq, Eq)]
690pub enum ValueType {
691    Nil,
692    Bool,
693    Int,
694    Float,
695    String,
696    Array,
697    Tuple,
698    Map,
699    Struct,
700    Enum,
701    Function,
702    NativeFunction,
703    Closure,
704    Iterator,
705    Task,
706}
707
708impl Value {
709    #[inline]
710    pub fn tag(&self) -> ValueTag {
711        match self {
712            Value::Nil => ValueTag::Nil,
713            Value::Bool(_) => ValueTag::Bool,
714            Value::Int(_) => ValueTag::Int,
715            Value::Float(_) => ValueTag::Float,
716            Value::String(_) => ValueTag::String,
717            Value::Array(_) => ValueTag::Array,
718            Value::Tuple(_) => ValueTag::Tuple,
719            Value::Map(_) => ValueTag::Map,
720            Value::Struct { .. } | Value::WeakStruct(_) => ValueTag::Struct,
721            Value::Enum { .. } => ValueTag::Enum,
722            Value::Function(_) => ValueTag::Function,
723            Value::NativeFunction(_) => ValueTag::NativeFunction,
724            Value::Closure { .. } => ValueTag::Closure,
725            Value::Iterator(_) => ValueTag::Iterator,
726            Value::Task(_) => ValueTag::Task,
727        }
728    }
729
730    pub fn type_of(&self) -> ValueType {
731        match self {
732            Value::Nil => ValueType::Nil,
733            Value::Bool(_) => ValueType::Bool,
734            Value::Int(_) => ValueType::Int,
735            Value::Float(_) => ValueType::Float,
736            Value::String(_) => ValueType::String,
737            Value::Array(_) => ValueType::Array,
738            Value::Tuple(_) => ValueType::Tuple,
739            Value::Map(_) => ValueType::Map,
740            Value::Struct { .. } | Value::WeakStruct(_) => ValueType::Struct,
741            Value::Enum { .. } => ValueType::Enum,
742            Value::Function(_) => ValueType::Function,
743            Value::NativeFunction(_) => ValueType::NativeFunction,
744            Value::Closure { .. } => ValueType::Closure,
745            Value::Iterator(_) => ValueType::Iterator,
746            Value::Task(_) => ValueType::Task,
747        }
748    }
749
750    pub fn is_truthy(&self) -> bool {
751        match self {
752            Value::Nil => false,
753            Value::Bool(false) => false,
754            Value::Enum {
755                enum_name, variant, ..
756            } if enum_name == "Option" && variant == "None" => false,
757            _ => true,
758        }
759    }
760
761    pub fn to_bool(&self) -> bool {
762        self.is_truthy()
763    }
764
765    pub fn as_int(&self) -> Option<LustInt> {
766        match self {
767            Value::Int(i) => Some(*i),
768            Value::Float(f) => Some(int_from_float(*f)),
769            _ => None,
770        }
771    }
772
773    pub fn as_float(&self) -> Option<LustFloat> {
774        match self {
775            Value::Float(f) => Some(*f),
776            Value::Int(i) => Some(float_from_int(*i)),
777            _ => None,
778        }
779    }
780
781    pub fn as_string(&self) -> Option<&str> {
782        match self {
783            Value::String(s) => Some(s.as_str()),
784            _ => None,
785        }
786    }
787
788    pub fn as_string_rc(&self) -> Option<Rc<String>> {
789        match self {
790            Value::String(s) => Some(s.clone()),
791            _ => None,
792        }
793    }
794
795    pub fn as_task_handle(&self) -> Option<TaskHandle> {
796        match self {
797            Value::Task(handle) => Some(*handle),
798            _ => None,
799        }
800    }
801
802    pub fn as_array(&self) -> Option<Vec<Value>> {
803        match self {
804            Value::Array(arr) => Some(arr.borrow().clone()),
805            _ => None,
806        }
807    }
808
809    pub fn array_len(&self) -> Option<usize> {
810        match self {
811            Value::Array(arr) => Some(arr.borrow().len()),
812            _ => None,
813        }
814    }
815
816    pub fn array_get(&self, index: usize) -> Option<Value> {
817        match self {
818            Value::Array(arr) => arr.borrow().get(index).cloned(),
819            _ => None,
820        }
821    }
822
823    pub fn array_push(&self, value: Value) -> Result<(), String> {
824        match self {
825            Value::Array(arr) => {
826                arr.borrow_mut().push(value);
827                Ok(())
828            }
829
830            _ => Err("Cannot push to non-array".to_string()),
831        }
832    }
833
834    pub fn array_pop(&self) -> Result<Option<Value>, String> {
835        match self {
836            Value::Array(arr) => Ok(arr.borrow_mut().pop()),
837            _ => Err("Cannot pop from non-array".to_string()),
838        }
839    }
840
841    pub fn as_map(&self) -> Option<LustMap> {
842        match self {
843            Value::Map(map) => Some(map.borrow().clone()),
844            _ => None,
845        }
846    }
847
848    pub fn map_get(&self, key: &ValueKey) -> Option<Value> {
849        match self {
850            Value::Map(map) => map.borrow().get(key).cloned(),
851            _ => None,
852        }
853    }
854
855    pub fn map_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
856        match self {
857            Value::Map(map) => {
858                map.borrow_mut().insert(key, value);
859                Ok(())
860            }
861
862            _ => Err("Cannot set key on non-map".to_string()),
863        }
864    }
865
866    pub fn map_has(&self, key: &ValueKey) -> Option<bool> {
867        match self {
868            Value::Map(map) => Some(map.borrow().contains_key(key)),
869            _ => None,
870        }
871    }
872
873    pub fn map_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
874        match self {
875            Value::Map(map) => Ok(map.borrow_mut().remove(key)),
876            _ => Err("Cannot delete key from non-map".to_string()),
877        }
878    }
879
880    pub fn map_len(&self) -> Option<usize> {
881        match self {
882            Value::Map(map) => Some(map.borrow().len()),
883            _ => None,
884        }
885    }
886
887    pub fn string(s: impl Into<String>) -> Self {
888        Value::String(Rc::new(s.into()))
889    }
890
891    pub fn array(values: Vec<Value>) -> Self {
892        Value::Array(Rc::new(RefCell::new(values)))
893    }
894
895    pub fn tuple(values: Vec<Value>) -> Self {
896        Value::Tuple(Rc::new(values))
897    }
898
899    pub fn tuple_len(&self) -> Option<usize> {
900        match self {
901            Value::Tuple(values) => Some(values.len()),
902            _ => None,
903        }
904    }
905
906    pub fn tuple_get(&self, index: usize) -> Option<Value> {
907        match self {
908            Value::Tuple(values) => values.get(index).cloned(),
909            _ => None,
910        }
911    }
912
913    pub fn map(entries: LustMap) -> Self {
914        Value::Map(Rc::new(RefCell::new(entries)))
915    }
916
917    pub fn task(handle: TaskHandle) -> Self {
918        Value::Task(handle)
919    }
920
921    pub fn struct_get_field_rc(&self, field: &Rc<String>) -> Option<Value> {
922        match self {
923            Value::Struct { layout, fields, .. } => layout
924                .index_of_rc(field)
925                .or_else(|| layout.index_of_str(field.as_str()))
926                .or_else(|| {
927                    layout
928                        .field_names()
929                        .iter()
930                        .position(|name| name.as_str() == field.as_str())
931                })
932                .and_then(|idx| {
933                    fields
934                        .borrow()
935                        .get(idx)
936                        .cloned()
937                        .map(|value| layout.materialize_field_value(idx, value))
938                }),
939            _ => None,
940        }
941    }
942
943    pub fn struct_get_field(&self, field: &str) -> Option<Value> {
944        match self {
945            Value::Struct { layout, fields, .. } => layout.index_of_str(field).and_then(|idx| {
946                fields
947                    .borrow()
948                    .get(idx)
949                    .cloned()
950                    .map(|value| layout.materialize_field_value(idx, value))
951            }),
952            _ => None,
953        }
954    }
955
956    pub fn struct_get_field_indexed(&self, index: usize) -> Option<Value> {
957        match self {
958            Value::Struct { layout, fields, .. } => fields
959                .borrow()
960                .get(index)
961                .cloned()
962                .map(|value| layout.materialize_field_value(index, value)),
963            _ => None,
964        }
965    }
966
967    pub fn struct_set_field_rc(&self, field: &Rc<String>, value: Value) -> Result<(), String> {
968        match self {
969            Value::Struct { layout, .. } => {
970                if let Some(index) = layout
971                    .index_of_rc(field)
972                    .or_else(|| layout.index_of_str(field.as_str()))
973                {
974                    self.struct_set_field_indexed(index, value)
975                } else {
976                    Err(format!(
977                        "Struct '{}' has no field '{}'",
978                        layout.name(),
979                        field.as_str()
980                    ))
981                }
982            }
983
984            _ => Err("Attempted to set field on non-struct value".to_string()),
985        }
986    }
987
988    pub fn struct_set_field(&self, field: &str, value: Value) -> Result<(), String> {
989        match self {
990            Value::Struct { layout, .. } => {
991                if let Some(index) = layout.index_of_str(field) {
992                    self.struct_set_field_indexed(index, value)
993                } else {
994                    Err(format!(
995                        "Struct '{}' has no field '{}'",
996                        layout.name(),
997                        field
998                    ))
999                }
1000            }
1001
1002            _ => Err("Attempted to set field on non-struct value".to_string()),
1003        }
1004    }
1005
1006    pub fn struct_set_field_indexed(&self, index: usize, value: Value) -> Result<(), String> {
1007        match self {
1008            Value::Struct {
1009                name,
1010                layout,
1011                fields,
1012            } => {
1013                let mut borrowed = fields.borrow_mut();
1014                if index < borrowed.len() {
1015                    let canonical = layout.canonicalize_field_value(index, value)?;
1016                    borrowed[index] = canonical;
1017                    Ok(())
1018                } else {
1019                    Err(format!(
1020                        "Struct '{}' field index {} out of bounds (len {})",
1021                        name,
1022                        index,
1023                        borrowed.len()
1024                    ))
1025                }
1026            }
1027
1028            _ => Err("Attempted to set field on non-struct value".to_string()),
1029        }
1030    }
1031
1032    pub fn enum_unit(enum_name: impl Into<String>, variant: impl Into<String>) -> Self {
1033        Value::Enum {
1034            enum_name: enum_name.into(),
1035            variant: variant.into(),
1036            values: None,
1037        }
1038    }
1039
1040    pub fn enum_variant(
1041        enum_name: impl Into<String>,
1042        variant: impl Into<String>,
1043        values: Vec<Value>,
1044    ) -> Self {
1045        Value::Enum {
1046            enum_name: enum_name.into(),
1047            variant: variant.into(),
1048            values: Some(Rc::new(values)),
1049        }
1050    }
1051
1052    pub fn as_enum(&self) -> Option<(&str, &str, Option<&[Value]>)> {
1053        match self {
1054            Value::Enum {
1055                enum_name,
1056                variant,
1057                values,
1058            } => Some((
1059                enum_name.as_str(),
1060                variant.as_str(),
1061                values.as_ref().map(|v| v.as_slice()),
1062            )),
1063            _ => None,
1064        }
1065    }
1066
1067    pub fn is_enum_variant(&self, enum_name: &str, variant: &str) -> bool {
1068        match self {
1069            Value::Enum {
1070                enum_name: en,
1071                variant: v,
1072                ..
1073            } => (enum_name.is_empty() || en == enum_name) && v == variant,
1074            _ => false,
1075        }
1076    }
1077
1078    pub fn some(value: Value) -> Self {
1079        Value::enum_variant("Option", "Some", vec![value])
1080    }
1081
1082    pub fn none() -> Self {
1083        Value::enum_unit("Option", "None")
1084    }
1085
1086    pub fn ok(value: Value) -> Self {
1087        Value::enum_variant("Result", "Ok", vec![value])
1088    }
1089
1090    pub fn err(error: Value) -> Self {
1091        Value::enum_variant("Result", "Err", vec![error])
1092    }
1093
1094    pub fn to_string(&self) -> String {
1095        format!("{}", self)
1096    }
1097}
1098
1099impl fmt::Debug for Value {
1100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1101        match self {
1102            Value::Nil => write!(f, "Nil"),
1103            Value::Bool(b) => write!(f, "Bool({})", b),
1104            Value::Int(i) => write!(f, "Int({})", i),
1105            Value::Float(fl) => write!(f, "Float({})", fl),
1106            Value::String(s) => write!(f, "String({:?})", s),
1107            Value::Array(arr) => write!(f, "Array({:?})", arr.borrow()),
1108            Value::Tuple(values) => write!(f, "Tuple({:?})", values),
1109            Value::Map(map) => write!(f, "Map({:?})", map.borrow()),
1110            Value::Struct {
1111                name,
1112                layout,
1113                fields,
1114            } => {
1115                let borrowed = fields.borrow();
1116                let mut display_fields = Vec::with_capacity(borrowed.len());
1117                for (idx, field_name) in layout.field_names().iter().enumerate() {
1118                    let value = borrowed.get(idx).cloned().unwrap_or(Value::Nil);
1119                    display_fields.push((field_name.as_str().to_string(), value));
1120                }
1121
1122                write!(
1123                    f,
1124                    "Struct {{ name: {:?}, fields: {:?} }}",
1125                    name, display_fields
1126                )
1127            }
1128
1129            Value::WeakStruct(weak) => {
1130                if let Some(upgraded) = weak.upgrade() {
1131                    write!(f, "WeakStruct({:?})", upgraded)
1132                } else {
1133                    write!(f, "WeakStruct(<dangling>)")
1134                }
1135            }
1136
1137            Value::Enum {
1138                enum_name,
1139                variant,
1140                values,
1141            } => {
1142                write!(
1143                    f,
1144                    "Enum {{ enum: {:?}, variant: {:?}, values: {:?} }}",
1145                    enum_name, variant, values
1146                )
1147            }
1148
1149            Value::Function(idx) => write!(f, "Function({})", idx),
1150            Value::NativeFunction(_) => write!(f, "NativeFunction(<fn>)"),
1151            Value::Closure {
1152                function_idx,
1153                upvalues,
1154            } => {
1155                write!(
1156                    f,
1157                    "Closure {{ function: {}, upvalues: {:?} }}",
1158                    function_idx, upvalues
1159                )
1160            }
1161
1162            Value::Iterator(_) => write!(f, "Iterator(<state>)"),
1163            Value::Task(handle) => write!(f, "Task({})", handle.0),
1164        }
1165    }
1166}
1167
1168impl fmt::Display for Value {
1169    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1170        match self {
1171            Value::Nil => write!(f, "nil"),
1172            Value::Bool(b) => write!(f, "{}", b),
1173            Value::Int(i) => write!(f, "{}", i),
1174            Value::Float(fl) => write!(f, "{}", fl),
1175            Value::String(s) => write!(f, "{}", s),
1176            Value::Array(arr) => {
1177                write!(f, "[")?;
1178                let borrowed = arr.borrow();
1179                for (i, val) in borrowed.iter().enumerate() {
1180                    if i > 0 {
1181                        write!(f, ", ")?;
1182                    }
1183
1184                    write!(f, "{}", val)?;
1185                }
1186
1187                write!(f, "]")
1188            }
1189
1190            Value::Tuple(values) => {
1191                write!(f, "(")?;
1192                for (i, val) in values.iter().enumerate() {
1193                    if i > 0 {
1194                        write!(f, ", ")?;
1195                    }
1196
1197                    write!(f, "{}", val)?;
1198                }
1199
1200                write!(f, ")")
1201            }
1202
1203            Value::Map(map) => {
1204                write!(f, "{{")?;
1205                let borrowed = map.borrow();
1206                for (i, (k, v)) in borrowed.iter().enumerate() {
1207                    if i > 0 {
1208                        write!(f, ", ")?;
1209                    }
1210
1211                    write!(f, "{}: {}", k, v)?;
1212                }
1213
1214                write!(f, "}}")
1215            }
1216
1217            Value::Struct {
1218                name,
1219                layout,
1220                fields,
1221            } => {
1222                let borrowed = fields.borrow();
1223                write!(f, "{} {{", name)?;
1224                for (i, field_name) in layout.field_names().iter().enumerate() {
1225                    if i > 0 {
1226                        write!(f, ", ")?;
1227                    }
1228
1229                    let value = borrowed.get(i).unwrap_or(&Value::Nil);
1230                    write!(f, "{}: {}", field_name, value)?;
1231                }
1232
1233                write!(f, "}}")
1234            }
1235
1236            Value::WeakStruct(weak) => {
1237                if let Some(strong) = weak.upgrade() {
1238                    strong.fmt(f)
1239                } else {
1240                    write!(f, "nil")
1241                }
1242            }
1243
1244            Value::Enum {
1245                enum_name,
1246                variant,
1247                values,
1248            } => {
1249                write!(f, "{}.{}", enum_name, variant)?;
1250                if let Some(vals) = values {
1251                    write!(f, "(")?;
1252                    for (i, val) in vals.iter().enumerate() {
1253                        if i > 0 {
1254                            write!(f, ", ")?;
1255                        }
1256
1257                        write!(f, "{}", val)?;
1258                    }
1259
1260                    write!(f, ")")?;
1261                }
1262
1263                Ok(())
1264            }
1265
1266            Value::Function(idx) => write!(f, "<function@{}>", idx),
1267            Value::NativeFunction(_) => write!(f, "<native function>"),
1268            Value::Closure { function_idx, .. } => write!(f, "<closure@{}>", function_idx),
1269            Value::Iterator(_) => write!(f, "<iterator>"),
1270            Value::Task(handle) => write!(f, "<task {}>", handle.0),
1271        }
1272    }
1273}
1274
1275impl PartialEq for Value {
1276    fn eq(&self, other: &Self) -> bool {
1277        match (self, other) {
1278            (Value::Nil, Value::Nil) => true,
1279            (Value::Bool(a), Value::Bool(b)) => a == b,
1280            (Value::Int(a), Value::Int(b)) => a == b,
1281            (Value::Float(a), Value::Float(b)) => a == b,
1282            (Value::String(a), Value::String(b)) => a == b,
1283            (Value::Array(a), Value::Array(b)) => *a.borrow() == *b.borrow(),
1284            (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
1285            (Value::Map(a), Value::Map(b)) => *a.borrow() == *b.borrow(),
1286            (
1287                Value::Struct {
1288                    name: n1,
1289                    layout: l1,
1290                    fields: f1,
1291                },
1292                Value::Struct {
1293                    name: n2,
1294                    layout: l2,
1295                    fields: f2,
1296                },
1297            ) => {
1298                if n1 != n2 {
1299                    return false;
1300                }
1301
1302                let borrowed_f1 = f1.borrow();
1303                let borrowed_f2 = f2.borrow();
1304                if borrowed_f1.len() != borrowed_f2.len() {
1305                    return false;
1306                }
1307
1308                if Rc::ptr_eq(l1, l2) {
1309                    return borrowed_f1
1310                        .iter()
1311                        .zip(borrowed_f2.iter())
1312                        .all(|(a, b)| a == b);
1313                }
1314
1315                l1.field_names()
1316                    .iter()
1317                    .enumerate()
1318                    .all(|(idx, field_name)| {
1319                        if let Some(other_idx) = l2.index_of_rc(field_name) {
1320                            borrowed_f1
1321                                .get(idx)
1322                                .zip(borrowed_f2.get(other_idx))
1323                                .map(|(a, b)| a == b)
1324                                .unwrap_or(false)
1325                        } else {
1326                            false
1327                        }
1328                    })
1329            }
1330
1331            (Value::WeakStruct(a), Value::WeakStruct(b)) => match (a.upgrade(), b.upgrade()) {
1332                (Some(left), Some(right)) => left == right,
1333                (None, None) => true,
1334                _ => false,
1335            },
1336            (Value::WeakStruct(a), other) => a
1337                .upgrade()
1338                .map(|upgraded| upgraded == *other)
1339                .unwrap_or(matches!(other, Value::Nil)),
1340            (value, Value::WeakStruct(b)) => b
1341                .upgrade()
1342                .map(|upgraded| *value == upgraded)
1343                .unwrap_or(matches!(value, Value::Nil)),
1344            (
1345                Value::Enum {
1346                    enum_name: e1,
1347                    variant: v1,
1348                    values: vals1,
1349                },
1350                Value::Enum {
1351                    enum_name: e2,
1352                    variant: v2,
1353                    values: vals2,
1354                },
1355            ) => e1 == e2 && v1 == v2 && vals1 == vals2,
1356            (Value::Function(a), Value::Function(b)) => a == b,
1357            (
1358                Value::Closure {
1359                    function_idx: f1,
1360                    upvalues: u1,
1361                },
1362                Value::Closure {
1363                    function_idx: f2,
1364                    upvalues: u2,
1365                },
1366            ) => f1 == f2 && Rc::ptr_eq(u1, u2),
1367            (Value::Iterator(_), Value::Iterator(_)) => false,
1368            (Value::Task(a), Value::Task(b)) => a == b,
1369            _ => false,
1370        }
1371    }
1372}
1373
1374#[cfg(feature = "std")]
1375#[no_mangle]
1376pub unsafe extern "C" fn jit_array_get_safe(
1377    array_value_ptr: *const Value,
1378    index: i64,
1379    out: *mut Value,
1380) -> u8 {
1381    if array_value_ptr.is_null() || out.is_null() {
1382        eprintln!("❌ jit_array_get_safe: null pointer detected!");
1383        return 0;
1384    }
1385
1386    let array_value = &*array_value_ptr;
1387    let arr = match array_value {
1388        Value::Array(arr) => arr,
1389        _ => {
1390            return 0;
1391        }
1392    };
1393    if index < 0 {
1394        return 0;
1395    }
1396
1397    let idx = index as usize;
1398    let borrowed = match arr.try_borrow() {
1399        Ok(b) => b,
1400        Err(_) => {
1401            return 0;
1402        }
1403    };
1404    if idx >= borrowed.len() {
1405        return 0;
1406    }
1407
1408    ptr::write(out, borrowed[idx].clone());
1409    1
1410}
1411
1412#[cfg(feature = "std")]
1413#[no_mangle]
1414pub unsafe extern "C" fn jit_array_len_safe(array_value_ptr: *const Value) -> i64 {
1415    if array_value_ptr.is_null() {
1416        return -1;
1417    }
1418
1419    let array_value = &*array_value_ptr;
1420    match array_value {
1421        Value::Array(arr) => match arr.try_borrow() {
1422            Ok(borrowed) => int_from_usize(borrowed.len()),
1423            Err(_) => -1,
1424        },
1425        _ => -1,
1426    }
1427}
1428
1429#[cfg(feature = "std")]
1430static JIT_NEW_ARRAY_COUNTER: core::sync::atomic::AtomicUsize =
1431    core::sync::atomic::AtomicUsize::new(0);
1432
1433#[cfg(feature = "std")]
1434#[no_mangle]
1435pub unsafe extern "C" fn jit_new_array_safe(
1436    elements_ptr: *const Value,
1437    element_count: usize,
1438    out_ptr: *mut Value,
1439) -> u8 {
1440    let _call_num = JIT_NEW_ARRAY_COUNTER.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
1441    // jit::log(|| format!("jit_new_array_safe call #{}: ENTER - elements_ptr={:?}, count={}, out_ptr={:?}", call_num, elements_ptr, element_count, out_ptr));
1442
1443    if out_ptr.is_null() {
1444        // jit::log(|| "jit_new_array_safe: out_ptr is null".to_string());
1445        return 0;
1446    }
1447
1448    // jit::log(|| format!("jit_new_array_safe #{}: about to create Vec", call_num));
1449    let elements = if element_count == 0 {
1450        Vec::new()
1451    } else {
1452        if elements_ptr.is_null() {
1453            // jit::log(|| "jit_new_array_safe: elements_ptr is null but count > 0".to_string());
1454            return 0;
1455        }
1456
1457        let slice = slice::from_raw_parts(elements_ptr, element_count);
1458        slice.to_vec()
1459    };
1460
1461    // jit::log(|| format!("jit_new_array_safe #{}: about to call Value::array with {} elements", call_num, elements.len()));
1462    let array_value = Value::array(elements);
1463    // jit::log(|| format!("jit_new_array_safe #{}: about to write to out_ptr", call_num));
1464    ptr::write(out_ptr, array_value);
1465    // jit::log(|| format!("jit_new_array_safe #{}: EXIT - success, returning 1", call_num));
1466    1
1467}
1468
1469#[cfg(feature = "std")]
1470#[no_mangle]
1471pub unsafe extern "C" fn jit_array_push_safe(
1472    array_ptr: *const Value,
1473    value_ptr: *const Value,
1474) -> u8 {
1475    if array_ptr.is_null() || value_ptr.is_null() {
1476        return 0;
1477    }
1478
1479    let array_value = &*array_ptr;
1480    let value = &*value_ptr;
1481
1482    match array_value {
1483        Value::Array(arr) => {
1484            // Use unchecked borrow for maximum performance
1485            let cell_ptr = arr.as_ptr();
1486            (*cell_ptr).push(value.clone());
1487            1
1488        }
1489        _ => 0,
1490    }
1491}
1492
1493/// Unbox Array<int> from Value to Vec<LustInt> for specialized JIT operations
1494/// IMPORTANT: This takes ownership of the array's data. The original Vec<Value> is emptied.
1495/// Returns 1 on success, 0 on failure
1496/// Outputs: vec_ptr (pointer to data), vec_len, vec_cap
1497#[cfg(feature = "std")]
1498#[no_mangle]
1499pub unsafe extern "C" fn jit_unbox_array_int(
1500    array_value_ptr: *const Value,
1501    out_vec_ptr: *mut *mut LustInt,
1502    out_len: *mut usize,
1503    out_cap: *mut usize,
1504) -> u8 {
1505    if array_value_ptr.is_null() || out_vec_ptr.is_null() || out_len.is_null() || out_cap.is_null()
1506    {
1507        return 0;
1508    }
1509
1510    let array_value = &*array_value_ptr;
1511    match array_value {
1512        Value::Array(arr_rc) => {
1513            // Get exclusive access to the inner vector
1514            let cell_ptr = arr_rc.as_ptr();
1515            let vec_ref = &mut *cell_ptr;
1516
1517            // Take ownership of the Vec<Value> by swapping with empty vec
1518            let original_vec = core::mem::replace(vec_ref, Vec::new());
1519
1520            // Convert Vec<Value> to Vec<LustInt>
1521            let mut specialized_vec: Vec<LustInt> = Vec::with_capacity(original_vec.len());
1522            for elem in original_vec.into_iter() {
1523                match elem {
1524                    Value::Int(i) => specialized_vec.push(i),
1525                    _ => {
1526                        // Type mismatch - restore original data and fail
1527                        // This shouldn't happen if types are correct, but be safe
1528                        return 0;
1529                    }
1530                }
1531            }
1532
1533            // Extract Vec metadata
1534            let len = specialized_vec.len();
1535            let cap = specialized_vec.capacity();
1536            let ptr = specialized_vec.as_mut_ptr();
1537
1538            // Prevent Vec from being dropped
1539            core::mem::forget(specialized_vec);
1540
1541            // Write outputs
1542            ptr::write(out_vec_ptr, ptr);
1543            ptr::write(out_len, len);
1544            ptr::write(out_cap, cap);
1545
1546            // Note: The original Rc<RefCell<Vec<Value>>> now contains an empty Vec
1547            // This is fine - when we rebox, we'll refill it
1548
1549            1
1550        }
1551        _ => 0,
1552    }
1553}
1554
1555/// Rebox Vec<LustInt> back to Array Value
1556/// IMPORTANT: Writes the specialized vec data back into the EXISTING Rc<RefCell<Vec<Value>>>
1557/// This ensures the original array is updated, not replaced
1558#[cfg(feature = "std")]
1559#[no_mangle]
1560pub unsafe extern "C" fn jit_rebox_array_int(
1561    vec_ptr: *mut LustInt,
1562    vec_len: usize,
1563    vec_cap: usize,
1564    array_value_ptr: *mut Value,
1565) -> u8 {
1566    if vec_ptr.is_null() || array_value_ptr.is_null() {
1567        return 0;
1568    }
1569
1570    // Reconstruct Vec<LustInt> from raw parts
1571    let specialized_vec = Vec::from_raw_parts(vec_ptr, vec_len, vec_cap);
1572
1573    // Get the existing Array value
1574    let array_value = &mut *array_value_ptr;
1575    match array_value {
1576        Value::Array(arr_rc) => {
1577            // Get exclusive access to the inner vector (should be empty from unbox)
1578            let cell_ptr = arr_rc.as_ptr();
1579            let vec_ref = &mut *cell_ptr;
1580
1581            // Convert Vec<LustInt> back to Vec<Value> and write into the existing RefCell
1582            *vec_ref = specialized_vec.into_iter().map(Value::Int).collect();
1583
1584            1
1585        }
1586        _ => {
1587            // This shouldn't happen - the register should still contain the Array
1588            // But if it doesn't, create a new array
1589            let value_vec: Vec<Value> = specialized_vec.into_iter().map(Value::Int).collect();
1590            let array_value_new = Value::array(value_vec);
1591            ptr::write(array_value_ptr, array_value_new);
1592            1
1593        }
1594    }
1595}
1596
1597/// Specialized push operation for Vec<LustInt>
1598/// Directly pushes LustInt to the specialized vector
1599#[cfg(feature = "std")]
1600#[no_mangle]
1601pub unsafe extern "C" fn jit_vec_int_push(
1602    vec_ptr: *mut *mut LustInt,
1603    vec_len: *mut usize,
1604    vec_cap: *mut usize,
1605    value: LustInt,
1606) -> u8 {
1607    if vec_ptr.is_null() || vec_len.is_null() || vec_cap.is_null() {
1608        return 0;
1609    }
1610
1611    let ptr = *vec_ptr;
1612    let len = *vec_len;
1613    let cap = *vec_cap;
1614
1615    // Reconstruct Vec temporarily
1616    let mut vec = Vec::from_raw_parts(ptr, len, cap);
1617
1618    // Push the value
1619    vec.push(value);
1620
1621    // Extract new metadata
1622    let new_len = vec.len();
1623    let new_cap = vec.capacity();
1624    let new_ptr = vec.as_mut_ptr();
1625
1626    // Prevent drop
1627    core::mem::forget(vec);
1628
1629    // Update outputs
1630    ptr::write(vec_ptr, new_ptr);
1631    ptr::write(vec_len, new_len);
1632    ptr::write(vec_cap, new_cap);
1633
1634    1
1635}
1636
1637/// Drop a specialized Vec<LustInt> (cleanup for leaked specializations)
1638/// WARNING: This should NOT be called! Specialized values that get invalidated
1639/// during loop recording don't actually exist on the stack during execution.
1640#[cfg(feature = "std")]
1641#[no_mangle]
1642pub unsafe extern "C" fn jit_drop_vec_int(vec_ptr: *mut LustInt, vec_len: usize, vec_cap: usize) {
1643    eprintln!(
1644        "🗑️  jit_drop_vec_int: ptr={:p}, len={}, cap={}",
1645        vec_ptr, vec_len, vec_cap
1646    );
1647    eprintln!("🗑️  jit_drop_vec_int: THIS SHOULD NOT BE CALLED - THE VEC DATA IS STALE!");
1648
1649    // DO NOT drop - the Vec data on the stack is stale from trace recording
1650    // The actual arrays are managed by their Rc<RefCell<>> wrappers
1651    eprintln!("🗑️  jit_drop_vec_int: skipping drop (would cause corruption)");
1652}
1653
1654#[cfg(feature = "std")]
1655#[no_mangle]
1656pub unsafe extern "C" fn jit_enum_is_some_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1657    if enum_ptr.is_null() || out_ptr.is_null() {
1658        return 0;
1659    }
1660
1661    let enum_value = &*enum_ptr;
1662    match enum_value {
1663        Value::Enum { variant, .. } => {
1664            let is_some = variant == "Some";
1665            ptr::write(out_ptr, Value::Bool(is_some));
1666            1
1667        }
1668        _ => 0,
1669    }
1670}
1671
1672#[cfg(feature = "std")]
1673#[no_mangle]
1674pub unsafe extern "C" fn jit_enum_unwrap_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1675    if enum_ptr.is_null() || out_ptr.is_null() {
1676        return 0;
1677    }
1678
1679    let enum_value = &*enum_ptr;
1680    match enum_value {
1681        Value::Enum {
1682            values: Some(vals), ..
1683        } if vals.len() == 1 => {
1684            ptr::write(out_ptr, vals[0].clone());
1685            1
1686        }
1687        _ => 0,
1688    }
1689}
1690
1691#[cfg(feature = "std")]
1692#[no_mangle]
1693pub unsafe extern "C" fn jit_set_field_strong_safe(
1694    object_ptr: *const Value,
1695    field_index: usize,
1696    value_ptr: *const Value,
1697) -> u8 {
1698    if object_ptr.is_null() || value_ptr.is_null() {
1699        return 0;
1700    }
1701
1702    let object = &*object_ptr;
1703    let value = (&*value_ptr).clone();
1704
1705    match object {
1706        Value::Struct { fields, .. } => {
1707            // Skip canonicalization for strong fields - just set directly
1708            match fields.try_borrow_mut() {
1709                Ok(mut borrowed) => {
1710                    if field_index < borrowed.len() {
1711                        borrowed[field_index] = value;
1712                        1
1713                    } else {
1714                        0
1715                    }
1716                }
1717                Err(_) => 0,
1718            }
1719        }
1720        _ => 0,
1721    }
1722}
1723
1724#[cfg(feature = "std")]
1725#[no_mangle]
1726pub unsafe extern "C" fn jit_concat_safe(
1727    left_value_ptr: *const Value,
1728    right_value_ptr: *const Value,
1729    out: *mut Value,
1730) -> u8 {
1731    if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1732        return 0;
1733    }
1734
1735    let left = &*left_value_ptr;
1736    let right = &*right_value_ptr;
1737    const NO_VM_ERROR: &str = "task API requires a running VM";
1738    let left_str = match VM::with_current(|vm| {
1739        let left_copy = left.clone();
1740        vm.value_to_string_for_concat(&left_copy)
1741            .map_err(|err| err.to_string())
1742    }) {
1743        Ok(rc) => rc,
1744        Err(err) if err == NO_VM_ERROR => Rc::new(left.to_string()),
1745        Err(_) => return 0,
1746    };
1747    let right_str = match VM::with_current(|vm| {
1748        let right_copy = right.clone();
1749        vm.value_to_string_for_concat(&right_copy)
1750            .map_err(|err| err.to_string())
1751    }) {
1752        Ok(rc) => rc,
1753        Err(err) if err == NO_VM_ERROR => Rc::new(right.to_string()),
1754        Err(_) => return 0,
1755    };
1756    let mut combined = String::with_capacity(left_str.len() + right_str.len());
1757    combined.push_str(left_str.as_ref());
1758    combined.push_str(right_str.as_ref());
1759    let result = Value::string(combined);
1760    ptr::write(out, result);
1761    1
1762}
1763
1764#[no_mangle]
1765pub unsafe extern "C" fn jit_guard_native_function(
1766    value_ptr: *const Value,
1767    expected_fn_ptr: *const (),
1768    register_index: u8,
1769) -> u8 {
1770    if value_ptr.is_null() || expected_fn_ptr.is_null() {
1771        jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1772        return 0;
1773    }
1774
1775    match &*value_ptr {
1776        Value::NativeFunction(func) => {
1777            let actual = Rc::as_ptr(func) as *const ();
1778            if actual == expected_fn_ptr {
1779                1
1780            } else {
1781                jit::log(|| {
1782                    format!(
1783                        "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1784                        register_index, actual, expected_fn_ptr
1785                    )
1786                });
1787                0
1788            }
1789        }
1790
1791        other => {
1792            jit::log(|| {
1793                format!(
1794                    "jit_guard_native_function: value not native in reg {} ({:?})",
1795                    register_index,
1796                    other.tag()
1797                )
1798            });
1799            0
1800        }
1801    }
1802}
1803
1804#[no_mangle]
1805pub unsafe extern "C" fn jit_guard_function_identity(
1806    value_ptr: *const Value,
1807    expected_kind: u8,
1808    expected_function_idx: usize,
1809    expected_upvalues: *const (),
1810    register_index: u8,
1811) -> u8 {
1812    if value_ptr.is_null() {
1813        jit::log(|| "jit_guard_function_identity: null pointer input".to_string());
1814        return 0;
1815    }
1816
1817    let value = &*value_ptr;
1818    match (expected_kind, value) {
1819        (0, Value::Function(idx)) => {
1820            if *idx == expected_function_idx {
1821                1
1822            } else {
1823                jit::log(|| {
1824                    format!(
1825                        "jit_guard_function_identity: function idx mismatch (reg {}) actual={} expected={}",
1826                        register_index, idx, expected_function_idx
1827                    )
1828                });
1829                0
1830            }
1831        }
1832
1833        (
1834            1,
1835            Value::Closure {
1836                function_idx,
1837                upvalues,
1838            },
1839        ) => {
1840            if *function_idx != expected_function_idx {
1841                jit::log(|| {
1842                    format!(
1843                        "jit_guard_function_identity: closure idx mismatch (reg {}) actual={} expected={}",
1844                        register_index, function_idx, expected_function_idx
1845                    )
1846                });
1847                return 0;
1848            }
1849
1850            let actual_ptr = Rc::as_ptr(upvalues) as *const ();
1851            if actual_ptr == expected_upvalues {
1852                1
1853            } else {
1854                jit::log(|| {
1855                    format!(
1856                        "jit_guard_function_identity: upvalues mismatch (reg {}) actual={:p} expected={:p}",
1857                        register_index, actual_ptr, expected_upvalues
1858                    )
1859                });
1860                0
1861            }
1862        }
1863
1864        (0, Value::Closure { function_idx, .. }) => {
1865            jit::log(|| {
1866                format!(
1867                    "jit_guard_function_identity: expected function, saw closure (reg {}, idx {})",
1868                    register_index, function_idx
1869                )
1870            });
1871            0
1872        }
1873
1874        (1, Value::Function(idx)) => {
1875            jit::log(|| {
1876                format!(
1877                    "jit_guard_function_identity: expected closure, saw function (reg {}, idx {})",
1878                    register_index, idx
1879                )
1880            });
1881            0
1882        }
1883
1884        (_, other) => {
1885            jit::log(|| {
1886                format!(
1887                    "jit_guard_function_identity: value in reg {} not callable ({:?})",
1888                    register_index,
1889                    other.tag()
1890                )
1891            });
1892            0
1893        }
1894    }
1895}
1896
1897#[no_mangle]
1898pub unsafe extern "C" fn jit_call_native_safe(
1899    vm_ptr: *mut VM,
1900    callee_ptr: *const Value,
1901    expected_fn_ptr: *const (),
1902    args_ptr: *const Value,
1903    arg_count: u8,
1904    out: *mut Value,
1905) -> u8 {
1906    if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1907        jit::log(|| "jit_call_native_safe: null argument".to_string());
1908        return 0;
1909    }
1910
1911    let callee = &*callee_ptr;
1912    let native_fn = match callee {
1913        Value::NativeFunction(func) => func.clone(),
1914        other => {
1915            jit::log(|| {
1916                format!(
1917                    "jit_call_native_safe: callee not native ({:?})",
1918                    other.tag()
1919                )
1920            });
1921            return 0;
1922        }
1923    };
1924
1925    if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1926        jit::log(|| {
1927            format!(
1928                "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1929                Rc::as_ptr(&native_fn),
1930                expected_fn_ptr
1931            )
1932        });
1933        return 0;
1934    }
1935
1936    let mut args = Vec::with_capacity(arg_count as usize);
1937    if arg_count > 0 {
1938        if args_ptr.is_null() {
1939            jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1940            return 0;
1941        }
1942
1943        for i in 0..(arg_count as usize) {
1944            let arg = &*args_ptr.add(i);
1945            args.push(arg.clone());
1946        }
1947    }
1948
1949    push_vm_ptr(vm_ptr);
1950    let outcome = native_fn(&args);
1951    pop_vm_ptr();
1952
1953    let outcome = match outcome {
1954        Ok(result) => result,
1955        Err(err) => {
1956            jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1957            return 0;
1958        }
1959    };
1960
1961    match outcome {
1962        NativeCallResult::Return(value) => {
1963            ptr::write(out, value);
1964            1
1965        }
1966
1967        NativeCallResult::Yield(_) => {
1968            jit::log(|| "jit_call_native_safe: native attempted to yield".to_string());
1969            0
1970        }
1971
1972        NativeCallResult::Stop(_) => {
1973            jit::log(|| "jit_call_native_safe: native attempted to stop".to_string());
1974            0
1975        }
1976    }
1977}
1978
1979#[no_mangle]
1980pub unsafe extern "C" fn jit_call_function_safe(
1981    vm_ptr: *mut VM,
1982    callee_ptr: *const Value,
1983    args_ptr: *const Value,
1984    arg_count: u8,
1985    dest_reg: u8,
1986) -> u8 {
1987    if vm_ptr.is_null() || callee_ptr.is_null() {
1988        jit::log(|| "jit_call_function_safe: null argument".to_string());
1989        return 0;
1990    }
1991
1992    if arg_count > 0 && args_ptr.is_null() {
1993        jit::log(|| "jit_call_function_safe: args_ptr null with non-zero arg_count".to_string());
1994        return 0;
1995    }
1996
1997    // Clone the callee BEFORE any operations that might reallocate registers
1998    let callee = (&*callee_ptr).clone();
1999    let mut args = Vec::with_capacity(arg_count as usize);
2000    for i in 0..(arg_count as usize) {
2001        let arg_ptr = args_ptr.add(i);
2002        args.push((&*arg_ptr).clone());
2003    }
2004
2005    let vm = &mut *vm_ptr;
2006    push_vm_ptr(vm_ptr);
2007
2008    // Temporarily disable JIT to prevent recursive JIT execution
2009    let jit_was_enabled = vm.jit.enabled;
2010    vm.jit.enabled = false;
2011
2012    let call_result = vm.call_value(&callee, args);
2013
2014    // Restore JIT state
2015    vm.jit.enabled = jit_was_enabled;
2016    pop_vm_ptr();
2017
2018    match call_result {
2019        Ok(value) => {
2020            // Get current registers pointer AFTER the call (it may have reallocated)
2021            let vm = &mut *vm_ptr;
2022            if let Some(frame) = vm.call_stack.last_mut() {
2023                if (dest_reg as usize) < frame.registers.len() {
2024                    frame.registers[dest_reg as usize] = value;
2025                    1
2026                } else {
2027                    jit::log(|| {
2028                        format!(
2029                            "jit_call_function_safe: dest_reg {} out of bounds",
2030                            dest_reg
2031                        )
2032                    });
2033                    0
2034                }
2035            } else {
2036                jit::log(|| "jit_call_function_safe: no call frame".to_string());
2037                0
2038            }
2039        }
2040
2041        Err(err) => {
2042            jit::log(|| format!("jit_call_function_safe: {}", err));
2043            0
2044        }
2045    }
2046}
2047
2048#[no_mangle]
2049pub unsafe extern "C" fn jit_current_registers(vm_ptr: *mut VM) -> *mut Value {
2050    if vm_ptr.is_null() {
2051        return core::ptr::null_mut();
2052    }
2053
2054    let vm = &mut *vm_ptr;
2055    vm.call_stack
2056        .last_mut()
2057        .map(|frame| frame.registers.as_mut_ptr())
2058        .unwrap_or(core::ptr::null_mut())
2059}
2060
2061#[no_mangle]
2062pub unsafe extern "C" fn jit_value_is_truthy(value_ptr: *const Value) -> u8 {
2063    if value_ptr.is_null() {
2064        return 0;
2065    }
2066
2067    let value = &*value_ptr;
2068    if value.is_truthy() {
2069        1
2070    } else {
2071        0
2072    }
2073}
2074
2075#[no_mangle]
2076pub unsafe extern "C" fn jit_new_enum_unit_safe(
2077    enum_name_ptr: *const u8,
2078    enum_name_len: usize,
2079    variant_name_ptr: *const u8,
2080    variant_name_len: usize,
2081    out: *mut Value,
2082) -> u8 {
2083    if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2084        return 0;
2085    }
2086
2087    let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2088    let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2089    let enum_name = match str::from_utf8(enum_name_slice) {
2090        Ok(s) => s.to_string(),
2091        Err(_) => return 0,
2092    };
2093    let variant_name = match str::from_utf8(variant_name_slice) {
2094        Ok(s) => s.to_string(),
2095        Err(_) => return 0,
2096    };
2097    let value = Value::enum_unit(enum_name, variant_name);
2098    ptr::write(out, value);
2099    1
2100}
2101
2102#[no_mangle]
2103pub unsafe extern "C" fn jit_new_enum_variant_safe(
2104    enum_name_ptr: *const u8,
2105    enum_name_len: usize,
2106    variant_name_ptr: *const u8,
2107    variant_name_len: usize,
2108    values_ptr: *const Value,
2109    value_count: usize,
2110    out: *mut Value,
2111) -> u8 {
2112    if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2113        return 0;
2114    }
2115
2116    if value_count > 0 && values_ptr.is_null() {
2117        return 0;
2118    }
2119
2120    let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2121    let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2122    let enum_name = match str::from_utf8(enum_name_slice) {
2123        Ok(s) => s.to_string(),
2124        Err(_) => return 0,
2125    };
2126    let variant_name = match str::from_utf8(variant_name_slice) {
2127        Ok(s) => s.to_string(),
2128        Err(_) => return 0,
2129    };
2130    let mut values = Vec::with_capacity(value_count);
2131    for i in 0..value_count {
2132        let value = &*values_ptr.add(i);
2133        values.push(value.clone());
2134    }
2135
2136    let value = Value::enum_variant(enum_name, variant_name, values);
2137    ptr::write(out, value);
2138    1
2139}
2140
2141#[no_mangle]
2142pub unsafe extern "C" fn jit_is_enum_variant_safe(
2143    value_ptr: *const Value,
2144    enum_name_ptr: *const u8,
2145    enum_name_len: usize,
2146    variant_name_ptr: *const u8,
2147    variant_name_len: usize,
2148) -> u8 {
2149    if value_ptr.is_null() || enum_name_ptr.is_null() || variant_name_ptr.is_null() {
2150        return 0;
2151    }
2152
2153    let value = &*value_ptr;
2154    let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2155    let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2156    let enum_name = match str::from_utf8(enum_name_slice) {
2157        Ok(s) => s,
2158        Err(_) => return 0,
2159    };
2160    let variant_name = match str::from_utf8(variant_name_slice) {
2161        Ok(s) => s,
2162        Err(_) => return 0,
2163    };
2164    if value.is_enum_variant(enum_name, variant_name) {
2165        1
2166    } else {
2167        0
2168    }
2169}
2170
2171#[no_mangle]
2172pub unsafe extern "C" fn jit_get_enum_value_safe(
2173    enum_ptr: *const Value,
2174    index: usize,
2175    out: *mut Value,
2176) -> u8 {
2177    if enum_ptr.is_null() || out.is_null() {
2178        return 0;
2179    }
2180
2181    let enum_value = &*enum_ptr;
2182    if let Some((_, _, Some(values))) = enum_value.as_enum() {
2183        if index < values.len() {
2184            ptr::write(out, values[index].clone());
2185            1
2186        } else {
2187            0
2188        }
2189    } else {
2190        0
2191    }
2192}
2193
2194#[no_mangle]
2195pub unsafe extern "C" fn jit_call_method_safe(
2196    vm_ptr: *mut VM,
2197    object_ptr: *const Value,
2198    method_name_ptr: *const u8,
2199    method_name_len: usize,
2200    args_ptr: *const Value,
2201    arg_count: u8,
2202    dest_reg: u8,
2203) -> u8 {
2204    if vm_ptr.is_null() || object_ptr.is_null() || method_name_ptr.is_null() {
2205        jit::log(|| "jit_call_method_safe: null pointer argument".to_string());
2206        return 0;
2207    }
2208
2209    if arg_count > 0 && args_ptr.is_null() {
2210        return 0;
2211    }
2212
2213    let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
2214    let method_name = match str::from_utf8(method_name_slice) {
2215        Ok(s) => s,
2216        Err(_) => return 0,
2217    };
2218
2219    let object = (&*object_ptr).clone();
2220    if matches!(object, Value::Struct { .. }) {
2221        return 0;
2222    }
2223
2224    let mut args = Vec::with_capacity(arg_count as usize);
2225    for i in 0..arg_count {
2226        let arg_ptr = args_ptr.add(i as usize);
2227        args.push((&*arg_ptr).clone());
2228    }
2229
2230    crate::vm::push_vm_ptr(vm_ptr);
2231    let outcome = call_builtin_method_simple(&object, method_name, args);
2232    crate::vm::pop_vm_ptr();
2233    match outcome {
2234        Ok(val) => {
2235            let vm = &mut *vm_ptr;
2236            if let Some(frame) = vm.call_stack.last_mut() {
2237                if (dest_reg as usize) < frame.registers.len() {
2238                    frame.registers[dest_reg as usize] = val;
2239                    1
2240                } else {
2241                    jit::log(|| {
2242                        format!("jit_call_method_safe: dest_reg {} out of bounds", dest_reg)
2243                    });
2244                    0
2245                }
2246            } else {
2247                jit::log(|| "jit_call_method_safe: no call frame".to_string());
2248                0
2249            }
2250        }
2251        Err(_) => 0,
2252    }
2253}
2254
2255fn call_builtin_method_simple(
2256    object: &Value,
2257    method_name: &str,
2258    args: Vec<Value>,
2259) -> Result<Value, String> {
2260    match object {
2261        Value::Struct { name, .. } => Err(format!(
2262            "User-defined methods on {} require deoptimization",
2263            name
2264        )),
2265        Value::Iterator(state_rc) => match method_name {
2266            "next" => {
2267                let mut state = state_rc.borrow_mut();
2268                match &mut *state {
2269                    IteratorState::Array { items, index } => {
2270                        if *index < items.len() {
2271                            let v = items[*index].clone();
2272                            *index += 1;
2273                            Ok(Value::some(v))
2274                        } else {
2275                            Ok(Value::none())
2276                        }
2277                    }
2278
2279                    IteratorState::MapPairs { items, index } => {
2280                        if *index < items.len() {
2281                            let (k, v) = items[*index].clone();
2282                            *index += 1;
2283                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
2284                        } else {
2285                            Ok(Value::none())
2286                        }
2287                    }
2288                }
2289            }
2290
2291            _ => Err(format!(
2292                "Iterator method '{}' not supported in JIT",
2293                method_name
2294            )),
2295        },
2296        Value::Enum {
2297            enum_name,
2298            variant,
2299            values,
2300        } if enum_name == "Option" => match method_name {
2301            "is_some" => Ok(Value::Bool(variant == "Some")),
2302            "is_none" => Ok(Value::Bool(variant == "None")),
2303            "unwrap" => {
2304                if variant == "Some" {
2305                    if let Some(vals) = values {
2306                        if vals.len() == 1 {
2307                            Ok(vals[0].clone())
2308                        } else {
2309                            Err("Option::Some should have exactly 1 value".to_string())
2310                        }
2311                    } else {
2312                        Err("Option::Some should have a value".to_string())
2313                    }
2314                } else {
2315                    Err("Called unwrap() on Option::None".to_string())
2316                }
2317            }
2318
2319            _ => Err(format!(
2320                "Option method '{}' not supported in JIT",
2321                method_name
2322            )),
2323        },
2324        Value::Array(arr) => match method_name {
2325            "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
2326            "push" => {
2327                let value = args
2328                    .get(0)
2329                    .cloned()
2330                    .ok_or_else(|| "Array:push requires a value argument".to_string())?;
2331                arr.borrow_mut().push(value);
2332                Ok(Value::Nil)
2333            }
2334            "pop" => {
2335                let popped = arr.borrow_mut().pop();
2336                Ok(popped.map(Value::some).unwrap_or_else(Value::none))
2337            }
2338            "first" => {
2339                let borrowed = arr.borrow();
2340                Ok(borrowed
2341                    .first()
2342                    .cloned()
2343                    .map(Value::some)
2344                    .unwrap_or_else(Value::none))
2345            }
2346            "last" => {
2347                let borrowed = arr.borrow();
2348                Ok(borrowed
2349                    .last()
2350                    .cloned()
2351                    .map(Value::some)
2352                    .unwrap_or_else(Value::none))
2353            }
2354            "get" => {
2355                let index = args
2356                    .get(0)
2357                    .and_then(Value::as_int)
2358                    .ok_or_else(|| "Array:get requires an integer index".to_string())?;
2359                let borrowed = arr.borrow();
2360                Ok(borrowed
2361                    .get(index as usize)
2362                    .cloned()
2363                    .map(Value::some)
2364                    .unwrap_or_else(Value::none))
2365            }
2366            "iter" => {
2367                let items = arr.borrow().clone();
2368                let iter = IteratorState::Array { items, index: 0 };
2369                Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
2370            }
2371            _ => Err(format!(
2372                "Array method '{}' not supported in JIT",
2373                method_name
2374            )),
2375        },
2376        _ => Err(format!(
2377            "Method '{}' not supported in JIT (deoptimizing)",
2378            method_name
2379        )),
2380    }
2381}
2382
2383#[no_mangle]
2384pub unsafe extern "C" fn jit_get_field_safe(
2385    object_ptr: *const Value,
2386    field_name_ptr: *const u8,
2387    field_name_len: usize,
2388    out: *mut Value,
2389) -> u8 {
2390    if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
2391        return 0;
2392    }
2393
2394    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2395    let field_name = match str::from_utf8(field_name_slice) {
2396        Ok(s) => s,
2397        Err(_) => return 0,
2398    };
2399    let object = &*object_ptr;
2400    let field_value = match object {
2401        Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
2402            Some(idx) => match fields.borrow().get(idx) {
2403                Some(val) => val.clone(),
2404                None => return 0,
2405            },
2406            None => return 0,
2407        },
2408        _ => return 0,
2409    };
2410    ptr::write(out, field_value);
2411    1
2412}
2413
2414#[no_mangle]
2415pub unsafe extern "C" fn jit_set_field_safe(
2416    object_ptr: *const Value,
2417    field_name_ptr: *const u8,
2418    field_name_len: usize,
2419    value_ptr: *const Value,
2420) -> u8 {
2421    if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
2422        return 0;
2423    }
2424
2425    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2426    let field_name = match str::from_utf8(field_name_slice) {
2427        Ok(s) => s,
2428        Err(_) => return 0,
2429    };
2430    let object = &*object_ptr;
2431    let value = (&*value_ptr).clone();
2432    match object {
2433        Value::Struct { .. } => match object.struct_set_field(field_name, value) {
2434            Ok(()) => 1,
2435            Err(_) => 0,
2436        },
2437        Value::Map(map) => {
2438            use crate::bytecode::ValueKey;
2439            let key = ValueKey::from(field_name.to_string());
2440            map.borrow_mut().insert(key, value);
2441            1
2442        }
2443
2444        _ => 0,
2445    }
2446}
2447
2448#[no_mangle]
2449pub unsafe extern "C" fn jit_get_field_indexed_safe(
2450    object_ptr: *const Value,
2451    field_index: usize,
2452    out: *mut Value,
2453) -> u8 {
2454    if object_ptr.is_null() || out.is_null() {
2455        return 0;
2456    }
2457
2458    let object = &*object_ptr;
2459    match object.struct_get_field_indexed(field_index) {
2460        Some(value) => {
2461            ptr::write(out, value);
2462            1
2463        }
2464
2465        None => 0,
2466    }
2467}
2468
2469#[no_mangle]
2470pub unsafe extern "C" fn jit_set_field_indexed_safe(
2471    object_ptr: *const Value,
2472    field_index: usize,
2473    value_ptr: *const Value,
2474) -> u8 {
2475    if object_ptr.is_null() || value_ptr.is_null() {
2476        return 0;
2477    }
2478
2479    let object = &*object_ptr;
2480    let value = (&*value_ptr).clone();
2481    match object.struct_set_field_indexed(field_index, value) {
2482        Ok(()) => 1,
2483        Err(_) => 0,
2484    }
2485}
2486
2487#[no_mangle]
2488pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
2489    object_ptr: *const Value,
2490    field_index: usize,
2491    out: *mut Value,
2492) -> u8 {
2493    if object_ptr.is_null() || out.is_null() {
2494        return 0;
2495    }
2496
2497    let object = &*object_ptr;
2498    let out_ref = &mut *out;
2499    match object {
2500        Value::Struct { layout, fields, .. } => {
2501            if layout.is_weak(field_index) {
2502                return 0;
2503            }
2504
2505            if let Ok(borrowed) = fields.try_borrow() {
2506                if let Some(Value::Int(val)) = borrowed.get(field_index) {
2507                    *out_ref = Value::Int(*val);
2508                    return 1;
2509                }
2510            }
2511
2512            0
2513        }
2514
2515        _ => 0,
2516    }
2517}
2518
2519#[no_mangle]
2520pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
2521    object_ptr: *const Value,
2522    field_index: usize,
2523    value_ptr: *const Value,
2524) -> u8 {
2525    if object_ptr.is_null() || value_ptr.is_null() {
2526        return 0;
2527    }
2528
2529    let object = &*object_ptr;
2530    let value = &*value_ptr;
2531    let new_value = match value {
2532        Value::Int(v) => *v,
2533        _ => return 0,
2534    };
2535    match object {
2536        Value::Struct { layout, fields, .. } => {
2537            if layout.is_weak(field_index) {
2538                return 0;
2539            }
2540
2541            if let Ok(mut borrowed) = fields.try_borrow_mut() {
2542                if field_index < borrowed.len() {
2543                    borrowed[field_index] = Value::Int(new_value);
2544                    return 1;
2545                }
2546            }
2547
2548            0
2549        }
2550
2551        _ => 0,
2552    }
2553}
2554
2555#[no_mangle]
2556pub unsafe extern "C" fn jit_new_struct_safe(
2557    vm_ptr: *mut VM,
2558    struct_name_ptr: *const u8,
2559    struct_name_len: usize,
2560    field_names_ptr: *const *const u8,
2561    field_name_lens_ptr: *const usize,
2562    field_values_ptr: *const Value,
2563    field_count: usize,
2564    out: *mut Value,
2565) -> u8 {
2566    if struct_name_ptr.is_null() || out.is_null() || vm_ptr.is_null() {
2567        jit::log(|| "jit_new_struct_safe: null pointer input".to_string());
2568        return 0;
2569    }
2570
2571    if field_count > 0
2572        && (field_names_ptr.is_null()
2573            || field_name_lens_ptr.is_null()
2574            || field_values_ptr.is_null())
2575    {
2576        return 0;
2577    }
2578
2579    let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
2580    let struct_name = match str::from_utf8(struct_name_slice) {
2581        Ok(s) => s.to_string(),
2582        Err(_) => return 0,
2583    };
2584    let mut fields = Vec::with_capacity(field_count);
2585    for i in 0..field_count {
2586        let field_name_ptr = *field_names_ptr.add(i);
2587        let field_name_len = *field_name_lens_ptr.add(i);
2588        let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2589        let field_name = match str::from_utf8(field_name_slice) {
2590            Ok(s) => Rc::new(s.to_string()),
2591            Err(_) => return 0,
2592        };
2593        let field_value_ptr = field_values_ptr.add(i);
2594        let field_value = (&*field_value_ptr).clone();
2595        fields.push((field_name, field_value));
2596    }
2597
2598    let vm = &mut *vm_ptr;
2599    let struct_value = match vm.instantiate_struct(&struct_name, fields) {
2600        Ok(value) => value,
2601        Err(err) => {
2602            jit::log(|| {
2603                format!(
2604                    "jit_new_struct_safe: failed to instantiate '{}': {}",
2605                    struct_name, err
2606                )
2607            });
2608            return 0;
2609        }
2610    };
2611    ptr::write(out, struct_value);
2612    1
2613}
2614
2615#[no_mangle]
2616pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
2617    if src_ptr.is_null() || dest_ptr.is_null() {
2618        return 0;
2619    }
2620
2621    let src_value = &*src_ptr;
2622    let cloned_value = src_value.clone();
2623    ptr::write(dest_ptr, cloned_value);
2624    1
2625}