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::{DefaultHashBuilder, 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 struct ValueKey {
31 original: Value,
32 hashed: Value,
33}
34
35impl ValueKey {
36 pub fn from_value(value: &Value) -> Self {
37 ValueKey {
38 original: value.clone(),
39 hashed: value.clone(),
40 }
41 }
42
43 pub fn with_hashed(original: Value, hashed: Value) -> Self {
44 ValueKey { original, hashed }
45 }
46
47 pub fn string<S>(value: S) -> Self
48 where
49 S: Into<String>,
50 {
51 ValueKey::from(Value::String(Rc::new(value.into())))
52 }
53
54 pub fn to_value(&self) -> Value {
55 self.original.clone()
56 }
57}
58
59impl PartialEq for ValueKey {
60 fn eq(&self, other: &Self) -> bool {
61 value_key_eq(&self.hashed, &other.hashed)
62 }
63}
64
65impl Eq for ValueKey {}
66impl Hash for ValueKey {
67 fn hash<H: Hasher>(&self, state: &mut H) {
68 hash_value_for_key(&self.hashed, state);
69 }
70}
71
72impl fmt::Display for ValueKey {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 write!(f, "{}", self.original)
75 }
76}
77
78impl From<Value> for ValueKey {
79 fn from(value: Value) -> Self {
80 ValueKey {
81 original: value.clone(),
82 hashed: value,
83 }
84 }
85}
86
87impl From<LustInt> for ValueKey {
88 fn from(value: LustInt) -> Self {
89 ValueKey::from(Value::Int(value))
90 }
91}
92
93impl From<LustFloat> for ValueKey {
94 fn from(value: LustFloat) -> Self {
95 ValueKey::from(Value::Float(value))
96 }
97}
98
99impl From<bool> for ValueKey {
100 fn from(value: bool) -> Self {
101 ValueKey::from(Value::Bool(value))
102 }
103}
104
105impl From<String> for ValueKey {
106 fn from(value: String) -> Self {
107 ValueKey::from(Value::String(Rc::new(value)))
108 }
109}
110
111impl From<&str> for ValueKey {
112 fn from(value: &str) -> Self {
113 ValueKey::from(Value::String(Rc::new(value.to_owned())))
114 }
115}
116
117impl From<Rc<String>> for ValueKey {
118 fn from(value: Rc<String>) -> Self {
119 ValueKey::from(Value::String(value))
120 }
121}
122
123fn unwrap_lua_value_for_key(value: &Value) -> Value {
125 if let Value::Enum {
126 enum_name,
127 variant,
128 values,
129 } = value
130 {
131 if enum_name == "LuaValue" {
132 return match variant.as_str() {
133 "Nil" => Value::Nil,
134 "Bool" => values
135 .as_ref()
136 .and_then(|v| v.get(0))
137 .cloned()
138 .unwrap_or(Value::Bool(false)),
139 "Int" | "Number" => values
140 .as_ref()
141 .and_then(|v| v.get(0))
142 .cloned()
143 .unwrap_or(Value::Int(0)),
144 "String" => values
145 .as_ref()
146 .and_then(|v| v.get(0))
147 .cloned()
148 .unwrap_or(Value::String(Rc::new(String::new()))),
149 "Table" => values
150 .as_ref()
151 .and_then(|v| v.get(0))
152 .cloned()
153 .unwrap_or(Value::Nil),
154 "Function" => values
155 .as_ref()
156 .and_then(|v| v.get(0))
157 .cloned()
158 .unwrap_or(Value::Nil),
159 _ => value.clone(),
160 };
161 }
162 }
163 value.clone()
164}
165
166fn value_key_eq(left: &Value, right: &Value) -> bool {
167 use Value::*;
168
169 let is_lua_value_left = matches!(left, Enum { enum_name, .. } if enum_name == "LuaValue");
171 let is_lua_value_right = matches!(right, Enum { enum_name, .. } if enum_name == "LuaValue");
172
173 if is_lua_value_left || is_lua_value_right {
175 let unwrapped_left = unwrap_lua_value_for_key(left);
176 let unwrapped_right = unwrap_lua_value_for_key(right);
177 return value_key_eq(&unwrapped_left, &unwrapped_right);
178 }
179
180 match (left, right) {
181 (Nil, Nil) => true,
182 (Bool(a), Bool(b)) => a == b,
183 (Int(a), Int(b)) => a == b,
184 (Float(a), Float(b)) => {
185 if float_is_nan(*a) && float_is_nan(*b) {
186 true
187 } else {
188 a == b
189 }
190 }
191 (String(a), String(b)) => a == b,
192 (Array(a), Array(b)) => Rc::ptr_eq(a, b),
193 (Tuple(a), Tuple(b)) => Rc::ptr_eq(a, b),
194 (Map(a), Map(b)) => Rc::ptr_eq(a, b),
195 (Struct { fields: f1, .. }, Struct { fields: f2, .. }) => Rc::ptr_eq(f1, f2),
196 (WeakStruct(a), WeakStruct(b)) => Weak::ptr_eq(a.fields(), b.fields()),
197 (
198 Enum {
199 enum_name: n1,
200 variant: v1,
201 values: vals1,
202 },
203 Enum {
204 enum_name: n2,
205 variant: v2,
206 values: vals2,
207 },
208 ) => n1 == n2 && v1 == v2 && values_ptr_eq(vals1, vals2),
209 (Function(a), Function(b)) => a == b,
210 (NativeFunction(a), NativeFunction(b)) => Rc::ptr_eq(a, b),
211 (
212 Closure {
213 function_idx: f1,
214 upvalues: u1,
215 },
216 Closure {
217 function_idx: f2,
218 upvalues: u2,
219 },
220 ) => f1 == f2 && Rc::ptr_eq(u1, u2),
221 (Iterator(a), Iterator(b)) => Rc::ptr_eq(a, b),
222 (Task(a), Task(b)) => a == b,
223 _ => false,
224 }
225}
226
227fn hash_value_for_key<H: Hasher>(value: &Value, state: &mut H) {
228 use Value::*;
229
230 if matches!(value, Enum { enum_name, .. } if enum_name == "LuaValue") {
232 let unwrapped = unwrap_lua_value_for_key(value);
233 return hash_value_for_key(&unwrapped, state);
234 }
235
236 match value {
237 Nil => {
238 0u8.hash(state);
239 }
240 Bool(b) => {
241 1u8.hash(state);
242 b.hash(state);
243 }
244 Int(i) => {
245 2u8.hash(state);
246 i.hash(state);
247 }
248 Float(f) => {
249 3u8.hash(state);
250 if float_is_nan(*f) {
251 u64::MAX.hash(state);
252 } else {
253 float_to_hash_bits(*f).hash(state);
254 }
255 }
256 String(s) => {
257 4u8.hash(state);
258 s.hash(state);
259 }
260 Array(arr) => {
261 5u8.hash(state);
262 (Rc::as_ptr(arr) as usize).hash(state);
263 }
264 Tuple(tuple) => {
265 6u8.hash(state);
266 (Rc::as_ptr(tuple) as usize).hash(state);
267 }
268 Map(map) => {
269 7u8.hash(state);
270 (Rc::as_ptr(map) as usize).hash(state);
271 }
272 Struct { fields, .. } => {
273 8u8.hash(state);
274 (Rc::as_ptr(fields) as usize).hash(state);
275 }
276 WeakStruct(weak) => {
277 9u8.hash(state);
278 (weak.fields_ptr() as usize).hash(state);
279 }
280 Enum {
281 enum_name,
282 variant,
283 values,
284 } => {
285 10u8.hash(state);
286 enum_name.hash(state);
287 variant.hash(state);
288 values
289 .as_ref()
290 .map(|rc| Rc::as_ptr(rc) as usize)
291 .hash(state);
292 }
293 Function(idx) => {
294 11u8.hash(state);
295 idx.hash(state);
296 }
297 NativeFunction(func) => {
298 12u8.hash(state);
299 (Rc::as_ptr(func) as *const () as usize).hash(state);
300 }
301 Closure {
302 function_idx,
303 upvalues,
304 } => {
305 13u8.hash(state);
306 function_idx.hash(state);
307 (Rc::as_ptr(upvalues) as usize).hash(state);
308 }
309 Iterator(iter) => {
310 14u8.hash(state);
311 (Rc::as_ptr(iter) as usize).hash(state);
312 }
313 Task(handle) => {
314 15u8.hash(state);
315 handle.hash(state);
316 }
317 }
318}
319
320fn values_ptr_eq(left: &Option<Rc<Vec<Value>>>, right: &Option<Rc<Vec<Value>>>) -> bool {
321 match (left, right) {
322 (Some(a), Some(b)) => Rc::ptr_eq(a, b),
323 (None, None) => true,
324 _ => false,
325 }
326}
327
328pub type LustMap = HashMap<ValueKey, Value, DefaultHashBuilder>;
329
330#[repr(u8)]
331#[derive(Debug, Clone, Copy, PartialEq, Eq)]
332pub enum ValueTag {
333 Nil,
334 Bool,
335 Int,
336 Float,
337 String,
338 Array,
339 Tuple,
340 Map,
341 Struct,
342 Enum,
343 Function,
344 NativeFunction,
345 Closure,
346 Iterator,
347 Task,
348}
349
350impl ValueTag {
351 #[inline]
352 pub const fn as_u8(self) -> u8 {
353 self as u8
354 }
355}
356
357#[derive(Debug, Clone, Copy, PartialEq, Eq)]
358pub enum FieldStorage {
359 Strong,
360 Weak,
361}
362
363#[derive(Debug)]
364pub struct StructLayout {
365 name: String,
366 field_names: Vec<Rc<String>>,
367 field_lookup_ptr: HashMap<usize, usize>,
368 field_lookup_str: HashMap<String, usize>,
369 field_storage: Vec<FieldStorage>,
370 field_types: Vec<Type>,
371 weak_targets: Vec<Option<Type>>,
372}
373
374impl StructLayout {
375 pub fn new(
376 name: String,
377 field_names: Vec<Rc<String>>,
378 field_storage: Vec<FieldStorage>,
379 field_types: Vec<Type>,
380 weak_targets: Vec<Option<Type>>,
381 ) -> Self {
382 debug_assert_eq!(
383 field_names.len(),
384 field_storage.len(),
385 "StructLayout::new expects field names and storage metadata to align"
386 );
387 debug_assert_eq!(
388 field_names.len(),
389 field_types.len(),
390 "StructLayout::new expects field names and type metadata to align"
391 );
392 debug_assert_eq!(
393 field_names.len(),
394 weak_targets.len(),
395 "StructLayout::new expects field names and weak target metadata to align"
396 );
397 let mut field_lookup_ptr = HashMap::with_capacity(field_names.len());
398 let mut field_lookup_str = HashMap::with_capacity(field_names.len());
399 for (index, field_name_rc) in field_names.iter().enumerate() {
400 let ptr = Rc::as_ptr(field_name_rc) as usize;
401 field_lookup_ptr.insert(ptr, index);
402 field_lookup_str.insert((**field_name_rc).clone(), index);
403 }
404
405 Self {
406 name,
407 field_names,
408 field_lookup_ptr,
409 field_lookup_str,
410 field_storage,
411 field_types,
412 weak_targets,
413 }
414 }
415
416 #[inline]
417 pub fn name(&self) -> &str {
418 &self.name
419 }
420
421 #[inline]
422 pub fn field_names(&self) -> &[Rc<String>] {
423 &self.field_names
424 }
425
426 #[inline]
427 pub fn index_of_rc(&self, key: &Rc<String>) -> Option<usize> {
428 let ptr = Rc::as_ptr(key) as usize;
429 self.field_lookup_ptr
430 .get(&ptr)
431 .copied()
432 .or_else(|| self.field_lookup_str.get(key.as_str()).copied())
433 }
434
435 #[inline]
436 pub fn index_of_str(&self, key: &str) -> Option<usize> {
437 self.field_lookup_str.get(key).copied()
438 }
439
440 #[inline]
441 pub fn field_storage(&self, index: usize) -> FieldStorage {
442 self.field_storage[index]
443 }
444
445 #[inline]
446 pub fn field_type(&self, index: usize) -> &Type {
447 &self.field_types[index]
448 }
449
450 #[inline]
451 pub fn weak_target(&self, index: usize) -> Option<&Type> {
452 self.weak_targets[index].as_ref()
453 }
454
455 #[inline]
456 pub fn is_weak(&self, index: usize) -> bool {
457 matches!(self.field_storage(index), FieldStorage::Weak)
458 }
459
460 pub fn canonicalize_field_value(&self, index: usize, value: Value) -> Result<Value, String> {
461 match self.field_storage(index) {
462 FieldStorage::Strong => Ok(value),
463 FieldStorage::Weak => self.canonicalize_weak_field(index, value),
464 }
465 }
466
467 pub fn materialize_field_value(&self, index: usize, value: Value) -> Value {
468 match self.field_storage(index) {
469 FieldStorage::Strong => value,
470 FieldStorage::Weak => self.materialize_weak_field(value),
471 }
472 }
473
474 fn canonicalize_weak_field(&self, index: usize, value: Value) -> Result<Value, String> {
475 let field_name = self.field_names[index].as_str();
476 match value {
477 Value::Enum {
478 enum_name,
479 variant,
480 values,
481 } if enum_name == "Option" => {
482 if variant == "Some" {
483 if let Some(inner_values) = values {
484 if let Some(inner) = inner_values.get(0) {
485 let coerced = self.to_weak_struct(field_name, inner.clone())?;
486 Ok(Value::enum_variant("Option", "Some", vec![coerced]))
487 } else {
488 Ok(Value::enum_unit("Option", "None"))
489 }
490 } else {
491 Ok(Value::enum_unit("Option", "None"))
492 }
493 } else if variant == "None" {
494 Ok(Value::enum_unit("Option", "None"))
495 } else {
496 Err(format!(
497 "Struct '{}' field '{}' uses 'ref' and must store Option values; received variant '{}'",
498 self.name, field_name, variant
499 ))
500 }
501 }
502
503 Value::Nil => Ok(Value::enum_unit("Option", "None")),
504 other => {
505 let coerced = self.to_weak_struct(field_name, other)?;
506 Ok(Value::enum_variant("Option", "Some", vec![coerced]))
507 }
508 }
509 }
510
511 fn materialize_weak_field(&self, value: Value) -> Value {
512 match value {
513 Value::Enum {
514 enum_name,
515 variant,
516 values,
517 } if enum_name == "Option" => {
518 if variant == "Some" {
519 if let Some(inner_values) = values {
520 if let Some(inner) = inner_values.get(0) {
521 match inner {
522 Value::WeakStruct(ref weak) => {
523 if let Some(upgraded) = weak.upgrade() {
524 Value::enum_variant("Option", "Some", vec![upgraded])
525 } else {
526 Value::enum_unit("Option", "None")
527 }
528 }
529
530 _ => Value::enum_variant("Option", "Some", vec![inner.clone()]),
531 }
532 } else {
533 Value::enum_unit("Option", "None")
534 }
535 } else {
536 Value::enum_unit("Option", "None")
537 }
538 } else {
539 Value::enum_unit("Option", "None")
540 }
541 }
542
543 Value::Nil => Value::enum_unit("Option", "None"),
544 other => Value::enum_variant("Option", "Some", vec![other]),
545 }
546 }
547
548 fn to_weak_struct(&self, field_name: &str, value: Value) -> Result<Value, String> {
549 match value {
550 Value::Struct {
551 name,
552 layout,
553 fields,
554 } => Ok(Value::WeakStruct(WeakStructRef::new(name, layout, &fields))),
555 Value::WeakStruct(_) => Ok(value),
556 other => {
557 let ty = other.type_of();
558 Err(format!(
559 "Struct '{}' field '{}' expects a struct reference but received value of type '{:?}'",
560 self.name, field_name, ty
561 ))
562 }
563 }
564 }
565}
566
567#[repr(C, u8)]
568#[derive(Clone)]
569pub enum Value {
570 Nil,
571 Bool(bool),
572 Int(LustInt),
573 Float(LustFloat),
574 String(Rc<String>),
575 Array(Rc<RefCell<Vec<Value>>>),
576 Tuple(Rc<Vec<Value>>),
577 Map(Rc<RefCell<LustMap>>),
578 Struct {
579 name: String,
580 layout: Rc<StructLayout>,
581 fields: Rc<RefCell<Vec<Value>>>,
582 },
583 WeakStruct(WeakStructRef),
584 Enum {
585 enum_name: String,
586 variant: String,
587 values: Option<Rc<Vec<Value>>>,
588 },
589 Function(usize),
590 NativeFunction(NativeFn),
591 Closure {
592 function_idx: usize,
593 upvalues: Rc<Vec<Upvalue>>,
594 },
595 Iterator(Rc<RefCell<IteratorState>>),
596 Task(TaskHandle),
597}
598
599#[derive(Debug, Clone)]
600pub struct WeakStructRef {
601 name: String,
602 layout: Rc<StructLayout>,
603 fields: Weak<RefCell<Vec<Value>>>,
604}
605
606impl WeakStructRef {
607 pub fn new(name: String, layout: Rc<StructLayout>, fields: &Rc<RefCell<Vec<Value>>>) -> Self {
608 Self {
609 name,
610 layout,
611 fields: Rc::downgrade(fields),
612 }
613 }
614
615 pub fn upgrade(&self) -> Option<Value> {
616 self.fields.upgrade().map(|fields| Value::Struct {
617 name: self.name.clone(),
618 layout: self.layout.clone(),
619 fields,
620 })
621 }
622
623 pub fn struct_name(&self) -> &str {
624 &self.name
625 }
626
627 pub(crate) fn fields(&self) -> &Weak<RefCell<Vec<Value>>> {
628 &self.fields
629 }
630
631 pub(crate) fn fields_ptr(&self) -> *const RefCell<Vec<Value>> {
632 self.fields.as_ptr()
633 }
634}
635
636#[derive(Clone)]
637pub enum IteratorState {
638 Array {
639 items: Vec<Value>,
640 index: usize,
641 },
642 MapPairs {
643 items: Vec<(ValueKey, Value)>,
644 index: usize,
645 },
646}
647
648#[derive(Clone)]
649pub struct Upvalue {
650 value: Rc<RefCell<Value>>,
651}
652
653impl Upvalue {
654 pub fn new(value: Value) -> Self {
655 Self {
656 value: Rc::new(RefCell::new(value)),
657 }
658 }
659
660 pub fn get(&self) -> Value {
661 self.value.borrow().clone()
662 }
663
664 pub fn set(&self, value: Value) {
665 *self.value.borrow_mut() = value;
666 }
667}
668
669impl fmt::Debug for Upvalue {
670 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
671 write!(f, "Upvalue({:?})", self.value.borrow())
672 }
673}
674
675#[derive(Debug, Clone)]
676pub enum NativeCallResult {
677 Return(Value),
678 Yield(Value),
679 Stop(Value),
680}
681
682impl From<Value> for NativeCallResult {
683 fn from(value: Value) -> Self {
684 NativeCallResult::Return(value)
685 }
686}
687
688pub type NativeFn = Rc<dyn Fn(&[Value]) -> Result<NativeCallResult, String>>;
689#[derive(Debug, Clone, Copy, PartialEq, Eq)]
690pub enum ValueType {
691 Nil,
692 Bool,
693 Int,
694 Float,
695 String,
696 Array,
697 Tuple,
698 Map,
699 Struct,
700 Enum,
701 Function,
702 NativeFunction,
703 Closure,
704 Iterator,
705 Task,
706}
707
708impl Value {
709 #[inline]
710 pub fn tag(&self) -> ValueTag {
711 match self {
712 Value::Nil => ValueTag::Nil,
713 Value::Bool(_) => ValueTag::Bool,
714 Value::Int(_) => ValueTag::Int,
715 Value::Float(_) => ValueTag::Float,
716 Value::String(_) => ValueTag::String,
717 Value::Array(_) => ValueTag::Array,
718 Value::Tuple(_) => ValueTag::Tuple,
719 Value::Map(_) => ValueTag::Map,
720 Value::Struct { .. } | Value::WeakStruct(_) => ValueTag::Struct,
721 Value::Enum { .. } => ValueTag::Enum,
722 Value::Function(_) => ValueTag::Function,
723 Value::NativeFunction(_) => ValueTag::NativeFunction,
724 Value::Closure { .. } => ValueTag::Closure,
725 Value::Iterator(_) => ValueTag::Iterator,
726 Value::Task(_) => ValueTag::Task,
727 }
728 }
729
730 pub fn type_of(&self) -> ValueType {
731 match self {
732 Value::Nil => ValueType::Nil,
733 Value::Bool(_) => ValueType::Bool,
734 Value::Int(_) => ValueType::Int,
735 Value::Float(_) => ValueType::Float,
736 Value::String(_) => ValueType::String,
737 Value::Array(_) => ValueType::Array,
738 Value::Tuple(_) => ValueType::Tuple,
739 Value::Map(_) => ValueType::Map,
740 Value::Struct { .. } | Value::WeakStruct(_) => ValueType::Struct,
741 Value::Enum { .. } => ValueType::Enum,
742 Value::Function(_) => ValueType::Function,
743 Value::NativeFunction(_) => ValueType::NativeFunction,
744 Value::Closure { .. } => ValueType::Closure,
745 Value::Iterator(_) => ValueType::Iterator,
746 Value::Task(_) => ValueType::Task,
747 }
748 }
749
750 pub fn is_truthy(&self) -> bool {
751 match self {
752 Value::Nil => false,
753 Value::Bool(false) => false,
754 Value::Enum {
755 enum_name, variant, ..
756 } if enum_name == "Option" && variant == "None" => false,
757 _ => true,
758 }
759 }
760
761 pub fn to_bool(&self) -> bool {
762 self.is_truthy()
763 }
764
765 pub fn as_int(&self) -> Option<LustInt> {
766 match self {
767 Value::Int(i) => Some(*i),
768 Value::Float(f) => Some(int_from_float(*f)),
769 _ => None,
770 }
771 }
772
773 pub fn as_float(&self) -> Option<LustFloat> {
774 match self {
775 Value::Float(f) => Some(*f),
776 Value::Int(i) => Some(float_from_int(*i)),
777 _ => None,
778 }
779 }
780
781 pub fn as_string(&self) -> Option<&str> {
782 match self {
783 Value::String(s) => Some(s.as_str()),
784 _ => None,
785 }
786 }
787
788 pub fn as_string_rc(&self) -> Option<Rc<String>> {
789 match self {
790 Value::String(s) => Some(s.clone()),
791 _ => None,
792 }
793 }
794
795 pub fn as_task_handle(&self) -> Option<TaskHandle> {
796 match self {
797 Value::Task(handle) => Some(*handle),
798 _ => None,
799 }
800 }
801
802 pub fn as_array(&self) -> Option<Vec<Value>> {
803 match self {
804 Value::Array(arr) => Some(arr.borrow().clone()),
805 _ => None,
806 }
807 }
808
809 pub fn array_len(&self) -> Option<usize> {
810 match self {
811 Value::Array(arr) => Some(arr.borrow().len()),
812 _ => None,
813 }
814 }
815
816 pub fn array_get(&self, index: usize) -> Option<Value> {
817 match self {
818 Value::Array(arr) => arr.borrow().get(index).cloned(),
819 _ => None,
820 }
821 }
822
823 pub fn array_push(&self, value: Value) -> Result<(), String> {
824 match self {
825 Value::Array(arr) => {
826 arr.borrow_mut().push(value);
827 Ok(())
828 }
829
830 _ => Err("Cannot push to non-array".to_string()),
831 }
832 }
833
834 pub fn array_pop(&self) -> Result<Option<Value>, String> {
835 match self {
836 Value::Array(arr) => Ok(arr.borrow_mut().pop()),
837 _ => Err("Cannot pop from non-array".to_string()),
838 }
839 }
840
841 pub fn as_map(&self) -> Option<LustMap> {
842 match self {
843 Value::Map(map) => Some(map.borrow().clone()),
844 _ => None,
845 }
846 }
847
848 pub fn map_get(&self, key: &ValueKey) -> Option<Value> {
849 match self {
850 Value::Map(map) => map.borrow().get(key).cloned(),
851 _ => None,
852 }
853 }
854
855 pub fn map_set(&self, key: ValueKey, value: Value) -> Result<(), String> {
856 match self {
857 Value::Map(map) => {
858 map.borrow_mut().insert(key, value);
859 Ok(())
860 }
861
862 _ => Err("Cannot set key on non-map".to_string()),
863 }
864 }
865
866 pub fn map_has(&self, key: &ValueKey) -> Option<bool> {
867 match self {
868 Value::Map(map) => Some(map.borrow().contains_key(key)),
869 _ => None,
870 }
871 }
872
873 pub fn map_delete(&self, key: &ValueKey) -> Result<Option<Value>, String> {
874 match self {
875 Value::Map(map) => Ok(map.borrow_mut().remove(key)),
876 _ => Err("Cannot delete key from non-map".to_string()),
877 }
878 }
879
880 pub fn map_len(&self) -> Option<usize> {
881 match self {
882 Value::Map(map) => Some(map.borrow().len()),
883 _ => None,
884 }
885 }
886
887 pub fn string(s: impl Into<String>) -> Self {
888 Value::String(Rc::new(s.into()))
889 }
890
891 pub fn array(values: Vec<Value>) -> Self {
892 Value::Array(Rc::new(RefCell::new(values)))
893 }
894
895 pub fn tuple(values: Vec<Value>) -> Self {
896 Value::Tuple(Rc::new(values))
897 }
898
899 pub fn tuple_len(&self) -> Option<usize> {
900 match self {
901 Value::Tuple(values) => Some(values.len()),
902 _ => None,
903 }
904 }
905
906 pub fn tuple_get(&self, index: usize) -> Option<Value> {
907 match self {
908 Value::Tuple(values) => values.get(index).cloned(),
909 _ => None,
910 }
911 }
912
913 pub fn map(entries: LustMap) -> Self {
914 Value::Map(Rc::new(RefCell::new(entries)))
915 }
916
917 pub fn task(handle: TaskHandle) -> Self {
918 Value::Task(handle)
919 }
920
921 pub fn struct_get_field_rc(&self, field: &Rc<String>) -> Option<Value> {
922 match self {
923 Value::Struct { layout, fields, .. } => layout
924 .index_of_rc(field)
925 .or_else(|| layout.index_of_str(field.as_str()))
926 .or_else(|| {
927 layout
928 .field_names()
929 .iter()
930 .position(|name| name.as_str() == field.as_str())
931 })
932 .and_then(|idx| {
933 fields
934 .borrow()
935 .get(idx)
936 .cloned()
937 .map(|value| layout.materialize_field_value(idx, value))
938 }),
939 _ => None,
940 }
941 }
942
943 pub fn struct_get_field(&self, field: &str) -> Option<Value> {
944 match self {
945 Value::Struct { layout, fields, .. } => layout.index_of_str(field).and_then(|idx| {
946 fields
947 .borrow()
948 .get(idx)
949 .cloned()
950 .map(|value| layout.materialize_field_value(idx, value))
951 }),
952 _ => None,
953 }
954 }
955
956 pub fn struct_get_field_indexed(&self, index: usize) -> Option<Value> {
957 match self {
958 Value::Struct { layout, fields, .. } => fields
959 .borrow()
960 .get(index)
961 .cloned()
962 .map(|value| layout.materialize_field_value(index, value)),
963 _ => None,
964 }
965 }
966
967 pub fn struct_set_field_rc(&self, field: &Rc<String>, value: Value) -> Result<(), String> {
968 match self {
969 Value::Struct { layout, .. } => {
970 if let Some(index) = layout
971 .index_of_rc(field)
972 .or_else(|| layout.index_of_str(field.as_str()))
973 {
974 self.struct_set_field_indexed(index, value)
975 } else {
976 Err(format!(
977 "Struct '{}' has no field '{}'",
978 layout.name(),
979 field.as_str()
980 ))
981 }
982 }
983
984 _ => Err("Attempted to set field on non-struct value".to_string()),
985 }
986 }
987
988 pub fn struct_set_field(&self, field: &str, value: Value) -> Result<(), String> {
989 match self {
990 Value::Struct { layout, .. } => {
991 if let Some(index) = layout.index_of_str(field) {
992 self.struct_set_field_indexed(index, value)
993 } else {
994 Err(format!(
995 "Struct '{}' has no field '{}'",
996 layout.name(),
997 field
998 ))
999 }
1000 }
1001
1002 _ => Err("Attempted to set field on non-struct value".to_string()),
1003 }
1004 }
1005
1006 pub fn struct_set_field_indexed(&self, index: usize, value: Value) -> Result<(), String> {
1007 match self {
1008 Value::Struct {
1009 name,
1010 layout,
1011 fields,
1012 } => {
1013 let mut borrowed = fields.borrow_mut();
1014 if index < borrowed.len() {
1015 let canonical = layout.canonicalize_field_value(index, value)?;
1016 borrowed[index] = canonical;
1017 Ok(())
1018 } else {
1019 Err(format!(
1020 "Struct '{}' field index {} out of bounds (len {})",
1021 name,
1022 index,
1023 borrowed.len()
1024 ))
1025 }
1026 }
1027
1028 _ => Err("Attempted to set field on non-struct value".to_string()),
1029 }
1030 }
1031
1032 pub fn enum_unit(enum_name: impl Into<String>, variant: impl Into<String>) -> Self {
1033 Value::Enum {
1034 enum_name: enum_name.into(),
1035 variant: variant.into(),
1036 values: None,
1037 }
1038 }
1039
1040 pub fn enum_variant(
1041 enum_name: impl Into<String>,
1042 variant: impl Into<String>,
1043 values: Vec<Value>,
1044 ) -> Self {
1045 Value::Enum {
1046 enum_name: enum_name.into(),
1047 variant: variant.into(),
1048 values: Some(Rc::new(values)),
1049 }
1050 }
1051
1052 pub fn as_enum(&self) -> Option<(&str, &str, Option<&[Value]>)> {
1053 match self {
1054 Value::Enum {
1055 enum_name,
1056 variant,
1057 values,
1058 } => Some((
1059 enum_name.as_str(),
1060 variant.as_str(),
1061 values.as_ref().map(|v| v.as_slice()),
1062 )),
1063 _ => None,
1064 }
1065 }
1066
1067 pub fn is_enum_variant(&self, enum_name: &str, variant: &str) -> bool {
1068 match self {
1069 Value::Enum {
1070 enum_name: en,
1071 variant: v,
1072 ..
1073 } => (enum_name.is_empty() || en == enum_name) && v == variant,
1074 _ => false,
1075 }
1076 }
1077
1078 pub fn some(value: Value) -> Self {
1079 Value::enum_variant("Option", "Some", vec![value])
1080 }
1081
1082 pub fn none() -> Self {
1083 Value::enum_unit("Option", "None")
1084 }
1085
1086 pub fn ok(value: Value) -> Self {
1087 Value::enum_variant("Result", "Ok", vec![value])
1088 }
1089
1090 pub fn err(error: Value) -> Self {
1091 Value::enum_variant("Result", "Err", vec![error])
1092 }
1093
1094 pub fn to_string(&self) -> String {
1095 format!("{}", self)
1096 }
1097}
1098
1099impl fmt::Debug for Value {
1100 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1101 match self {
1102 Value::Nil => write!(f, "Nil"),
1103 Value::Bool(b) => write!(f, "Bool({})", b),
1104 Value::Int(i) => write!(f, "Int({})", i),
1105 Value::Float(fl) => write!(f, "Float({})", fl),
1106 Value::String(s) => write!(f, "String({:?})", s),
1107 Value::Array(arr) => write!(f, "Array({:?})", arr.borrow()),
1108 Value::Tuple(values) => write!(f, "Tuple({:?})", values),
1109 Value::Map(map) => write!(f, "Map({:?})", map.borrow()),
1110 Value::Struct {
1111 name,
1112 layout,
1113 fields,
1114 } => {
1115 let borrowed = fields.borrow();
1116 let mut display_fields = Vec::with_capacity(borrowed.len());
1117 for (idx, field_name) in layout.field_names().iter().enumerate() {
1118 let value = borrowed.get(idx).cloned().unwrap_or(Value::Nil);
1119 display_fields.push((field_name.as_str().to_string(), value));
1120 }
1121
1122 write!(
1123 f,
1124 "Struct {{ name: {:?}, fields: {:?} }}",
1125 name, display_fields
1126 )
1127 }
1128
1129 Value::WeakStruct(weak) => {
1130 if let Some(upgraded) = weak.upgrade() {
1131 write!(f, "WeakStruct({:?})", upgraded)
1132 } else {
1133 write!(f, "WeakStruct(<dangling>)")
1134 }
1135 }
1136
1137 Value::Enum {
1138 enum_name,
1139 variant,
1140 values,
1141 } => {
1142 write!(
1143 f,
1144 "Enum {{ enum: {:?}, variant: {:?}, values: {:?} }}",
1145 enum_name, variant, values
1146 )
1147 }
1148
1149 Value::Function(idx) => write!(f, "Function({})", idx),
1150 Value::NativeFunction(_) => write!(f, "NativeFunction(<fn>)"),
1151 Value::Closure {
1152 function_idx,
1153 upvalues,
1154 } => {
1155 write!(
1156 f,
1157 "Closure {{ function: {}, upvalues: {:?} }}",
1158 function_idx, upvalues
1159 )
1160 }
1161
1162 Value::Iterator(_) => write!(f, "Iterator(<state>)"),
1163 Value::Task(handle) => write!(f, "Task({})", handle.0),
1164 }
1165 }
1166}
1167
1168impl fmt::Display for Value {
1169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1170 match self {
1171 Value::Nil => write!(f, "nil"),
1172 Value::Bool(b) => write!(f, "{}", b),
1173 Value::Int(i) => write!(f, "{}", i),
1174 Value::Float(fl) => write!(f, "{}", fl),
1175 Value::String(s) => write!(f, "{}", s),
1176 Value::Array(arr) => {
1177 write!(f, "[")?;
1178 let borrowed = arr.borrow();
1179 for (i, val) in borrowed.iter().enumerate() {
1180 if i > 0 {
1181 write!(f, ", ")?;
1182 }
1183
1184 write!(f, "{}", val)?;
1185 }
1186
1187 write!(f, "]")
1188 }
1189
1190 Value::Tuple(values) => {
1191 write!(f, "(")?;
1192 for (i, val) in values.iter().enumerate() {
1193 if i > 0 {
1194 write!(f, ", ")?;
1195 }
1196
1197 write!(f, "{}", val)?;
1198 }
1199
1200 write!(f, ")")
1201 }
1202
1203 Value::Map(map) => {
1204 write!(f, "{{")?;
1205 let borrowed = map.borrow();
1206 for (i, (k, v)) in borrowed.iter().enumerate() {
1207 if i > 0 {
1208 write!(f, ", ")?;
1209 }
1210
1211 write!(f, "{}: {}", k, v)?;
1212 }
1213
1214 write!(f, "}}")
1215 }
1216
1217 Value::Struct {
1218 name,
1219 layout,
1220 fields,
1221 } => {
1222 let borrowed = fields.borrow();
1223 write!(f, "{} {{", name)?;
1224 for (i, field_name) in layout.field_names().iter().enumerate() {
1225 if i > 0 {
1226 write!(f, ", ")?;
1227 }
1228
1229 let value = borrowed.get(i).unwrap_or(&Value::Nil);
1230 write!(f, "{}: {}", field_name, value)?;
1231 }
1232
1233 write!(f, "}}")
1234 }
1235
1236 Value::WeakStruct(weak) => {
1237 if let Some(strong) = weak.upgrade() {
1238 strong.fmt(f)
1239 } else {
1240 write!(f, "nil")
1241 }
1242 }
1243
1244 Value::Enum {
1245 enum_name,
1246 variant,
1247 values,
1248 } => {
1249 write!(f, "{}.{}", enum_name, variant)?;
1250 if let Some(vals) = values {
1251 write!(f, "(")?;
1252 for (i, val) in vals.iter().enumerate() {
1253 if i > 0 {
1254 write!(f, ", ")?;
1255 }
1256
1257 write!(f, "{}", val)?;
1258 }
1259
1260 write!(f, ")")?;
1261 }
1262
1263 Ok(())
1264 }
1265
1266 Value::Function(idx) => write!(f, "<function@{}>", idx),
1267 Value::NativeFunction(_) => write!(f, "<native function>"),
1268 Value::Closure { function_idx, .. } => write!(f, "<closure@{}>", function_idx),
1269 Value::Iterator(_) => write!(f, "<iterator>"),
1270 Value::Task(handle) => write!(f, "<task {}>", handle.0),
1271 }
1272 }
1273}
1274
1275impl PartialEq for Value {
1276 fn eq(&self, other: &Self) -> bool {
1277 match (self, other) {
1278 (Value::Nil, Value::Nil) => true,
1279 (Value::Bool(a), Value::Bool(b)) => a == b,
1280 (Value::Int(a), Value::Int(b)) => a == b,
1281 (Value::Float(a), Value::Float(b)) => a == b,
1282 (Value::String(a), Value::String(b)) => a == b,
1283 (Value::Array(a), Value::Array(b)) => *a.borrow() == *b.borrow(),
1284 (Value::Tuple(a), Value::Tuple(b)) => *a == *b,
1285 (Value::Map(a), Value::Map(b)) => *a.borrow() == *b.borrow(),
1286 (
1287 Value::Struct {
1288 name: n1,
1289 layout: l1,
1290 fields: f1,
1291 },
1292 Value::Struct {
1293 name: n2,
1294 layout: l2,
1295 fields: f2,
1296 },
1297 ) => {
1298 if n1 != n2 {
1299 return false;
1300 }
1301
1302 let borrowed_f1 = f1.borrow();
1303 let borrowed_f2 = f2.borrow();
1304 if borrowed_f1.len() != borrowed_f2.len() {
1305 return false;
1306 }
1307
1308 if Rc::ptr_eq(l1, l2) {
1309 return borrowed_f1
1310 .iter()
1311 .zip(borrowed_f2.iter())
1312 .all(|(a, b)| a == b);
1313 }
1314
1315 l1.field_names()
1316 .iter()
1317 .enumerate()
1318 .all(|(idx, field_name)| {
1319 if let Some(other_idx) = l2.index_of_rc(field_name) {
1320 borrowed_f1
1321 .get(idx)
1322 .zip(borrowed_f2.get(other_idx))
1323 .map(|(a, b)| a == b)
1324 .unwrap_or(false)
1325 } else {
1326 false
1327 }
1328 })
1329 }
1330
1331 (Value::WeakStruct(a), Value::WeakStruct(b)) => match (a.upgrade(), b.upgrade()) {
1332 (Some(left), Some(right)) => left == right,
1333 (None, None) => true,
1334 _ => false,
1335 },
1336 (Value::WeakStruct(a), other) => a
1337 .upgrade()
1338 .map(|upgraded| upgraded == *other)
1339 .unwrap_or(matches!(other, Value::Nil)),
1340 (value, Value::WeakStruct(b)) => b
1341 .upgrade()
1342 .map(|upgraded| *value == upgraded)
1343 .unwrap_or(matches!(value, Value::Nil)),
1344 (
1345 Value::Enum {
1346 enum_name: e1,
1347 variant: v1,
1348 values: vals1,
1349 },
1350 Value::Enum {
1351 enum_name: e2,
1352 variant: v2,
1353 values: vals2,
1354 },
1355 ) => e1 == e2 && v1 == v2 && vals1 == vals2,
1356 (Value::Function(a), Value::Function(b)) => a == b,
1357 (
1358 Value::Closure {
1359 function_idx: f1,
1360 upvalues: u1,
1361 },
1362 Value::Closure {
1363 function_idx: f2,
1364 upvalues: u2,
1365 },
1366 ) => f1 == f2 && Rc::ptr_eq(u1, u2),
1367 (Value::Iterator(_), Value::Iterator(_)) => false,
1368 (Value::Task(a), Value::Task(b)) => a == b,
1369 _ => false,
1370 }
1371 }
1372}
1373
1374#[cfg(feature = "std")]
1375#[no_mangle]
1376pub unsafe extern "C" fn jit_array_get_safe(
1377 array_value_ptr: *const Value,
1378 index: i64,
1379 out: *mut Value,
1380) -> u8 {
1381 if array_value_ptr.is_null() || out.is_null() {
1382 eprintln!("❌ jit_array_get_safe: null pointer detected!");
1383 return 0;
1384 }
1385
1386 let array_value = &*array_value_ptr;
1387 let arr = match array_value {
1388 Value::Array(arr) => arr,
1389 _ => {
1390 return 0;
1391 }
1392 };
1393 if index < 0 {
1394 return 0;
1395 }
1396
1397 let idx = index as usize;
1398 let borrowed = match arr.try_borrow() {
1399 Ok(b) => b,
1400 Err(_) => {
1401 return 0;
1402 }
1403 };
1404 if idx >= borrowed.len() {
1405 return 0;
1406 }
1407
1408 ptr::write(out, borrowed[idx].clone());
1409 1
1410}
1411
1412#[cfg(feature = "std")]
1413#[no_mangle]
1414pub unsafe extern "C" fn jit_array_len_safe(array_value_ptr: *const Value) -> i64 {
1415 if array_value_ptr.is_null() {
1416 return -1;
1417 }
1418
1419 let array_value = &*array_value_ptr;
1420 match array_value {
1421 Value::Array(arr) => match arr.try_borrow() {
1422 Ok(borrowed) => int_from_usize(borrowed.len()),
1423 Err(_) => -1,
1424 },
1425 _ => -1,
1426 }
1427}
1428
1429#[cfg(feature = "std")]
1430static JIT_NEW_ARRAY_COUNTER: core::sync::atomic::AtomicUsize =
1431 core::sync::atomic::AtomicUsize::new(0);
1432
1433#[cfg(feature = "std")]
1434#[no_mangle]
1435pub unsafe extern "C" fn jit_new_array_safe(
1436 vm_ptr: *mut VM,
1437 elements_ptr: *const Value,
1438 element_count: usize,
1439 out_ptr: *mut Value,
1440) -> u8 {
1441 let _call_num = JIT_NEW_ARRAY_COUNTER.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
1442 if out_ptr.is_null() {
1445 return 0;
1447 }
1448
1449 if !vm_ptr.is_null() {
1450 let vm = &mut *vm_ptr;
1451 if !vm.try_charge_memory_value_vec(element_count) {
1452 return 0;
1453 }
1454 }
1455
1456 let elements = if element_count == 0 {
1458 Vec::new()
1459 } else {
1460 if elements_ptr.is_null() {
1461 return 0;
1463 }
1464
1465 let slice = slice::from_raw_parts(elements_ptr, element_count);
1466 slice.to_vec()
1467 };
1468
1469 let array_value = Value::array(elements);
1471 ptr::write(out_ptr, array_value);
1473 1
1475}
1476
1477#[cfg(feature = "std")]
1478#[no_mangle]
1479pub unsafe extern "C" fn jit_array_push_safe(
1480 vm_ptr: *mut VM,
1481 array_ptr: *const Value,
1482 value_ptr: *const Value,
1483) -> u8 {
1484 if array_ptr.is_null() || value_ptr.is_null() {
1485 return 0;
1486 }
1487
1488 let array_value = &*array_ptr;
1489 let value = &*value_ptr;
1490
1491 match array_value {
1492 Value::Array(arr) => {
1493 let cell_ptr = arr.as_ptr();
1495 let vec_ref = &mut *cell_ptr;
1496 if !vm_ptr.is_null() {
1497 let vm = &mut *vm_ptr;
1498 let len = vec_ref.len();
1499 let cap = vec_ref.capacity();
1500 if len == cap {
1501 let new_cap = if cap == 0 { 4 } else { cap.saturating_mul(2) };
1502 if !vm.try_charge_memory_vec_growth::<Value>(cap, new_cap) {
1503 return 0;
1504 }
1505 }
1506 }
1507 vec_ref.push(value.clone());
1508 1
1509 }
1510 _ => 0,
1511 }
1512}
1513
1514#[cfg(feature = "std")]
1519#[no_mangle]
1520pub unsafe extern "C" fn jit_unbox_array_int(
1521 array_value_ptr: *const Value,
1522 out_vec_ptr: *mut *mut LustInt,
1523 out_len: *mut usize,
1524 out_cap: *mut usize,
1525) -> u8 {
1526 if array_value_ptr.is_null() || out_vec_ptr.is_null() || out_len.is_null() || out_cap.is_null()
1527 {
1528 return 0;
1529 }
1530
1531 let array_value = &*array_value_ptr;
1532 match array_value {
1533 Value::Array(arr_rc) => {
1534 let cell_ptr = arr_rc.as_ptr();
1536 let vec_ref = &mut *cell_ptr;
1537
1538 let original_vec = core::mem::replace(vec_ref, Vec::new());
1540
1541 let mut specialized_vec: Vec<LustInt> = Vec::with_capacity(original_vec.len());
1543 for elem in original_vec.into_iter() {
1544 match elem {
1545 Value::Int(i) => specialized_vec.push(i),
1546 _ => {
1547 return 0;
1550 }
1551 }
1552 }
1553
1554 let len = specialized_vec.len();
1556 let cap = specialized_vec.capacity();
1557 let ptr = specialized_vec.as_mut_ptr();
1558
1559 core::mem::forget(specialized_vec);
1561
1562 ptr::write(out_vec_ptr, ptr);
1564 ptr::write(out_len, len);
1565 ptr::write(out_cap, cap);
1566
1567 1
1571 }
1572 _ => 0,
1573 }
1574}
1575
1576#[cfg(feature = "std")]
1580#[no_mangle]
1581pub unsafe extern "C" fn jit_rebox_array_int(
1582 vec_ptr: *mut LustInt,
1583 vec_len: usize,
1584 vec_cap: usize,
1585 array_value_ptr: *mut Value,
1586) -> u8 {
1587 if vec_ptr.is_null() || array_value_ptr.is_null() {
1588 return 0;
1589 }
1590
1591 let specialized_vec = Vec::from_raw_parts(vec_ptr, vec_len, vec_cap);
1593
1594 let array_value = &mut *array_value_ptr;
1596 match array_value {
1597 Value::Array(arr_rc) => {
1598 let cell_ptr = arr_rc.as_ptr();
1600 let vec_ref = &mut *cell_ptr;
1601
1602 *vec_ref = specialized_vec.into_iter().map(Value::Int).collect();
1604
1605 1
1606 }
1607 _ => {
1608 let value_vec: Vec<Value> = specialized_vec.into_iter().map(Value::Int).collect();
1611 let array_value_new = Value::array(value_vec);
1612 ptr::write(array_value_ptr, array_value_new);
1613 1
1614 }
1615 }
1616}
1617
1618#[cfg(feature = "std")]
1621#[no_mangle]
1622pub unsafe extern "C" fn jit_vec_int_push(
1623 vec_ptr: *mut *mut LustInt,
1624 vec_len: *mut usize,
1625 vec_cap: *mut usize,
1626 value: LustInt,
1627) -> u8 {
1628 if vec_ptr.is_null() || vec_len.is_null() || vec_cap.is_null() {
1629 return 0;
1630 }
1631
1632 let ptr = *vec_ptr;
1633 let len = *vec_len;
1634 let cap = *vec_cap;
1635
1636 let mut vec = Vec::from_raw_parts(ptr, len, cap);
1638
1639 vec.push(value);
1641
1642 let new_len = vec.len();
1644 let new_cap = vec.capacity();
1645 let new_ptr = vec.as_mut_ptr();
1646
1647 core::mem::forget(vec);
1649
1650 ptr::write(vec_ptr, new_ptr);
1652 ptr::write(vec_len, new_len);
1653 ptr::write(vec_cap, new_cap);
1654
1655 1
1656}
1657
1658#[cfg(feature = "std")]
1662#[no_mangle]
1663pub unsafe extern "C" fn jit_drop_vec_int(vec_ptr: *mut LustInt, vec_len: usize, vec_cap: usize) {
1664 eprintln!(
1665 "🗑️ jit_drop_vec_int: ptr={:p}, len={}, cap={}",
1666 vec_ptr, vec_len, vec_cap
1667 );
1668 eprintln!("🗑️ jit_drop_vec_int: THIS SHOULD NOT BE CALLED - THE VEC DATA IS STALE!");
1669
1670 eprintln!("🗑️ jit_drop_vec_int: skipping drop (would cause corruption)");
1673}
1674
1675#[cfg(feature = "std")]
1676#[no_mangle]
1677pub unsafe extern "C" fn jit_enum_is_some_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1678 if enum_ptr.is_null() || out_ptr.is_null() {
1679 return 0;
1680 }
1681
1682 let enum_value = &*enum_ptr;
1683 match enum_value {
1684 Value::Enum { variant, .. } => {
1685 let is_some = variant == "Some";
1686 ptr::write(out_ptr, Value::Bool(is_some));
1687 1
1688 }
1689 _ => 0,
1690 }
1691}
1692
1693#[cfg(feature = "std")]
1694#[no_mangle]
1695pub unsafe extern "C" fn jit_enum_unwrap_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1696 if enum_ptr.is_null() || out_ptr.is_null() {
1697 return 0;
1698 }
1699
1700 let enum_value = &*enum_ptr;
1701 match enum_value {
1702 Value::Enum {
1703 values: Some(vals), ..
1704 } if vals.len() == 1 => {
1705 ptr::write(out_ptr, vals[0].clone());
1706 1
1707 }
1708 _ => 0,
1709 }
1710}
1711
1712#[cfg(feature = "std")]
1713#[no_mangle]
1714pub unsafe extern "C" fn jit_set_field_strong_safe(
1715 object_ptr: *const Value,
1716 field_index: usize,
1717 value_ptr: *const Value,
1718) -> u8 {
1719 if object_ptr.is_null() || value_ptr.is_null() {
1720 return 0;
1721 }
1722
1723 let object = &*object_ptr;
1724 let value = (&*value_ptr).clone();
1725
1726 match object {
1727 Value::Struct { fields, .. } => {
1728 match fields.try_borrow_mut() {
1730 Ok(mut borrowed) => {
1731 if field_index < borrowed.len() {
1732 borrowed[field_index] = value;
1733 1
1734 } else {
1735 0
1736 }
1737 }
1738 Err(_) => 0,
1739 }
1740 }
1741 _ => 0,
1742 }
1743}
1744
1745#[cfg(feature = "std")]
1746#[no_mangle]
1747pub unsafe extern "C" fn jit_concat_safe(
1748 vm_ptr: *mut VM,
1749 left_value_ptr: *const Value,
1750 right_value_ptr: *const Value,
1751 out: *mut Value,
1752) -> u8 {
1753 if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1754 return 0;
1755 }
1756
1757 let left = &*left_value_ptr;
1758 let right = &*right_value_ptr;
1759 let (left_str, right_str) = if !vm_ptr.is_null() {
1760 let vm = &mut *vm_ptr;
1761 let left_copy = left.clone();
1762 let right_copy = right.clone();
1763 let left_str = match vm.value_to_string_for_concat(&left_copy) {
1764 Ok(rc) => rc,
1765 Err(_) => return 0,
1766 };
1767 let right_str = match vm.value_to_string_for_concat(&right_copy) {
1768 Ok(rc) => rc,
1769 Err(_) => return 0,
1770 };
1771 (left_str, right_str)
1772 } else {
1773 (Rc::new(left.to_string()), Rc::new(right.to_string()))
1774 };
1775 let cap = left_str.len().saturating_add(right_str.len());
1776 if !vm_ptr.is_null() {
1777 let vm = &mut *vm_ptr;
1778 if !vm.try_charge_memory_bytes(cap) {
1779 return 0;
1780 }
1781 }
1782 let mut combined = String::with_capacity(cap);
1783 combined.push_str(left_str.as_ref());
1784 combined.push_str(right_str.as_ref());
1785 let result = Value::string(combined);
1786 ptr::write(out, result);
1787 1
1788}
1789
1790#[no_mangle]
1791pub unsafe extern "C" fn jit_guard_native_function(
1792 value_ptr: *const Value,
1793 expected_fn_ptr: *const (),
1794 register_index: u8,
1795) -> u8 {
1796 if value_ptr.is_null() || expected_fn_ptr.is_null() {
1797 jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1798 return 0;
1799 }
1800
1801 match &*value_ptr {
1802 Value::NativeFunction(func) => {
1803 let actual = Rc::as_ptr(func) as *const ();
1804 if actual == expected_fn_ptr {
1805 1
1806 } else {
1807 jit::log(|| {
1808 format!(
1809 "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1810 register_index, actual, expected_fn_ptr
1811 )
1812 });
1813 0
1814 }
1815 }
1816
1817 other => {
1818 jit::log(|| {
1819 format!(
1820 "jit_guard_native_function: value not native in reg {} ({:?})",
1821 register_index,
1822 other.tag()
1823 )
1824 });
1825 0
1826 }
1827 }
1828}
1829
1830#[no_mangle]
1831pub unsafe extern "C" fn jit_guard_function_identity(
1832 value_ptr: *const Value,
1833 expected_kind: u8,
1834 expected_function_idx: usize,
1835 expected_upvalues: *const (),
1836 register_index: u8,
1837) -> u8 {
1838 if value_ptr.is_null() {
1839 jit::log(|| "jit_guard_function_identity: null pointer input".to_string());
1840 return 0;
1841 }
1842
1843 let value = &*value_ptr;
1844 match (expected_kind, value) {
1845 (0, Value::Function(idx)) => {
1846 if *idx == expected_function_idx {
1847 1
1848 } else {
1849 jit::log(|| {
1850 format!(
1851 "jit_guard_function_identity: function idx mismatch (reg {}) actual={} expected={}",
1852 register_index, idx, expected_function_idx
1853 )
1854 });
1855 0
1856 }
1857 }
1858
1859 (
1860 1,
1861 Value::Closure {
1862 function_idx,
1863 upvalues,
1864 },
1865 ) => {
1866 if *function_idx != expected_function_idx {
1867 jit::log(|| {
1868 format!(
1869 "jit_guard_function_identity: closure idx mismatch (reg {}) actual={} expected={}",
1870 register_index, function_idx, expected_function_idx
1871 )
1872 });
1873 return 0;
1874 }
1875
1876 let actual_ptr = Rc::as_ptr(upvalues) as *const ();
1877 if actual_ptr == expected_upvalues {
1878 1
1879 } else {
1880 jit::log(|| {
1881 format!(
1882 "jit_guard_function_identity: upvalues mismatch (reg {}) actual={:p} expected={:p}",
1883 register_index, actual_ptr, expected_upvalues
1884 )
1885 });
1886 0
1887 }
1888 }
1889
1890 (0, Value::Closure { function_idx, .. }) => {
1891 jit::log(|| {
1892 format!(
1893 "jit_guard_function_identity: expected function, saw closure (reg {}, idx {})",
1894 register_index, function_idx
1895 )
1896 });
1897 0
1898 }
1899
1900 (1, Value::Function(idx)) => {
1901 jit::log(|| {
1902 format!(
1903 "jit_guard_function_identity: expected closure, saw function (reg {}, idx {})",
1904 register_index, idx
1905 )
1906 });
1907 0
1908 }
1909
1910 (_, other) => {
1911 jit::log(|| {
1912 format!(
1913 "jit_guard_function_identity: value in reg {} not callable ({:?})",
1914 register_index,
1915 other.tag()
1916 )
1917 });
1918 0
1919 }
1920 }
1921}
1922
1923#[no_mangle]
1924pub unsafe extern "C" fn jit_call_native_safe(
1925 vm_ptr: *mut VM,
1926 callee_ptr: *const Value,
1927 expected_fn_ptr: *const (),
1928 args_ptr: *const Value,
1929 arg_count: u8,
1930 out: *mut Value,
1931) -> u8 {
1932 if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1933 jit::log(|| "jit_call_native_safe: null argument".to_string());
1934 return 0;
1935 }
1936
1937 let callee = &*callee_ptr;
1938 let native_fn = match callee {
1939 Value::NativeFunction(func) => func.clone(),
1940 other => {
1941 jit::log(|| {
1942 format!(
1943 "jit_call_native_safe: callee not native ({:?})",
1944 other.tag()
1945 )
1946 });
1947 return 0;
1948 }
1949 };
1950
1951 if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1952 jit::log(|| {
1953 format!(
1954 "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1955 Rc::as_ptr(&native_fn),
1956 expected_fn_ptr
1957 )
1958 });
1959 return 0;
1960 }
1961
1962 let mut args = Vec::with_capacity(arg_count as usize);
1963 if arg_count > 0 {
1964 if args_ptr.is_null() {
1965 jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1966 return 0;
1967 }
1968
1969 for i in 0..(arg_count as usize) {
1970 let arg = &*args_ptr.add(i);
1971 args.push(arg.clone());
1972 }
1973 }
1974
1975 push_vm_ptr(vm_ptr);
1976 let outcome = native_fn(&args);
1977 pop_vm_ptr();
1978
1979 let outcome = match outcome {
1980 Ok(result) => result,
1981 Err(err) => {
1982 jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1983 return 0;
1984 }
1985 };
1986
1987 match outcome {
1988 NativeCallResult::Return(value) => {
1989 ptr::write(out, value);
1990 1
1991 }
1992
1993 NativeCallResult::Yield(value) => {
1994 let vm = &mut *vm_ptr;
1995 if vm.current_task.is_none() {
1996 jit::log(|| "jit_call_native_safe: native attempted to yield outside a task".to_string());
1997 return 0;
1998 }
1999
2000 let dest_reg = vm.call_stack.last().and_then(|frame| {
2001 let base = frame.registers.as_ptr() as usize;
2002 let out_ptr = out as usize;
2003 let value_size = core::mem::size_of::<Value>();
2004 let end = base + value_size * frame.registers.len();
2005 if out_ptr < base || out_ptr >= end {
2006 return None;
2007 }
2008 let offset = out_ptr - base;
2009 if offset % value_size != 0 {
2010 return None;
2011 }
2012 let reg = offset / value_size;
2013 if reg > u8::MAX as usize {
2014 return None;
2015 }
2016 Some(reg as u8)
2017 });
2018 let Some(dest_reg) = dest_reg else {
2019 jit::log(|| "jit_call_native_safe: could not compute dest register for yield".to_string());
2020 return 0;
2021 };
2022
2023 ptr::write(out, Value::Nil);
2024 vm.pending_task_signal = Some(crate::vm::TaskSignal::Yield { dest: dest_reg, value });
2025 2
2026 }
2027
2028 NativeCallResult::Stop(value) => {
2029 let vm = &mut *vm_ptr;
2030 if vm.current_task.is_none() {
2031 jit::log(|| "jit_call_native_safe: native attempted to stop outside a task".to_string());
2032 return 0;
2033 }
2034
2035 ptr::write(out, Value::Nil);
2036 vm.pending_task_signal = Some(crate::vm::TaskSignal::Stop { value });
2037 3
2038 }
2039 }
2040}
2041
2042#[no_mangle]
2043pub unsafe extern "C" fn jit_call_function_safe(
2044 vm_ptr: *mut VM,
2045 callee_ptr: *const Value,
2046 args_ptr: *const Value,
2047 arg_count: u8,
2048 dest_reg: u8,
2049) -> u8 {
2050 if vm_ptr.is_null() || callee_ptr.is_null() {
2051 jit::log(|| "jit_call_function_safe: null argument".to_string());
2052 return 0;
2053 }
2054
2055 if arg_count > 0 && args_ptr.is_null() {
2056 jit::log(|| "jit_call_function_safe: args_ptr null with non-zero arg_count".to_string());
2057 return 0;
2058 }
2059
2060 let callee = (&*callee_ptr).clone();
2062 let mut args = Vec::with_capacity(arg_count as usize);
2063 for i in 0..(arg_count as usize) {
2064 let arg_ptr = args_ptr.add(i);
2065 args.push((&*arg_ptr).clone());
2066 }
2067
2068 let vm = &mut *vm_ptr;
2069 push_vm_ptr(vm_ptr);
2070
2071 let jit_was_enabled = vm.jit.enabled;
2073 vm.jit.enabled = false;
2074
2075 let call_result = vm.call_value(&callee, args);
2076
2077 vm.jit.enabled = jit_was_enabled;
2079 pop_vm_ptr();
2080
2081 match call_result {
2082 Ok(value) => {
2083 let vm = &mut *vm_ptr;
2085 if let Some(frame) = vm.call_stack.last_mut() {
2086 if (dest_reg as usize) < frame.registers.len() {
2087 frame.registers[dest_reg as usize] = value;
2088 1
2089 } else {
2090 jit::log(|| {
2091 format!(
2092 "jit_call_function_safe: dest_reg {} out of bounds",
2093 dest_reg
2094 )
2095 });
2096 0
2097 }
2098 } else {
2099 jit::log(|| "jit_call_function_safe: no call frame".to_string());
2100 0
2101 }
2102 }
2103
2104 Err(err) => {
2105 jit::log(|| format!("jit_call_function_safe: {}", err));
2106 0
2107 }
2108 }
2109}
2110
2111#[no_mangle]
2112pub unsafe extern "C" fn jit_current_registers(vm_ptr: *mut VM) -> *mut Value {
2113 if vm_ptr.is_null() {
2114 return core::ptr::null_mut();
2115 }
2116
2117 let vm = &mut *vm_ptr;
2118 vm.call_stack
2119 .last_mut()
2120 .map(|frame| frame.registers.as_mut_ptr())
2121 .unwrap_or(core::ptr::null_mut())
2122}
2123
2124#[no_mangle]
2125pub unsafe extern "C" fn jit_value_is_truthy(value_ptr: *const Value) -> u8 {
2126 if value_ptr.is_null() {
2127 return 0;
2128 }
2129
2130 let value = &*value_ptr;
2131 if value.is_truthy() {
2132 1
2133 } else {
2134 0
2135 }
2136}
2137
2138#[no_mangle]
2139pub unsafe extern "C" fn jit_new_enum_unit_safe(
2140 vm_ptr: *mut VM,
2141 enum_name_ptr: *const u8,
2142 enum_name_len: usize,
2143 variant_name_ptr: *const u8,
2144 variant_name_len: usize,
2145 out: *mut Value,
2146) -> u8 {
2147 if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2148 return 0;
2149 }
2150
2151 let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2152 let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2153 let enum_name_str = match str::from_utf8(enum_name_slice) {
2154 Ok(s) => s,
2155 Err(_) => return 0,
2156 };
2157 let variant_name_str = match str::from_utf8(variant_name_slice) {
2158 Ok(s) => s,
2159 Err(_) => return 0,
2160 };
2161
2162 if !vm_ptr.is_null() {
2163 let vm = &mut *vm_ptr;
2164 let bytes = enum_name_len.saturating_add(variant_name_len);
2165 if !vm.try_charge_memory_bytes(bytes) {
2166 return 0;
2167 }
2168 }
2169
2170 let enum_name = enum_name_str.to_string();
2171 let variant_name = variant_name_str.to_string();
2172 let value = Value::enum_unit(enum_name, variant_name);
2173 ptr::write(out, value);
2174 1
2175}
2176
2177#[no_mangle]
2178pub unsafe extern "C" fn jit_new_enum_variant_safe(
2179 vm_ptr: *mut VM,
2180 enum_name_ptr: *const u8,
2181 enum_name_len: usize,
2182 variant_name_ptr: *const u8,
2183 variant_name_len: usize,
2184 values_ptr: *const Value,
2185 value_count: usize,
2186 out: *mut Value,
2187) -> u8 {
2188 if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2189 return 0;
2190 }
2191
2192 if value_count > 0 && values_ptr.is_null() {
2193 return 0;
2194 }
2195
2196 let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2197 let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2198 let enum_name_str = match str::from_utf8(enum_name_slice) {
2199 Ok(s) => s,
2200 Err(_) => return 0,
2201 };
2202 let variant_name_str = match str::from_utf8(variant_name_slice) {
2203 Ok(s) => s,
2204 Err(_) => return 0,
2205 };
2206
2207 if !vm_ptr.is_null() {
2208 let vm = &mut *vm_ptr;
2209 let name_bytes = enum_name_len.saturating_add(variant_name_len);
2210 if !vm.try_charge_memory_bytes(name_bytes) {
2211 return 0;
2212 }
2213 if !vm.try_charge_memory_value_vec(value_count) {
2214 return 0;
2215 }
2216 }
2217
2218 let enum_name = enum_name_str.to_string();
2219 let variant_name = variant_name_str.to_string();
2220 let mut values = Vec::with_capacity(value_count);
2221 for i in 0..value_count {
2222 let value = &*values_ptr.add(i);
2223 values.push(value.clone());
2224 }
2225
2226 let value = Value::enum_variant(enum_name, variant_name, values);
2227 ptr::write(out, value);
2228 1
2229}
2230
2231#[no_mangle]
2232pub unsafe extern "C" fn jit_is_enum_variant_safe(
2233 value_ptr: *const Value,
2234 enum_name_ptr: *const u8,
2235 enum_name_len: usize,
2236 variant_name_ptr: *const u8,
2237 variant_name_len: usize,
2238) -> u8 {
2239 if value_ptr.is_null() || enum_name_ptr.is_null() || variant_name_ptr.is_null() {
2240 return 0;
2241 }
2242
2243 let value = &*value_ptr;
2244 let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2245 let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2246 let enum_name = match str::from_utf8(enum_name_slice) {
2247 Ok(s) => s,
2248 Err(_) => return 0,
2249 };
2250 let variant_name = match str::from_utf8(variant_name_slice) {
2251 Ok(s) => s,
2252 Err(_) => return 0,
2253 };
2254 if value.is_enum_variant(enum_name, variant_name) {
2255 1
2256 } else {
2257 0
2258 }
2259}
2260
2261#[no_mangle]
2262pub unsafe extern "C" fn jit_get_enum_value_safe(
2263 enum_ptr: *const Value,
2264 index: usize,
2265 out: *mut Value,
2266) -> u8 {
2267 if enum_ptr.is_null() || out.is_null() {
2268 return 0;
2269 }
2270
2271 let enum_value = &*enum_ptr;
2272 if let Some((_, _, Some(values))) = enum_value.as_enum() {
2273 if index < values.len() {
2274 ptr::write(out, values[index].clone());
2275 1
2276 } else {
2277 0
2278 }
2279 } else {
2280 0
2281 }
2282}
2283
2284#[no_mangle]
2285pub unsafe extern "C" fn jit_call_method_safe(
2286 vm_ptr: *mut VM,
2287 object_ptr: *const Value,
2288 method_name_ptr: *const u8,
2289 method_name_len: usize,
2290 args_ptr: *const Value,
2291 arg_count: u8,
2292 dest_reg: u8,
2293) -> u8 {
2294 if vm_ptr.is_null() || object_ptr.is_null() || method_name_ptr.is_null() {
2295 jit::log(|| "jit_call_method_safe: null pointer argument".to_string());
2296 return 0;
2297 }
2298
2299 if arg_count > 0 && args_ptr.is_null() {
2300 return 0;
2301 }
2302
2303 let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
2304 let method_name = match str::from_utf8(method_name_slice) {
2305 Ok(s) => s,
2306 Err(_) => return 0,
2307 };
2308
2309 let object = (&*object_ptr).clone();
2310 if matches!(object, Value::Struct { .. }) {
2311 return 0;
2312 }
2313
2314 let mut args = Vec::with_capacity(arg_count as usize);
2315 for i in 0..arg_count {
2316 let arg_ptr = args_ptr.add(i as usize);
2317 args.push((&*arg_ptr).clone());
2318 }
2319
2320 crate::vm::push_vm_ptr(vm_ptr);
2321 let outcome = call_builtin_method_simple(&object, method_name, args);
2322 crate::vm::pop_vm_ptr();
2323 match outcome {
2324 Ok(val) => {
2325 let vm = &mut *vm_ptr;
2326 if let Some(frame) = vm.call_stack.last_mut() {
2327 if (dest_reg as usize) < frame.registers.len() {
2328 frame.registers[dest_reg as usize] = val;
2329 1
2330 } else {
2331 jit::log(|| {
2332 format!("jit_call_method_safe: dest_reg {} out of bounds", dest_reg)
2333 });
2334 0
2335 }
2336 } else {
2337 jit::log(|| "jit_call_method_safe: no call frame".to_string());
2338 0
2339 }
2340 }
2341 Err(_) => 0,
2342 }
2343}
2344
2345fn call_builtin_method_simple(
2346 object: &Value,
2347 method_name: &str,
2348 args: Vec<Value>,
2349) -> Result<Value, String> {
2350 match object {
2351 Value::Struct { name, .. } => Err(format!(
2352 "User-defined methods on {} require deoptimization",
2353 name
2354 )),
2355 Value::Iterator(state_rc) => match method_name {
2356 "next" => {
2357 let mut state = state_rc.borrow_mut();
2358 match &mut *state {
2359 IteratorState::Array { items, index } => {
2360 if *index < items.len() {
2361 let v = items[*index].clone();
2362 *index += 1;
2363 Ok(Value::some(v))
2364 } else {
2365 Ok(Value::none())
2366 }
2367 }
2368
2369 IteratorState::MapPairs { items, index } => {
2370 if *index < items.len() {
2371 let (k, v) = items[*index].clone();
2372 *index += 1;
2373 Ok(Value::some(Value::array(vec![k.to_value(), v])))
2374 } else {
2375 Ok(Value::none())
2376 }
2377 }
2378 }
2379 }
2380
2381 _ => Err(format!(
2382 "Iterator method '{}' not supported in JIT",
2383 method_name
2384 )),
2385 },
2386 Value::Enum {
2387 enum_name,
2388 variant,
2389 values,
2390 } if enum_name == "Option" => match method_name {
2391 "is_some" => Ok(Value::Bool(variant == "Some")),
2392 "is_none" => Ok(Value::Bool(variant == "None")),
2393 "unwrap" => {
2394 if variant == "Some" {
2395 if let Some(vals) = values {
2396 if vals.len() == 1 {
2397 Ok(vals[0].clone())
2398 } else {
2399 Err("Option::Some should have exactly 1 value".to_string())
2400 }
2401 } else {
2402 Err("Option::Some should have a value".to_string())
2403 }
2404 } else {
2405 Err("Called unwrap() on Option::None".to_string())
2406 }
2407 }
2408
2409 _ => Err(format!(
2410 "Option method '{}' not supported in JIT",
2411 method_name
2412 )),
2413 },
2414 Value::Array(arr) => match method_name {
2415 "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
2416 "push" => {
2417 let value = args
2418 .get(0)
2419 .cloned()
2420 .ok_or_else(|| "Array:push requires a value argument".to_string())?;
2421 arr.borrow_mut().push(value);
2422 Ok(Value::Nil)
2423 }
2424 "pop" => {
2425 let popped = arr.borrow_mut().pop();
2426 Ok(popped.map(Value::some).unwrap_or_else(Value::none))
2427 }
2428 "first" => {
2429 let borrowed = arr.borrow();
2430 Ok(borrowed
2431 .first()
2432 .cloned()
2433 .map(Value::some)
2434 .unwrap_or_else(Value::none))
2435 }
2436 "last" => {
2437 let borrowed = arr.borrow();
2438 Ok(borrowed
2439 .last()
2440 .cloned()
2441 .map(Value::some)
2442 .unwrap_or_else(Value::none))
2443 }
2444 "get" => {
2445 let index = args
2446 .get(0)
2447 .and_then(Value::as_int)
2448 .ok_or_else(|| "Array:get requires an integer index".to_string())?;
2449 let borrowed = arr.borrow();
2450 Ok(borrowed
2451 .get(index as usize)
2452 .cloned()
2453 .map(Value::some)
2454 .unwrap_or_else(Value::none))
2455 }
2456 "iter" => {
2457 let items = arr.borrow().clone();
2458 let iter = IteratorState::Array { items, index: 0 };
2459 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
2460 }
2461 _ => Err(format!(
2462 "Array method '{}' not supported in JIT",
2463 method_name
2464 )),
2465 },
2466 _ => Err(format!(
2467 "Method '{}' not supported in JIT (deoptimizing)",
2468 method_name
2469 )),
2470 }
2471}
2472
2473#[no_mangle]
2474pub unsafe extern "C" fn jit_get_field_safe(
2475 object_ptr: *const Value,
2476 field_name_ptr: *const u8,
2477 field_name_len: usize,
2478 out: *mut Value,
2479) -> u8 {
2480 if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
2481 return 0;
2482 }
2483
2484 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2485 let field_name = match str::from_utf8(field_name_slice) {
2486 Ok(s) => s,
2487 Err(_) => return 0,
2488 };
2489 let object = &*object_ptr;
2490 let field_value = match object {
2491 Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
2492 Some(idx) => match fields.borrow().get(idx) {
2493 Some(val) => val.clone(),
2494 None => return 0,
2495 },
2496 None => return 0,
2497 },
2498 _ => return 0,
2499 };
2500 ptr::write(out, field_value);
2501 1
2502}
2503
2504#[no_mangle]
2505pub unsafe extern "C" fn jit_set_field_safe(
2506 object_ptr: *const Value,
2507 field_name_ptr: *const u8,
2508 field_name_len: usize,
2509 value_ptr: *const Value,
2510) -> u8 {
2511 if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
2512 return 0;
2513 }
2514
2515 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2516 let field_name = match str::from_utf8(field_name_slice) {
2517 Ok(s) => s,
2518 Err(_) => return 0,
2519 };
2520 let object = &*object_ptr;
2521 let value = (&*value_ptr).clone();
2522 match object {
2523 Value::Struct { .. } => match object.struct_set_field(field_name, value) {
2524 Ok(()) => 1,
2525 Err(_) => 0,
2526 },
2527 Value::Map(map) => {
2528 use crate::bytecode::ValueKey;
2529 let key = ValueKey::from(field_name.to_string());
2530 map.borrow_mut().insert(key, value);
2531 1
2532 }
2533
2534 _ => 0,
2535 }
2536}
2537
2538#[no_mangle]
2539pub unsafe extern "C" fn jit_get_field_indexed_safe(
2540 object_ptr: *const Value,
2541 field_index: usize,
2542 out: *mut Value,
2543) -> u8 {
2544 if object_ptr.is_null() || out.is_null() {
2545 return 0;
2546 }
2547
2548 let object = &*object_ptr;
2549 match object.struct_get_field_indexed(field_index) {
2550 Some(value) => {
2551 ptr::write(out, value);
2552 1
2553 }
2554
2555 None => 0,
2556 }
2557}
2558
2559#[no_mangle]
2560pub unsafe extern "C" fn jit_set_field_indexed_safe(
2561 object_ptr: *const Value,
2562 field_index: usize,
2563 value_ptr: *const Value,
2564) -> u8 {
2565 if object_ptr.is_null() || value_ptr.is_null() {
2566 return 0;
2567 }
2568
2569 let object = &*object_ptr;
2570 let value = (&*value_ptr).clone();
2571 match object.struct_set_field_indexed(field_index, value) {
2572 Ok(()) => 1,
2573 Err(_) => 0,
2574 }
2575}
2576
2577#[no_mangle]
2578pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
2579 object_ptr: *const Value,
2580 field_index: usize,
2581 out: *mut Value,
2582) -> u8 {
2583 if object_ptr.is_null() || out.is_null() {
2584 return 0;
2585 }
2586
2587 let object = &*object_ptr;
2588 let out_ref = &mut *out;
2589 match object {
2590 Value::Struct { layout, fields, .. } => {
2591 if layout.is_weak(field_index) {
2592 return 0;
2593 }
2594
2595 if let Ok(borrowed) = fields.try_borrow() {
2596 if let Some(Value::Int(val)) = borrowed.get(field_index) {
2597 *out_ref = Value::Int(*val);
2598 return 1;
2599 }
2600 }
2601
2602 0
2603 }
2604
2605 _ => 0,
2606 }
2607}
2608
2609#[no_mangle]
2610pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
2611 object_ptr: *const Value,
2612 field_index: usize,
2613 value_ptr: *const Value,
2614) -> u8 {
2615 if object_ptr.is_null() || value_ptr.is_null() {
2616 return 0;
2617 }
2618
2619 let object = &*object_ptr;
2620 let value = &*value_ptr;
2621 let new_value = match value {
2622 Value::Int(v) => *v,
2623 _ => return 0,
2624 };
2625 match object {
2626 Value::Struct { layout, fields, .. } => {
2627 if layout.is_weak(field_index) {
2628 return 0;
2629 }
2630
2631 if let Ok(mut borrowed) = fields.try_borrow_mut() {
2632 if field_index < borrowed.len() {
2633 borrowed[field_index] = Value::Int(new_value);
2634 return 1;
2635 }
2636 }
2637
2638 0
2639 }
2640
2641 _ => 0,
2642 }
2643}
2644
2645#[no_mangle]
2646pub unsafe extern "C" fn jit_new_struct_safe(
2647 vm_ptr: *mut VM,
2648 struct_name_ptr: *const u8,
2649 struct_name_len: usize,
2650 field_names_ptr: *const *const u8,
2651 field_name_lens_ptr: *const usize,
2652 field_values_ptr: *const Value,
2653 field_count: usize,
2654 out: *mut Value,
2655) -> u8 {
2656 if struct_name_ptr.is_null() || out.is_null() || vm_ptr.is_null() {
2657 jit::log(|| "jit_new_struct_safe: null pointer input".to_string());
2658 return 0;
2659 }
2660
2661 if field_count > 0
2662 && (field_names_ptr.is_null()
2663 || field_name_lens_ptr.is_null()
2664 || field_values_ptr.is_null())
2665 {
2666 return 0;
2667 }
2668
2669 let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
2670 let struct_name = match str::from_utf8(struct_name_slice) {
2671 Ok(s) => s.to_string(),
2672 Err(_) => return 0,
2673 };
2674 let mut fields = Vec::with_capacity(field_count);
2675 for i in 0..field_count {
2676 let field_name_ptr = *field_names_ptr.add(i);
2677 let field_name_len = *field_name_lens_ptr.add(i);
2678 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2679 let field_name = match str::from_utf8(field_name_slice) {
2680 Ok(s) => Rc::new(s.to_string()),
2681 Err(_) => return 0,
2682 };
2683 let field_value_ptr = field_values_ptr.add(i);
2684 let field_value = (&*field_value_ptr).clone();
2685 fields.push((field_name, field_value));
2686 }
2687
2688 let vm = &mut *vm_ptr;
2689 let struct_value = match vm.instantiate_struct(&struct_name, fields) {
2690 Ok(value) => value,
2691 Err(err) => {
2692 jit::log(|| {
2693 format!(
2694 "jit_new_struct_safe: failed to instantiate '{}': {}",
2695 struct_name, err
2696 )
2697 });
2698 return 0;
2699 }
2700 };
2701 ptr::write(out, struct_value);
2702 1
2703}
2704
2705#[no_mangle]
2706pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
2707 if src_ptr.is_null() || dest_ptr.is_null() {
2708 return 0;
2709 }
2710
2711 let src_value = &*src_ptr;
2712 let cloned_value = src_value.clone();
2713 ptr::write(dest_ptr, cloned_value);
2714 1
2715}