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