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 elements_ptr: *const Value,
1437 element_count: usize,
1438 out_ptr: *mut Value,
1439) -> u8 {
1440 let _call_num = JIT_NEW_ARRAY_COUNTER.fetch_add(1, core::sync::atomic::Ordering::SeqCst);
1441 if out_ptr.is_null() {
1444 return 0;
1446 }
1447
1448 let elements = if element_count == 0 {
1450 Vec::new()
1451 } else {
1452 if elements_ptr.is_null() {
1453 return 0;
1455 }
1456
1457 let slice = slice::from_raw_parts(elements_ptr, element_count);
1458 slice.to_vec()
1459 };
1460
1461 let array_value = Value::array(elements);
1463 ptr::write(out_ptr, array_value);
1465 1
1467}
1468
1469#[cfg(feature = "std")]
1470#[no_mangle]
1471pub unsafe extern "C" fn jit_array_push_safe(
1472 array_ptr: *const Value,
1473 value_ptr: *const Value,
1474) -> u8 {
1475 if array_ptr.is_null() || value_ptr.is_null() {
1476 return 0;
1477 }
1478
1479 let array_value = &*array_ptr;
1480 let value = &*value_ptr;
1481
1482 match array_value {
1483 Value::Array(arr) => {
1484 let cell_ptr = arr.as_ptr();
1486 (*cell_ptr).push(value.clone());
1487 1
1488 }
1489 _ => 0,
1490 }
1491}
1492
1493#[cfg(feature = "std")]
1498#[no_mangle]
1499pub unsafe extern "C" fn jit_unbox_array_int(
1500 array_value_ptr: *const Value,
1501 out_vec_ptr: *mut *mut LustInt,
1502 out_len: *mut usize,
1503 out_cap: *mut usize,
1504) -> u8 {
1505 if array_value_ptr.is_null() || out_vec_ptr.is_null() || out_len.is_null() || out_cap.is_null()
1506 {
1507 return 0;
1508 }
1509
1510 let array_value = &*array_value_ptr;
1511 match array_value {
1512 Value::Array(arr_rc) => {
1513 let cell_ptr = arr_rc.as_ptr();
1515 let vec_ref = &mut *cell_ptr;
1516
1517 let original_vec = core::mem::replace(vec_ref, Vec::new());
1519
1520 let mut specialized_vec: Vec<LustInt> = Vec::with_capacity(original_vec.len());
1522 for elem in original_vec.into_iter() {
1523 match elem {
1524 Value::Int(i) => specialized_vec.push(i),
1525 _ => {
1526 return 0;
1529 }
1530 }
1531 }
1532
1533 let len = specialized_vec.len();
1535 let cap = specialized_vec.capacity();
1536 let ptr = specialized_vec.as_mut_ptr();
1537
1538 core::mem::forget(specialized_vec);
1540
1541 ptr::write(out_vec_ptr, ptr);
1543 ptr::write(out_len, len);
1544 ptr::write(out_cap, cap);
1545
1546 1
1550 }
1551 _ => 0,
1552 }
1553}
1554
1555#[cfg(feature = "std")]
1559#[no_mangle]
1560pub unsafe extern "C" fn jit_rebox_array_int(
1561 vec_ptr: *mut LustInt,
1562 vec_len: usize,
1563 vec_cap: usize,
1564 array_value_ptr: *mut Value,
1565) -> u8 {
1566 if vec_ptr.is_null() || array_value_ptr.is_null() {
1567 return 0;
1568 }
1569
1570 let specialized_vec = Vec::from_raw_parts(vec_ptr, vec_len, vec_cap);
1572
1573 let array_value = &mut *array_value_ptr;
1575 match array_value {
1576 Value::Array(arr_rc) => {
1577 let cell_ptr = arr_rc.as_ptr();
1579 let vec_ref = &mut *cell_ptr;
1580
1581 *vec_ref = specialized_vec.into_iter().map(Value::Int).collect();
1583
1584 1
1585 }
1586 _ => {
1587 let value_vec: Vec<Value> = specialized_vec.into_iter().map(Value::Int).collect();
1590 let array_value_new = Value::array(value_vec);
1591 ptr::write(array_value_ptr, array_value_new);
1592 1
1593 }
1594 }
1595}
1596
1597#[cfg(feature = "std")]
1600#[no_mangle]
1601pub unsafe extern "C" fn jit_vec_int_push(
1602 vec_ptr: *mut *mut LustInt,
1603 vec_len: *mut usize,
1604 vec_cap: *mut usize,
1605 value: LustInt,
1606) -> u8 {
1607 if vec_ptr.is_null() || vec_len.is_null() || vec_cap.is_null() {
1608 return 0;
1609 }
1610
1611 let ptr = *vec_ptr;
1612 let len = *vec_len;
1613 let cap = *vec_cap;
1614
1615 let mut vec = Vec::from_raw_parts(ptr, len, cap);
1617
1618 vec.push(value);
1620
1621 let new_len = vec.len();
1623 let new_cap = vec.capacity();
1624 let new_ptr = vec.as_mut_ptr();
1625
1626 core::mem::forget(vec);
1628
1629 ptr::write(vec_ptr, new_ptr);
1631 ptr::write(vec_len, new_len);
1632 ptr::write(vec_cap, new_cap);
1633
1634 1
1635}
1636
1637#[cfg(feature = "std")]
1641#[no_mangle]
1642pub unsafe extern "C" fn jit_drop_vec_int(vec_ptr: *mut LustInt, vec_len: usize, vec_cap: usize) {
1643 eprintln!(
1644 "🗑️ jit_drop_vec_int: ptr={:p}, len={}, cap={}",
1645 vec_ptr, vec_len, vec_cap
1646 );
1647 eprintln!("🗑️ jit_drop_vec_int: THIS SHOULD NOT BE CALLED - THE VEC DATA IS STALE!");
1648
1649 eprintln!("🗑️ jit_drop_vec_int: skipping drop (would cause corruption)");
1652}
1653
1654#[cfg(feature = "std")]
1655#[no_mangle]
1656pub unsafe extern "C" fn jit_enum_is_some_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1657 if enum_ptr.is_null() || out_ptr.is_null() {
1658 return 0;
1659 }
1660
1661 let enum_value = &*enum_ptr;
1662 match enum_value {
1663 Value::Enum { variant, .. } => {
1664 let is_some = variant == "Some";
1665 ptr::write(out_ptr, Value::Bool(is_some));
1666 1
1667 }
1668 _ => 0,
1669 }
1670}
1671
1672#[cfg(feature = "std")]
1673#[no_mangle]
1674pub unsafe extern "C" fn jit_enum_unwrap_safe(enum_ptr: *const Value, out_ptr: *mut Value) -> u8 {
1675 if enum_ptr.is_null() || out_ptr.is_null() {
1676 return 0;
1677 }
1678
1679 let enum_value = &*enum_ptr;
1680 match enum_value {
1681 Value::Enum {
1682 values: Some(vals), ..
1683 } if vals.len() == 1 => {
1684 ptr::write(out_ptr, vals[0].clone());
1685 1
1686 }
1687 _ => 0,
1688 }
1689}
1690
1691#[cfg(feature = "std")]
1692#[no_mangle]
1693pub unsafe extern "C" fn jit_set_field_strong_safe(
1694 object_ptr: *const Value,
1695 field_index: usize,
1696 value_ptr: *const Value,
1697) -> u8 {
1698 if object_ptr.is_null() || value_ptr.is_null() {
1699 return 0;
1700 }
1701
1702 let object = &*object_ptr;
1703 let value = (&*value_ptr).clone();
1704
1705 match object {
1706 Value::Struct { fields, .. } => {
1707 match fields.try_borrow_mut() {
1709 Ok(mut borrowed) => {
1710 if field_index < borrowed.len() {
1711 borrowed[field_index] = value;
1712 1
1713 } else {
1714 0
1715 }
1716 }
1717 Err(_) => 0,
1718 }
1719 }
1720 _ => 0,
1721 }
1722}
1723
1724#[cfg(feature = "std")]
1725#[no_mangle]
1726pub unsafe extern "C" fn jit_concat_safe(
1727 left_value_ptr: *const Value,
1728 right_value_ptr: *const Value,
1729 out: *mut Value,
1730) -> u8 {
1731 if left_value_ptr.is_null() || right_value_ptr.is_null() || out.is_null() {
1732 return 0;
1733 }
1734
1735 let left = &*left_value_ptr;
1736 let right = &*right_value_ptr;
1737 const NO_VM_ERROR: &str = "task API requires a running VM";
1738 let left_str = match VM::with_current(|vm| {
1739 let left_copy = left.clone();
1740 vm.value_to_string_for_concat(&left_copy)
1741 .map_err(|err| err.to_string())
1742 }) {
1743 Ok(rc) => rc,
1744 Err(err) if err == NO_VM_ERROR => Rc::new(left.to_string()),
1745 Err(_) => return 0,
1746 };
1747 let right_str = match VM::with_current(|vm| {
1748 let right_copy = right.clone();
1749 vm.value_to_string_for_concat(&right_copy)
1750 .map_err(|err| err.to_string())
1751 }) {
1752 Ok(rc) => rc,
1753 Err(err) if err == NO_VM_ERROR => Rc::new(right.to_string()),
1754 Err(_) => return 0,
1755 };
1756 let mut combined = String::with_capacity(left_str.len() + right_str.len());
1757 combined.push_str(left_str.as_ref());
1758 combined.push_str(right_str.as_ref());
1759 let result = Value::string(combined);
1760 ptr::write(out, result);
1761 1
1762}
1763
1764#[no_mangle]
1765pub unsafe extern "C" fn jit_guard_native_function(
1766 value_ptr: *const Value,
1767 expected_fn_ptr: *const (),
1768 register_index: u8,
1769) -> u8 {
1770 if value_ptr.is_null() || expected_fn_ptr.is_null() {
1771 jit::log(|| "jit_guard_native_function: null pointer input".to_string());
1772 return 0;
1773 }
1774
1775 match &*value_ptr {
1776 Value::NativeFunction(func) => {
1777 let actual = Rc::as_ptr(func) as *const ();
1778 if actual == expected_fn_ptr {
1779 1
1780 } else {
1781 jit::log(|| {
1782 format!(
1783 "jit_guard_native_function: pointer mismatch (reg {}) actual={:p} expected={:p}",
1784 register_index, actual, expected_fn_ptr
1785 )
1786 });
1787 0
1788 }
1789 }
1790
1791 other => {
1792 jit::log(|| {
1793 format!(
1794 "jit_guard_native_function: value not native in reg {} ({:?})",
1795 register_index,
1796 other.tag()
1797 )
1798 });
1799 0
1800 }
1801 }
1802}
1803
1804#[no_mangle]
1805pub unsafe extern "C" fn jit_guard_function_identity(
1806 value_ptr: *const Value,
1807 expected_kind: u8,
1808 expected_function_idx: usize,
1809 expected_upvalues: *const (),
1810 register_index: u8,
1811) -> u8 {
1812 if value_ptr.is_null() {
1813 jit::log(|| "jit_guard_function_identity: null pointer input".to_string());
1814 return 0;
1815 }
1816
1817 let value = &*value_ptr;
1818 match (expected_kind, value) {
1819 (0, Value::Function(idx)) => {
1820 if *idx == expected_function_idx {
1821 1
1822 } else {
1823 jit::log(|| {
1824 format!(
1825 "jit_guard_function_identity: function idx mismatch (reg {}) actual={} expected={}",
1826 register_index, idx, expected_function_idx
1827 )
1828 });
1829 0
1830 }
1831 }
1832
1833 (
1834 1,
1835 Value::Closure {
1836 function_idx,
1837 upvalues,
1838 },
1839 ) => {
1840 if *function_idx != expected_function_idx {
1841 jit::log(|| {
1842 format!(
1843 "jit_guard_function_identity: closure idx mismatch (reg {}) actual={} expected={}",
1844 register_index, function_idx, expected_function_idx
1845 )
1846 });
1847 return 0;
1848 }
1849
1850 let actual_ptr = Rc::as_ptr(upvalues) as *const ();
1851 if actual_ptr == expected_upvalues {
1852 1
1853 } else {
1854 jit::log(|| {
1855 format!(
1856 "jit_guard_function_identity: upvalues mismatch (reg {}) actual={:p} expected={:p}",
1857 register_index, actual_ptr, expected_upvalues
1858 )
1859 });
1860 0
1861 }
1862 }
1863
1864 (0, Value::Closure { function_idx, .. }) => {
1865 jit::log(|| {
1866 format!(
1867 "jit_guard_function_identity: expected function, saw closure (reg {}, idx {})",
1868 register_index, function_idx
1869 )
1870 });
1871 0
1872 }
1873
1874 (1, Value::Function(idx)) => {
1875 jit::log(|| {
1876 format!(
1877 "jit_guard_function_identity: expected closure, saw function (reg {}, idx {})",
1878 register_index, idx
1879 )
1880 });
1881 0
1882 }
1883
1884 (_, other) => {
1885 jit::log(|| {
1886 format!(
1887 "jit_guard_function_identity: value in reg {} not callable ({:?})",
1888 register_index,
1889 other.tag()
1890 )
1891 });
1892 0
1893 }
1894 }
1895}
1896
1897#[no_mangle]
1898pub unsafe extern "C" fn jit_call_native_safe(
1899 vm_ptr: *mut VM,
1900 callee_ptr: *const Value,
1901 expected_fn_ptr: *const (),
1902 args_ptr: *const Value,
1903 arg_count: u8,
1904 out: *mut Value,
1905) -> u8 {
1906 if vm_ptr.is_null() || callee_ptr.is_null() || expected_fn_ptr.is_null() || out.is_null() {
1907 jit::log(|| "jit_call_native_safe: null argument".to_string());
1908 return 0;
1909 }
1910
1911 let callee = &*callee_ptr;
1912 let native_fn = match callee {
1913 Value::NativeFunction(func) => func.clone(),
1914 other => {
1915 jit::log(|| {
1916 format!(
1917 "jit_call_native_safe: callee not native ({:?})",
1918 other.tag()
1919 )
1920 });
1921 return 0;
1922 }
1923 };
1924
1925 if Rc::as_ptr(&native_fn) as *const () != expected_fn_ptr {
1926 jit::log(|| {
1927 format!(
1928 "jit_call_native_safe: pointer mismatch actual={:p} expected={:p}",
1929 Rc::as_ptr(&native_fn),
1930 expected_fn_ptr
1931 )
1932 });
1933 return 0;
1934 }
1935
1936 let mut args = Vec::with_capacity(arg_count as usize);
1937 if arg_count > 0 {
1938 if args_ptr.is_null() {
1939 jit::log(|| "jit_call_native_safe: args_ptr null with non-zero arg_count".to_string());
1940 return 0;
1941 }
1942
1943 for i in 0..(arg_count as usize) {
1944 let arg = &*args_ptr.add(i);
1945 args.push(arg.clone());
1946 }
1947 }
1948
1949 push_vm_ptr(vm_ptr);
1950 let outcome = native_fn(&args);
1951 pop_vm_ptr();
1952
1953 let outcome = match outcome {
1954 Ok(result) => result,
1955 Err(err) => {
1956 jit::log(|| format!("jit_call_native_safe: native returned error: {}", err));
1957 return 0;
1958 }
1959 };
1960
1961 match outcome {
1962 NativeCallResult::Return(value) => {
1963 ptr::write(out, value);
1964 1
1965 }
1966
1967 NativeCallResult::Yield(_) => {
1968 jit::log(|| "jit_call_native_safe: native attempted to yield".to_string());
1969 0
1970 }
1971
1972 NativeCallResult::Stop(_) => {
1973 jit::log(|| "jit_call_native_safe: native attempted to stop".to_string());
1974 0
1975 }
1976 }
1977}
1978
1979#[no_mangle]
1980pub unsafe extern "C" fn jit_call_function_safe(
1981 vm_ptr: *mut VM,
1982 callee_ptr: *const Value,
1983 args_ptr: *const Value,
1984 arg_count: u8,
1985 dest_reg: u8,
1986) -> u8 {
1987 if vm_ptr.is_null() || callee_ptr.is_null() {
1988 jit::log(|| "jit_call_function_safe: null argument".to_string());
1989 return 0;
1990 }
1991
1992 if arg_count > 0 && args_ptr.is_null() {
1993 jit::log(|| "jit_call_function_safe: args_ptr null with non-zero arg_count".to_string());
1994 return 0;
1995 }
1996
1997 let callee = (&*callee_ptr).clone();
1999 let mut args = Vec::with_capacity(arg_count as usize);
2000 for i in 0..(arg_count as usize) {
2001 let arg_ptr = args_ptr.add(i);
2002 args.push((&*arg_ptr).clone());
2003 }
2004
2005 let vm = &mut *vm_ptr;
2006 push_vm_ptr(vm_ptr);
2007
2008 let jit_was_enabled = vm.jit.enabled;
2010 vm.jit.enabled = false;
2011
2012 let call_result = vm.call_value(&callee, args);
2013
2014 vm.jit.enabled = jit_was_enabled;
2016 pop_vm_ptr();
2017
2018 match call_result {
2019 Ok(value) => {
2020 let vm = &mut *vm_ptr;
2022 if let Some(frame) = vm.call_stack.last_mut() {
2023 if (dest_reg as usize) < frame.registers.len() {
2024 frame.registers[dest_reg as usize] = value;
2025 1
2026 } else {
2027 jit::log(|| {
2028 format!(
2029 "jit_call_function_safe: dest_reg {} out of bounds",
2030 dest_reg
2031 )
2032 });
2033 0
2034 }
2035 } else {
2036 jit::log(|| "jit_call_function_safe: no call frame".to_string());
2037 0
2038 }
2039 }
2040
2041 Err(err) => {
2042 jit::log(|| format!("jit_call_function_safe: {}", err));
2043 0
2044 }
2045 }
2046}
2047
2048#[no_mangle]
2049pub unsafe extern "C" fn jit_current_registers(vm_ptr: *mut VM) -> *mut Value {
2050 if vm_ptr.is_null() {
2051 return core::ptr::null_mut();
2052 }
2053
2054 let vm = &mut *vm_ptr;
2055 vm.call_stack
2056 .last_mut()
2057 .map(|frame| frame.registers.as_mut_ptr())
2058 .unwrap_or(core::ptr::null_mut())
2059}
2060
2061#[no_mangle]
2062pub unsafe extern "C" fn jit_value_is_truthy(value_ptr: *const Value) -> u8 {
2063 if value_ptr.is_null() {
2064 return 0;
2065 }
2066
2067 let value = &*value_ptr;
2068 if value.is_truthy() {
2069 1
2070 } else {
2071 0
2072 }
2073}
2074
2075#[no_mangle]
2076pub unsafe extern "C" fn jit_new_enum_unit_safe(
2077 enum_name_ptr: *const u8,
2078 enum_name_len: usize,
2079 variant_name_ptr: *const u8,
2080 variant_name_len: usize,
2081 out: *mut Value,
2082) -> u8 {
2083 if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2084 return 0;
2085 }
2086
2087 let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2088 let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2089 let enum_name = match str::from_utf8(enum_name_slice) {
2090 Ok(s) => s.to_string(),
2091 Err(_) => return 0,
2092 };
2093 let variant_name = match str::from_utf8(variant_name_slice) {
2094 Ok(s) => s.to_string(),
2095 Err(_) => return 0,
2096 };
2097 let value = Value::enum_unit(enum_name, variant_name);
2098 ptr::write(out, value);
2099 1
2100}
2101
2102#[no_mangle]
2103pub unsafe extern "C" fn jit_new_enum_variant_safe(
2104 enum_name_ptr: *const u8,
2105 enum_name_len: usize,
2106 variant_name_ptr: *const u8,
2107 variant_name_len: usize,
2108 values_ptr: *const Value,
2109 value_count: usize,
2110 out: *mut Value,
2111) -> u8 {
2112 if enum_name_ptr.is_null() || variant_name_ptr.is_null() || out.is_null() {
2113 return 0;
2114 }
2115
2116 if value_count > 0 && values_ptr.is_null() {
2117 return 0;
2118 }
2119
2120 let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2121 let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2122 let enum_name = match str::from_utf8(enum_name_slice) {
2123 Ok(s) => s.to_string(),
2124 Err(_) => return 0,
2125 };
2126 let variant_name = match str::from_utf8(variant_name_slice) {
2127 Ok(s) => s.to_string(),
2128 Err(_) => return 0,
2129 };
2130 let mut values = Vec::with_capacity(value_count);
2131 for i in 0..value_count {
2132 let value = &*values_ptr.add(i);
2133 values.push(value.clone());
2134 }
2135
2136 let value = Value::enum_variant(enum_name, variant_name, values);
2137 ptr::write(out, value);
2138 1
2139}
2140
2141#[no_mangle]
2142pub unsafe extern "C" fn jit_is_enum_variant_safe(
2143 value_ptr: *const Value,
2144 enum_name_ptr: *const u8,
2145 enum_name_len: usize,
2146 variant_name_ptr: *const u8,
2147 variant_name_len: usize,
2148) -> u8 {
2149 if value_ptr.is_null() || enum_name_ptr.is_null() || variant_name_ptr.is_null() {
2150 return 0;
2151 }
2152
2153 let value = &*value_ptr;
2154 let enum_name_slice = slice::from_raw_parts(enum_name_ptr, enum_name_len);
2155 let variant_name_slice = slice::from_raw_parts(variant_name_ptr, variant_name_len);
2156 let enum_name = match str::from_utf8(enum_name_slice) {
2157 Ok(s) => s,
2158 Err(_) => return 0,
2159 };
2160 let variant_name = match str::from_utf8(variant_name_slice) {
2161 Ok(s) => s,
2162 Err(_) => return 0,
2163 };
2164 if value.is_enum_variant(enum_name, variant_name) {
2165 1
2166 } else {
2167 0
2168 }
2169}
2170
2171#[no_mangle]
2172pub unsafe extern "C" fn jit_get_enum_value_safe(
2173 enum_ptr: *const Value,
2174 index: usize,
2175 out: *mut Value,
2176) -> u8 {
2177 if enum_ptr.is_null() || out.is_null() {
2178 return 0;
2179 }
2180
2181 let enum_value = &*enum_ptr;
2182 if let Some((_, _, Some(values))) = enum_value.as_enum() {
2183 if index < values.len() {
2184 ptr::write(out, values[index].clone());
2185 1
2186 } else {
2187 0
2188 }
2189 } else {
2190 0
2191 }
2192}
2193
2194#[no_mangle]
2195pub unsafe extern "C" fn jit_call_method_safe(
2196 vm_ptr: *mut VM,
2197 object_ptr: *const Value,
2198 method_name_ptr: *const u8,
2199 method_name_len: usize,
2200 args_ptr: *const Value,
2201 arg_count: u8,
2202 dest_reg: u8,
2203) -> u8 {
2204 if vm_ptr.is_null() || object_ptr.is_null() || method_name_ptr.is_null() {
2205 jit::log(|| "jit_call_method_safe: null pointer argument".to_string());
2206 return 0;
2207 }
2208
2209 if arg_count > 0 && args_ptr.is_null() {
2210 return 0;
2211 }
2212
2213 let method_name_slice = slice::from_raw_parts(method_name_ptr, method_name_len);
2214 let method_name = match str::from_utf8(method_name_slice) {
2215 Ok(s) => s,
2216 Err(_) => return 0,
2217 };
2218
2219 let object = (&*object_ptr).clone();
2220 if matches!(object, Value::Struct { .. }) {
2221 return 0;
2222 }
2223
2224 let mut args = Vec::with_capacity(arg_count as usize);
2225 for i in 0..arg_count {
2226 let arg_ptr = args_ptr.add(i as usize);
2227 args.push((&*arg_ptr).clone());
2228 }
2229
2230 crate::vm::push_vm_ptr(vm_ptr);
2231 let outcome = call_builtin_method_simple(&object, method_name, args);
2232 crate::vm::pop_vm_ptr();
2233 match outcome {
2234 Ok(val) => {
2235 let vm = &mut *vm_ptr;
2236 if let Some(frame) = vm.call_stack.last_mut() {
2237 if (dest_reg as usize) < frame.registers.len() {
2238 frame.registers[dest_reg as usize] = val;
2239 1
2240 } else {
2241 jit::log(|| {
2242 format!("jit_call_method_safe: dest_reg {} out of bounds", dest_reg)
2243 });
2244 0
2245 }
2246 } else {
2247 jit::log(|| "jit_call_method_safe: no call frame".to_string());
2248 0
2249 }
2250 }
2251 Err(_) => 0,
2252 }
2253}
2254
2255fn call_builtin_method_simple(
2256 object: &Value,
2257 method_name: &str,
2258 args: Vec<Value>,
2259) -> Result<Value, String> {
2260 match object {
2261 Value::Struct { name, .. } => Err(format!(
2262 "User-defined methods on {} require deoptimization",
2263 name
2264 )),
2265 Value::Iterator(state_rc) => match method_name {
2266 "next" => {
2267 let mut state = state_rc.borrow_mut();
2268 match &mut *state {
2269 IteratorState::Array { items, index } => {
2270 if *index < items.len() {
2271 let v = items[*index].clone();
2272 *index += 1;
2273 Ok(Value::some(v))
2274 } else {
2275 Ok(Value::none())
2276 }
2277 }
2278
2279 IteratorState::MapPairs { items, index } => {
2280 if *index < items.len() {
2281 let (k, v) = items[*index].clone();
2282 *index += 1;
2283 Ok(Value::some(Value::array(vec![k.to_value(), v])))
2284 } else {
2285 Ok(Value::none())
2286 }
2287 }
2288 }
2289 }
2290
2291 _ => Err(format!(
2292 "Iterator method '{}' not supported in JIT",
2293 method_name
2294 )),
2295 },
2296 Value::Enum {
2297 enum_name,
2298 variant,
2299 values,
2300 } if enum_name == "Option" => match method_name {
2301 "is_some" => Ok(Value::Bool(variant == "Some")),
2302 "is_none" => Ok(Value::Bool(variant == "None")),
2303 "unwrap" => {
2304 if variant == "Some" {
2305 if let Some(vals) = values {
2306 if vals.len() == 1 {
2307 Ok(vals[0].clone())
2308 } else {
2309 Err("Option::Some should have exactly 1 value".to_string())
2310 }
2311 } else {
2312 Err("Option::Some should have a value".to_string())
2313 }
2314 } else {
2315 Err("Called unwrap() on Option::None".to_string())
2316 }
2317 }
2318
2319 _ => Err(format!(
2320 "Option method '{}' not supported in JIT",
2321 method_name
2322 )),
2323 },
2324 Value::Array(arr) => match method_name {
2325 "len" => Ok(Value::Int(int_from_usize(arr.borrow().len()))),
2326 "push" => {
2327 let value = args
2328 .get(0)
2329 .cloned()
2330 .ok_or_else(|| "Array:push requires a value argument".to_string())?;
2331 arr.borrow_mut().push(value);
2332 Ok(Value::Nil)
2333 }
2334 "pop" => {
2335 let popped = arr.borrow_mut().pop();
2336 Ok(popped.map(Value::some).unwrap_or_else(Value::none))
2337 }
2338 "first" => {
2339 let borrowed = arr.borrow();
2340 Ok(borrowed
2341 .first()
2342 .cloned()
2343 .map(Value::some)
2344 .unwrap_or_else(Value::none))
2345 }
2346 "last" => {
2347 let borrowed = arr.borrow();
2348 Ok(borrowed
2349 .last()
2350 .cloned()
2351 .map(Value::some)
2352 .unwrap_or_else(Value::none))
2353 }
2354 "get" => {
2355 let index = args
2356 .get(0)
2357 .and_then(Value::as_int)
2358 .ok_or_else(|| "Array:get requires an integer index".to_string())?;
2359 let borrowed = arr.borrow();
2360 Ok(borrowed
2361 .get(index as usize)
2362 .cloned()
2363 .map(Value::some)
2364 .unwrap_or_else(Value::none))
2365 }
2366 "iter" => {
2367 let items = arr.borrow().clone();
2368 let iter = IteratorState::Array { items, index: 0 };
2369 Ok(Value::Iterator(Rc::new(RefCell::new(iter))))
2370 }
2371 _ => Err(format!(
2372 "Array method '{}' not supported in JIT",
2373 method_name
2374 )),
2375 },
2376 _ => Err(format!(
2377 "Method '{}' not supported in JIT (deoptimizing)",
2378 method_name
2379 )),
2380 }
2381}
2382
2383#[no_mangle]
2384pub unsafe extern "C" fn jit_get_field_safe(
2385 object_ptr: *const Value,
2386 field_name_ptr: *const u8,
2387 field_name_len: usize,
2388 out: *mut Value,
2389) -> u8 {
2390 if object_ptr.is_null() || field_name_ptr.is_null() || out.is_null() {
2391 return 0;
2392 }
2393
2394 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2395 let field_name = match str::from_utf8(field_name_slice) {
2396 Ok(s) => s,
2397 Err(_) => return 0,
2398 };
2399 let object = &*object_ptr;
2400 let field_value = match object {
2401 Value::Struct { layout, fields, .. } => match layout.index_of_str(field_name) {
2402 Some(idx) => match fields.borrow().get(idx) {
2403 Some(val) => val.clone(),
2404 None => return 0,
2405 },
2406 None => return 0,
2407 },
2408 _ => return 0,
2409 };
2410 ptr::write(out, field_value);
2411 1
2412}
2413
2414#[no_mangle]
2415pub unsafe extern "C" fn jit_set_field_safe(
2416 object_ptr: *const Value,
2417 field_name_ptr: *const u8,
2418 field_name_len: usize,
2419 value_ptr: *const Value,
2420) -> u8 {
2421 if object_ptr.is_null() || field_name_ptr.is_null() || value_ptr.is_null() {
2422 return 0;
2423 }
2424
2425 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2426 let field_name = match str::from_utf8(field_name_slice) {
2427 Ok(s) => s,
2428 Err(_) => return 0,
2429 };
2430 let object = &*object_ptr;
2431 let value = (&*value_ptr).clone();
2432 match object {
2433 Value::Struct { .. } => match object.struct_set_field(field_name, value) {
2434 Ok(()) => 1,
2435 Err(_) => 0,
2436 },
2437 Value::Map(map) => {
2438 use crate::bytecode::ValueKey;
2439 let key = ValueKey::from(field_name.to_string());
2440 map.borrow_mut().insert(key, value);
2441 1
2442 }
2443
2444 _ => 0,
2445 }
2446}
2447
2448#[no_mangle]
2449pub unsafe extern "C" fn jit_get_field_indexed_safe(
2450 object_ptr: *const Value,
2451 field_index: usize,
2452 out: *mut Value,
2453) -> u8 {
2454 if object_ptr.is_null() || out.is_null() {
2455 return 0;
2456 }
2457
2458 let object = &*object_ptr;
2459 match object.struct_get_field_indexed(field_index) {
2460 Some(value) => {
2461 ptr::write(out, value);
2462 1
2463 }
2464
2465 None => 0,
2466 }
2467}
2468
2469#[no_mangle]
2470pub unsafe extern "C" fn jit_set_field_indexed_safe(
2471 object_ptr: *const Value,
2472 field_index: usize,
2473 value_ptr: *const Value,
2474) -> u8 {
2475 if object_ptr.is_null() || value_ptr.is_null() {
2476 return 0;
2477 }
2478
2479 let object = &*object_ptr;
2480 let value = (&*value_ptr).clone();
2481 match object.struct_set_field_indexed(field_index, value) {
2482 Ok(()) => 1,
2483 Err(_) => 0,
2484 }
2485}
2486
2487#[no_mangle]
2488pub unsafe extern "C" fn jit_get_field_indexed_int_fast(
2489 object_ptr: *const Value,
2490 field_index: usize,
2491 out: *mut Value,
2492) -> u8 {
2493 if object_ptr.is_null() || out.is_null() {
2494 return 0;
2495 }
2496
2497 let object = &*object_ptr;
2498 let out_ref = &mut *out;
2499 match object {
2500 Value::Struct { layout, fields, .. } => {
2501 if layout.is_weak(field_index) {
2502 return 0;
2503 }
2504
2505 if let Ok(borrowed) = fields.try_borrow() {
2506 if let Some(Value::Int(val)) = borrowed.get(field_index) {
2507 *out_ref = Value::Int(*val);
2508 return 1;
2509 }
2510 }
2511
2512 0
2513 }
2514
2515 _ => 0,
2516 }
2517}
2518
2519#[no_mangle]
2520pub unsafe extern "C" fn jit_set_field_indexed_int_fast(
2521 object_ptr: *const Value,
2522 field_index: usize,
2523 value_ptr: *const Value,
2524) -> u8 {
2525 if object_ptr.is_null() || value_ptr.is_null() {
2526 return 0;
2527 }
2528
2529 let object = &*object_ptr;
2530 let value = &*value_ptr;
2531 let new_value = match value {
2532 Value::Int(v) => *v,
2533 _ => return 0,
2534 };
2535 match object {
2536 Value::Struct { layout, fields, .. } => {
2537 if layout.is_weak(field_index) {
2538 return 0;
2539 }
2540
2541 if let Ok(mut borrowed) = fields.try_borrow_mut() {
2542 if field_index < borrowed.len() {
2543 borrowed[field_index] = Value::Int(new_value);
2544 return 1;
2545 }
2546 }
2547
2548 0
2549 }
2550
2551 _ => 0,
2552 }
2553}
2554
2555#[no_mangle]
2556pub unsafe extern "C" fn jit_new_struct_safe(
2557 vm_ptr: *mut VM,
2558 struct_name_ptr: *const u8,
2559 struct_name_len: usize,
2560 field_names_ptr: *const *const u8,
2561 field_name_lens_ptr: *const usize,
2562 field_values_ptr: *const Value,
2563 field_count: usize,
2564 out: *mut Value,
2565) -> u8 {
2566 if struct_name_ptr.is_null() || out.is_null() || vm_ptr.is_null() {
2567 jit::log(|| "jit_new_struct_safe: null pointer input".to_string());
2568 return 0;
2569 }
2570
2571 if field_count > 0
2572 && (field_names_ptr.is_null()
2573 || field_name_lens_ptr.is_null()
2574 || field_values_ptr.is_null())
2575 {
2576 return 0;
2577 }
2578
2579 let struct_name_slice = slice::from_raw_parts(struct_name_ptr, struct_name_len);
2580 let struct_name = match str::from_utf8(struct_name_slice) {
2581 Ok(s) => s.to_string(),
2582 Err(_) => return 0,
2583 };
2584 let mut fields = Vec::with_capacity(field_count);
2585 for i in 0..field_count {
2586 let field_name_ptr = *field_names_ptr.add(i);
2587 let field_name_len = *field_name_lens_ptr.add(i);
2588 let field_name_slice = slice::from_raw_parts(field_name_ptr, field_name_len);
2589 let field_name = match str::from_utf8(field_name_slice) {
2590 Ok(s) => Rc::new(s.to_string()),
2591 Err(_) => return 0,
2592 };
2593 let field_value_ptr = field_values_ptr.add(i);
2594 let field_value = (&*field_value_ptr).clone();
2595 fields.push((field_name, field_value));
2596 }
2597
2598 let vm = &mut *vm_ptr;
2599 let struct_value = match vm.instantiate_struct(&struct_name, fields) {
2600 Ok(value) => value,
2601 Err(err) => {
2602 jit::log(|| {
2603 format!(
2604 "jit_new_struct_safe: failed to instantiate '{}': {}",
2605 struct_name, err
2606 )
2607 });
2608 return 0;
2609 }
2610 };
2611 ptr::write(out, struct_value);
2612 1
2613}
2614
2615#[no_mangle]
2616pub unsafe extern "C" fn jit_move_safe(src_ptr: *const Value, dest_ptr: *mut Value) -> u8 {
2617 if src_ptr.is_null() || dest_ptr.is_null() {
2618 return 0;
2619 }
2620
2621 let src_value = &*src_ptr;
2622 let cloned_value = src_value.clone();
2623 ptr::write(dest_ptr, cloned_value);
2624 1
2625}