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