lust/bytecode/
value.rs

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