lust/bytecode/
value.rs

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