| 517 | } |
| 518 | |
| 519 | pub fn parse(mut self) -> (SSAChunk, Vec<Diagnostic>) { |
| 520 | while !self.at_end() { |
| 521 | while self.eat_if(TokenType::Semi) {} |
| 522 | if self.at_end() { break; } |
| 523 | |
| 524 | let produced_value = self.stmt(); |
| 525 | // Pop expression-statement results; chunk's implicit ReturnValue expects empty stack. |
| 526 | if produced_value { self.chunk.emit(OpCode::PopTop, 0); } |
| 527 | } |
| 528 | |
| 529 | if self.chunk.overflow { |
| 530 | let n = self.source.len(); |
| 531 | self.errors.push(Diagnostic { |
| 532 | start: n, end: n, |
| 533 | msg: "program too large: exceeded maximum instruction limit".to_string(), |
| 534 | }); |
| 535 | } |
| 536 | |
| 537 | if !self.errors.is_empty() { |
| 538 | // Clear bytecode state so `finalize_prev_slots` doesn't use stale phi sources. |
| 539 | self.chunk.instructions.clear(); |
| 540 | self.chunk.constants.clear(); |
| 541 | self.chunk.names.clear(); |
| 542 | self.chunk.phi_sources.clear(); |
| 543 | self.chunk.phi_map.clear(); |
| 544 | self.chunk.functions.clear(); |
| 545 | self.chunk.classes.clear(); |
| 546 | self.chunk.name_index.clear(); |
| 547 | self.chunk.nonlocals.clear(); |
| 548 | self.chunk.stmt_pos.clear(); |
| 549 | self.loop_kinds.clear(); |
| 550 | } |
| 551 | |
| 552 | self.chunk.emit(OpCode::ReturnValue, 0); |
| 553 | self.chunk.finalize_prev_slots(); |
| 554 | (self.chunk, self.errors) |
| 555 | } |
| 556 | } |