Skip to main content

shape_jit/ffi/
iterator.rs

1// Heap allocation audit (PR-9 V8 Gap Closure):
2//   Category A (NaN-boxed returns): 1 site
3//     jit_box(HK_STRING, ...) — jit_iter_next string char iteration
4//   Category B (intermediate/consumed): 0 sites
5//   Category C (heap islands): 0 sites
6//!
7//! Iterator FFI Functions for JIT
8//!
9//! Functions for iterator operations (done check, next element) in JIT-compiled code.
10
11use super::super::context::JITRange;
12// super::super::jit_array::JitArray removed — see jit_array.rs SURFACE
13// comment. The HK_ARRAY arms surface per ADR-006 §2.7.4 / W10
14// jit-playbook §5.
15use super::jit_kinds::*;
16use super::value_ffi::*;
17use std::collections::HashMap;
18
19// ============================================================================
20// Iterator Operations
21// ============================================================================
22
23/// Check if iterator is exhausted
24/// Stack input: [iter, idx]
25/// Returns: TAG_BOOL_TRUE if done, TAG_BOOL_FALSE otherwise
26pub extern "C" fn jit_iter_done(iter_bits: u64, idx_bits: u64) -> u64 {
27    unsafe {
28        let idx = if is_number(idx_bits) {
29            unbox_number(idx_bits) as i64
30        } else {
31            return TAG_BOOL_TRUE; // Invalid index = done
32        };
33
34        if idx < 0 {
35            return TAG_BOOL_TRUE;
36        }
37
38        let done = match heap_kind(iter_bits) {
39            Some(HK_ARRAY) => {
40                // SURFACE (W10 jit-playbook §5 / ADR-006 §2.7.4):
41                // length read decoded the deleted JitArray layout.
42                // Kinded rebuild reads `Arc<TypedArrayData>::len`.
43                todo!(
44                    "phase-2c §2.7.4 / W10 jit-playbook §5: \
45                     JitArray rebuild — jit_iter_done HK_ARRAY arm."
46                )
47            }
48            Some(HK_STRING) => {
49                let s = unbox_string(iter_bits);
50                idx as usize >= s.chars().count()
51            }
52            Some(HK_JIT_OBJECT) => {
53                // Check if it's a Range object with start/end fields
54                let obj = unified_unbox::<HashMap<String, u64>>(iter_bits);
55                if let (Some(&start_bits), Some(&end_bits)) = (obj.get("start"), obj.get("end")) {
56                    if is_number(start_bits) && is_number(end_bits) {
57                        let start = unbox_number(start_bits) as i64;
58                        let end = unbox_number(end_bits) as i64;
59                        let count = end - start;
60                        count <= 0 || idx >= count
61                    } else {
62                        true
63                    }
64                } else {
65                    true
66                }
67            }
68            Some(HK_RANGE) => {
69                let range = unified_unbox::<JITRange>(iter_bits);
70                if is_number(range.start) && is_number(range.end) {
71                    let start = unbox_number(range.start) as i64;
72                    let end = unbox_number(range.end) as i64;
73                    let count = end - start;
74                    count <= 0 || idx >= count
75                } else {
76                    true
77                }
78            }
79            _ => true, // Unknown type = done
80        };
81
82        if done { TAG_BOOL_TRUE } else { TAG_BOOL_FALSE }
83    }
84}
85
86/// Get next element from iterator
87/// Stack input: [iter, idx]
88/// Returns: Element at idx, or TAG_NULL if out of bounds
89pub extern "C" fn jit_iter_next(iter_bits: u64, idx_bits: u64) -> u64 {
90    unsafe {
91        let idx = if is_number(idx_bits) {
92            unbox_number(idx_bits) as i64
93        } else {
94            return TAG_NULL;
95        };
96
97        if idx < 0 {
98            return TAG_NULL;
99        }
100
101        match heap_kind(iter_bits) {
102            Some(HK_ARRAY) => {
103                // SURFACE (W10 jit-playbook §5 / ADR-006 §2.7.4):
104                // index read decoded the deleted JitArray layout.
105                // Kinded rebuild reads Arc<TypedArrayData> per
106                // ADR-006 §2.7.6/Q8.
107                todo!(
108                    "phase-2c §2.7.4 / W10 jit-playbook §5: \
109                     JitArray rebuild — jit_iter_next HK_ARRAY arm."
110                )
111            }
112            Some(HK_STRING) => {
113                let s = unbox_string(iter_bits);
114                if let Some(ch) = s.chars().nth(idx as usize) {
115                    box_string(ch.to_string())
116                } else {
117                    TAG_NULL
118                }
119            }
120            Some(HK_JIT_OBJECT) => {
121                let obj = unified_unbox::<HashMap<String, u64>>(iter_bits);
122                if let (Some(&start_bits), Some(&end_bits)) = (obj.get("start"), obj.get("end")) {
123                    if is_number(start_bits) && is_number(end_bits) {
124                        let start = unbox_number(start_bits) as i64;
125                        let end = unbox_number(end_bits) as i64;
126                        let count = end - start;
127                        if count <= 0 || idx >= count {
128                            TAG_NULL
129                        } else {
130                            box_number((start + idx) as f64)
131                        }
132                    } else {
133                        TAG_NULL
134                    }
135                } else {
136                    TAG_NULL
137                }
138            }
139            Some(HK_RANGE) => {
140                let range = unified_unbox::<JITRange>(iter_bits);
141                if is_number(range.start) && is_number(range.end) {
142                    let start = unbox_number(range.start) as i64;
143                    let end = unbox_number(range.end) as i64;
144                    let count = end - start;
145                    if count <= 0 || idx >= count {
146                        TAG_NULL
147                    } else {
148                        box_number((start + idx) as f64)
149                    }
150                } else {
151                    TAG_NULL
152                }
153            }
154            _ => TAG_NULL,
155        }
156    }
157}