MCPcopy Create free account
hub / github.com/dylan-sutton-chavez/edge-python / comprehension_loop

Method comprehension_loop

compiler/src/modules/parser/literals.rs:153–230  ·  view source on GitHub ↗

Emits for/if comprehension scaffolding; reinjcts body with loop-bound SSA slots. */

(&mut self, elem_bodies: &[(usize, Vec<Instruction>)], append_op: OpCode, versions_before: &HashMap<String, u32>)

Source from the content-addressed store, hash-verified

151
152 /* Emits for/if comprehension scaffolding; reinjcts body with loop-bound SSA slots. */
153 pub(super) fn comprehension_loop(&mut self, elem_bodies: &[(usize, Vec<Instruction>)], append_op: OpCode, versions_before: &HashMap<String, u32>) {
154 let mut loop_starts: Vec<u16> = Vec::new();
155 let mut for_iters: Vec<usize> = Vec::new();
156 let mut all_vars: Vec<String> = Vec::new();
157
158 while self.eat_if(TokenType::For) {
159 let mut vars: Vec<String> = Vec::new();
160 loop {
161 vars.push(self.advance_text());
162 if !self.eat_if(TokenType::Comma) { break; }
163 if matches!(self.peek(), Some(TokenType::In)) { break; }
164 }
165
166 self.eat(TokenType::In);
167 self.expr_bp(1);
168 self.chunk.emit(OpCode::GetIter, 0);
169
170 let ls = self.chunk.instructions.len() as u16;
171 let fi = self.emit_jump(OpCode::ForIter);
172
173 if vars.len() == 1 {
174 self.store_name(vars[0].clone());
175 } else {
176 self.chunk.emit(OpCode::UnpackSequence, vars.len() as u16);
177 for var in &vars {
178 self.store_name(var.clone());
179 }
180 }
181 for v in &vars { all_vars.push(v.clone()); }
182
183 while self.eat_if(TokenType::If) {
184 self.expr_bp(1);
185 self.chunk.emit(OpCode::JumpIfFalse, ls);
186 }
187
188 loop_starts.push(ls);
189 for_iters.push(fi);
190 }
191
192 // Linear scan: size 1-5 beats HashMap and avoids monomorphizing for u16 keys.
193 let mut var_map: Vec<(u16, u16)> = Vec::new();
194 for var in &all_vars {
195 let old_ver = versions_before.get(var).copied().unwrap_or(0);
196 let new_ver = self.current_version(var);
197 if old_ver == new_ver { continue; }
198 let mut ob = [0u8; 128];
199 let old_name = Self::ssa_name(var, old_ver, &mut ob);
200 let Some(&old_slot) = self.chunk.name_index.get(old_name) else { continue };
201 let mut nb = [0u8; 128];
202 let new_slot = self.chunk.push_name(Self::ssa_name(var, new_ver, &mut nb));
203 var_map.push((old_slot, new_slot));
204 }
205
206 for (orig_base, body) in elem_bodies {
207 // Body is relocated by this delta; internal jump targets (from `or`/`and`/membership) must shift with it.
208 let delta = self.chunk.instructions.len() as i64 - *orig_base as i64;
209 for ins in body {
210 let operand = if matches!(ins.opcode, OpCode::LoadName | OpCode::StoreName) {

Callers 4

brace_literalMethod · 0.80
list_literalMethod · 0.80
parse_argsMethod · 0.80
parse_atomMethod · 0.80

Calls 15

eat_ifMethod · 0.80
pushMethod · 0.80
advance_textMethod · 0.80
eatMethod · 0.80
expr_bpMethod · 0.80
emitMethod · 0.80
emit_jumpMethod · 0.80
store_nameMethod · 0.80
current_versionMethod · 0.80
push_nameMethod · 0.80
emit_constMethod · 0.80
patchMethod · 0.80

Tested by

no test coverage detected