| 717 | |
| 718 | |
| 719 | def clone_merge(expr, memo=None, merge_literals=False): |
| 720 | nodes = dfs(expr) |
| 721 | if memo is None: |
| 722 | memo = {} |
| 723 | # -- args are somewhat slow to construct, so cache them out front |
| 724 | # XXX node.arg does not always work (builtins, weird co_flags) |
| 725 | node_args = [(node.pos_args, node.named_args) for node in nodes] |
| 726 | try: |
| 727 | del node |
| 728 | except: |
| 729 | pass |
| 730 | for ii, node_ii in enumerate(nodes): |
| 731 | if node_ii in memo: |
| 732 | continue |
| 733 | new_ii = None |
| 734 | if node_ii.pure: |
| 735 | for jj in range(ii): |
| 736 | node_jj = nodes[jj] |
| 737 | if node_ii.name != node_jj.name: |
| 738 | continue |
| 739 | if node_ii.name == "literal": |
| 740 | if not merge_literals: |
| 741 | continue |
| 742 | if node_ii._obj != node_jj._obj: |
| 743 | continue |
| 744 | else: |
| 745 | if node_args[ii] != node_args[jj]: |
| 746 | continue |
| 747 | logger.debug("clone_merge %s %i <- %i" % (node_ii.name, jj, ii)) |
| 748 | new_ii = node_jj |
| 749 | break |
| 750 | if new_ii is None: |
| 751 | new_inputs = [memo[arg] for arg in node_ii.inputs()] |
| 752 | new_ii = node_ii.clone_from_inputs(new_inputs) |
| 753 | memo[node_ii] = new_ii |
| 754 | |
| 755 | return memo[expr] |
| 756 | |
| 757 | |
| 758 | ############################################################################## |