Push a lightweight scope for comprehensions. Unlike enter(), this reuses the same LowLevelIRBuilder (same basic blocks and registers) but pushes new symtable and fn_info entries so that the closure machinery sees a scope boundary.
(self, fn_info: FuncInfo)
| 1351 | |
| 1352 | @contextmanager |
| 1353 | def enter_scope(self, fn_info: FuncInfo) -> Iterator[None]: |
| 1354 | """Push a lightweight scope for comprehensions. |
| 1355 | |
| 1356 | Unlike enter(), this reuses the same LowLevelIRBuilder (same basic |
| 1357 | blocks and registers) but pushes new symtable and fn_info entries |
| 1358 | so that the closure machinery sees a scope boundary. |
| 1359 | """ |
| 1360 | self.builders.append(self.builder) |
| 1361 | # Copy the parent symtable so variables from the enclosing scope |
| 1362 | # (e.g. function parameters used as the comprehension iterable) |
| 1363 | # remain accessible. The comprehension is inlined (same basic blocks |
| 1364 | # and registers), so the parent's register references are still valid. |
| 1365 | self.symtables.append(dict(self.symtables[-1])) |
| 1366 | self.runtime_args.append([]) |
| 1367 | self.fn_info = fn_info |
| 1368 | self.fn_infos.append(self.fn_info) |
| 1369 | self.ret_types.append(none_rprimitive) |
| 1370 | self.nonlocal_control.append(BaseNonlocalControl()) |
| 1371 | try: |
| 1372 | yield |
| 1373 | finally: |
| 1374 | self.builders.pop() |
| 1375 | self.symtables.pop() |
| 1376 | self.runtime_args.pop() |
| 1377 | self.ret_types.pop() |
| 1378 | self.fn_infos.pop() |
| 1379 | self.nonlocal_control.pop() |
| 1380 | self.builder = self.builders[-1] |
| 1381 | self.fn_info = self.fn_infos[-1] |
| 1382 | |
| 1383 | @contextmanager |
| 1384 | def enter_method( |
no test coverage detected