Changeset 92
- Timestamp:
- 11/16/05 03:32:07
- Files:
-
- trunk/codewalk.py (modified) (9 diffs)
- trunk/test_logic.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/codewalk.py
r91 r92 120 120 121 121 def __init__(self, obj): 122 self.verbose = False 123 122 124 # Distill supplied 'obj' arg to a code block string. 123 125 if isinstance(obj, FunctionType): … … 135 137 136 138 self._bytecode = obj 139 140 def debug(self, *messages): 141 if self.verbose: 142 for term in messages: 143 print term, 144 else: 145 pass 137 146 138 147 def walk(self): … … 243 252 244 253 def __init__(self, obj): 254 self.verbose = False 255 245 256 if isinstance(obj, FunctionType): 246 257 self._func = obj … … 387 398 pos = self.const_index(value) 388 399 self.tail(3, 'LOAD_CONST', pos & 0xFF, pos >> 8) 389 if self.verbose: 390 print name, '-->', value 400 self.debug(name, ' --> ', value) 391 401 392 402 … … 678 688 679 689 def __init__(self, obj): 690 self.verbose = False 691 680 692 # Distill supplied 'obj' arg to a code block string. 681 693 if isinstance(obj, FunctionType): … … 723 735 self.newcode = [] 724 736 725 # Add a list of 'and' and 'or' mappings {target: [(previous TOS, and/or)...]}737 self.jump_values = {} 726 738 self.targets = {} 727 739 b = self._bytecode 740 self.debug("\nWALKING: ", b) 728 741 while self.cursor < len(b): 729 if self.cursor in self.targets: 730 self.visit_target(self.targets[self.cursor]) 742 self.debug("\n") 743 744 ip = self.cursor 745 if ip in self.targets: 746 self.debug(">>") 747 748 self.debug(self.cursor) 749 731 750 op = b[self.cursor] 732 751 self.cursor += 1 … … 740 759 args = () 741 760 761 self.debug("visit (%s, %s)" % (op, repr(args))) 742 762 self.visit_instruction(op, *args) 743 763 744 764 name = 'visit_' + opname[op] 745 765 name = name.replace('+', '_PLUS_') 746 747 766 if hasattr(self, name): 767 self.debug("=> %s(%s)" % (name, repr(args))) 748 768 getattr(self, name)(*args) 749 750 def visit_target(self, terms): 751 comp = self.stack.pop() 752 while terms: 753 term, operation = terms.pop() 754 comp = "(%s) %s (%s)" % (term, operation, comp) 755 self.stack.append(comp) 769 770 # Combine any targets into a single clause 771 self.debug(self.targets) 772 targets = [(k, v) for k, v in self.targets.iteritems()] 773 if targets: 774 targets.sort() 775 for target_ip, sources in targets: 776 sources.sort() 777 sources.reverse() 778 for jump_ip, op in sources: 779 # Find term1 at the jump. 780 term1 = self.jump_values[jump_ip] 781 # Find term2 at or just before the target. 782 ip2, term2 = None, None 783 jumps = [(k, v) for k, v in self.jump_values.iteritems()] 784 jumps.sort() 785 for temp_ip, temp_val in jumps: 786 if temp_ip > target_ip: 787 break 788 ip2 = temp_ip 789 term2 = temp_val 790 self.debug("###", target_ip, jump_ip, ip2, "#") 791 clause = "(%s) %s (%s)" % (term1, op, term2) 792 # Replace term2 with the new clause, so that further 793 # combinations have access to it. 794 self.jump_values[ip2] = clause 795 # Just for fun and debuggability, delete term1 796 if jump_ip != ip2: 797 del self.jump_values[jump_ip] 798 self.debug("\n", self.jump_values) 799 self.stack = [self.jump_values[ip2]] 800 self.debug("stack:", self.stack) 756 801 757 802 def visit_BUILD_TUPLE(self, lo, hi): … … 789 834 790 835 def visit_JUMP_IF_FALSE(self, lo, hi): 836 # Note that self.cursor has already advanced to the next instruction. 837 ip = self.cursor - 3 838 self.jump_values[ip] = self.stack[-1] 839 791 840 target = self.cursor + (lo + (hi << 8)) 792 targetstack= self.targets.setdefault(target, [])793 targetstack.append((self.stack.pop(), 'and'))841 bucket = self.targets.setdefault(target, []) 842 bucket.append((ip, 'and')) 794 843 795 844 def visit_JUMP_IF_TRUE(self, lo, hi): 845 # Note that self.cursor has already advanced to the next instruction. 846 ip = self.cursor - 3 847 self.jump_values[ip] = self.stack[-1] 848 796 849 target = self.cursor + (lo + (hi << 8)) 797 targetstack= self.targets.setdefault(target, [])798 targetstack.append((self.stack.pop(), 'or'))850 bucket = self.targets.setdefault(target, []) 851 bucket.append((ip, 'or')) 799 852 800 853 def visit_LOAD_ATTR(self, lo, hi): … … 819 872 self.stack.append(self.co_names[lo + (hi << 8)]) 820 873 874 def visit_POP_TOP(self): 875 self.stack.pop() 876 877 def visit_RETURN_VALUE(self): 878 # Note that self.cursor is already the next instruction. 879 ip = self.cursor - 1 880 self.jump_values[ip] = self.stack[-1] 881 821 882 def visit_SLICE_PLUS_0(self): 822 883 arg = self.stack.pop() trunk/test_logic.py
r91 r92 59 59 "lambda x: (x.TripStatus != 'Inquiry') and ((x.Field " 60 60 "== 'BC') and (x.StartDate >= 3))") 61 61 62 62 # Test Expression pickling 63 63 e = logic.Expression(lambda x: x.LastDate > datetime.date(2004, 3, 1)) … … 70 70 f = pickle.loads(p) 71 71 self.assertEqual(repr(e), repr(f)) 72 73 72 74 73 def test_Expression_addition(self): … … 78 77 e += logic.Expression(b) 79 78 self.assertEqual(e.code(), "lambda x: (x.Date == 3) and (x.Qty == 5)") 79 80 # This failed in endue.price_filter on 11/14/2005 81 f = logic.Expression(lambda x: ((x.DateFrom == None or x.DateFrom <= datetime.date(2005, 11, 17)) 82 and (x.DateTo == None or x.DateTo >= datetime.date(2005, 11, 17)))) 83 f += logic.Expression(lambda x: x.DirectoryID == None or x.DirectoryID == 0) 84 self.assertEqual(f.code(), 85 'lambda x: (((x.DateFrom == None) or (x.DateFrom <= datetime.date(2005, 11, 17))) ' 86 'and ((x.DateTo == None) or (x.DateTo >= datetime.date(2005, 11, 17)))) ' 87 'and ((x.DirectoryID == None) or (x.DirectoryID == 0))') 80 88 81 89 def test_Aggregator(self):
