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_call_native_safe(
1335    vm_ptr: *mut VM,
1336    callee_ptr: *const Value,
1337    expected_fn_ptr: *const (),
1338    args_ptr: *const Value,
1339    arg_count: u8,
1340    out: *mut Value,
1341) -> u8 {
1342    if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1343        jit::log(|| "jit_call_native_safe: null argument".to_string());
1344        return 0;
1345    }
1346
1347    let callee = &*callee_ptr;
1348    let native_fn = match callee {
1349        Value::NativeFunction(func) => func.clone(),
1350        other => {
1351            jit::log(|| {
1352                format!(
1353                    "jit_call_native_safe: callee not native ({:?})",
1354                    other.tag()
1355                )
1356            });
1357            return 0;
1358        }
1359    };
1360
1361    if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1362        jit::log(|| {
1363            format!(
1364                "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1365                Rc::as_ptr(&native_fn),
1366                expected_fn_ptr
1367            )
1368        });
1369        return 0;
1370    }
1371
1372    let mut args = Vec::with_capacity(arg_count as usize);
1373    if arg_count > 0 {
1374        if args_ptr.is_null() {
1375            jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1376            return 0;
1377        }
1378
1379        for i in 0..(arg_count as usize) {
1380            let arg = &*args_ptr.add(i);
1381            args.push(arg.clone());
1382        }
1383    }
1384
1385    push_vm_ptr(vm_ptr);
1386    let outcome = native_fn(&args);
1387    pop_vm_ptr();
1388
1389    let outcome = match outcome {
1390        Ok(result) => result,
1391        Err(err) => {
1392            jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1393            return 0;
1394        }
1395    };
1396
1397    match outcome {
1398        NativeCallResult::Return(value) => {
1399            ptr::write(out, value);
1400            1
1401        }
1402
1403        NativeCallResult::Yield(_) => {
1404            jit::log(|| "jit_call_native_safe: native attempted to yield".to_string());
1405            0
1406        }
1407
1408        NativeCallResult::Stop(_) => {
1409            jit::log(|| "jit_call_native_safe: native attempted to stop".to_string());
1410            0
1411        }
1412    }
1413}
1414
1415#[no_mangle]
1416pub unsafe extern "C" fn jit_call_method_safe(
1417    object_ptr: *const Value,
1418    method_name_ptr: *const u8,
1419    method_name_len: usize,
1420    args_ptr: *const Value,
1421    arg_count: u8,
1422    out: *mut Value,
1423) -> u8 {
1424    if object_ptr.is_null() || method_name_ptr.is_null() || out.is_null() {
1425        return 0;
1426    }
1427
1428    if arg_count > 0 && args_ptr.is_null() {
1429        return 0;
1430    }
1431
1432    let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
1433    let method_name = match str::from_utf8(method_name_slice) {
1434        Ok(s) => s,
1435        Err(_) => return 0,
1436    };
1437    let object = &*object_ptr;
1438    if matches!(object, Value::Struct { .. }) {
1439        return 0;
1440    }
1441
1442    let mut args = Vec::with_capacity(arg_count as usize);
1443    for i in 0..arg_count {
1444        let arg_ptr = args_ptr.add(i as usize);
1445        args.push((&*arg_ptr).clone());
1446    }
1447
1448    let result = match call_builtin_method_simple(object, method_name, args) {
1449        Ok(val) => val,
1450        Err(_) => return 0,
1451    };
1452    ptr::write(out, result);
1453    1
1454}
1455
1456fn call_builtin_method_simple(
1457    object: &Value,
1458    method_name: &str,
1459    args: Vec<Value>,
1460) -> Result<Value, String> {
1461    match object {
1462        Value::Struct { name, .. } => Err(format!(
1463            "User-defined methods on {} require deoptimization",
1464            name
1465        )),
1466        Value::Iterator(state_rc) => match method_name {
1467            "next" => {
1468                let mut state = state_rc.borrow_mut();
1469                match &mut *state {
1470                    IteratorState::Array { items, index } => {
1471                        if *index < items.len() {
1472                            let v = items[*index].clone();
1473                            *index += 1;
1474                            Ok(Value::some(v))
1475                        } else {
1476                            Ok(Value::none())
1477                        }
1478                    }
1479
1480                    IteratorState::MapPairs { items, index } => {
1481                        if *index < items.len() {
1482                            let (k, v) = items[*index].clone();
1483                            *index += 1;
1484                            Ok(Value::some(Value::array(vec![k.to_value(), v])))
1485                        } else {
1486                            Ok(Value::none())
1487                        }
1488                    }
1489                }
1490            }
1491
1492            _ => Err(format!(
1493                "Iterator method '{}' not supported in JIT",
1494                method_name
1495            )),
1496        },
1497        Value::Enum {
1498            enum_name,
1499            variant,
1500            values,
1501        } if enum_name == "Option" => match method_name {
1502            "unwrap" => {
1503                if variant == "Some" {
1504                    if let Some(vals) = values {
1505                        if vals.len() == 1 {
1506                            Ok(vals[0].clone())
1507                        } else {
1508                            Err("Option::Some should have exactly 1 value".to_string())
1509                        }
1510                    } else {
1511                        Err("Option::Some should have a value".to_string())
1512                    }
1513                } else {
1514                    Err("Called unwrap() on Option::None".to_string())
1515                }
1516            }
1517
1518            _ => Err(format!(
1519                "Option method '{}' not supported in JIT",
1520                method_name
1521            )),
1522        },
1523        Value::Array(arr) => match method_name {
1524            "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
1525            "push" => {
1526                let value = args
1527                    .get(0)
1528                    .cloned()
1529                    .ok_or_else(|| "Array:push requires a value argument".to_string())?;
1530                arr.borrow_mut().push(value);
1531                Ok(Value::Nil)
1532            }
1533            "pop" => {
1534                let popped = arr.borrow_mut().pop();
1535                Ok(popped.map(Value::some).unwrap_or_else(Value::none))
1536            }
1537            "first" => {
1538                let borrowed = arr.borrow();
1539                Ok(borrowed
1540                    .first()
1541                    .cloned()
1542                    .map(Value::some)
1543                    .unwrap_or_else(Value::none))
1544            }
1545            "last" => {
1546                let borrowed = arr.borrow();
1547                Ok(borrowed
1548                    .last()
1549                    .cloned()
1550                    .map(Value::some)
1551                    .unwrap_or_else(Value::none))
1552            }
1553            "get" => {
1554                let index = args
1555                    .get(0)
1556                    .and_then(Value::as_int)
1557                    .ok_or_else(|| "Array:get requires an integer index".to_string())?;
1558                let borrowed = arr.borrow();
1559                Ok(borrowed
1560                    .get(index as usize)
1561                    .cloned()
1562                    .map(Value::some)
1563                    .unwrap_or_else(Value::none))
1564            }
1565            "iter" => {
1566                let items = arr.borrow().clone();
1567                let iter = IteratorState::Array { items, index: 0 };
1568                Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
1569            }
1570            _ => Err(format!(
1571                "Array method '{}' not supported in JIT",
1572                method_name
1573            )),
1574        },
1575        _ => Err(format!(
1576            "Method '{}' not supported in JIT (deoptimizing)",
1577            method_name
1578        )),
1579    }
1580}
1581
1582#[no_mangle]
1583pub unsafe extern "C" fn jit_get_field_safe(
1584    object_ptr: *const Value,
1585    field_name_ptr: *const u8,
1586    field_name_len: usize,
1587    out: *mut Value,
1588) -> u8 {
1589    if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
1590        return 0;
1591    }
1592
1593    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1594    let field_name = match str::from_utf8(field_name_slice) {
1595        Ok(s) => s,
1596        Err(_) => return 0,
1597    };
1598    let object = &*object_ptr;
1599    let field_value = match object {
1600        Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
1601            Some(idx) => match fields.borrow().get(idx) {
1602                Some(val) => val.clone(),
1603                None => return 0,
1604            },
1605            None => return 0,
1606        },
1607        _ => return 0,
1608    };
1609    ptr::write(out, field_value);
1610    1
1611}
1612
1613#[no_mangle]
1614pub unsafe extern "C" fn jit_set_field_safe(
1615    object_ptr: *const Value,
1616    field_name_ptr: *const u8,
1617    field_name_len: usize,
1618    value_ptr: *const Value,
1619) -> u8 {
1620    if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
1621        return 0;
1622    }
1623
1624    let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1625    let field_name = match str::from_utf8(field_name_slice) {
1626        Ok(s) => s,
1627        Err(_) => return 0,
1628    };
1629    let object = &*object_ptr;
1630    let value = (&*value_ptr).clone();
1631    match object {
1632        Value::Struct { .. } => match object.struct_set_field(field_name, value) {
1633            Ok(()) => 1,
1634            Err(_) => 0,
1635        },
1636        Value::Map(map) => {
1637            use crate::bytecode::ValueKey;
1638            let key = ValueKey::String(Rc::new(field_name.to_string()));
1639            map.borrow_mut().insert(key, value);
1640            1
1641        }
1642
1643        _ => 0,
1644    }
1645}
1646
1647#[no_mangle]
1648pub unsafe extern "C" fn jit_get_field_indexed_safe(
1649    object_ptr: *const Value,
1650    field_index: usize,
1651    out: *mut Value,
1652) -> u8 {
1653    if object_ptr.is_null() || out.is_null() {
1654        return 0;
1655    }
1656
1657    let object = &*object_ptr;
1658    match object.struct_get_field_indexed(field_index) {
1659        Some(value) => {
1660            ptr::write(out, value);
1661            1
1662        }
1663
1664        None => 0,
1665    }
1666}
1667
1668#[no_mangle]
1669pub unsafe extern "C" fn jit_set_field_indexed_safe(
1670    object_ptr: *const Value,
1671    field_index: usize,
1672    value_ptr: *const Value,
1673) -> u8 {
1674    if object_ptr.is_null() || value_ptr.is_null() {
1675        return 0;
1676    }
1677
1678    let object = &*object_ptr;
1679    let value = (&*value_ptr).clone();
1680    match object.struct_set_field_indexed(field_index, value) {
1681        Ok(()) => 1,
1682        Err(_) => 0,
1683    }
1684}
1685
1686#[no_mangle]
1687pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
1688    object_ptr: *const Value,
1689    field_index: usize,
1690    out: *mut Value,
1691) -> u8 {
1692    if object_ptr.is_null() || out.is_null() {
1693        return 0;
1694    }
1695
1696    let object = &*object_ptr;
1697    let out_ref = &mut *out;
1698    match object {
1699        Value::Struct { layout, fields, .. } => {
1700            if layout.is_weak(field_index) {
1701                return 0;
1702            }
1703
1704            if let Ok(borrowed) = fields.try_borrow() {
1705                if let Some(Value::Int(val)) = borrowed.get(field_index) {
1706                    *out_ref = Value::Int(*val);
1707                    return 1;
1708                }
1709            }
1710
1711            0
1712        }
1713
1714        _ => 0,
1715    }
1716}
1717
1718#[no_mangle]
1719pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
1720    object_ptr: *const Value,
1721    field_index: usize,
1722    value_ptr: *const Value,
1723) -> u8 {
1724    if object_ptr.is_null() || value_ptr.is_null() {
1725        return 0;
1726    }
1727
1728    let object = &*object_ptr;
1729    let value = &*value_ptr;
1730    let new_value = match value {
1731        Value::Int(v) => *v,
1732        _ => return 0,
1733    };
1734    match object {
1735        Value::Struct { layout, fields, .. } => {
1736            if layout.is_weak(field_index) {
1737                return 0;
1738            }
1739
1740            if let Ok(mut borrowed) = fields.try_borrow_mut() {
1741                if field_index < borrowed.len() {
1742                    borrowed[field_index] = Value::Int(new_value);
1743                    return 1;
1744                }
1745            }
1746
1747            0
1748        }
1749
1750        _ => 0,
1751    }
1752}
1753
1754#[no_mangle]
1755pub unsafe extern "C" fn jit_new_struct_safe(
1756    struct_name_ptr: *const u8,
1757    struct_name_len: usize,
1758    field_names_ptr: *const *const u8,
1759    field_name_lens_ptr: *const usize,
1760    field_values_ptr: *const Value,
1761    field_count: usize,
1762    out: *mut Value,
1763) -> u8 {
1764    if struct_name_ptr.is_null() || out.is_null() {
1765        return 0;
1766    }
1767
1768    if field_count > 0
1769        && (field_names_ptr.is_null()
1770            || field_name_lens_ptr.is_null()
1771            || field_values_ptr.is_null())
1772    {
1773        return 0;
1774    }
1775
1776    let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
1777    let struct_name = match str::from_utf8(struct_name_slice) {
1778        Ok(s) => s.to_string(),
1779        Err(_) => return 0,
1780    };
1781    let mut fields = Vec::with_capacity(field_count);
1782    for i in 0..field_count {
1783        let field_name_ptr = *field_names_ptr.add(i);
1784        let field_name_len = *field_name_lens_ptr.add(i);
1785        let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1786        let field_name = match str::from_utf8(field_name_slice) {
1787            Ok(s) => Rc::new(s.to_string()),
1788            Err(_) => return 0,
1789        };
1790        let field_value_ptr = field_values_ptr.add(i);
1791        let field_value = (&*field_value_ptr).clone();
1792        fields.push((field_name, field_value));
1793    }
1794
1795    let struct_value = match crate::vm::VM::with_current(move |vm| {
1796        vm.instantiate_struct(&struct_name, fields)
1797            .map_err(|err| err.to_string())
1798    }) {
1799        Ok(value) => value,
1800        Err(_) => return 0,
1801    };
1802    ptr::write(out, struct_value);
1803    1
1804}
1805
1806#[no_mangle]
1807pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
1808    if src_ptr.is_null() || dest_ptr.is_null() {
1809        return 0;
1810    }
1811
1812    let src_value = &*src_ptr;
1813    let cloned_value = src_value.clone();
1814    ptr::write(dest_ptr, cloned_value);
1815    1
1816}