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