shape_jit/ffi/call_method/
array.rs1use crate::jit_array::JitArray;
13use crate::nan_boxing::*;
14
15#[inline(always)]
17pub fn call_array_method(receiver_bits: u64, method_name: &str, args: &[u64]) -> u64 {
18 unsafe {
19 let arr = jit_unbox::<JitArray>(receiver_bits);
20 let slice = arr.as_slice();
21
22 match method_name {
23 "length" | "len" => box_number(arr.len() as f64),
24 "first" => arr.first().copied().unwrap_or(TAG_NULL),
25 "last" => arr.last().copied().unwrap_or(TAG_NULL),
26 "includes" | "contains" => {
27 if args.is_empty() {
28 return TAG_BOOL_FALSE;
29 }
30 let needle = args[0];
31 for &elem in slice.iter() {
32 if elem == needle {
33 return TAG_BOOL_TRUE;
34 }
35 if is_number(elem)
36 && is_number(needle)
37 && unbox_number(elem) == unbox_number(needle)
38 {
39 return TAG_BOOL_TRUE;
40 }
41 }
42 TAG_BOOL_FALSE
43 }
44 "indexOf" => {
45 if args.is_empty() {
46 return box_number(-1.0);
47 }
48 let needle = args[0];
49 for (i, &elem) in slice.iter().enumerate() {
50 if elem == needle {
51 return box_number(i as f64);
52 }
53 if is_number(elem)
54 && is_number(needle)
55 && unbox_number(elem) == unbox_number(needle)
56 {
57 return box_number(i as f64);
58 }
59 }
60 box_number(-1.0)
61 }
62 "reverse" => {
63 let mut reversed = slice.to_vec();
64 reversed.reverse();
65 jit_box(HK_ARRAY, JitArray::from_vec(reversed))
66 }
67 "slice" => {
68 let len = arr.len() as i64;
69 let start = if !args.is_empty() && is_number(args[0]) {
70 let s = unbox_number(args[0]) as i64;
71 if s < 0 {
72 (len + s).max(0) as usize
73 } else {
74 s.min(len) as usize
75 }
76 } else {
77 0
78 };
79 let end = if args.len() > 1 && is_number(args[1]) {
80 let e = unbox_number(args[1]) as i64;
81 if e < 0 {
82 (len + e).max(0) as usize
83 } else {
84 e.min(len) as usize
85 }
86 } else {
87 arr.len()
88 };
89 let sliced = if start < end && start < arr.len() {
90 JitArray::from_slice(&slice[start..end.min(arr.len())])
91 } else {
92 JitArray::new()
93 };
94 jit_box(HK_ARRAY, sliced)
95 }
96 "join" => {
97 let separator = if !args.is_empty() {
98 if is_heap_kind(args[0], HK_STRING) {
99 jit_unbox::<String>(args[0]).clone()
100 } else {
101 ",".to_string()
102 }
103 } else {
104 ",".to_string()
105 };
106
107 let parts: Vec<String> = slice
108 .iter()
109 .map(|&elem| {
110 if is_number(elem) {
111 format!("{}", unbox_number(elem))
112 } else if is_heap_kind(elem, HK_STRING) {
113 jit_unbox::<String>(elem).clone()
114 } else if elem == TAG_NULL {
115 "null".to_string()
116 } else if elem == TAG_BOOL_TRUE {
117 "true".to_string()
118 } else if elem == TAG_BOOL_FALSE {
119 "false".to_string()
120 } else {
121 "[object]".to_string()
122 }
123 })
124 .collect();
125
126 let joined = parts.join(&separator);
127 jit_box(HK_STRING, joined)
128 }
129 "sum" => {
130 let mut total = 0.0;
131 for &elem in slice.iter() {
132 if is_number(elem) {
133 total += unbox_number(elem);
134 }
135 }
136 box_number(total)
137 }
138 "avg" | "mean" => {
139 if arr.is_empty() {
140 return TAG_NULL;
141 }
142 let mut total = 0.0;
143 for &elem in slice.iter() {
144 if is_number(elem) {
145 total += unbox_number(elem);
146 }
147 }
148 box_number(total / arr.len() as f64)
149 }
150 "min" => {
151 if arr.is_empty() {
152 return TAG_NULL;
153 }
154 let mut min_val = f64::INFINITY;
155 for &elem in slice.iter() {
156 if is_number(elem) {
157 let v = unbox_number(elem);
158 if v < min_val {
159 min_val = v;
160 }
161 }
162 }
163 if min_val.is_finite() {
164 box_number(min_val)
165 } else {
166 TAG_NULL
167 }
168 }
169 "max" => {
170 if arr.is_empty() {
171 return TAG_NULL;
172 }
173 let mut max_val = f64::NEG_INFINITY;
174 for &elem in slice.iter() {
175 if is_number(elem) {
176 let v = unbox_number(elem);
177 if v > max_val {
178 max_val = v;
179 }
180 }
181 }
182 if max_val.is_finite() {
183 box_number(max_val)
184 } else {
185 TAG_NULL
186 }
187 }
188 "take" => {
189 if args.is_empty() {
190 return receiver_bits;
191 }
192 let count = if is_number(args[0]) {
193 (unbox_number(args[0]) as usize).min(arr.len())
194 } else {
195 return receiver_bits;
196 };
197 jit_box(HK_ARRAY, JitArray::from_slice(&slice[..count]))
198 }
199 "drop" => {
200 if args.is_empty() {
201 return receiver_bits;
202 }
203 let count = if is_number(args[0]) {
204 (unbox_number(args[0]) as usize).min(arr.len())
205 } else {
206 return receiver_bits;
207 };
208 jit_box(HK_ARRAY, JitArray::from_slice(&slice[count..]))
209 }
210 "concat" => {
211 let mut result: Vec<u64> = slice.to_vec();
212 for arg in args.iter() {
213 if is_heap_kind(*arg, HK_ARRAY) {
214 let other = jit_unbox::<JitArray>(*arg);
215 result.extend_from_slice(other.as_slice());
216 } else {
217 result.push(*arg);
218 }
219 }
220 jit_box(HK_ARRAY, JitArray::from_vec(result))
221 }
222 "flatten" | "flat" => {
223 let mut result = Vec::new();
224 for &elem in slice.iter() {
225 if is_heap_kind(elem, HK_ARRAY) {
226 let inner = jit_unbox::<JitArray>(elem);
227 result.extend_from_slice(inner.as_slice());
228 } else {
229 result.push(elem);
230 }
231 }
232 jit_box(HK_ARRAY, JitArray::from_vec(result))
233 }
234 "unique" => {
235 let mut seen = Vec::new();
236 let mut result = Vec::new();
237 for &elem in slice.iter() {
238 let is_dup = seen.iter().any(|&s| {
239 if is_number(elem) && is_number(s) {
240 unbox_number(elem) == unbox_number(s)
241 } else {
242 elem == s
243 }
244 });
245 if !is_dup {
246 seen.push(elem);
247 result.push(elem);
248 }
249 }
250 jit_box(HK_ARRAY, JitArray::from_vec(result))
251 }
252 "sort" | "sorted" => {
253 let mut sorted = slice.to_vec();
254 sorted.sort_by(|&a, &b| {
255 if is_number(a) && is_number(b) {
256 unbox_number(a)
257 .partial_cmp(&unbox_number(b))
258 .unwrap_or(std::cmp::Ordering::Equal)
259 } else {
260 std::cmp::Ordering::Equal
261 }
262 });
263 jit_box(HK_ARRAY, JitArray::from_vec(sorted))
264 }
265 _ => TAG_NULL,
266 }
267 }
268}