|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | | -from ..statement import BlockStatement, SimpleStatement |
| 3 | +from functools import cached_property |
4 | 4 |
|
| 5 | +from ..statement import BlockStatement, SimpleStatement, Statement |
5 | 6 |
|
6 | | -class GoSimpleStatement(SimpleStatement): ... |
7 | 7 |
|
| 8 | +class GoSimpleStatement(SimpleStatement): |
| 9 | + @cached_property |
| 10 | + def post_controls(self) -> list[Statement]: |
| 11 | + if self.node_type in self.language.EXIT_STATEMENTS: |
| 12 | + return [] |
| 13 | + exits_statements = self.function.exits if self.function is not None else [] |
8 | 14 |
|
9 | | -class GoBlockStatement(BlockStatement): ... |
| 15 | + last_defer_statement = [] |
| 16 | + from .function import GoFunction |
| 17 | + |
| 18 | + if self.function is not None and isinstance(self.function, GoFunction): |
| 19 | + last_defer_statement = ( |
| 20 | + self.function.defer_statements[-1:] |
| 21 | + if len(self.function.defer_statements) > 0 |
| 22 | + else [] |
| 23 | + ) |
| 24 | + |
| 25 | + if self.node_type == "defer_statement": |
| 26 | + assert isinstance(self.function, GoFunction) |
| 27 | + defter_index = self.function.defer_statements.index(self) |
| 28 | + return ( |
| 29 | + [self.function.defer_statements[defter_index - 1]] |
| 30 | + if defter_index > 0 |
| 31 | + else exits_statements |
| 32 | + ) |
| 33 | + |
| 34 | + if self.node_type in self.language.CONTINUE_STATEMENTS: |
| 35 | + loop_stat = self.ancestor_by_types(self.language.LOOP_STATEMENTS) |
| 36 | + return [loop_stat] if loop_stat else [] |
| 37 | + if self.node_type in self.language.BREAK_STATEMENTS: |
| 38 | + loop_stat = self.ancestor_by_types( |
| 39 | + self.language.LOOP_STATEMENTS + self.language.SWITCH_STATEMENTS |
| 40 | + ) |
| 41 | + preorder_successor = loop_stat.preorder_successor if loop_stat else None |
| 42 | + return [preorder_successor] if preorder_successor else [] |
| 43 | + if self.node_type in self.language.GOTO_STATEMENTS: |
| 44 | + function = self.function |
| 45 | + if function is not None: |
| 46 | + label_name_node = self.node.child_by_field_name("label") |
| 47 | + assert label_name_node is not None and label_name_node.text is not None |
| 48 | + label_name = label_name_node.text.decode() |
| 49 | + label_stat = function.query_oneshot( |
| 50 | + self.language.query_goto_label(label_name) |
| 51 | + ) |
| 52 | + return [label_stat] if label_stat else [] |
| 53 | + |
| 54 | + if self.parent.node_type in self.language.LOOP_STATEMENTS: |
| 55 | + # while () {last_statement;} |
| 56 | + loop_stat = self.ancestor_by_types(self.language.LOOP_STATEMENTS) |
| 57 | + is_last_statement = self.next_sibling is None |
| 58 | + if is_last_statement: |
| 59 | + return [loop_stat] if loop_stat else [] |
| 60 | + if self.parent.node_type in self.language.IF_STATEMENTS: |
| 61 | + # if () {last_statement;} else { ...} |
| 62 | + consequences = self.parent.statements_by_field_name("consequence") |
| 63 | + if self in consequences: |
| 64 | + is_last_consequences = consequences.index(self) == len(consequences) - 1 |
| 65 | + if is_last_consequences: |
| 66 | + return ( |
| 67 | + [self.right_uncle_ancestor] if self.right_uncle_ancestor else [] |
| 68 | + ) |
| 69 | + |
| 70 | + preorder_successor = self.preorder_successor |
| 71 | + while ( |
| 72 | + preorder_successor is not None |
| 73 | + and preorder_successor.node_type == "defer_statement" |
| 74 | + ): |
| 75 | + preorder_successor = preorder_successor.preorder_successor |
| 76 | + if preorder_successor is None: |
| 77 | + return last_defer_statement |
| 78 | + if preorder_successor.node_type in self.language.EXIT_STATEMENTS: |
| 79 | + return last_defer_statement |
| 80 | + else: |
| 81 | + return [preorder_successor] |
| 82 | + |
| 83 | + |
| 84 | +class GoBlockStatement(BlockStatement): |
| 85 | + @cached_property |
| 86 | + def post_controls(self) -> list[Statement]: |
| 87 | + exits_statements = self.function.exits if self.function is not None else [] |
| 88 | + last_defer_statement = [] |
| 89 | + from .function import GoFunction |
| 90 | + |
| 91 | + if self.function is not None and isinstance(self.function, GoFunction): |
| 92 | + last_defer_statement = ( |
| 93 | + self.function.defer_statements[-1:] |
| 94 | + if len(self.function.defer_statements) > 0 |
| 95 | + else [] |
| 96 | + ) |
| 97 | + |
| 98 | + if self.node_type in self.language.IF_STATEMENTS: |
| 99 | + consequences = self.statements_by_field_name("consequence") |
| 100 | + alternatives = self.statements_by_field_name("alternative") |
| 101 | + nexts = [] |
| 102 | + if len(consequences) > 0: |
| 103 | + nexts.append(consequences[0]) |
| 104 | + if len(alternatives) > 0: |
| 105 | + nexts.append(alternatives[0]) |
| 106 | + elif ( |
| 107 | + self.preorder_successor is not None |
| 108 | + and self.preorder_successor not in exits_statements |
| 109 | + ): |
| 110 | + nexts.append(self.preorder_successor) |
| 111 | + else: |
| 112 | + nexts.extend(last_defer_statement) |
| 113 | + return nexts |
| 114 | + if self.node_type in self.language.SWITCH_STATEMENTS: |
| 115 | + if len(self.statements) > 0: |
| 116 | + return [self.statements[0]] |
| 117 | + if self.parent.node_type in self.language.SWITCH_STATEMENTS: |
| 118 | + if self.text.strip().startswith("default:") and len(self.statements) > 0: |
| 119 | + return [self.statements[0]] |
| 120 | + if self.parent.node_type in self.language.LOOP_STATEMENTS: |
| 121 | + # while () {last_statement;} |
| 122 | + loop_stat = self.ancestor_by_types(self.language.LOOP_STATEMENTS) |
| 123 | + is_last_statement = self.next_sibling is None |
| 124 | + if is_last_statement: |
| 125 | + return [loop_stat] if loop_stat else [] |
| 126 | + |
| 127 | + nexts = [self.statements[0]] if len(self.statements) > 0 else [] |
| 128 | + if self.preorder_successor is not None: |
| 129 | + nexts.append(self.preorder_successor) |
| 130 | + |
| 131 | + if len(last_defer_statement) > 0: |
| 132 | + nexts = [stat for stat in nexts if stat not in exits_statements] |
| 133 | + if len(nexts) == 0: |
| 134 | + return last_defer_statement |
| 135 | + return nexts |
0 commit comments