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 !matches!(self, Value::Nil | Value::Bool(false))
585 }
586
587 pub fn to_bool(&self) -> bool {
588 self.is_truthy()
589 }
590
591 pub fn as_int(&self) -> Option<LustInt> {
592 match self {
593 Value::Int(i) => Some(*i),
594 Value::Float(f) => Some(int_from_float(*f)),
595 _ => None,
596 }
597 }
598
599 pub fn as_float(&self) -> Option<LustFloat> {
600 match self {
601 Value::Float(f) => Some(*f),
602 Value::Int(i) => Some(float_from_int(*i)),
603 _ => None,
604 }
605 }
606
607 pub fn as_string(&self) -> Option<&str> {
608 match self {
609 Value::String(s) => Some(s.as_str()),
610 _ => None,
611 }
612 }
613
614 pub fn as_string_rc(&self) -> Option<Rc<String>> {
615 match self {
616 Value::String(s) => Some(s.clone()),
617 _ => None,
618 }
619 }
620
621 pub fn as_task_handle(&self) -> Option<TaskHandle> {
622 match self {
623 Value::Task(handle) => Some(*handle),
624 _ => None,
625 }
626 }
627
628 pub fn as_array(&self) -> Option<Vec<Value>> {
629 match self {
630 Value::Array(arr) => Some(arr.borrow().clone()),
631 _ => None,
632 }
633 }
634
635 pub fn array_len(&self) -> Option<usize> {
636 match self {
637 Value::Array(arr) => Some(arr.borrow().len()),
638 _ => None,
639 }
640 }
641
642 pub fn array_get(&self, index: usize) -> Option<Value> {
643 match self {
644 Value::Array(arr) => arr.borrow().get(index).cloned(),
645 _ => None,
646 }
647 }
648
649 pub fn array_push(&self, value: Value) -> Result<(), String> {
650 match self {
651 Value::Array(arr) => {
652 arr.borrow_mut().push(value);
653 Ok(())
654 }
655
656 _ => Err("Cannot push to non-array".to_string()),
657 }
658 }
659
660 pub fn array_pop(&self) -> Result<Option<Value>, String> {
661 match self {
662 Value::Array(arr) => Ok(arr.borrow_mut().pop()),
663 _ => Err("Cannot pop from non-array".to_string()),
664 }
665 }
666
667 pub fn as_map(&self) -> Option<HashMap<ValueKey, Value>> {
668 match self {
669 Value::Map(map) => Some(map.borrow().clone()),
670 _ => None,
671 }
672 }
673
674 pub fn map_get(&self, key: &ValueKey) -> Option<Value> {
675 match self {
676 Value::Map(map) => map.borrow().get(key).cloned(),
677 _ => None,
678 }
679 }
680
681 pub fn map_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
682 match self {
683 Value::Map(map) => {
684 map.borrow_mut().insert(key, value);
685 Ok(())
686 }
687
688 _ => Err("Cannot set key on non-map".to_string()),
689 }
690 }
691
692 pub fn map_has(&self, key: &ValueKey) -> Option<bool> {
693 match self {
694 Value::Map(map) => Some(map.borrow().contains_key(key)),
695 _ => None,
696 }
697 }
698
699 pub fn map_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
700 match self {
701 Value::Map(map) => Ok(map.borrow_mut().remove(key)),
702 _ => Err("Cannot delete key from non-map".to_string()),
703 }
704 }
705
706 pub fn map_len(&self) -> Option<usize> {
707 match self {
708 Value::Map(map) => Some(map.borrow().len()),
709 _ => None,
710 }
711 }
712
713 pub fn as_table(&self) -> Option<HashMap<ValueKey, Value>> {
714 match self {
715 Value::Table(table) => Some(table.borrow().clone()),
716 _ => None,
717 }
718 }
719
720 pub fn table_get(&self, key: &ValueKey) -> Option<Value> {
721 match self {
722 Value::Table(table) => table.borrow().get(key).cloned(),
723 _ => None,
724 }
725 }
726
727 pub fn table_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
728 match self {
729 Value::Table(table) => {
730 table.borrow_mut().insert(key, value);
731 Ok(())
732 }
733
734 _ => Err("Cannot set key on non-table".to_string()),
735 }
736 }
737
738 pub fn table_has(&self, key: &ValueKey) -> Option<bool> {
739 match self {
740 Value::Table(table) => Some(table.borrow().contains_key(key)),
741 _ => None,
742 }
743 }
744
745 pub fn table_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
746 match self {
747 Value::Table(table) => Ok(table.borrow_mut().remove(key)),
748 _ => Err("Cannot delete key from non-table".to_string()),
749 }
750 }
751
752 pub fn table_len(&self) -> Option<usize> {
753 match self {
754 Value::Table(table) => Some(table.borrow().len()),
755 _ => None,
756 }
757 }
758
759 pub fn string(s: impl Into<String>) -> Self {
760 Value::String(Rc::new(s.into()))
761 }
762
763 pub fn array(values: Vec<Value>) -> Self {
764 Value::Array(Rc::new(RefCell::new(values)))
765 }
766
767 pub fn tuple(values: Vec<Value>) -> Self {
768 Value::Tuple(Rc::new(values))
769 }
770
771 pub fn tuple_len(&self) -> Option<usize> {
772 match self {
773 Value::Tuple(values) => Some(values.len()),
774 _ => None,
775 }
776 }
777
778 pub fn tuple_get(&self, index: usize) -> Option<Value> {
779 match self {
780 Value::Tuple(values) => values.get(index).cloned(),
781 _ => None,
782 }
783 }
784
785 pub fn map(entries: HashMap<ValueKey, Value>) -> Self {
786 Value::Map(Rc::new(RefCell::new(entries)))
787 }
788
789 pub fn table(entries: HashMap<ValueKey, Value>) -> Self {
790 Value::Table(Rc::new(RefCell::new(entries)))
791 }
792
793 pub fn task(handle: TaskHandle) -> Self {
794 Value::Task(handle)
795 }
796
797 pub fn struct_get_field_rc(&self, field: &Rc<String>) -> Option<Value> {
798 match self {
799 Value::Struct { layout, fields, .. } => layout
800 .index_of_rc(field)
801 .or_else(|| layout.index_of_str(field.as_str()))
802 .and_then(|idx| {
803 fields
804 .borrow()
805 .get(idx)
806 .cloned()
807 .map(|value| layout.materialize_field_value(idx, value))
808 }),
809 _ => None,
810 }
811 }
812
813 pub fn struct_get_field(&self, field: &str) -> Option<Value> {
814 match self {
815 Value::Struct { layout, fields, .. } => layout.index_of_str(field).and_then(|idx| {
816 fields
817 .borrow()
818 .get(idx)
819 .cloned()
820 .map(|value| layout.materialize_field_value(idx, value))
821 }),
822 _ => None,
823 }
824 }
825
826 pub fn struct_get_field_indexed(&self, index: usize) -> Option<Value> {
827 match self {
828 Value::Struct { layout, fields, .. } => fields
829 .borrow()
830 .get(index)
831 .cloned()
832 .map(|value| layout.materialize_field_value(index, value)),
833 _ => None,
834 }
835 }
836
837 pub fn struct_set_field_rc(&self, field: &Rc<String>, value: Value) -> Result<(), String> {
838 match self {
839 Value::Struct { layout, .. } => {
840 if let Some(index) = layout
841 .index_of_rc(field)
842 .or_else(|| layout.index_of_str(field.as_str()))
843 {
844 self.struct_set_field_indexed(index, value)
845 } else {
846 Err(format!(
847 "Struct '{}' has no field '{}'",
848 layout.name(),
849 field.as_str()
850 ))
851 }
852 }
853
854 _ => Err("Attempted to set field on non-struct value".to_string()),
855 }
856 }
857
858 pub fn struct_set_field(&self, field: &str, value: Value) -> Result<(), String> {
859 match self {
860 Value::Struct { layout, .. } => {
861 if let Some(index) = layout.index_of_str(field) {
862 self.struct_set_field_indexed(index, value)
863 } else {
864 Err(format!(
865 "Struct '{}' has no field '{}'",
866 layout.name(),
867 field
868 ))
869 }
870 }
871
872 _ => Err("Attempted to set field on non-struct value".to_string()),
873 }
874 }
875
876 pub fn struct_set_field_indexed(&self, index: usize, value: Value) -> Result<(), String> {
877 match self {
878 Value::Struct {
879 name,
880 layout,
881 fields,
882 } => {
883 let mut borrowed = fields.borrow_mut();
884 if index < borrowed.len() {
885 let canonical = layout.canonicalize_field_value(index, value)?;
886 borrowed[index] = canonical;
887 Ok(())
888 } else {
889 Err(format!(
890 "Struct '{}' field index {} out of bounds (len {})",
891 name,
892 index,
893 borrowed.len()
894 ))
895 }
896 }
897
898 _ => Err("Attempted to set field on non-struct value".to_string()),
899 }
900 }
901
902 pub fn enum_unit(enum_name: impl Into<String>, variant: impl Into<String>) -> Self {
903 Value::Enum {
904 enum_name: enum_name.into(),
905 variant: variant.into(),
906 values: None,
907 }
908 }
909
910 pub fn enum_variant(
911 enum_name: impl Into<String>,
912 variant: impl Into<String>,
913 values: Vec<Value>,
914 ) -> Self {
915 Value::Enum {
916 enum_name: enum_name.into(),
917 variant: variant.into(),
918 values: Some(Rc::new(values)),
919 }
920 }
921
922 pub fn as_enum(&self) -> Option<(&str, &str, Option<&[Value]>)> {
923 match self {
924 Value::Enum {
925 enum_name,
926 variant,
927 values,
928 } => Some((
929 enum_name.as_str(),
930 variant.as_str(),
931 values.as_ref().map(|v| v.as_slice()),
932 )),
933 _ => None,
934 }
935 }
936
937 pub fn is_enum_variant(&self, enum_name: &str, variant: &str) -> bool {
938 match self {
939 Value::Enum {
940 enum_name: en,
941 variant: v,
942 ..
943 } => (enum_name.is_empty() || en == enum_name) && v == variant,
944 _ => false,
945 }
946 }
947
948 pub fn some(value: Value) -> Self {
949 Value::enum_variant("Option", "Some", vec![value])
950 }
951
952 pub fn none() -> Self {
953 Value::enum_unit("Option", "None")
954 }
955
956 pub fn ok(value: Value) -> Self {
957 Value::enum_variant("Result", "Ok", vec![value])
958 }
959
960 pub fn err(error: Value) -> Self {
961 Value::enum_variant("Result", "Err", vec![error])
962 }
963
964 pub fn to_string(&self) -> String {
965 format!("{}", self)
966 }
967}
968
969impl fmt::Debug for Value {
970 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
971 match self {
972 Value::Nil => write!(f, "Nil"),
973 Value::Bool(b) => write!(f, "Bool({})", b),
974 Value::Int(i) => write!(f, "Int({})", i),
975 Value::Float(fl) => write!(f, "Float({})", fl),
976 Value::String(s) => write!(f, "String({:?})", s),
977 Value::Array(arr) => write!(f, "Array({:?})", arr.borrow()),
978 Value::Tuple(values) => write!(f, "Tuple({:?})", values),
979 Value::Map(map) => write!(f, "Map({:?})", map.borrow()),
980 Value::Table(table) => write!(f, "Table({:?})", table.borrow()),
981 Value::Struct {
982 name,
983 layout,
984 fields,
985 } => {
986 let borrowed = fields.borrow();
987 let mut display_fields = Vec::with_capacity(borrowed.len());
988 for (idx, field_name) in layout.field_names().iter().enumerate() {
989 let value = borrowed.get(idx).cloned().unwrap_or(Value::Nil);
990 display_fields.push((field_name.as_str().to_string(), value));
991 }
992
993 write!(
994 f,
995 "Struct {{ name: {:?}, fields: {:?} }}",
996 name, display_fields
997 )
998 }
999
1000 Value::WeakStruct(weak) => {
1001 if let Some(upgraded) = weak.upgrade() {
1002 write!(f, "WeakStruct({:?})", upgraded)
1003 } else {
1004 write!(f, "WeakStruct(<dangling>)")
1005 }
1006 }
1007
1008 Value::Enum {
1009 enum_name,
1010 variant,
1011 values,
1012 } => {
1013 write!(
1014 f,
1015 "Enum {{ enum: {:?}, variant: {:?}, values: {:?} }}",
1016 enum_name, variant, values
1017 )
1018 }
1019
1020 Value::Function(idx) => write!(f, "Function({})", idx),
1021 Value::NativeFunction(_) => write!(f, "NativeFunction(<fn>)"),
1022 Value::Closure {
1023 function_idx,
1024 upvalues,
1025 } => {
1026 write!(
1027 f,
1028 "Closure {{ function: {}, upvalues: {:?} }}",
1029 function_idx, upvalues
1030 )
1031 }
1032
1033 Value::Iterator(_) => write!(f, "Iterator(<state>)"),
1034 Value::Task(handle) => write!(f, "Task({})", handle.0),
1035 }
1036 }
1037}
1038
1039impl fmt::Display for Value {
1040 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1041 match self {
1042 Value::Nil => write!(f, "nil"),
1043 Value::Bool(b) => write!(f, "{}", b),
1044 Value::Int(i) => write!(f, "{}", i),
1045 Value::Float(fl) => write!(f, "{}", fl),
1046 Value::String(s) => write!(f, "{}", s),
1047 Value::Array(arr) => {
1048 write!(f, "[")?;
1049 let borrowed = arr.borrow();
1050 for (i, val) in borrowed.iter().enumerate() {
1051 if i > 0 {
1052 write!(f, ", ")?;
1053 }
1054
1055 write!(f, "{}", val)?;
1056 }
1057
1058 write!(f, "]")
1059 }
1060
1061 Value::Tuple(values) => {
1062 write!(f, "(")?;
1063 for (i, val) in values.iter().enumerate() {
1064 if i > 0 {
1065 write!(f, ", ")?;
1066 }
1067
1068 write!(f, "{}", val)?;
1069 }
1070
1071 write!(f, ")")
1072 }
1073
1074 Value::Map(map) => {
1075 write!(f, "{{")?;
1076 let borrowed = map.borrow();
1077 for (i, (k, v)) in borrowed.iter().enumerate() {
1078 if i > 0 {
1079 write!(f, ", ")?;
1080 }
1081
1082 write!(f, "{}: {}", k, v)?;
1083 }
1084
1085 write!(f, "}}")
1086 }
1087
1088 Value::Table(table) => {
1089 write!(f, "{{")?;
1090 let borrowed = table.borrow();
1091 for (i, (k, v)) in borrowed.iter().enumerate() {
1092 if i > 0 {
1093 write!(f, ", ")?;
1094 }
1095
1096 write!(f, "{}: {}", k, v)?;
1097 }
1098
1099 write!(f, "}}")
1100 }
1101
1102 Value::Struct {
1103 name,
1104 layout,
1105 fields,
1106 } => {
1107 let borrowed = fields.borrow();
1108 write!(f, "{} {{", name)?;
1109 for (i, field_name) in layout.field_names().iter().enumerate() {
1110 if i > 0 {
1111 write!(f, ", ")?;
1112 }
1113
1114 let value = borrowed.get(i).unwrap_or(&Value::Nil);
1115 write!(f, "{}: {}", field_name, value)?;
1116 }
1117
1118 write!(f, "}}")
1119 }
1120
1121 Value::WeakStruct(weak) => {
1122 if let Some(strong) = weak.upgrade() {
1123 strong.fmt(f)
1124 } else {
1125 write!(f, "nil")
1126 }
1127 }
1128
1129 Value::Enum {
1130 enum_name,
1131 variant,
1132 values,
1133 } => {
1134 write!(f, "{}.{}", enum_name, variant)?;
1135 if let Some(vals) = values {
1136 write!(f, "(")?;
1137 for (i, val) in vals.iter().enumerate() {
1138 if i > 0 {
1139 write!(f, ", ")?;
1140 }
1141
1142 write!(f, "{}", val)?;
1143 }
1144
1145 write!(f, ")")?;
1146 }
1147
1148 Ok(())
1149 }
1150
1151 Value::Function(idx) => write!(f, "<function@{}>", idx),
1152 Value::NativeFunction(_) => write!(f, "<native function>"),
1153 Value::Closure { function_idx, .. } => write!(f, "<closure@{}>", function_idx),
1154 Value::Iterator(_) => write!(f, "<iterator>"),
1155 Value::Task(handle) => write!(f, "<task {}>", handle.0),
1156 }
1157 }
1158}
1159
1160impl PartialEq for Value {
1161 fn eq(&self, other: &Self) -> bool {
1162 match (self, other) {
1163 (Value::Nil, Value::Nil) => true,
1164 (Value::Bool(a), Value::Bool(b)) => a == b,
1165 (Value::Int(a), Value::Int(b)) => a == b,
1166 (Value::Float(a), Value::Float(b)) => a == b,
1167 (Value::String(a), Value::String(b)) => a == b,
1168 (Value::Array(a), Value::Array(b)) => *a.borrow() == *b.borrow(),
1169 (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
1170 (Value::Map(a), Value::Map(b)) => *a.borrow() == *b.borrow(),
1171 (Value::Table(a), Value::Table(b)) => *a.borrow() == *b.borrow(),
1172 (
1173 Value::Struct {
1174 name: n1,
1175 layout: l1,
1176 fields: f1,
1177 },
1178 Value::Struct {
1179 name: n2,
1180 layout: l2,
1181 fields: f2,
1182 },
1183 ) => {
1184 if n1 != n2 {
1185 return false;
1186 }
1187
1188 let borrowed_f1 = f1.borrow();
1189 let borrowed_f2 = f2.borrow();
1190 if borrowed_f1.len() != borrowed_f2.len() {
1191 return false;
1192 }
1193
1194 if Rc::ptr_eq(l1, l2) {
1195 return borrowed_f1
1196 .iter()
1197 .zip(borrowed_f2.iter())
1198 .all(|(a, b)| a == b);
1199 }
1200
1201 l1.field_names()
1202 .iter()
1203 .enumerate()
1204 .all(|(idx, field_name)| {
1205 if let Some(other_idx) = l2.index_of_rc(field_name) {
1206 borrowed_f1
1207 .get(idx)
1208 .zip(borrowed_f2.get(other_idx))
1209 .map(|(a, b)| a == b)
1210 .unwrap_or(false)
1211 } else {
1212 false
1213 }
1214 })
1215 }
1216
1217 (Value::WeakStruct(a), Value::WeakStruct(b)) => match (a.upgrade(), b.upgrade()) {
1218 (Some(left), Some(right)) => left == right,
1219 (None, None) => true,
1220 _ => false,
1221 },
1222 (Value::WeakStruct(a), other) => a
1223 .upgrade()
1224 .map(|upgraded| upgraded == *other)
1225 .unwrap_or(matches!(other, Value::Nil)),
1226 (value, Value::WeakStruct(b)) => b
1227 .upgrade()
1228 .map(|upgraded| *value == upgraded)
1229 .unwrap_or(matches!(value, Value::Nil)),
1230 (
1231 Value::Enum {
1232 enum_name: e1,
1233 variant: v1,
1234 values: vals1,
1235 },
1236 Value::Enum {
1237 enum_name: e2,
1238 variant: v2,
1239 values: vals2,
1240 },
1241 ) => e1 == e2 && v1 == v2 && vals1 == vals2,
1242 (Value::Function(a), Value::Function(b)) => a == b,
1243 (
1244 Value::Closure {
1245 function_idx: f1,
1246 upvalues: u1,
1247 },
1248 Value::Closure {
1249 function_idx: f2,
1250 upvalues: u2,
1251 },
1252 ) => f1 == f2 && Rc::ptr_eq(u1, u2),
1253 (Value::Iterator(_), Value::Iterator(_)) => false,
1254 (Value::Task(a), Value::Task(b)) => a == b,
1255 _ => false,
1256 }
1257 }
1258}
1259
1260#[cfg(feature = "std")]
1261#[no_mangle]
1262pub unsafe extern "C" fn jit_array_get_safe(
1263 array_value_ptr: *const Value,
1264 index: i64,
1265 out: *mut Value,
1266) -> u8 {
1267 if array_value_ptr.is_null() || out.is_null() {
1268 eprintln!("❌ jit_array_get_safe: null pointer detected!");
1269 return 0;
1270 }
1271
1272 let array_value = &*array_value_ptr;
1273 let arr = match array_value {
1274 Value::Array(arr) => arr,
1275 _ => {
1276 return 0;
1277 }
1278 };
1279 if index < 0 {
1280 return 0;
1281 }
1282
1283 let idx = index as usize;
1284 let borrowed = match arr.try_borrow() {
1285 Ok(b) => b,
1286 Err(_) => {
1287 return 0;
1288 }
1289 };
1290 if idx >= borrowed.len() {
1291 return 0;
1292 }
1293
1294 ptr::write(out, borrowed[idx].clone());
1295 1
1296}
1297
1298#[cfg(feature = "std")]
1299#[no_mangle]
1300pub unsafe extern "C" fn jit_array_len_safe(array_value_ptr: *const Value) -> i64 {
1301 if array_value_ptr.is_null() {
1302 return -1;
1303 }
1304
1305 let array_value = &*array_value_ptr;
1306 match array_value {
1307 Value::Array(arr) => match arr.try_borrow() {
1308 Ok(borrowed) => int_from_usize(borrowed.len()),
1309 Err(_) => -1,
1310 },
1311 _ => -1,
1312 }
1313}
1314
1315#[cfg(feature = "std")]
1316#[no_mangle]
1317pub unsafe extern "C" fn jit_concat_safe(
1318 left_value_ptr: *const Value,
1319 right_value_ptr: *const Value,
1320 out: *mut Value,
1321) -> u8 {
1322 if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1323 return 0;
1324 }
1325
1326 let left = &*left_value_ptr;
1327 let right = &*right_value_ptr;
1328 const NO_VM_ERROR: &str = "task API requires a running VM";
1329 let left_str = match VM::with_current(|vm| {
1330 let left_copy = left.clone();
1331 vm.value_to_string_for_concat(&left_copy)
1332 .map_err(|err| err.to_string())
1333 }) {
1334 Ok(rc) => rc,
1335 Err(err) if err == NO_VM_ERROR => Rc::new(left.to_string()),
1336 Err(_) => return 0,
1337 };
1338 let right_str = match VM::with_current(|vm| {
1339 let right_copy = right.clone();
1340 vm.value_to_string_for_concat(&right_copy)
1341 .map_err(|err| err.to_string())
1342 }) {
1343 Ok(rc) => rc,
1344 Err(err) if err == NO_VM_ERROR => Rc::new(right.to_string()),
1345 Err(_) => return 0,
1346 };
1347 let mut combined = String::with_capacity(left_str.len() + right_str.len());
1348 combined.push_str(left_str.as_ref());
1349 combined.push_str(right_str.as_ref());
1350 let result = Value::string(combined);
1351 ptr::write(out, result);
1352 1
1353}
1354
1355#[no_mangle]
1356pub unsafe extern "C" fn jit_guard_native_function(
1357 value_ptr: *const Value,
1358 expected_fn_ptr: *const (),
1359 register_index: u8,
1360) -> u8 {
1361 if value_ptr.is_null() || expected_fn_ptr.is_null() {
1362 jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1363 return 0;
1364 }
1365
1366 match &*value_ptr {
1367 Value::NativeFunction(func) => {
1368 let actual = Rc::as_ptr(func) as *const ();
1369 if actual == expected_fn_ptr {
1370 1
1371 } else {
1372 jit::log(|| {
1373 format!(
1374 "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1375 register_index, actual, expected_fn_ptr
1376 )
1377 });
1378 0
1379 }
1380 }
1381
1382 other => {
1383 jit::log(|| {
1384 format!(
1385 "jit_guard_native_function: value not native in reg {} ({:?})",
1386 register_index,
1387 other.tag()
1388 )
1389 });
1390 0
1391 }
1392 }
1393}
1394
1395#[no_mangle]
1396pub unsafe extern "C" fn jit_call_native_safe(
1397 vm_ptr: *mut VM,
1398 callee_ptr: *const Value,
1399 expected_fn_ptr: *const (),
1400 args_ptr: *const Value,
1401 arg_count: u8,
1402 out: *mut Value,
1403) -> u8 {
1404 if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1405 jit::log(|| "jit_call_native_safe: null argument".to_string());
1406 return 0;
1407 }
1408
1409 let callee = &*callee_ptr;
1410 let native_fn = match callee {
1411 Value::NativeFunction(func) => func.clone(),
1412 other => {
1413 jit::log(|| {
1414 format!(
1415 "jit_call_native_safe: callee not native ({:?})",
1416 other.tag()
1417 )
1418 });
1419 return 0;
1420 }
1421 };
1422
1423 if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1424 jit::log(|| {
1425 format!(
1426 "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1427 Rc::as_ptr(&native_fn),
1428 expected_fn_ptr
1429 )
1430 });
1431 return 0;
1432 }
1433
1434 let mut args = Vec::with_capacity(arg_count as usize);
1435 if arg_count > 0 {
1436 if args_ptr.is_null() {
1437 jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1438 return 0;
1439 }
1440
1441 for i in 0..(arg_count as usize) {
1442 let arg = &*args_ptr.add(i);
1443 args.push(arg.clone());
1444 }
1445 }
1446
1447 push_vm_ptr(vm_ptr);
1448 let outcome = native_fn(&args);
1449 pop_vm_ptr();
1450
1451 let outcome = match outcome {
1452 Ok(result) => result,
1453 Err(err) => {
1454 jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1455 return 0;
1456 }
1457 };
1458
1459 match outcome {
1460 NativeCallResult::Return(value) => {
1461 ptr::write(out, value);
1462 1
1463 }
1464
1465 NativeCallResult::Yield(_) => {
1466 jit::log(|| "jit_call_native_safe: native attempted to yield".to_string());
1467 0
1468 }
1469
1470 NativeCallResult::Stop(_) => {
1471 jit::log(|| "jit_call_native_safe: native attempted to stop".to_string());
1472 0
1473 }
1474 }
1475}
1476
1477#[no_mangle]
1478pub unsafe extern "C" fn jit_call_method_safe(
1479 object_ptr: *const Value,
1480 method_name_ptr: *const u8,
1481 method_name_len: usize,
1482 args_ptr: *const Value,
1483 arg_count: u8,
1484 out: *mut Value,
1485) -> u8 {
1486 if object_ptr.is_null() || method_name_ptr.is_null() || out.is_null() {
1487 return 0;
1488 }
1489
1490 if arg_count > 0 && args_ptr.is_null() {
1491 return 0;
1492 }
1493
1494 let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
1495 let method_name = match str::from_utf8(method_name_slice) {
1496 Ok(s) => s,
1497 Err(_) => return 0,
1498 };
1499 let object = &*object_ptr;
1500 if matches!(object, Value::Struct { .. }) {
1501 return 0;
1502 }
1503
1504 let mut args = Vec::with_capacity(arg_count as usize);
1505 for i in 0..arg_count {
1506 let arg_ptr = args_ptr.add(i as usize);
1507 args.push((&*arg_ptr).clone());
1508 }
1509
1510 let result = match call_builtin_method_simple(object, method_name, args) {
1511 Ok(val) => val,
1512 Err(_) => return 0,
1513 };
1514 ptr::write(out, result);
1515 1
1516}
1517
1518fn call_builtin_method_simple(
1519 object: &Value,
1520 method_name: &str,
1521 args: Vec<Value>,
1522) -> Result<Value, String> {
1523 match object {
1524 Value::Struct { name, .. } => Err(format!(
1525 "User-defined methods on {} require deoptimization",
1526 name
1527 )),
1528 Value::Iterator(state_rc) => match method_name {
1529 "next" => {
1530 let mut state = state_rc.borrow_mut();
1531 match &mut *state {
1532 IteratorState::Array { items, index } => {
1533 if *index < items.len() {
1534 let v = items[*index].clone();
1535 *index += 1;
1536 Ok(Value::some(v))
1537 } else {
1538 Ok(Value::none())
1539 }
1540 }
1541
1542 IteratorState::MapPairs { items, index } => {
1543 if *index < items.len() {
1544 let (k, v) = items[*index].clone();
1545 *index += 1;
1546 Ok(Value::some(Value::array(vec![k.to_value(), v])))
1547 } else {
1548 Ok(Value::none())
1549 }
1550 }
1551
1552 IteratorState::TablePairs { items, index } => {
1553 if *index < items.len() {
1554 let (k, v) = items[*index].clone();
1555 *index += 1;
1556 Ok(Value::some(Value::array(vec![k.to_value(), v])))
1557 } else {
1558 Ok(Value::none())
1559 }
1560 }
1561 }
1562 }
1563
1564 _ => Err(format!(
1565 "Iterator method '{}' not supported in JIT",
1566 method_name
1567 )),
1568 },
1569 Value::Enum {
1570 enum_name,
1571 variant,
1572 values,
1573 } if enum_name == "Option" => match method_name {
1574 "unwrap" => {
1575 if variant == "Some" {
1576 if let Some(vals) = values {
1577 if vals.len() == 1 {
1578 Ok(vals[0].clone())
1579 } else {
1580 Err("Option::Some should have exactly 1 value".to_string())
1581 }
1582 } else {
1583 Err("Option::Some should have a value".to_string())
1584 }
1585 } else {
1586 Err("Called unwrap() on Option::None".to_string())
1587 }
1588 }
1589
1590 _ => Err(format!(
1591 "Option method '{}' not supported in JIT",
1592 method_name
1593 )),
1594 },
1595 Value::Array(arr) => match method_name {
1596 "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
1597 "push" => {
1598 let value = args
1599 .get(0)
1600 .cloned()
1601 .ok_or_else(|| "Array:push requires a value argument".to_string())?;
1602 arr.borrow_mut().push(value);
1603 Ok(Value::Nil)
1604 }
1605 "pop" => {
1606 let popped = arr.borrow_mut().pop();
1607 Ok(popped.map(Value::some).unwrap_or_else(Value::none))
1608 }
1609 "first" => {
1610 let borrowed = arr.borrow();
1611 Ok(borrowed
1612 .first()
1613 .cloned()
1614 .map(Value::some)
1615 .unwrap_or_else(Value::none))
1616 }
1617 "last" => {
1618 let borrowed = arr.borrow();
1619 Ok(borrowed
1620 .last()
1621 .cloned()
1622 .map(Value::some)
1623 .unwrap_or_else(Value::none))
1624 }
1625 "get" => {
1626 let index = args
1627 .get(0)
1628 .and_then(Value::as_int)
1629 .ok_or_else(|| "Array:get requires an integer index".to_string())?;
1630 let borrowed = arr.borrow();
1631 Ok(borrowed
1632 .get(index as usize)
1633 .cloned()
1634 .map(Value::some)
1635 .unwrap_or_else(Value::none))
1636 }
1637 "iter" => {
1638 let items = arr.borrow().clone();
1639 let iter = IteratorState::Array { items, index: 0 };
1640 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
1641 }
1642 _ => Err(format!(
1643 "Array method '{}' not supported in JIT",
1644 method_name
1645 )),
1646 },
1647 _ => Err(format!(
1648 "Method '{}' not supported in JIT (deoptimizing)",
1649 method_name
1650 )),
1651 }
1652}
1653
1654#[no_mangle]
1655pub unsafe extern "C" fn jit_get_field_safe(
1656 object_ptr: *const Value,
1657 field_name_ptr: *const u8,
1658 field_name_len: usize,
1659 out: *mut Value,
1660) -> u8 {
1661 if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
1662 return 0;
1663 }
1664
1665 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1666 let field_name = match str::from_utf8(field_name_slice) {
1667 Ok(s) => s,
1668 Err(_) => return 0,
1669 };
1670 let object = &*object_ptr;
1671 let field_value = match object {
1672 Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
1673 Some(idx) => match fields.borrow().get(idx) {
1674 Some(val) => val.clone(),
1675 None => return 0,
1676 },
1677 None => return 0,
1678 },
1679 _ => return 0,
1680 };
1681 ptr::write(out, field_value);
1682 1
1683}
1684
1685#[no_mangle]
1686pub unsafe extern "C" fn jit_set_field_safe(
1687 object_ptr: *const Value,
1688 field_name_ptr: *const u8,
1689 field_name_len: usize,
1690 value_ptr: *const Value,
1691) -> u8 {
1692 if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
1693 return 0;
1694 }
1695
1696 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1697 let field_name = match str::from_utf8(field_name_slice) {
1698 Ok(s) => s,
1699 Err(_) => return 0,
1700 };
1701 let object = &*object_ptr;
1702 let value = (&*value_ptr).clone();
1703 match object {
1704 Value::Struct { .. } => match object.struct_set_field(field_name, value) {
1705 Ok(()) => 1,
1706 Err(_) => 0,
1707 },
1708 Value::Map(map) => {
1709 use crate::bytecode::ValueKey;
1710 let key = ValueKey::String(Rc::new(field_name.to_string()));
1711 map.borrow_mut().insert(key, value);
1712 1
1713 }
1714
1715 _ => 0,
1716 }
1717}
1718
1719#[no_mangle]
1720pub unsafe extern "C" fn jit_get_field_indexed_safe(
1721 object_ptr: *const Value,
1722 field_index: usize,
1723 out: *mut Value,
1724) -> u8 {
1725 if object_ptr.is_null() || out.is_null() {
1726 return 0;
1727 }
1728
1729 let object = &*object_ptr;
1730 match object.struct_get_field_indexed(field_index) {
1731 Some(value) => {
1732 ptr::write(out, value);
1733 1
1734 }
1735
1736 None => 0,
1737 }
1738}
1739
1740#[no_mangle]
1741pub unsafe extern "C" fn jit_set_field_indexed_safe(
1742 object_ptr: *const Value,
1743 field_index: usize,
1744 value_ptr: *const Value,
1745) -> u8 {
1746 if object_ptr.is_null() || value_ptr.is_null() {
1747 return 0;
1748 }
1749
1750 let object = &*object_ptr;
1751 let value = (&*value_ptr).clone();
1752 match object.struct_set_field_indexed(field_index, value) {
1753 Ok(()) => 1,
1754 Err(_) => 0,
1755 }
1756}
1757
1758#[no_mangle]
1759pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
1760 object_ptr: *const Value,
1761 field_index: usize,
1762 out: *mut Value,
1763) -> u8 {
1764 if object_ptr.is_null() || out.is_null() {
1765 return 0;
1766 }
1767
1768 let object = &*object_ptr;
1769 let out_ref = &mut *out;
1770 match object {
1771 Value::Struct { layout, fields, .. } => {
1772 if layout.is_weak(field_index) {
1773 return 0;
1774 }
1775
1776 if let Ok(borrowed) = fields.try_borrow() {
1777 if let Some(Value::Int(val)) = borrowed.get(field_index) {
1778 *out_ref = Value::Int(*val);
1779 return 1;
1780 }
1781 }
1782
1783 0
1784 }
1785
1786 _ => 0,
1787 }
1788}
1789
1790#[no_mangle]
1791pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
1792 object_ptr: *const Value,
1793 field_index: usize,
1794 value_ptr: *const Value,
1795) -> u8 {
1796 if object_ptr.is_null() || value_ptr.is_null() {
1797 return 0;
1798 }
1799
1800 let object = &*object_ptr;
1801 let value = &*value_ptr;
1802 let new_value = match value {
1803 Value::Int(v) => *v,
1804 _ => return 0,
1805 };
1806 match object {
1807 Value::Struct { layout, fields, .. } => {
1808 if layout.is_weak(field_index) {
1809 return 0;
1810 }
1811
1812 if let Ok(mut borrowed) = fields.try_borrow_mut() {
1813 if field_index < borrowed.len() {
1814 borrowed[field_index] = Value::Int(new_value);
1815 return 1;
1816 }
1817 }
1818
1819 0
1820 }
1821
1822 _ => 0,
1823 }
1824}
1825
1826#[no_mangle]
1827pub unsafe extern "C" fn jit_new_struct_safe(
1828 struct_name_ptr: *const u8,
1829 struct_name_len: usize,
1830 field_names_ptr: *const *const u8,
1831 field_name_lens_ptr: *const usize,
1832 field_values_ptr: *const Value,
1833 field_count: usize,
1834 out: *mut Value,
1835) -> u8 {
1836 if struct_name_ptr.is_null() || out.is_null() {
1837 return 0;
1838 }
1839
1840 if field_count > 0
1841 && (field_names_ptr.is_null()
1842 || field_name_lens_ptr.is_null()
1843 || field_values_ptr.is_null())
1844 {
1845 return 0;
1846 }
1847
1848 let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
1849 let struct_name = match str::from_utf8(struct_name_slice) {
1850 Ok(s) => s.to_string(),
1851 Err(_) => return 0,
1852 };
1853 let mut fields = Vec::with_capacity(field_count);
1854 for i in 0..field_count {
1855 let field_name_ptr = *field_names_ptr.add(i);
1856 let field_name_len = *field_name_lens_ptr.add(i);
1857 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
1858 let field_name = match str::from_utf8(field_name_slice) {
1859 Ok(s) => Rc::new(s.to_string()),
1860 Err(_) => return 0,
1861 };
1862 let field_value_ptr = field_values_ptr.add(i);
1863 let field_value = (&*field_value_ptr).clone();
1864 fields.push((field_name, field_value));
1865 }
1866
1867 let struct_value = match crate::vm::VM::with_current(move |vm| {
1868 vm.instantiate_struct(&struct_name, fields)
1869 .map_err(|err| err.to_string())
1870 }) {
1871 Ok(value) => value,
1872 Err(_) => return 0,
1873 };
1874 ptr::write(out, struct_value);
1875 1
1876}
1877
1878#[no_mangle]
1879pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
1880 if src_ptr.is_null() || dest_ptr.is_null() {
1881 return 0;
1882 }
1883
1884 let src_value = &*src_ptr;
1885 let cloned_value = src_value.clone();
1886 ptr::write(dest_ptr, cloned_value);
1887 1
1888}