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