Skip to main content

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    vm_ptr: *mut VM,
1437    elements_ptr: *const Value,
1438    element_count: usize,
1439    out_ptr: *mut Value,
1440) -> u8 {
1441    let _call_num = JIT_NEW_ARRAY_COUNTER.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
1442    // jit::log(|| format!("jit_new_array_safe call #{}: ENTER - elements_ptr={:?}, count={}, out_ptr={:?}", call_num, elements_ptr, element_count, out_ptr));
1443
1444    if out_ptr.is_null() {
1445        // jit::log(|| "jit_new_array_safe: out_ptr is null".to_string());
1446        return 0;
1447    }
1448
1449    if !vm_ptr.is_null() {
1450        let vm = &mut *vm_ptr;
1451        if !vm.try_charge_memory_value_vec(element_count) {
1452            return 0;
1453        }
1454    }
1455
1456    // jit::log(|| format!("jit_new_array_safe #{}: about to create Vec", call_num));
1457    let elements = if element_count == 0 {
1458        Vec::new()
1459    } else {
1460        if elements_ptr.is_null() {
1461            // jit::log(|| "jit_new_array_safe: elements_ptr is null but count > 0".to_string());
1462            return 0;
1463        }
1464
1465        let slice = slice::from_raw_parts(elements_ptr, element_count);
1466        slice.to_vec()
1467    };
1468
1469    // jit::log(|| format!("jit_new_array_safe #{}: about to call Value::array with {} elements", call_num, elements.len()));
1470    let array_value = Value::array(elements);
1471    // jit::log(|| format!("jit_new_array_safe #{}: about to write to out_ptr", call_num));
1472    ptr::write(out_ptr, array_value);
1473    // jit::log(|| format!("jit_new_array_safe #{}: EXIT - success, returning 1", call_num));
1474    1
1475}
1476
1477#[cfg(feature = "std")]
1478#[no_mangle]
1479pub unsafe extern "C" fn jit_array_push_safe(
1480    vm_ptr: *mut VM,
1481    array_ptr: *const Value,
1482    value_ptr: *const Value,
1483) -> u8 {
1484    if array_ptr.is_null() || value_ptr.is_null() {
1485        return 0;
1486    }
1487
1488    let array_value = &*array_ptr;
1489    let value = &*value_ptr;
1490
1491    match array_value {
1492        Value::Array(arr) => {
1493            // Use unchecked borrow for maximum performance
1494            let cell_ptr = arr.as_ptr();
1495            let vec_ref = &mut *cell_ptr;
1496            if !vm_ptr.is_null() {
1497                let vm = &mut *vm_ptr;
1498                let len = vec_ref.len();
1499                let cap = vec_ref.capacity();
1500                if len == cap {
1501                    let new_cap = if cap == 0 { 4 } else { cap.saturating_mul(2) };
1502                    if !vm.try_charge_memory_vec_growth::<Value>(cap, new_cap) {
1503                        return 0;
1504                    }
1505                }
1506            }
1507            vec_ref.push(value.clone());
1508            1
1509        }
1510        _ => 0,
1511    }
1512}
1513
1514/// Unbox Array<int> from Value to Vec<LustInt> for specialized JIT operations
1515/// IMPORTANT: This takes ownership of the array's data. The original Vec<Value> is emptied.
1516/// Returns 1 on success, 0 on failure
1517/// Outputs: vec_ptr (pointer to data), vec_len, vec_cap
1518#[cfg(feature = "std")]
1519#[no_mangle]
1520pub unsafe extern "C" fn jit_unbox_array_int(
1521    array_value_ptr: *const Value,
1522    out_vec_ptr: *mut *mut LustInt,
1523    out_len: *mut usize,
1524    out_cap: *mut usize,
1525) -> u8 {
1526    if array_value_ptr.is_null() || out_vec_ptr.is_null() || out_len.is_null() || out_cap.is_null()
1527    {
1528        return 0;
1529    }
1530
1531    let array_value = &*array_value_ptr;
1532    match array_value {
1533        Value::Array(arr_rc) => {
1534            // Get exclusive access to the inner vector
1535            let cell_ptr = arr_rc.as_ptr();
1536            let vec_ref = &mut *cell_ptr;
1537
1538            // Take ownership of the Vec<Value> by swapping with empty vec
1539            let original_vec = core::mem::replace(vec_ref, Vec::new());
1540
1541            // Convert Vec<Value> to Vec<LustInt>
1542            let mut specialized_vec: Vec<LustInt> = Vec::with_capacity(original_vec.len());
1543            for elem in original_vec.into_iter() {
1544                match elem {
1545                    Value::Int(i) => specialized_vec.push(i),
1546                    _ => {
1547                        // Type mismatch - restore original data and fail
1548                        // This shouldn't happen if types are correct, but be safe
1549                        return 0;
1550                    }
1551                }
1552            }
1553
1554            // Extract Vec metadata
1555            let len = specialized_vec.len();
1556            let cap = specialized_vec.capacity();
1557            let ptr = specialized_vec.as_mut_ptr();
1558
1559            // Prevent Vec from being dropped
1560            core::mem::forget(specialized_vec);
1561
1562            // Write outputs
1563            ptr::write(out_vec_ptr, ptr);
1564            ptr::write(out_len, len);
1565            ptr::write(out_cap, cap);
1566
1567            // Note: The original Rc<RefCell<Vec<Value>>> now contains an empty Vec
1568            // This is fine - when we rebox, we'll refill it
1569
1570            1
1571        }
1572        _ => 0,
1573    }
1574}
1575
1576/// Rebox Vec<LustInt> back to Array Value
1577/// IMPORTANT: Writes the specialized vec data back into the EXISTING Rc<RefCell<Vec<Value>>>
1578/// This ensures the original array is updated, not replaced
1579#[cfg(feature = "std")]
1580#[no_mangle]
1581pub unsafe extern "C" fn jit_rebox_array_int(
1582    vec_ptr: *mut LustInt,
1583    vec_len: usize,
1584    vec_cap: usize,
1585    array_value_ptr: *mut Value,
1586) -> u8 {
1587    if vec_ptr.is_null() || array_value_ptr.is_null() {
1588        return 0;
1589    }
1590
1591    // Reconstruct Vec<LustInt> from raw parts
1592    let specialized_vec = Vec::from_raw_parts(vec_ptr, vec_len, vec_cap);
1593
1594    // Get the existing Array value
1595    let array_value = &mut *array_value_ptr;
1596    match array_value {
1597        Value::Array(arr_rc) => {
1598            // Get exclusive access to the inner vector (should be empty from unbox)
1599            let cell_ptr = arr_rc.as_ptr();
1600            let vec_ref = &mut *cell_ptr;
1601
1602            // Convert Vec<LustInt> back to Vec<Value> and write into the existing RefCell
1603            *vec_ref = specialized_vec.into_iter().map(Value::Int).collect();
1604
1605            1
1606        }
1607        _ => {
1608            // This shouldn't happen - the register should still contain the Array
1609            // But if it doesn't, create a new array
1610            let value_vec: Vec<Value> = specialized_vec.into_iter().map(Value::Int).collect();
1611            let array_value_new = Value::array(value_vec);
1612            ptr::write(array_value_ptr, array_value_new);
1613            1
1614        }
1615    }
1616}
1617
1618/// Specialized push operation for Vec<LustInt>
1619/// Directly pushes LustInt to the specialized vector
1620#[cfg(feature = "std")]
1621#[no_mangle]
1622pub unsafe extern "C" fn jit_vec_int_push(
1623    vec_ptr: *mut *mut LustInt,
1624    vec_len: *mut usize,
1625    vec_cap: *mut usize,
1626    value: LustInt,
1627) -> u8 {
1628    if vec_ptr.is_null() || vec_len.is_null() || vec_cap.is_null() {
1629        return 0;
1630    }
1631
1632    let ptr = *vec_ptr;
1633    let len = *vec_len;
1634    let cap = *vec_cap;
1635
1636    // Reconstruct Vec temporarily
1637    let mut vec = Vec::from_raw_parts(ptr, len, cap);
1638
1639    // Push the value
1640    vec.push(value);
1641
1642    // Extract new metadata
1643    let new_len = vec.len();
1644    let new_cap = vec.capacity();
1645    let new_ptr = vec.as_mut_ptr();
1646
1647    // Prevent drop
1648    core::mem::forget(vec);
1649
1650    // Update outputs
1651    ptr::write(vec_ptr, new_ptr);
1652    ptr::write(vec_len, new_len);
1653    ptr::write(vec_cap, new_cap);
1654
1655    1
1656}
1657
1658/// Drop a specialized Vec<LustInt> (cleanup for leaked specializations)
1659/// WARNING: This should NOT be called! Specialized values that get invalidated
1660/// during loop recording don't actually exist on the stack during execution.
1661#[cfg(feature = "std")]
1662#[no_mangle]
1663pub unsafe extern "C" fn jit_drop_vec_int(vec_ptr: *mut LustInt, vec_len: usize, vec_cap: usize) {
1664    eprintln!(
1665        "🗑️  jit_drop_vec_int: ptr={:p}, len={}, cap={}",
1666        vec_ptr, vec_len, vec_cap
1667    );
1668    eprintln!("🗑️  jit_drop_vec_int: THIS SHOULD NOT BE CALLED - THE VEC DATA IS STALE!");
1669
1670    // DO NOT drop - the Vec data on the stack is stale from trace recording
1671    // The actual arrays are managed by their Rc<RefCell<>> wrappers
1672    eprintln!("🗑️  jit_drop_vec_int: skipping drop (would cause corruption)");
1673}
1674
1675#[cfg(feature = "std")]
1676#[no_mangle]
1677pub unsafe extern "C" fn jit_enum_is_some_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1678    if enum_ptr.is_null() || out_ptr.is_null() {
1679        return 0;
1680    }
1681
1682    let enum_value = &*enum_ptr;
1683    match enum_value {
1684        Value::Enum { variant, .. } => {
1685            let is_some = variant == "Some";
1686            ptr::write(out_ptr, Value::Bool(is_some));
1687            1
1688        }
1689        _ => 0,
1690    }
1691}
1692
1693#[cfg(feature = "std")]
1694#[no_mangle]
1695pub unsafe extern "C" fn jit_enum_unwrap_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1696    if enum_ptr.is_null() || out_ptr.is_null() {
1697        return 0;
1698    }
1699
1700    let enum_value = &*enum_ptr;
1701    match enum_value {
1702        Value::Enum {
1703            values: Some(vals), ..
1704        } if vals.len() == 1 => {
1705            ptr::write(out_ptr, vals[0].clone());
1706            1
1707        }
1708        _ => 0,
1709    }
1710}
1711
1712#[cfg(feature = "std")]
1713#[no_mangle]
1714pub unsafe extern "C" fn jit_set_field_strong_safe(
1715    object_ptr: *const Value,
1716    field_index: usize,
1717    value_ptr: *const Value,
1718) -> u8 {
1719    if object_ptr.is_null() || value_ptr.is_null() {
1720        return 0;
1721    }
1722
1723    let object = &*object_ptr;
1724    let value = (&*value_ptr).clone();
1725
1726    match object {
1727        Value::Struct { fields, .. } => {
1728            // Skip canonicalization for strong fields - just set directly
1729            match fields.try_borrow_mut() {
1730                Ok(mut borrowed) => {
1731                    if field_index < borrowed.len() {
1732                        borrowed[field_index] = value;
1733                        1
1734                    } else {
1735                        0
1736                    }
1737                }
1738                Err(_) => 0,
1739            }
1740        }
1741        _ => 0,
1742    }
1743}
1744
1745#[cfg(feature = "std")]
1746#[no_mangle]
1747pub unsafe extern "C" fn jit_concat_safe(
1748    vm_ptr: *mut VM,
1749    left_value_ptr: *const Value,
1750    right_value_ptr: *const Value,
1751    out: *mut Value,
1752) -> u8 {
1753    if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1754        return 0;
1755    }
1756
1757    let left = &*left_value_ptr;
1758    let right = &*right_value_ptr;
1759    let (left_str, right_str) = if !vm_ptr.is_null() {
1760        let vm = &mut *vm_ptr;
1761        let left_copy = left.clone();
1762        let right_copy = right.clone();
1763        let left_str = match vm.value_to_string_for_concat(&left_copy) {
1764            Ok(rc) => rc,
1765            Err(_) => return 0,
1766        };
1767        let right_str = match vm.value_to_string_for_concat(&right_copy) {
1768            Ok(rc) => rc,
1769            Err(_) => return 0,
1770        };
1771        (left_str, right_str)
1772    } else {
1773        (Rc::new(left.to_string()), Rc::new(right.to_string()))
1774    };
1775    let cap = left_str.len().saturating_add(right_str.len());
1776    if !vm_ptr.is_null() {
1777        let vm = &mut *vm_ptr;
1778        if !vm.try_charge_memory_bytes(cap) {
1779            return 0;
1780        }
1781    }
1782    let mut combined = String::with_capacity(cap);
1783    combined.push_str(left_str.as_ref());
1784    combined.push_str(right_str.as_ref());
1785    let result = Value::string(combined);
1786    ptr::write(out, result);
1787    1
1788}
1789
1790#[no_mangle]
1791pub unsafe extern "C" fn jit_guard_native_function(
1792    value_ptr: *const Value,
1793    expected_fn_ptr: *const (),
1794    register_index: u8,
1795) -> u8 {
1796    if value_ptr.is_null() || expected_fn_ptr.is_null() {
1797        jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1798        return 0;
1799    }
1800
1801    match &*value_ptr {
1802        Value::NativeFunction(func) => {
1803            let actual = Rc::as_ptr(func) as *const ();
1804            if actual == expected_fn_ptr {
1805                1
1806            } else {
1807                jit::log(|| {
1808                    format!(
1809                        "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1810                        register_index, actual, expected_fn_ptr
1811                    )
1812                });
1813                0
1814            }
1815        }
1816
1817        other => {
1818            jit::log(|| {
1819                format!(
1820                    "jit_guard_native_function: value not native in reg {} ({:?})",
1821                    register_index,
1822                    other.tag()
1823                )
1824            });
1825            0
1826        }
1827    }
1828}
1829
1830#[no_mangle]
1831pub unsafe extern "C" fn jit_guard_function_identity(
1832    value_ptr: *const Value,
1833    expected_kind: u8,
1834    expected_function_idx: usize,
1835    expected_upvalues: *const (),
1836    register_index: u8,
1837) -> u8 {
1838    if value_ptr.is_null() {
1839        jit::log(|| "jit_guard_function_identity: null pointer input".to_string());
1840        return 0;
1841    }
1842
1843    let value = &*value_ptr;
1844    match (expected_kind, value) {
1845        (0, Value::Function(idx)) => {
1846            if *idx == expected_function_idx {
1847                1
1848            } else {
1849                jit::log(|| {
1850                    format!(
1851                        "jit_guard_function_identity: function idx mismatch (reg {}) actual={} expected={}",
1852                        register_index, idx, expected_function_idx
1853                    )
1854                });
1855                0
1856            }
1857        }
1858
1859        (
1860            1,
1861            Value::Closure {
1862                function_idx,
1863                upvalues,
1864            },
1865        ) => {
1866            if *function_idx != expected_function_idx {
1867                jit::log(|| {
1868                    format!(
1869                        "jit_guard_function_identity: closure idx mismatch (reg {}) actual={} expected={}",
1870                        register_index, function_idx, expected_function_idx
1871                    )
1872                });
1873                return 0;
1874            }
1875
1876            let actual_ptr = Rc::as_ptr(upvalues) as *const ();
1877            if actual_ptr == expected_upvalues {
1878                1
1879            } else {
1880                jit::log(|| {
1881                    format!(
1882                        "jit_guard_function_identity: upvalues mismatch (reg {}) actual={:p} expected={:p}",
1883                        register_index, actual_ptr, expected_upvalues
1884                    )
1885                });
1886                0
1887            }
1888        }
1889
1890        (0, Value::Closure { function_idx, .. }) => {
1891            jit::log(|| {
1892                format!(
1893                    "jit_guard_function_identity: expected function, saw closure (reg {}, idx {})",
1894                    register_index, function_idx
1895                )
1896            });
1897            0
1898        }
1899
1900        (1, Value::Function(idx)) => {
1901            jit::log(|| {
1902                format!(
1903                    "jit_guard_function_identity: expected closure, saw function (reg {}, idx {})",
1904                    register_index, idx
1905                )
1906            });
1907            0
1908        }
1909
1910        (_, other) => {
1911            jit::log(|| {
1912                format!(
1913                    "jit_guard_function_identity: value in reg {} not callable ({:?})",
1914                    register_index,
1915                    other.tag()
1916                )
1917            });
1918            0
1919        }
1920    }
1921}
1922
1923#[no_mangle]
1924pub unsafe extern "C" fn jit_call_native_safe(
1925    vm_ptr: *mut VM,
1926    callee_ptr: *const Value,
1927    expected_fn_ptr: *const (),
1928    args_ptr: *const Value,
1929    arg_count: u8,
1930    out: *mut Value,
1931) -> u8 {
1932    if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1933        jit::log(|| "jit_call_native_safe: null argument".to_string());
1934        return 0;
1935    }
1936
1937    let callee = &*callee_ptr;
1938    let native_fn = match callee {
1939        Value::NativeFunction(func) => func.clone(),
1940        other => {
1941            jit::log(|| {
1942                format!(
1943                    "jit_call_native_safe: callee not native ({:?})",
1944                    other.tag()
1945                )
1946            });
1947            return 0;
1948        }
1949    };
1950
1951    if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1952        jit::log(|| {
1953            format!(
1954                "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1955                Rc::as_ptr(&native_fn),
1956                expected_fn_ptr
1957            )
1958        });
1959        return 0;
1960    }
1961
1962    let mut args = Vec::with_capacity(arg_count as usize);
1963    if arg_count > 0 {
1964        if args_ptr.is_null() {
1965            jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1966            return 0;
1967        }
1968
1969        for i in 0..(arg_count as usize) {
1970            let arg = &*args_ptr.add(i);
1971            args.push(arg.clone());
1972        }
1973    }
1974
1975    push_vm_ptr(vm_ptr);
1976    let outcome = native_fn(&args);
1977    pop_vm_ptr();
1978
1979    let outcome = match outcome {
1980        Ok(result) => result,
1981        Err(err) => {
1982            jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1983            return 0;
1984        }
1985    };
1986
1987    match outcome {
1988        NativeCallResult::Return(value) => {
1989            ptr::write(out, value);
1990            1
1991        }
1992
1993        NativeCallResult::Yield(value) => {
1994            let vm = &mut *vm_ptr;
1995            if vm.current_task.is_none() {
1996                jit::log(|| "jit_call_native_safe: native attempted to yield outside a task".to_string());
1997                return 0;
1998            }
1999
2000            let dest_reg = vm.call_stack.last().and_then(|frame| {
2001                let base = frame.registers.as_ptr() as usize;
2002                let out_ptr = out as usize;
2003                let value_size = core::mem::size_of::<Value>();
2004                let end = base + value_size * frame.registers.len();
2005                if out_ptr < base || out_ptr >= end {
2006                    return None;
2007                }
2008                let offset = out_ptr - base;
2009                if offset % value_size != 0 {
2010                    return None;
2011                }
2012                let reg = offset / value_size;
2013                if reg > u8::MAX as usize {
2014                    return None;
2015                }
2016                Some(reg as u8)
2017            });
2018            let Some(dest_reg) = dest_reg else {
2019                jit::log(|| "jit_call_native_safe: could not compute dest register for yield".to_string());
2020                return 0;
2021            };
2022
2023            ptr::write(out, Value::Nil);
2024            vm.pending_task_signal = Some(crate::vm::TaskSignal::Yield { dest: dest_reg, value });
2025            2
2026        }
2027
2028        NativeCallResult::Stop(value) => {
2029            let vm = &mut *vm_ptr;
2030            if vm.current_task.is_none() {
2031                jit::log(|| "jit_call_native_safe: native attempted to stop outside a task".to_string());
2032                return 0;
2033            }
2034
2035            ptr::write(out, Value::Nil);
2036            vm.pending_task_signal = Some(crate::vm::TaskSignal::Stop { value });
2037            3
2038        }
2039    }
2040}
2041
2042#[no_mangle]
2043pub unsafe extern "C" fn jit_call_function_safe(
2044    vm_ptr: *mut VM,
2045    callee_ptr: *const Value,
2046    args_ptr: *const Value,
2047    arg_count: u8,
2048    dest_reg: u8,
2049) -> u8 {
2050    if vm_ptr.is_null() || callee_ptr.is_null() {
2051        jit::log(|| "jit_call_function_safe: null argument".to_string());
2052        return 0;
2053    }
2054
2055    if arg_count > 0 && args_ptr.is_null() {
2056        jit::log(|| "jit_call_function_safe: args_ptr null with non-zero arg_count".to_string());
2057        return 0;
2058    }
2059
2060    // Clone the callee BEFORE any operations that might reallocate registers
2061    let callee = (&*callee_ptr).clone();
2062    let mut args = Vec::with_capacity(arg_count as usize);
2063    for i in 0..(arg_count as usize) {
2064        let arg_ptr = args_ptr.add(i);
2065        args.push((&*arg_ptr).clone());
2066    }
2067
2068    let vm = &mut *vm_ptr;
2069    push_vm_ptr(vm_ptr);
2070
2071    // Temporarily disable JIT to prevent recursive JIT execution
2072    let jit_was_enabled = vm.jit.enabled;
2073    vm.jit.enabled = false;
2074
2075    let call_result = vm.call_value(&callee, args);
2076
2077    // Restore JIT state
2078    vm.jit.enabled = jit_was_enabled;
2079    pop_vm_ptr();
2080
2081    match call_result {
2082        Ok(value) => {
2083            // Get current registers pointer AFTER the call (it may have reallocated)
2084            let vm = &mut *vm_ptr;
2085            if let Some(frame) = vm.call_stack.last_mut() {
2086                if (dest_reg as usize) < frame.registers.len() {
2087                    frame.registers[dest_reg as usize] = value;
2088                    1
2089                } else {
2090                    jit::log(|| {
2091                        format!(
2092                            "jit_call_function_safe: dest_reg {} out of bounds",
2093                            dest_reg
2094                        )
2095                    });
2096                    0
2097                }
2098            } else {
2099                jit::log(|| "jit_call_function_safe: no call frame".to_string());
2100                0
2101            }
2102        }
2103
2104        Err(err) => {
2105            jit::log(|| format!("jit_call_function_safe: {}", err));
2106            0
2107        }
2108    }
2109}
2110
2111#[no_mangle]
2112pub unsafe extern "C" fn jit_current_registers(vm_ptr: *mut VM) -> *mut Value {
2113    if vm_ptr.is_null() {
2114        return core::ptr::null_mut();
2115    }
2116
2117    let vm = &mut *vm_ptr;
2118    vm.call_stack
2119        .last_mut()
2120        .map(|frame| frame.registers.as_mut_ptr())
2121        .unwrap_or(core::ptr::null_mut())
2122}
2123
2124#[no_mangle]
2125pub unsafe extern "C" fn jit_value_is_truthy(value_ptr: *const Value) -> u8 {
2126    if value_ptr.is_null() {
2127        return 0;
2128    }
2129
2130    let value = &*value_ptr;
2131    if value.is_truthy() {
2132        1
2133    } else {
2134        0
2135    }
2136}
2137
2138#[no_mangle]
2139pub unsafe extern "C" fn jit_new_enum_unit_safe(
2140    vm_ptr: *mut VM,
2141    enum_name_ptr: *const u8,
2142    enum_name_len: usize,
2143    variant_name_ptr: *const u8,
2144    variant_name_len: usize,
2145    out: *mut Value,
2146) -> u8 {
2147    if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2148        return 0;
2149    }
2150
2151    let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2152    let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2153    let enum_name_str = match str::from_utf8(enum_name_slice) {
2154        Ok(s) => s,
2155        Err(_) => return 0,
2156    };
2157    let variant_name_str = match str::from_utf8(variant_name_slice) {
2158        Ok(s) => s,
2159        Err(_) => return 0,
2160    };
2161
2162    if !vm_ptr.is_null() {
2163        let vm = &mut *vm_ptr;
2164        let bytes = enum_name_len.saturating_add(variant_name_len);
2165        if !vm.try_charge_memory_bytes(bytes) {
2166            return 0;
2167        }
2168    }
2169
2170    let enum_name = enum_name_str.to_string();
2171    let variant_name = variant_name_str.to_string();
2172    let value = Value::enum_unit(enum_name, variant_name);
2173    ptr::write(out, value);
2174    1
2175}
2176
2177#[no_mangle]
2178pub unsafe extern "C" fn jit_new_enum_variant_safe(
2179    vm_ptr: *mut VM,
2180    enum_name_ptr: *const u8,
2181    enum_name_len: usize,
2182    variant_name_ptr: *const u8,
2183    variant_name_len: usize,
2184    values_ptr: *const Value,
2185    value_count: usize,
2186    out: *mut Value,
2187) -> u8 {
2188    if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2189        return 0;
2190    }
2191
2192    if value_count > 0 && values_ptr.is_null() {
2193        return 0;
2194    }
2195
2196    let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2197    let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2198    let enum_name_str = match str::from_utf8(enum_name_slice) {
2199        Ok(s) => s,
2200        Err(_) => return 0,
2201    };
2202    let variant_name_str = match str::from_utf8(variant_name_slice) {
2203        Ok(s) => s,
2204        Err(_) => return 0,
2205    };
2206
2207    if !vm_ptr.is_null() {
2208        let vm = &mut *vm_ptr;
2209        let name_bytes = enum_name_len.saturating_add(variant_name_len);
2210        if !vm.try_charge_memory_bytes(name_bytes) {
2211            return 0;
2212        }
2213        if !vm.try_charge_memory_value_vec(value_count) {
2214            return 0;
2215        }
2216    }
2217
2218    let enum_name = enum_name_str.to_string();
2219    let variant_name = variant_name_str.to_string();
2220    let mut values = Vec::with_capacity(value_count);
2221    for i in 0..value_count {
2222        let value = &*values_ptr.add(i);
2223        values.push(value.clone());
2224    }
2225
2226    let value = Value::enum_variant(enum_name, variant_name, values);
2227    ptr::write(out, value);
2228    1
2229}
2230
2231#[no_mangle]
2232pub unsafe extern "C" fn jit_is_enum_variant_safe(
2233    value_ptr: *const Value,
2234    enum_name_ptr: *const u8,
2235    enum_name_len: usize,
2236    variant_name_ptr: *const u8,
2237    variant_name_len: usize,
2238) -> u8 {
2239    if value_ptr.is_null() || enum_name_ptr.is_null() || variant_name_ptr.is_null() {
2240        return 0;
2241    }
2242
2243    let value = &*value_ptr;
2244    let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2245    let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2246    let enum_name = match str::from_utf8(enum_name_slice) {
2247        Ok(s) => s,
2248        Err(_) => return 0,
2249    };
2250    let variant_name = match str::from_utf8(variant_name_slice) {
2251        Ok(s) => s,
2252        Err(_) => return 0,
2253    };
2254    if value.is_enum_variant(enum_name, variant_name) {
2255        1
2256    } else {
2257        0
2258    }
2259}
2260
2261#[no_mangle]
2262pub unsafe extern "C" fn jit_get_enum_value_safe(
2263    enum_ptr: *const Value,
2264    index: usize,
2265    out: *mut Value,
2266) -> u8 {
2267    if enum_ptr.is_null() || out.is_null() {
2268        return 0;
2269    }
2270
2271    let enum_value = &*enum_ptr;
2272    if let Some((_, _, Some(values))) = enum_value.as_enum() {
2273        if index < values.len() {
2274            ptr::write(out, values[index].clone());
2275            1
2276        } else {
2277            0
2278        }
2279    } else {
2280        0
2281    }
2282}
2283
2284#[no_mangle]
2285pub unsafe extern "C" fn jit_call_method_safe(
2286    vm_ptr: *mut VM,
2287    object_ptr: *const Value,
2288    method_name_ptr: *const u8,
2289    method_name_len: usize,
2290    args_ptr: *const Value,
2291    arg_count: u8,
2292    dest_reg: u8,
2293) -> u8 {
2294    if vm_ptr.is_null() || object_ptr.is_null() || method_name_ptr.is_null() {
2295        jit::log(|| "jit_call_method_safe: null pointer argument".to_string());
2296        return 0;
2297    }
2298
2299    if arg_count > 0 && args_ptr.is_null() {
2300        return 0;
2301    }
2302
2303    let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
2304    let method_name = match str::from_utf8(method_name_slice) {
2305        Ok(s) => s,
2306        Err(_) => return 0,
2307    };
2308
2309    let object = (&*object_ptr).clone();
2310    if matches!(object, Value::Struct { .. }) {
2311        return 0;
2312    }
2313
2314    let mut args = Vec::with_capacity(arg_count as usize);
2315    for i in 0..arg_count {
2316        let arg_ptr = args_ptr.add(i as usize);
2317        args.push((&*arg_ptr).clone());
2318    }
2319
2320    crate::vm::push_vm_ptr(vm_ptr);
2321    let outcome = call_builtin_method_simple(&object, method_name, args);
2322    crate::vm::pop_vm_ptr();
2323    match outcome {
2324        Ok(val) => {
2325            let vm = &mut *vm_ptr;
2326            if let Some(frame) = vm.call_stack.last_mut() {
2327                if (dest_reg as usize) < frame.registers.len() {
2328                    frame.registers[dest_reg as usize] = val;
2329                    1
2330                } else {
2331                    jit::log(|| {
2332                        format!("jit_call_method_safe: dest_reg {} out of bounds", dest_reg)
2333                    });
2334                    0
2335                }
2336            } else {
2337                jit::log(|| "jit_call_method_safe: no call frame".to_string());
2338                0
2339            }
2340        }
2341        Err(_) => 0,
2342    }
2343}
2344
2345fn call_builtin_method_simple(
2346    object: &Value,
2347    method_name: &str,
2348    args: Vec<Value>,
2349) -> Result<Value, String> {
2350    match object {
2351        Value::Struct { name, .. } => Err(format!(
2352            "User-defined methods on {} require deoptimization",
2353            name
2354        )),
2355        Value::Iterator(state_rc) => match method_name {
2356            "next" => {
2357                let mut state = state_rc.borrow_mut();
2358                match &mut *state {
2359                    IteratorState::Array { items, index } => {
2360                        if *index < items.len() {
2361                            let v = items[*index].clone();
2362                            *index += 1;
2363                            Ok(Value::some(v))
2364                        } else {
2365                            Ok(Value::none())
2366                        }
2367                    }
2368
2369                    IteratorState::MapPairs { items, index } => {
2370                        if *index < items.len() {
2371                            let (k, v) = items[*index].clone();
2372                            *index += 1;
2373                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
2374                        } else {
2375                            Ok(Value::none())
2376                        }
2377                    }
2378                }
2379            }
2380
2381            _ => Err(format!(
2382                "Iterator method '{}' not supported in JIT",
2383                method_name
2384            )),
2385        },
2386        Value::Enum {
2387            enum_name,
2388            variant,
2389            values,
2390        } if enum_name == "Option" => match method_name {
2391            "is_some" => Ok(Value::Bool(variant == "Some")),
2392            "is_none" => Ok(Value::Bool(variant == "None")),
2393            "unwrap" => {
2394                if variant == "Some" {
2395                    if let Some(vals) = values {
2396                        if vals.len() == 1 {
2397                            Ok(vals[0].clone())
2398                        } else {
2399                            Err("Option::Some should have exactly 1 value".to_string())
2400                        }
2401                    } else {
2402                        Err("Option::Some should have a value".to_string())
2403                    }
2404                } else {
2405                    Err("Called unwrap() on Option::None".to_string())
2406                }
2407            }
2408
2409            _ => Err(format!(
2410                "Option method '{}' not supported in JIT",
2411                method_name
2412            )),
2413        },
2414        Value::Array(arr) => match method_name {
2415            "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
2416            "push" => {
2417                let value = args
2418                    .get(0)
2419                    .cloned()
2420                    .ok_or_else(|| "Array:push requires a value argument".to_string())?;
2421                arr.borrow_mut().push(value);
2422                Ok(Value::Nil)
2423            }
2424            "pop" => {
2425                let popped = arr.borrow_mut().pop();
2426                Ok(popped.map(Value::some).unwrap_or_else(Value::none))
2427            }
2428            "first" => {
2429                let borrowed = arr.borrow();
2430                Ok(borrowed
2431                    .first()
2432                    .cloned()
2433                    .map(Value::some)
2434                    .unwrap_or_else(Value::none))
2435            }
2436            "last" => {
2437                let borrowed = arr.borrow();
2438                Ok(borrowed
2439                    .last()
2440                    .cloned()
2441                    .map(Value::some)
2442                    .unwrap_or_else(Value::none))
2443            }
2444            "get" => {
2445                let index = args
2446                    .get(0)
2447                    .and_then(Value::as_int)
2448                    .ok_or_else(|| "Array:get requires an integer index".to_string())?;
2449                let borrowed = arr.borrow();
2450                Ok(borrowed
2451                    .get(index as usize)
2452                    .cloned()
2453                    .map(Value::some)
2454                    .unwrap_or_else(Value::none))
2455            }
2456            "iter" => {
2457                let items = arr.borrow().clone();
2458                let iter = IteratorState::Array { items, index: 0 };
2459                Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
2460            }
2461            _ => Err(format!(
2462                "Array method '{}' not supported in JIT",
2463                method_name
2464            )),
2465        },
2466        _ => Err(format!(
2467            "Method '{}' not supported in JIT (deoptimizing)",
2468            method_name
2469        )),
2470    }
2471}
2472
2473#[no_mangle]
2474pub unsafe extern "C" fn jit_get_field_safe(
2475    object_ptr: *const Value,
2476    field_name_ptr: *const u8,
2477    field_name_len: usize,
2478    out: *mut Value,
2479) -> u8 {
2480    if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
2481        return 0;
2482    }
2483
2484    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2485    let field_name = match str::from_utf8(field_name_slice) {
2486        Ok(s) => s,
2487        Err(_) => return 0,
2488    };
2489    let object = &*object_ptr;
2490    let field_value = match object {
2491        Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
2492            Some(idx) => match fields.borrow().get(idx) {
2493                Some(val) => val.clone(),
2494                None => return 0,
2495            },
2496            None => return 0,
2497        },
2498        _ => return 0,
2499    };
2500    ptr::write(out, field_value);
2501    1
2502}
2503
2504#[no_mangle]
2505pub unsafe extern "C" fn jit_set_field_safe(
2506    object_ptr: *const Value,
2507    field_name_ptr: *const u8,
2508    field_name_len: usize,
2509    value_ptr: *const Value,
2510) -> u8 {
2511    if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
2512        return 0;
2513    }
2514
2515    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2516    let field_name = match str::from_utf8(field_name_slice) {
2517        Ok(s) => s,
2518        Err(_) => return 0,
2519    };
2520    let object = &*object_ptr;
2521    let value = (&*value_ptr).clone();
2522    match object {
2523        Value::Struct { .. } => match object.struct_set_field(field_name, value) {
2524            Ok(()) => 1,
2525            Err(_) => 0,
2526        },
2527        Value::Map(map) => {
2528            use crate::bytecode::ValueKey;
2529            let key = ValueKey::from(field_name.to_string());
2530            map.borrow_mut().insert(key, value);
2531            1
2532        }
2533
2534        _ => 0,
2535    }
2536}
2537
2538#[no_mangle]
2539pub unsafe extern "C" fn jit_get_field_indexed_safe(
2540    object_ptr: *const Value,
2541    field_index: usize,
2542    out: *mut Value,
2543) -> u8 {
2544    if object_ptr.is_null() || out.is_null() {
2545        return 0;
2546    }
2547
2548    let object = &*object_ptr;
2549    match object.struct_get_field_indexed(field_index) {
2550        Some(value) => {
2551            ptr::write(out, value);
2552            1
2553        }
2554
2555        None => 0,
2556    }
2557}
2558
2559#[no_mangle]
2560pub unsafe extern "C" fn jit_set_field_indexed_safe(
2561    object_ptr: *const Value,
2562    field_index: usize,
2563    value_ptr: *const Value,
2564) -> u8 {
2565    if object_ptr.is_null() || value_ptr.is_null() {
2566        return 0;
2567    }
2568
2569    let object = &*object_ptr;
2570    let value = (&*value_ptr).clone();
2571    match object.struct_set_field_indexed(field_index, value) {
2572        Ok(()) => 1,
2573        Err(_) => 0,
2574    }
2575}
2576
2577#[no_mangle]
2578pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
2579    object_ptr: *const Value,
2580    field_index: usize,
2581    out: *mut Value,
2582) -> u8 {
2583    if object_ptr.is_null() || out.is_null() {
2584        return 0;
2585    }
2586
2587    let object = &*object_ptr;
2588    let out_ref = &mut *out;
2589    match object {
2590        Value::Struct { layout, fields, .. } => {
2591            if layout.is_weak(field_index) {
2592                return 0;
2593            }
2594
2595            if let Ok(borrowed) = fields.try_borrow() {
2596                if let Some(Value::Int(val)) = borrowed.get(field_index) {
2597                    *out_ref = Value::Int(*val);
2598                    return 1;
2599                }
2600            }
2601
2602            0
2603        }
2604
2605        _ => 0,
2606    }
2607}
2608
2609#[no_mangle]
2610pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
2611    object_ptr: *const Value,
2612    field_index: usize,
2613    value_ptr: *const Value,
2614) -> u8 {
2615    if object_ptr.is_null() || value_ptr.is_null() {
2616        return 0;
2617    }
2618
2619    let object = &*object_ptr;
2620    let value = &*value_ptr;
2621    let new_value = match value {
2622        Value::Int(v) => *v,
2623        _ => return 0,
2624    };
2625    match object {
2626        Value::Struct { layout, fields, .. } => {
2627            if layout.is_weak(field_index) {
2628                return 0;
2629            }
2630
2631            if let Ok(mut borrowed) = fields.try_borrow_mut() {
2632                if field_index < borrowed.len() {
2633                    borrowed[field_index] = Value::Int(new_value);
2634                    return 1;
2635                }
2636            }
2637
2638            0
2639        }
2640
2641        _ => 0,
2642    }
2643}
2644
2645#[no_mangle]
2646pub unsafe extern "C" fn jit_new_struct_safe(
2647    vm_ptr: *mut VM,
2648    struct_name_ptr: *const u8,
2649    struct_name_len: usize,
2650    field_names_ptr: *const *const u8,
2651    field_name_lens_ptr: *const usize,
2652    field_values_ptr: *const Value,
2653    field_count: usize,
2654    out: *mut Value,
2655) -> u8 {
2656    if struct_name_ptr.is_null() || out.is_null() || vm_ptr.is_null() {
2657        jit::log(|| "jit_new_struct_safe: null pointer input".to_string());
2658        return 0;
2659    }
2660
2661    if field_count > 0
2662        && (field_names_ptr.is_null()
2663            || field_name_lens_ptr.is_null()
2664            || field_values_ptr.is_null())
2665    {
2666        return 0;
2667    }
2668
2669    let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
2670    let struct_name = match str::from_utf8(struct_name_slice) {
2671        Ok(s) => s.to_string(),
2672        Err(_) => return 0,
2673    };
2674    let mut fields = Vec::with_capacity(field_count);
2675    for i in 0..field_count {
2676        let field_name_ptr = *field_names_ptr.add(i);
2677        let field_name_len = *field_name_lens_ptr.add(i);
2678        let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2679        let field_name = match str::from_utf8(field_name_slice) {
2680            Ok(s) => Rc::new(s.to_string()),
2681            Err(_) => return 0,
2682        };
2683        let field_value_ptr = field_values_ptr.add(i);
2684        let field_value = (&*field_value_ptr).clone();
2685        fields.push((field_name, field_value));
2686    }
2687
2688    let vm = &mut *vm_ptr;
2689    let struct_value = match vm.instantiate_struct(&struct_name, fields) {
2690        Ok(value) => value,
2691        Err(err) => {
2692            jit::log(|| {
2693                format!(
2694                    "jit_new_struct_safe: failed to instantiate '{}': {}",
2695                    struct_name, err
2696                )
2697            });
2698            return 0;
2699        }
2700    };
2701    ptr::write(out, struct_value);
2702    1
2703}
2704
2705#[no_mangle]
2706pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
2707    if src_ptr.is_null() || dest_ptr.is_null() {
2708        return 0;
2709    }
2710
2711    let src_value = &*src_ptr;
2712    let cloned_value = src_value.clone();
2713    ptr::write(dest_ptr, cloned_value);
2714    1
2715}