|
15 | 15 | IgnoredNode, |
16 | 16 | Node, |
17 | 17 | RestoreNode, |
18 | | - ReturnNode |
| 18 | + ReturnNode, |
| 19 | + YieldNode |
19 | 20 | ) |
20 | 21 | from .expr_visitor_helper import ( |
21 | 22 | BUILTINS, |
@@ -113,22 +114,25 @@ def visit_Yield(self, node): |
113 | 114 | label = LabelVisitor() |
114 | 115 | label.visit(node) |
115 | 116 |
|
116 | | - try: |
117 | | - rhs_visitor = RHSVisitor() |
118 | | - rhs_visitor.visit(node.value) |
119 | | - except AttributeError: |
120 | | - rhs_visitor.result = 'EmptyYield' |
| 117 | + if node.value is None: |
| 118 | + rhs_visitor_result = [] |
| 119 | + else: |
| 120 | + rhs_visitor_result = RHSVisitor.result_for_node(node.value) |
121 | 121 |
|
| 122 | + # Yield is a bit like augmented assignment to a return value |
122 | 123 | this_function_name = self.function_return_stack[-1] |
123 | | - LHS = 'yield_' + this_function_name |
124 | | - return self.append_node(ReturnNode( |
125 | | - LHS + ' = ' + label.result, |
| 124 | + LHS = 'yld_' + this_function_name |
| 125 | + return self.append_node(YieldNode( |
| 126 | + LHS + ' += ' + label.result, |
126 | 127 | LHS, |
127 | 128 | node, |
128 | | - rhs_visitor.result, |
| 129 | + rhs_visitor_result + [LHS], |
129 | 130 | path=self.filenames[-1]) |
130 | 131 | ) |
131 | 132 |
|
| 133 | + def visit_YieldFrom(self, node): |
| 134 | + return self.visit_Yield(node) |
| 135 | + |
132 | 136 | def visit_Attribute(self, node): |
133 | 137 | return self.visit_miscelleaneous_node( |
134 | 138 | node |
@@ -449,24 +453,28 @@ def return_handler( |
449 | 453 | saved_function_call_index(int): Unique number for each call. |
450 | 454 | first_node(EntryOrExitNode or RestoreNode): Used to connect previous statements to this function. |
451 | 455 | """ |
452 | | - for node in function_nodes: |
| 456 | + if any(isinstance(node, YieldNode) for node in function_nodes): |
| 457 | + # Presence of a `YieldNode` means that the function is a generator |
| 458 | + rhs_prefix = 'yld_' |
| 459 | + elif any(isinstance(node, ConnectToExitNode) for node in function_nodes): |
453 | 460 | # Only `Return`s and `Raise`s can be of type ConnectToExitNode |
454 | | - if isinstance(node, ConnectToExitNode): |
455 | | - # Create e.g. ~call_1 = ret_func_foo RestoreNode |
456 | | - LHS = CALL_IDENTIFIER + 'call_' + str(saved_function_call_index) |
457 | | - RHS = 'ret_' + get_call_names_as_string(call_node.func) |
458 | | - return_node = RestoreNode( |
459 | | - LHS + ' = ' + RHS, |
460 | | - LHS, |
461 | | - [RHS], |
462 | | - line_number=call_node.lineno, |
463 | | - path=self.filenames[-1] |
464 | | - ) |
465 | | - return_node.first_node = first_node |
| 461 | + rhs_prefix = 'ret_' |
| 462 | + else: |
| 463 | + return # No return value |
466 | 464 |
|
467 | | - self.nodes[-1].connect(return_node) |
468 | | - self.nodes.append(return_node) |
469 | | - return |
| 465 | + # Create e.g. ~call_1 = ret_func_foo RestoreNode |
| 466 | + LHS = CALL_IDENTIFIER + 'call_' + str(saved_function_call_index) |
| 467 | + RHS = rhs_prefix + get_call_names_as_string(call_node.func) |
| 468 | + return_node = RestoreNode( |
| 469 | + LHS + ' = ' + RHS, |
| 470 | + LHS, |
| 471 | + [RHS], |
| 472 | + line_number=call_node.lineno, |
| 473 | + path=self.filenames[-1] |
| 474 | + ) |
| 475 | + return_node.first_node = first_node |
| 476 | + self.nodes[-1].connect(return_node) |
| 477 | + self.nodes.append(return_node) |
470 | 478 |
|
471 | 479 | def process_function(self, call_node, definition): |
472 | 480 | """Processes a user defined function when it is called. |
|
0 commit comments