seq_runtime/list_ops/
access.rs1use super::combinators::stack_depth;
5use crate::error::set_runtime_error;
6use crate::stack::{Stack, heap_value_mut, pop, push};
7use crate::value::{Value, VariantData};
8use std::sync::Arc;
9
10#[unsafe(no_mangle)]
13pub unsafe extern "C" fn patch_seq_list_get(stack: Stack) -> Stack {
14 unsafe {
15 if stack_depth(stack) < 2 {
17 set_runtime_error("list.get: stack underflow (need 2 values)");
18 return stack;
19 }
20 let (stack, index_val) = pop(stack);
21 let (stack, list_val) = pop(stack);
22
23 let index = match index_val {
24 Value::Int(i) => i,
25 _ => {
26 set_runtime_error(format!(
27 "list.get: expected Int (index), got {:?}",
28 index_val
29 ));
30 let stack = push(stack, Value::Int(0));
31 return push(stack, Value::Bool(false));
32 }
33 };
34
35 let variant_data = match list_val {
36 Value::Variant(v) => v,
37 _ => {
38 set_runtime_error(format!(
39 "list.get: expected Variant (list), got {:?}",
40 list_val
41 ));
42 let stack = push(stack, Value::Int(0));
43 return push(stack, Value::Bool(false));
44 }
45 };
46
47 if index < 0 || index as usize >= variant_data.fields.len() {
48 let stack = push(stack, Value::Int(0)); push(stack, Value::Bool(false))
51 } else {
52 let value = variant_data.fields[index as usize].clone();
53 let stack = push(stack, value);
54 push(stack, Value::Bool(true))
55 }
56 }
57}
58
59#[unsafe(no_mangle)]
79pub unsafe extern "C" fn patch_seq_list_set(stack: Stack) -> Stack {
80 unsafe {
81 if stack_depth(stack) < 3 {
83 set_runtime_error("list.set: stack underflow (need 3 values)");
84 return stack;
85 }
86
87 if let Some(Value::Variant(variant_arc)) = heap_value_mut(stack.sub(3))
92 && let Some(data) = Arc::get_mut(variant_arc)
93 {
94 let index_sv = *stack.sub(2);
97 if crate::tagged_stack::is_tagged_int(index_sv) {
98 let index = crate::tagged_stack::untag_int(index_sv);
99 if index >= 0 && (index as usize) < data.fields.len() {
100 let (stack, value) = pop(stack);
104 let (stack, _index) = pop(stack);
105 data.fields[index as usize] = value;
106 return push(stack, Value::Bool(true));
107 }
108 let (stack, _value) = pop(stack);
110 let (stack, _index) = pop(stack);
111 return push(stack, Value::Bool(false));
112 }
113 }
114
115 let (stack, value) = pop(stack);
117 let (stack, index_val) = pop(stack);
118 let (stack, list_val) = pop(stack);
119
120 let index = match index_val {
121 Value::Int(i) => i,
122 _ => {
123 set_runtime_error(format!(
124 "list.set: expected Int (index), got {:?}",
125 index_val
126 ));
127 let stack = push(stack, list_val);
128 return push(stack, Value::Bool(false));
129 }
130 };
131
132 let mut arc = match list_val {
133 Value::Variant(v) => v,
134 other => {
135 set_runtime_error(format!(
136 "list.set: expected Variant (list), got {:?}",
137 other
138 ));
139 let stack = push(stack, other);
140 return push(stack, Value::Bool(false));
141 }
142 };
143
144 if index < 0 || index as usize >= arc.fields.len() {
145 let stack = push(stack, Value::Variant(arc));
146 push(stack, Value::Bool(false))
147 } else if let Some(data) = Arc::get_mut(&mut arc) {
148 data.fields[index as usize] = value;
149 let stack = push(stack, Value::Variant(arc));
150 push(stack, Value::Bool(true))
151 } else {
152 let mut new_fields: Vec<Value> = arc.fields.to_vec();
153 new_fields[index as usize] = value;
154 let new_list = Value::Variant(Arc::new(VariantData::new(arc.tag.clone(), new_fields)));
155 let stack = push(stack, new_list);
156 push(stack, Value::Bool(true))
157 }
158 }
159}