lust/bytecode/
value.rs

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