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