|
12 | 12 | from typing import Callable, TextIO, Iterator, Iterable |
13 | 13 | from lexer import Token |
14 | 14 | from stack import Storage, StackError |
15 | | -from parser import Stmt, SimpleStmt, BlockStmt, IfStmt, ForStmt, WhileStmt |
| 15 | +from parser import Stmt, SimpleStmt, BlockStmt, IfStmt, ForStmt, WhileStmt, MacroIfStmt |
16 | 16 |
|
17 | 17 | # Set this to true for voluminous output showing state of stack and locals |
18 | 18 | PRINT_STACKS = False |
@@ -476,6 +476,8 @@ def _emit_stmt( |
476 | 476 | return self._emit_for(stmt, uop, storage, inst) |
477 | 477 | elif isinstance(stmt, WhileStmt): |
478 | 478 | return self._emit_while(stmt, uop, storage, inst) |
| 479 | + elif isinstance(stmt, MacroIfStmt): |
| 480 | + return self._emit_macro_if(stmt, uop, storage, inst) |
479 | 481 | else: |
480 | 482 | raise NotImplementedError("Unexpected statement") |
481 | 483 |
|
@@ -533,6 +535,37 @@ def _emit_simple( |
533 | 535 | except StackError as ex: |
534 | 536 | raise analysis_error(ex.args[0], tkn) #from None |
535 | 537 |
|
| 538 | + |
| 539 | + def _emit_macro_if( |
| 540 | + self, |
| 541 | + stmt: IfStmt, |
| 542 | + uop: CodeSection, |
| 543 | + storage: Storage, |
| 544 | + inst: Instruction | None, |
| 545 | + ) -> tuple[bool, Token, Storage]: |
| 546 | + self.out.emit(stmt.condition) |
| 547 | + branch = stmt.else_ is not None |
| 548 | + reachable = True |
| 549 | + for s in stmt.body: |
| 550 | + r, tkn, storage = self._emit_stmt(s, uop, storage, inst) |
| 551 | + if tkn is not None: |
| 552 | + self.out.emit(tkn) |
| 553 | + if not r: |
| 554 | + reachable = False |
| 555 | + if branch: |
| 556 | + else_storage = storage.copy() |
| 557 | + self.out.emit(stmt.else_) |
| 558 | + for s in stmt.else_body: |
| 559 | + r, tkn, else_storage = self._emit_stmt(s, uop, else_storage, inst) |
| 560 | + if tkn is not None: |
| 561 | + self.out.emit(tkn) |
| 562 | + if not r: |
| 563 | + reachable = False |
| 564 | + storage.merge(else_storage, self.out) |
| 565 | + self.out.emit(stmt.endif) |
| 566 | + return reachable, None, storage |
| 567 | + |
| 568 | + |
536 | 569 | def _emit_if( |
537 | 570 | self, |
538 | 571 | stmt: IfStmt, |
@@ -640,7 +673,7 @@ def emit_tokens( |
640 | 673 | if emit_braces: |
641 | 674 | self.out.emit(tkn) |
642 | 675 | except StackError as ex: |
643 | | - raise analysis_error(ex.args[0], last) from None |
| 676 | + raise analysis_error(ex.args[0], tkn) from None |
644 | 677 | return storage |
645 | 678 |
|
646 | 679 | def emit(self, txt: str | Token) -> None: |
|
0 commit comments