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