15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler import TypeSlots 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Compiler.ExprNodes import not_a_constant 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import cython 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)cython.declare(UtilityCode=object, EncodedString=object, BytesLiteral=object, 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes=object, ExprNodes=object, PyrexTypes=object, Builtin=object, 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UtilNodes=object, Naming=object) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Nodes 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import ExprNodes 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import PyrexTypes 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Visitor 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Builtin 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import UtilNodes 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Options 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import Naming 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Code import UtilityCode 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from StringEncoding import EncodedString, BytesLiteral 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Errors import error 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from ParseTreeTransforms import SkipDeclarations 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import copy 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import codecs 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)try: 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from __builtin__ import reduce 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)except ImportError: 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from functools import reduce 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)try: 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from __builtin__ import basestring 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)except ImportError: 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) basestring = str # Python 3 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def load_c_utility(name): 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilityCode.load_cached(name, "Optimize.c") 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def unwrap_coerced_node(node, coercion_nodes=(ExprNodes.CoerceToPyTypeNode, ExprNodes.CoerceFromPyTypeNode)): 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node, coercion_nodes): 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.arg 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def unwrap_node(node): 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while isinstance(node, UtilNodes.ResultRefNode): 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = node.expression 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def is_common_value(a, b): 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) a = unwrap_node(a) 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) b = unwrap_node(b) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(a, ExprNodes.NameNode) and isinstance(b, ExprNodes.NameNode): 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return a.name == b.name 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(a, ExprNodes.AttributeNode) and isinstance(b, ExprNodes.AttributeNode): 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not a.is_py_attr and is_common_value(a.obj, b.obj) and a.attribute == b.attribute 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def filter_none_node(node): 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node is not None and node.constant_result is None: 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class IterationTransform(Visitor.EnvTransform): 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform some common for-in loop patterns into efficient C loops: 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - for-in-dict loop becomes a while loop calling PyDict_Next() 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - for-in-enumerate is replaced by an external counter variable 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - for-in-range loop becomes a plain C for loop 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_PrimaryCmpNode(self, node): 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.is_ptr_contains(): 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # for t in operand2: 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # if operand1 == t: 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # res = True 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # break 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # else: 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # res = False 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = node.pos 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_ref = UtilNodes.ResultRefNode(node) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.operand2, ExprNodes.IndexNode): 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base_type = node.operand2.base.type.base_type 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base_type = node.operand2.type.base_type 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_handle = UtilNodes.TempHandle(base_type) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target = target_handle.ref(pos) 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node = ExprNodes.PrimaryCmpNode( 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos, operator=u'==', operand1=node.operand1, operand2=target) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if_body = Nodes.StatListNode( 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos, 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = [Nodes.SingleAssignmentNode(pos, lhs=result_ref, rhs=ExprNodes.BoolNode(pos, value=1)), 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.BreakStatNode(pos)]) 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if_node = Nodes.IfStatNode( 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos, 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if_clauses=[Nodes.IfClauseNode(pos, condition=cmp_node, body=if_body)], 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause=None) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for_loop = UtilNodes.TempsBlockNode( 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos, 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = [target_handle], 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = Nodes.ForInStatNode( 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos, 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target=target, 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) iterator=ExprNodes.IteratorNode(node.operand2.pos, sequence=node.operand2), 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body=if_node, 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause=Nodes.SingleAssignmentNode(pos, lhs=result_ref, rhs=ExprNodes.BoolNode(pos, value=0)))) 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for_loop = for_loop.analyse_expressions(self.current_env()) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for_loop = self.visit(for_loop) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = UtilNodes.TempResultFromStatNode(result_ref, for_loop) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operator == 'not_in': 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = ExprNodes.NotNode(pos, operand=new_node) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_node 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ForInStatNode(self, node): 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._optimise_for_loop(node, node.iterator.sequence) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _optimise_for_loop(self, node, iterator, reversed=False): 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.type is Builtin.dict_type: 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # like iterating over dict.keys() 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # CPython raises an error here: not a sequence 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_dict_iteration( 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, dict_obj=iterator, method=None, keys=True, values=False) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # C array (slice) iteration? 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.type.is_ptr or iterator.type.is_array: 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_carray_iteration(node, iterator, reversed=reversed) 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.type is Builtin.bytes_type: 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_bytes_iteration(node, iterator, reversed=reversed) 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.type is Builtin.unicode_type: 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_unicode_iteration(node, iterator, reversed=reversed) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # the rest is based on function calls 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(iterator, ExprNodes.SimpleCallNode): 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.args is None: 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_count = iterator.arg_tuple and len(iterator.arg_tuple.args) or 0 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_count = len(iterator.args) 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg_count and iterator.self is not None: 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_count -= 1 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function = iterator.function 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # dict iteration? 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if function.is_attribute and not reversed and not arg_count: 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base_obj = iterator.self or function.obj 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method = function.attribute 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # in Py3, items() is equivalent to Py2's iteritems() 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_safe_iter = self.global_scope().context.language_level >= 3 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not is_safe_iter and method in ('keys', 'values', 'items'): 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # try to reduce this to the corresponding .iter*() methods 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(base_obj, ExprNodes.SimpleCallNode): 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inner_function = base_obj.function 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (inner_function.is_name and inner_function.name == 'dict' 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and inner_function.entry 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and inner_function.entry.is_builtin): 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # e.g. dict(something).items() => safe to use .iter*() 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_safe_iter = True 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) keys = values = False 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if method == 'iterkeys' or (is_safe_iter and method == 'keys'): 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) keys = True 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif method == 'itervalues' or (is_safe_iter and method == 'values'): 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values = True 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif method == 'iteritems' or (is_safe_iter and method == 'items'): 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) keys = values = True 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if keys or values: 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_dict_iteration( 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, base_obj, method, keys, values) 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # enumerate/reversed ? 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.self is None and function.is_name and \ 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function.entry and function.entry.is_builtin: 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if function.name == 'enumerate': 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # CPython raises an error here: not a sequence 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_enumerate_iteration(node, iterator) 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif function.name == 'reversed': 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # CPython raises an error here: not a sequence 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_reversed_iteration(node, iterator) 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # range() iteration? 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if Options.convert_range and node.target.type.is_int: 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if iterator.self is None and function.is_name and \ 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function.entry and function.entry.is_builtin and \ 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function.name in ('range', 'xrange'): 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_range_iteration(node, iterator, reversed=reversed) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_reversed_iteration(self, node, reversed_function): 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = reversed_function.arg_tuple.args 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 0: 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(reversed_function.pos, 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "reversed() requires an iterable argument") 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(args) > 1: 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(reversed_function.pos, 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "reversed() takes exactly 1 argument") 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = args[0] 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # reversed(list/tuple) ? 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type in (Builtin.tuple_type, Builtin.list_type): 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.iterator.sequence = arg.as_none_safe_node("'NoneType' object is not iterable") 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.iterator.reversed = True 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._optimise_for_loop(node, arg, reversed=True) 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyBytes_AS_STRING_func_type = PyrexTypes.CFuncType( 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_char_ptr_type, [ 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("s", Builtin.bytes_type, None) 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyBytes_GET_SIZE_func_type = PyrexTypes.CFuncType( 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ssize_t_type, [ 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("s", Builtin.bytes_type, None) 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_bytes_iteration(self, node, slice_node, reversed=False): 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_type = node.target.type 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not target_type.is_int and target_type is not Builtin.bytes_type: 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # bytes iteration returns bytes objects in Py2, but 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # integers in Py3 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unpack_temp_node = UtilNodes.LetRefNode( 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.as_none_safe_node("'NoneType' is not iterable")) 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_base_node = ExprNodes.PythonCapiCallNode( 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, "PyBytes_AS_STRING", 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyBytes_AS_STRING_func_type, 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [unpack_temp_node], 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = 0, 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) len_node = ExprNodes.PythonCapiCallNode( 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, "PyBytes_GET_SIZE", 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyBytes_GET_SIZE_func_type, 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [unpack_temp_node], 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = 0, 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilNodes.LetNode( 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unpack_temp_node, 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._transform_carray_iteration( 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.SliceIndexNode( 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base = slice_base_node, 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = None, 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = None, 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = len_node, 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type = slice_base_node.type, 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = 1, 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ), 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reversed = reversed)) 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_READ_func_type = PyrexTypes.CFuncType( 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ucs4_type, [ 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("kind", PyrexTypes.c_int_type, None), 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("data", PyrexTypes.c_void_ptr_type, None), 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None) 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) init_unicode_iteration_func_type = PyrexTypes.CFuncType( 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_int_type, [ 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("s", PyrexTypes.py_object_type, None), 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("length", PyrexTypes.c_py_ssize_t_ptr_type, None), 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("data", PyrexTypes.c_void_ptr_ptr_type, None), 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("kind", PyrexTypes.c_int_ptr_type, None) 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = '-1') 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_unicode_iteration(self, node, slice_node, reversed=False): 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if slice_node.is_literal: 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # try to reduce to byte iteration for plain Latin-1 strings 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_value = BytesLiteral(slice_node.value.encode('latin1')) 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except UnicodeEncodeError: 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_slice = ExprNodes.SliceIndexNode( 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base=ExprNodes.BytesNode( 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, value=bytes_value, 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=bytes_value, 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_char_ptr_type).coerce_to( 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_uchar_ptr_type, self.current_env()), 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start=None, 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop=ExprNodes.IntNode( 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, value=str(len(bytes_value)), 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=len(bytes_value), 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_py_ssize_t_type), 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=Builtin.unicode_type, # hint for Python conversion 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_carray_iteration(node, bytes_slice, reversed) 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unpack_temp_node = UtilNodes.LetRefNode( 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.as_none_safe_node("'NoneType' is not iterable")) 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_node = ExprNodes.IntNode( 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value='0', constant_result=0, type=PyrexTypes.c_py_ssize_t_type) 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) length_temp = UtilNodes.TempHandle(PyrexTypes.c_py_ssize_t_type) 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) end_node = length_temp.ref(node.pos) 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation1, relation2 = '>', '>=' 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_node, end_node = end_node, start_node 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation1, relation2 = '<=', '<' 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kind_temp = UtilNodes.TempHandle(PyrexTypes.c_int_type) 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) data_temp = UtilNodes.TempHandle(PyrexTypes.c_void_ptr_type) 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) counter_temp = UtilNodes.TempHandle(PyrexTypes.c_py_ssize_t_type) 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = ExprNodes.PythonCapiCallNode( 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, "__Pyx_PyUnicode_READ", 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyUnicode_READ_func_type, 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [kind_temp.ref(slice_node.pos), 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) data_temp.ref(slice_node.pos), 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) counter_temp.ref(node.target.pos)], 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = False, 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if target_value.type != node.target.type: 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = target_value.coerce_to(node.target.type, 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.current_env()) 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_assign = Nodes.SingleAssignmentNode( 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = node.target.pos, 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = node.target, 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = target_value) 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = Nodes.StatListNode( 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = [target_assign, node.body]) 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = Nodes.ForFromStatNode( 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound1=start_node, relation1=relation1, 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target=counter_temp.ref(node.target.pos), 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation2=relation2, bound2=end_node, 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step=None, body=body, 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause=node.else_clause, 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from_range=True) 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) setup_node = Nodes.ExprStatNode( 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = ExprNodes.PythonCapiCallNode( 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, "__Pyx_init_unicode_iteration", 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.init_unicode_iteration_func_type, 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [unpack_temp_node, 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.AmpersandNode(slice_node.pos, operand=length_temp.ref(slice_node.pos), 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_py_ssize_t_ptr_type), 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.AmpersandNode(slice_node.pos, operand=data_temp.ref(slice_node.pos), 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_void_ptr_ptr_type), 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.AmpersandNode(slice_node.pos, operand=kind_temp.ref(slice_node.pos), 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_int_ptr_type), 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = True, 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_is_used = False, 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=UtilityCode.load_cached("unicode_iter", "Optimize.c"), 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) )) 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilNodes.LetNode( 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unpack_temp_node, 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UtilNodes.TempsBlockNode( 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, temps=[counter_temp, length_temp, data_temp, kind_temp], 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body=Nodes.StatListNode(node.pos, stats=[setup_node, loop_node]))) 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_carray_iteration(self, node, slice_node, reversed=False): 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) neg_step = False 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(slice_node, ExprNodes.SliceIndexNode): 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_base = slice_node.base 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = filter_none_node(slice_node.start) 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = filter_none_node(slice_node.stop) 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = None 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not stop: 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not slice_base.type.is_pyobject: 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(slice_node.pos, "C array iteration requires known end index") 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(slice_node, ExprNodes.IndexNode): 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert isinstance(slice_node.index, ExprNodes.SliceNode) 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_base = slice_node.base 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index = slice_node.index 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = filter_none_node(index.start) 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = filter_none_node(index.stop) 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = filter_none_node(index.step) 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if step: 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(step.constant_result, (int,long)) \ 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or step.constant_result == 0 \ 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or step.constant_result > 0 and not stop \ 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or step.constant_result < 0 and not start: 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not slice_base.type.is_pyobject: 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(step.pos, "C array iteration requires known step size and end index") 4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # step sign is handled internally by ForFromStatNode 4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_value = step.constant_result 4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_value = -step_value 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) neg_step = step_value < 0 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = ExprNodes.IntNode(step.pos, type=PyrexTypes.c_py_ssize_t_type, 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value=str(abs(step_value)), 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=abs(step_value)) 4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif slice_node.type.is_array: 4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if slice_node.type.size is None: 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(slice_node.pos, "C array iteration requires known end index") 4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_base = slice_node 4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = None 4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = ExprNodes.IntNode( 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, value=str(slice_node.type.size), 4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_py_ssize_t_type, constant_result=slice_node.type.size) 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = None 4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not slice_node.type.is_pyobject: 4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(slice_node.pos, "C array iteration requires known end index") 4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if start: 4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = start.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) 4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if stop: 4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = stop.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if stop is None: 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if neg_step: 4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = ExprNodes.IntNode( 4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slice_node.pos, value='-1', type=PyrexTypes.c_py_ssize_t_type, constant_result=-1) 4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(slice_node.pos, "C array iteration requires known step size and end index") 4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not start: 4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = ExprNodes.IntNode(slice_node.pos, value="0", constant_result=0, 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_py_ssize_t_type) 4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # if step was provided, it was already negated above 4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start, stop = stop, start 4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ptr_type = slice_base.type 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ptr_type.is_array: 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ptr_type = ptr_type.element_ptr_type() 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) carray_ptr = slice_base.coerce_to_simple(self.current_env()) 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if start and start.constant_result != 0: 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_ptr_node = ExprNodes.AddNode( 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start.pos, 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1=carray_ptr, 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator='+', 4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2=start, 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=ptr_type) 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_ptr_node = carray_ptr 4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if stop and stop.constant_result != 0: 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop_ptr_node = ExprNodes.AddNode( 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop.pos, 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1=ExprNodes.CloneNode(carray_ptr), 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator='+', 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2=stop, 4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=ptr_type 4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to_simple(self.current_env()) 4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop_ptr_node = ExprNodes.CloneNode(carray_ptr) 4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) counter = UtilNodes.TempHandle(ptr_type) 4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) counter_temp = counter.ref(node.target.pos) 4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if slice_base.type.is_string and node.target.type.is_pyobject: 4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # special case: char* -> bytes/unicode 4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if slice_node.type is Builtin.unicode_type: 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = ExprNodes.CastNode( 4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.DereferenceNode( 4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.target.pos, operand=counter_temp, 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=ptr_type.base_type), 4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ucs4_type).coerce_to( 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.target.type, self.current_env()) 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # char* -> bytes coercion requires slicing, not indexing 4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = ExprNodes.SliceIndexNode( 4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.target.pos, 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start=ExprNodes.IntNode(node.target.pos, value='0', 4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=0, 4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_int_type), 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop=ExprNodes.IntNode(node.target.pos, value='1', 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=1, 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_int_type), 4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base=counter_temp, 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=Builtin.bytes_type, 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=1) 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.target.type.is_ptr and not node.target.type.assignable_from(ptr_type.base_type): 5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Allow iteration with pointer target to avoid copy. 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = counter_temp 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # TODO: can this safely be replaced with DereferenceNode() as above? 5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = ExprNodes.IndexNode( 5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.target.pos, 5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index=ExprNodes.IntNode(node.target.pos, value='0', 5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=0, 5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_int_type), 5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base=counter_temp, 5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_buffer_access=False, 5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=ptr_type.base_type) 5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if target_value.type != node.target.type: 5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_value = target_value.coerce_to(node.target.type, 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.current_env()) 5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_assign = Nodes.SingleAssignmentNode( 5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = node.target.pos, 5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = node.target, 5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = target_value) 5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = Nodes.StatListNode( 5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = [target_assign, node.body]) 5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation1, relation2 = self._find_for_from_node_relations(neg_step, reversed) 5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for_node = Nodes.ForFromStatNode( 5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound1=start_ptr_node, relation1=relation1, 5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target=counter_temp, 5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation2=relation2, bound2=stop_ptr_node, 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step=step, body=body, 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause=node.else_clause, 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from_range=True) 5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilNodes.TempsBlockNode( 5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, temps=[counter], 5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body=for_node) 5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_enumerate_iteration(self, node, enumerate_function): 5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = enumerate_function.arg_tuple.args 5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 0: 5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(enumerate_function.pos, 5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "enumerate() requires an iterable argument") 5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(args) > 2: 5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(enumerate_function.pos, 5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "enumerate() takes at most 2 arguments") 5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.target.is_sequence_constructor: 5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # leave this untouched for now 5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) targets = node.target.args 5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(targets) != 2: 5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # leave this untouched for now 5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) enumerate_target, iterable_target = targets 5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) counter_type = enumerate_target.type 5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not counter_type.is_pyobject and not counter_type.is_int: 5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # nothing we can do here, I guess 5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 2: 5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = unwrap_coerced_node(args[1]).coerce_to(counter_type, self.current_env()) 5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = ExprNodes.IntNode(enumerate_function.pos, 5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value='0', 5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=counter_type, 5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=0) 5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp = UtilNodes.LetRefNode(start) 5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inc_expression = ExprNodes.AddNode( 5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) enumerate_function.pos, 5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1 = temp, 5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2 = ExprNodes.IntNode(node.pos, value='1', 5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=counter_type, 5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=1), 5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator = '+', 5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type = counter_type, 5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) #inplace = True, # not worth using in-place operation for Py ints 5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = counter_type.is_pyobject 5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_body = [ 5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.SingleAssignmentNode( 5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = enumerate_target.pos, 5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = enumerate_target, 5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = temp), 5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.SingleAssignmentNode( 5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = enumerate_target.pos, 5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = temp, 5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = inc_expression) 6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ] 6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.body, Nodes.StatListNode): 6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.body.stats = loop_body + node.body.stats 6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_body.append(node.body) 6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.body = Nodes.StatListNode( 6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.body.pos, 6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = loop_body) 6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.target = iterable_target 6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.item = node.item.coerce_to(iterable_target.type, self.current_env()) 6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.iterator.sequence = args[0] 6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # recurse into loop to check for further optimisations 6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilNodes.LetNode(temp, self._optimise_for_loop(node, node.iterator.sequence)) 6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _find_for_from_node_relations(self, neg_step_value, reversed): 6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if neg_step_value: 6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<', '<=' 6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '>', '>=' 6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if neg_step_value: 6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '>=', '>' 6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<=', '<' 6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_range_iteration(self, node, range_function, reversed=False): 6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = range_function.arg_tuple.args 6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) < 3: 6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_pos = range_function.pos 6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_value = 1 6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = ExprNodes.IntNode(step_pos, value='1', 6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=1) 6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = args[2] 6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_pos = step.pos 6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(step.constant_result, (int, long)): 6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # cannot determine step direction 6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_value = step.constant_result 6435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if step_value == 0: 6445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # will lead to an error elsewhere 6455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed and step_value not in (1, -1): 6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # FIXME: currently broken - requires calculation of the correct bounds 6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(step, ExprNodes.IntNode): 6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = ExprNodes.IntNode(step_pos, value=str(step_value), 6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=step_value) 6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 1: 6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound1 = ExprNodes.IntNode(range_function.pos, value='0', 6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=0) 6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound2 = args[0].coerce_to_integer(self.current_env()) 6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound1 = args[0].coerce_to_integer(self.current_env()) 6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound2 = args[1].coerce_to_integer(self.current_env()) 6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation1, relation2 = self._find_for_from_node_relations(step_value < 0, reversed) 6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if reversed: 6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound1, bound2 = bound2, bound1 6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if step_value < 0: 6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_value = -step_value 6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if step_value < 0: 6695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step_value = -step_value 6705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step.value = str(step_value) 6725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step.constant_result = step_value 6735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step = step.coerce_to_integer(self.current_env()) 6745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not bound2.is_literal: 6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # stop bound must be immutable => keep it in a temp var 6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound2_is_temp = True 6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound2 = UtilNodes.LetRefNode(bound2) 6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound2_is_temp = False 6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for_node = Nodes.ForFromStatNode( 6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target=node.target, 6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound1=bound1, relation1=relation1, 6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) relation2=relation2, bound2=bound2, 6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) step=step, body=node.body, 6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause=node.else_clause, 6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from_range=True) 6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if bound2_is_temp: 6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for_node = UtilNodes.LetNode(bound2, for_node) 6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return for_node 6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_dict_iteration(self, node, dict_obj, method, keys, values): 6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = [] 6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp = UtilNodes.TempHandle(PyrexTypes.py_object_type) 6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(temp) 7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_temp = temp.ref(dict_obj.pos) 7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp = UtilNodes.TempHandle(PyrexTypes.c_py_ssize_t_type) 7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(temp) 7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos_temp = temp.ref(node.pos) 7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) key_target = value_target = tuple_target = None 7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if keys and values: 7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.target.is_sequence_constructor: 7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(node.target.args) == 2: 7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) key_target, value_target = node.target.args 7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # unusual case that may or may not lead to an error 7125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 7135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tuple_target = node.target 7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif keys: 7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) key_target = node.target 7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value_target = node.target 7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.body, Nodes.StatListNode): 7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = node.body 7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = Nodes.StatListNode(pos = node.body.pos, 7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = [node.body]) 7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # keep original length to guard against dict modification 7275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_len_temp = UtilNodes.TempHandle(PyrexTypes.c_py_ssize_t_type) 7285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(dict_len_temp) 7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_len_temp_addr = ExprNodes.AmpersandNode( 7305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, operand=dict_len_temp.ref(dict_obj.pos), 7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_ptr_type(dict_len_temp.type)) 7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp = UtilNodes.TempHandle(PyrexTypes.c_int_type) 7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(temp) 7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_dict_temp = temp.ref(node.pos) 7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_dict_temp_addr = ExprNodes.AmpersandNode( 7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, operand=is_dict_temp, 7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_ptr_type(temp.type)) 7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) iter_next_node = Nodes.DictIterationNextNode( 7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_temp, dict_len_temp.ref(dict_obj.pos), pos_temp, 7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) key_target, value_target, tuple_target, 7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_dict_temp) 7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) iter_next_node = iter_next_node.analyse_expressions(self.current_env()) 7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body.stats[0:0] = [iter_next_node] 7455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if method: 7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_node = ExprNodes.StringNode( 7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_obj.pos, is_identifier=True, value=method) 7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_obj = dict_obj.as_none_safe_node( 7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "'NoneType' object has no attribute '%s'", 7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error = "PyExc_AttributeError", 7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) format_args = [method]) 7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_node = ExprNodes.NullNode(dict_obj.pos) 7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_obj = dict_obj.as_none_safe_node("'NoneType' object is not iterable") 7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def flag_node(value): 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value and 1 or 0 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode(node.pos, value=str(value), constant_result=value) 7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_code = [ 7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.SingleAssignmentNode( 7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = pos_temp, 7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = ExprNodes.IntNode(node.pos, value='0', 7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=0)), 7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.SingleAssignmentNode( 7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_obj.pos, 7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = dict_temp, 7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = ExprNodes.PythonCapiCallNode( 7715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dict_obj.pos, 7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "__Pyx_dict_iterator", 7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyDict_Iterator_func_type, 7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached("dict_iter", "Optimize.c"), 7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [dict_obj, flag_node(dict_obj.type is Builtin.dict_type), 7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_node, dict_len_temp_addr, is_dict_temp_addr, 7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=True, 7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) )), 7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.WhileStatNode( 7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition = None, 7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = body, 7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause = node.else_clause 7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ] 7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilNodes.TempsBlockNode( 7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, temps=temps, 7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body=Nodes.StatListNode( 7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = result_code 7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) )) 7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyDict_Iterator_func_type = PyrexTypes.CFuncType( 7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("dict", PyrexTypes.py_object_type, None), 7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("is_dict", PyrexTypes.c_int_type, None), 7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("method_name", PyrexTypes.py_object_type, None), 8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("p_orig_length", PyrexTypes.c_py_ssize_t_ptr_type, None), 8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("p_is_dict", PyrexTypes.c_int_ptr_type, None), 8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class SwitchTransform(Visitor.VisitorTransform): 8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) This transformation tries to turn long if statements into C switch statements. 8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) The requirement is that every clause be an (or of) var == value, where the var 8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is common among all clauses and both var and value are ints. 8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NO_MATCH = (None, None, None) 8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def extract_conditions(self, cond, allow_not_in): 8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while True: 8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(cond, (ExprNodes.CoerceToTempNode, 8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.CoerceToBooleanNode)): 8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cond = cond.arg 8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(cond, UtilNodes.EvalWithTempExprNode): 8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # this is what we get from the FlattenInListTransform 8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cond = cond.subexpression 8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(cond, ExprNodes.TypecastNode): 8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cond = cond.operand 8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(cond, ExprNodes.PrimaryCmpNode): 8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cond.cascade is not None: 8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif cond.is_c_string_contains() and \ 8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) isinstance(cond.operand2, (ExprNodes.UnicodeNode, ExprNodes.BytesNode)): 8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in = cond.operator == 'not_in' 8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not_in and not allow_not_in: 8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(cond.operand2, ExprNodes.UnicodeNode) and \ 8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cond.operand2.contains_surrogates(): 8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # dealing with surrogates leads to different 8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # behaviour on wide and narrow Unicode 8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # platforms => refuse to optimise this case 8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in, cond.operand1, self.extract_in_string_conditions(cond.operand2) 8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not cond.is_python_comparison(): 8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cond.operator == '==': 8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in = False 8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif allow_not_in and cond.operator == '!=': 8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in = True 8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # this looks somewhat silly, but it does the right 8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # checks for NameNode and AttributeNode 8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_common_value(cond.operand1, cond.operand1): 8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cond.operand2.is_literal: 8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in, cond.operand1, [cond.operand2] 8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif getattr(cond.operand2, 'entry', None) \ 8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and cond.operand2.entry.is_const: 8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in, cond.operand1, [cond.operand2] 8565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_common_value(cond.operand2, cond.operand2): 8575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cond.operand1.is_literal: 8585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in, cond.operand2, [cond.operand1] 8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif getattr(cond.operand1, 'entry', None) \ 8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and cond.operand1.entry.is_const: 8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in, cond.operand2, [cond.operand1] 8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(cond, ExprNodes.BoolBinopNode): 8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cond.operator == 'or' or (allow_not_in and cond.operator == 'and'): 8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) allow_not_in = (cond.operator == 'and') 8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in_1, t1, c1 = self.extract_conditions(cond.operand1, allow_not_in) 8665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in_2, t2, c2 = self.extract_conditions(cond.operand2, allow_not_in) 8675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if t1 is not None and not_in_1 == not_in_2 and is_common_value(t1, t2): 8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (not not_in_1) or allow_not_in: 8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in_1, t1, c1+c2 8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def extract_in_string_conditions(self, string_literal): 8735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(string_literal, ExprNodes.UnicodeNode): 8745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) charvals = list(map(ord, set(string_literal.value))) 8755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) charvals.sort() 8765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return [ ExprNodes.IntNode(string_literal.pos, value=str(charval), 8775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=charval) 8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for charval in charvals ] 8795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # this is a bit tricky as Py3's bytes type returns 8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # integers on iteration, whereas Py2 returns 1-char byte 8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # strings 8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) characters = string_literal.value 8845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) characters = list(set([ characters[i:i+1] for i in range(len(characters)) ])) 8855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) characters.sort() 8865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return [ ExprNodes.CharNode(string_literal.pos, value=charval, 8875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=charval) 8885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for charval in characters ] 8895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def extract_common_conditions(self, common_var, condition, allow_not_in): 8915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in, var, conditions = self.extract_conditions(condition, allow_not_in) 8925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if var is None: 8935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif common_var is not None and not is_common_value(var, common_var): 8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not (var.type.is_int or var.type.is_enum) or sum([not (cond.type.is_int or cond.type.is_enum) for cond in conditions]): 8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NO_MATCH 8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return not_in, var, conditions 8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def has_duplicate_values(self, condition_values): 9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # duplicated values don't work in a switch statement 9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) seen = set() 9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for value in condition_values: 9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value.has_constant_result(): 9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value.constant_result in seen: 9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return True 9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) seen.add(value.constant_result) 9085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 9095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # this isn't completely safe as we don't know the 9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # final C value, but this is about the best we can do 9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value.entry.cname in seen: 9135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return True 9145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except AttributeError: 9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return True # play safe 9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) seen.add(value.entry.cname) 9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_IfStatNode(self, node): 9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) common_var = None 9215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cases = [] 9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for if_clause in node.if_clauses: 9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _, common_var, conditions = self.extract_common_conditions( 9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) common_var, if_clause.condition, False) 9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if common_var is None: 9265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 9275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cases.append(Nodes.SwitchCaseNode(pos = if_clause.pos, 9295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) conditions = conditions, 9305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = if_clause.body)) 9315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition_values = [ 9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cond for case in cases for cond in case.conditions] 9345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(condition_values) < 2: 9355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 9365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.has_duplicate_values(condition_values): 9385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 9395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 9405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) common_var = unwrap_node(common_var) 9425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) switch_node = Nodes.SwitchStatNode(pos = node.pos, 9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test = common_var, 9445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cases = cases, 9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause = node.else_clause) 9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return switch_node 9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_CondExprNode(self, node): 9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in, common_var, conditions = self.extract_common_conditions( 9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) None, node.test, True) 9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if common_var is None \ 9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or len(conditions) < 2 \ 9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or self.has_duplicate_values(conditions): 9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.build_simple_switch_statement( 9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, common_var, conditions, not_in, 9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.true_val, node.false_val) 9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_BoolBinopNode(self, node): 9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in, common_var, conditions = self.extract_common_conditions( 9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) None, node, True) 9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if common_var is None \ 9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or len(conditions) < 2 \ 9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or self.has_duplicate_values(conditions): 9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.build_simple_switch_statement( 9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, common_var, conditions, not_in, 9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.BoolNode(node.pos, value=True, constant_result=True), 9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.BoolNode(node.pos, value=False, constant_result=False)) 9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_PrimaryCmpNode(self, node): 9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in, common_var, conditions = self.extract_common_conditions( 9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) None, node, True) 9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if common_var is None \ 9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or len(conditions) < 2 \ 9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or self.has_duplicate_values(conditions): 9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.build_simple_switch_statement( 9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, common_var, conditions, not_in, 9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.BoolNode(node.pos, value=True, constant_result=True), 9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.BoolNode(node.pos, value=False, constant_result=False)) 9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def build_simple_switch_statement(self, node, common_var, conditions, 9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_in, true_val, false_val): 9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_ref = UtilNodes.ResultRefNode(node) 9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) true_body = Nodes.SingleAssignmentNode( 9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = result_ref, 9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = true_val, 9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = True) 9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) false_body = Nodes.SingleAssignmentNode( 9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = result_ref, 9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = false_val, 10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = True) 10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not_in: 10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) true_body, false_body = false_body, true_body 10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cases = [Nodes.SwitchCaseNode(pos = node.pos, 10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) conditions = conditions, 10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = true_body)] 10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) common_var = unwrap_node(common_var) 10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) switch_node = Nodes.SwitchStatNode(pos = node.pos, 10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test = common_var, 10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cases = cases, 10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause = false_body) 10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) replacement = UtilNodes.TempResultFromStatNode(result_ref, switch_node) 10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return replacement 10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_EvalWithTempExprNode(self, node): 10185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # drop unused expression temp from FlattenInListTransform 10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) orig_expr = node.subexpression 10205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp_ref = node.lazy_temp 10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.subexpression is not orig_expr: 10235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # node was restructured => check if temp is still used 10245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not Visitor.tree_contains(node.subexpression, temp_ref): 10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.subexpression 10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.VisitorTransform.recurse_to_children 10295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FlattenInListTransform(Visitor.VisitorTransform, SkipDeclarations): 10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) This transformation flattens "x in [val1, ..., valn]" into a sequential list 10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) of comparisons. 10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_PrimaryCmpNode(self, node): 10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.cascade is not None: 10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.operator == 'in': 10425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) conjunction = 'or' 10435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) eq_or_neq = '==' 10445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.operator == 'not_in': 10455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) conjunction = 'and' 10465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) eq_or_neq = '!=' 10475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 10485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 10495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(node.operand2, (ExprNodes.TupleNode, 10515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.ListNode, 10525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.SetNode)): 10535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 10545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = node.operand2.args 10565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 0: 10575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # note: lhs may have side effects 10585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 10595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = UtilNodes.ResultRefNode(node.operand1) 10615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) conds = [] 10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = [] 10645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for arg in args: 10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 10665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Trial optimisation to avoid redundant temp 10675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # assignments. However, since is_simple() is meant to 10685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # be called after type analysis, we ignore any errors 10695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # and just play safe in that case. 10705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_simple_arg = arg.is_simple() 10715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except Exception: 10725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_simple_arg = False 10735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not is_simple_arg: 10745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # must evaluate all non-simple RHS before doing the comparisons 10755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = UtilNodes.LetRefNode(arg) 10765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(arg) 10775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cond = ExprNodes.PrimaryCmpNode( 10785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = node.pos, 10795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1 = lhs, 10805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator = eq_or_neq, 10815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2 = arg, 10825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cascade = None) 10835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) conds.append(ExprNodes.TypecastNode( 10845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = node.pos, 10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand = cond, 10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type = PyrexTypes.c_bint_type)) 10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def concat(left, right): 10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.BoolBinopNode( 10895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = node.pos, 10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator = conjunction, 10915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1 = left, 10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2 = right) 10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition = reduce(concat, conds) 10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = UtilNodes.EvalWithTempExprNode(lhs, condition) 10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for temp in temps[::-1]: 10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = UtilNodes.EvalWithTempExprNode(temp, new_node) 10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_node 10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.VisitorTransform.recurse_to_children 11015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class DropRefcountingTransform(Visitor.VisitorTransform): 11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Drop ref-counting in safe places. 11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.VisitorTransform.recurse_to_children 11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ParallelAssignmentNode(self, node): 11095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 11105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Parallel swap assignments like 'a,b = b,a' are safe. 11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) left_names, right_names = [], [] 11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) left_indices, right_indices = [], [] 11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = [] 11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for stat in node.stats: 11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(stat, Nodes.SingleAssignmentNode): 11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self._extract_operand(stat.lhs, left_names, 11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) left_indices, temps): 11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self._extract_operand(stat.rhs, right_names, 11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) right_indices, temps): 11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(stat, Nodes.CascadedAssignmentNode): 11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # FIXME 11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if left_names or right_names: 11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # lhs/rhs names must be a non-redundant permutation 11325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lnames = [ path for path, n in left_names ] 11335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rnames = [ path for path, n in right_names ] 11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if set(lnames) != set(rnames): 11355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(set(lnames)) != len(right_names): 11375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if left_indices or right_indices: 11405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # base name and index of index nodes must be a 11415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # non-redundant permutation 11425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lindices = [] 11435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for lhs_node in left_indices: 11445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_id = self._extract_index_id(lhs_node) 11455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not index_id: 11465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lindices.append(index_id) 11485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rindices = [] 11495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for rhs_node in right_indices: 11505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_id = self._extract_index_id(rhs_node) 11515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not index_id: 11525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rindices.append(index_id) 11545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if set(lindices) != set(rindices): 11565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(set(lindices)) != len(right_indices): 11585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # really supporting IndexNode requires support in 11615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # __Pyx_GetItemInt(), so let's stop short for now 11625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp_args = [t.arg for t in temps] 11655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for temp in temps: 11665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp.use_managed_ref = False 11675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for _, name_node in left_names + right_names: 11695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name_node not in temp_args: 11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name_node.use_managed_ref = False 11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for index_node in left_indices + right_indices: 11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_node.use_managed_ref = False 11745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 11765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _extract_operand(self, node, names, indices, temps): 11785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = unwrap_node(node) 11795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.type.is_pyobject: 11805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 11815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node, ExprNodes.CoerceToTempNode): 11825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(node) 11835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = node.arg 11845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name_path = [] 11855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) obj_node = node 11865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while isinstance(obj_node, ExprNodes.AttributeNode): 11875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if obj_node.is_py_attr: 11885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 11895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name_path.append(obj_node.member) 11905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) obj_node = obj_node.obj 11915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(obj_node, ExprNodes.NameNode): 11925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name_path.append(obj_node.name) 11935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) names.append( ('.'.join(name_path[::-1]), node) ) 11945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(node, ExprNodes.IndexNode): 11955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.base.type != Builtin.list_type: 11965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 11975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.index.type.is_int: 11985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 11995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(node.base, ExprNodes.NameNode): 12005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 12015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) indices.append(node) 12025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 12035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 12045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return True 12055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _extract_index_id(self, index_node): 12075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base = index_node.base 12085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index = index_node.index 12095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(index, ExprNodes.NameNode): 12105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_val = index.name 12115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(index, ExprNodes.ConstNode): 12125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # FIXME: 12135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 12145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 12155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 12165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (base.name, index_val) 12175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class EarlyReplaceBuiltinCalls(Visitor.EnvTransform): 12205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Optimize some common calls to builtin types *before* the type 12215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) analysis phase and *after* the declarations analysis phase. 12225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) This transform cannot make use of any argument types, but it can 12245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) restructure the tree in a way that the type analysis phase can 12255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) respond to. 12265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Introducing C function calls here may not be a good idea. Move 12285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) them to the OptimizeBuiltinCalls transform instead, which runs 12295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) after type analysis. 12305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 12315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # only intercept on call nodes 12325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.VisitorTransform.recurse_to_children 12335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_SimpleCallNode(self, node): 12355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 12365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function = node.function 12375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self._function_is_builtin_name(function): 12385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 12395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._dispatch_to_handler(node, function, node.args) 12405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_GeneralCallNode(self, node): 12425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 12435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function = node.function 12445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self._function_is_builtin_name(function): 12455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 12465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_tuple = node.positional_args 12475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(arg_tuple, ExprNodes.TupleNode): 12485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 12495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = arg_tuple.args 12505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._dispatch_to_handler( 12515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, node.keyword_args) 12525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _function_is_builtin_name(self, function): 12545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not function.is_name: 12555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 12565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) env = self.current_env() 12575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry = env.lookup(function.name) 12585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if entry is not env.builtin_scope().lookup_here(function.name): 12595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 12605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # if entry is None, it's at least an undeclared name, so likely builtin 12615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return True 12625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _dispatch_to_handler(self, node, function, args, kwargs=None): 12645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if kwargs is None: 12655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handler_name = '_handle_simple_function_%s' % function.name 12665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 12675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handler_name = '_handle_general_function_%s' % function.name 12685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) handle_call = getattr(self, handler_name, None) 12695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if handle_call is not None: 12705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if kwargs is None: 12715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return handle_call(node, args) 12725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 12735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return handle_call(node, args, kwargs) 12745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 12755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_capi_function(self, node, cname, func_type, utility_code=None): 12775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.function = ExprNodes.PythonCapiFunctionNode( 12785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.function.pos, node.function.name, cname, func_type, 12795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = utility_code) 12805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _error_wrong_arg_count(self, function_name, node, args, expected=None): 12825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not expected: # None or 0 12835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = '' 12845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(expected, basestring) or expected > 1: 12855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = '...' 12865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expected == 1: 12875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = 'x' 12885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 12895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = '' 12905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if expected is not None: 12915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expected_str = 'expected %s, ' % expected 12925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 12935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expected_str = '' 12945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(node.pos, "%s(%s) called with wrong number of args, %sfound %d" % ( 12955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name, arg_str, expected_str, len(args))) 12965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # specific handlers for simple call nodes 12985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 12995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_float(self, node, pos_args): 13005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not pos_args: 13015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.FloatNode(node.pos, value='0.0') 13025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) > 1: 13035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('float', node, pos_args, 1) 13045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_type = getattr(pos_args[0], 'type', None) 13055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg_type in (PyrexTypes.c_double_type, Builtin.float_type): 13065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return pos_args[0] 13075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 13085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) class YieldNodeCollector(Visitor.TreeVisitor): 13105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self): 13115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Visitor.TreeVisitor.__init__(self) 13125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.yield_stat_nodes = {} 13135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.yield_nodes = [] 13145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.TreeVisitor.visitchildren 13165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # XXX: disable inlining while it's not back supported 13175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __visit_YieldExprNode(self, node): 13185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.yield_nodes.append(node) 13195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 13205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __visit_ExprStatNode(self, node): 13225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 13235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.expr in self.yield_nodes: 13245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.yield_stat_nodes[node.expr] = node 13255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __visit_GeneratorExpressionNode(self, node): 13275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # enable when we support generic generator expressions 13285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # 13295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # everything below this node is out of scope 13305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 13315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _find_single_yield_expression(self, node): 13335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) collector = self.YieldNodeCollector() 13345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) collector.visitchildren(node) 13355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(collector.yield_nodes) != 1: 13365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None, None 13375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_node = collector.yield_nodes[0] 13385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 13395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (yield_node.arg, collector.yield_stat_nodes[yield_node]) 13405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except KeyError: 13415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None, None 13425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_all(self, node, pos_args): 13445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform 13455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _result = all(x for L in LL for x in L) 13475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) into 13495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for L in LL: 13515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for x in L: 13525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not x: 13535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _result = False 13545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 13555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 13565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 13575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 13585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 13595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _result = True 13605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 13615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_any_all(node, pos_args, False) 13625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_any(self, node, pos_args): 13645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform 13655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _result = any(x for L in LL for x in L) 13675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) into 13695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for L in LL: 13715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for x in L: 13725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if x: 13735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _result = True 13745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 13755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 13765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 13775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 13785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 13795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _result = False 13805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 13815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_any_all(node, pos_args, True) 13825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_any_all(self, node, pos_args, is_any): 13845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 13855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 13865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode): 13875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 13885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node = pos_args[0] 13895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = gen_expr_node.loop 13905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node) 13915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if yield_expression is None: 13925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 13935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_any: 13955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition = yield_expression 13965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 13975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition = ExprNodes.NotNode(yield_expression.pos, operand = yield_expression) 13985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_ref = UtilNodes.ResultRefNode(pos=node.pos, type=PyrexTypes.c_bint_type) 14005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test_node = Nodes.IfStatNode( 14015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression.pos, 14025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else_clause = None, 14035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if_clauses = [ Nodes.IfClauseNode( 14045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression.pos, 14055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition = condition, 14065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body = Nodes.StatListNode( 14075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 14085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = [ 14095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.SingleAssignmentNode( 14105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 14115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = result_ref, 14125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = ExprNodes.BoolNode(yield_expression.pos, value = is_any, 14135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result = is_any)), 14145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.BreakStatNode(node.pos) 14155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ])) ] 14165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 14175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop = loop_node 14185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while isinstance(loop.body, Nodes.LoopNode): 14195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_loop = loop.body 14205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop.body = Nodes.StatListNode(loop.body.pos, stats = [ 14215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop.body, 14225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.BreakStatNode(yield_expression.pos) 14235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 14245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_loop.else_clause = Nodes.ContinueStatNode(yield_expression.pos) 14255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop = next_loop 14265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node.else_clause = Nodes.SingleAssignmentNode( 14275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 14285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = result_ref, 14295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = ExprNodes.BoolNode(yield_expression.pos, value = not is_any, 14305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result = not is_any)) 14315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Visitor.recursively_replace_node(loop_node, yield_stat_node, test_node) 14335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.InlinedGeneratorExpressionNode( 14355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node.pos, loop = loop_node, result_node = result_ref, 14365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr_scope = gen_expr_node.expr_scope, orig_func = is_any and 'any' or 'all') 14375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_sorted(self, node, pos_args): 14395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform sorted(genexpr) and sorted([listcomp]) into 14405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [listcomp].sort(). CPython just reads the iterable into a 14415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) list and calls .sort() on it. Expanding the iterable in a 14425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) listcomp is still faster and the result can be sorted in 14435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) place. 14445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 14455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 14465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 14475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(pos_args[0], ExprNodes.ComprehensionNode) \ 14485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and pos_args[0].type is Builtin.list_type: 14495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) listcomp_node = pos_args[0] 14505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = listcomp_node.loop 14515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode): 14525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node = pos_args[0] 14535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = gen_expr_node.loop 14545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node) 14555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if yield_expression is None: 14565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 14575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append_node = ExprNodes.ComprehensionAppendNode( 14595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression.pos, expr = yield_expression) 14605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Visitor.recursively_replace_node(loop_node, yield_stat_node, append_node) 14625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) listcomp_node = ExprNodes.ComprehensionNode( 14645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node.pos, loop = loop_node, 14655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append = append_node, type = Builtin.list_type, 14665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr_scope = gen_expr_node.expr_scope, 14675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) has_local_scope = True) 14685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append_node.target = listcomp_node 14695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 14705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 14715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_node = UtilNodes.ResultRefNode( 14735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = loop_node.pos, type = Builtin.list_type, may_hold_none=False) 14745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) listcomp_assign_node = Nodes.SingleAssignmentNode( 14755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, lhs = result_node, rhs = listcomp_node, first = True) 14765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sort_method = ExprNodes.AttributeNode( 14785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, obj = result_node, attribute = EncodedString('sort'), 14795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # entry ? type ? 14805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) needs_none_check = False) 14815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sort_node = Nodes.ExprStatNode( 14825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, expr = ExprNodes.SimpleCallNode( 14835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, function = sort_method, args = [])) 14845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sort_node.analyse_declarations(self.current_env()) 14865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return UtilNodes.TempResultFromStatNode( 14885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_node, 14895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.StatListNode(node.pos, stats = [ listcomp_assign_node, sort_node ])) 14905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 14915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_sum(self, node, pos_args): 14925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform sum(genexpr) into an equivalent inlined aggregation loop. 14935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 14945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) not in (1,2): 14955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 14965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(pos_args[0], (ExprNodes.GeneratorExpressionNode, 14975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.ComprehensionNode)): 14985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 14995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node = pos_args[0] 15005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = gen_expr_node.loop 15015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(gen_expr_node, ExprNodes.GeneratorExpressionNode): 15035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node) 15045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if yield_expression is None: 15055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 15065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: # ComprehensionNode 15075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_stat_node = gen_expr_node.append 15085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression = yield_stat_node.expr 15095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 15105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not yield_expression.is_literal or not yield_expression.type.is_int: 15115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 15125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except AttributeError: 15135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node # in case we don't have a type yet 15145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # special case: old Py2 backwards compatible "sum([int_const for ...])" 15155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # can safely be unpacked into a genexpr 15165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) == 1: 15185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = ExprNodes.IntNode(node.pos, value='0', constant_result=0) 15195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 15205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = pos_args[1] 15215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_ref = UtilNodes.ResultRefNode(pos=node.pos, type=PyrexTypes.py_object_type) 15235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) add_node = Nodes.SingleAssignmentNode( 15245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression.pos, 15255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = result_ref, 15265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = ExprNodes.binop_node(node.pos, '+', result_ref, yield_expression) 15275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 15285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Visitor.recursively_replace_node(loop_node, yield_stat_node, add_node) 15305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exec_code = Nodes.StatListNode( 15325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 15335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stats = [ 15345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Nodes.SingleAssignmentNode( 15355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start.pos, 15365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = UtilNodes.ResultRefNode(pos=node.pos, expression=result_ref), 15375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) rhs = start, 15385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = True), 15395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node 15405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 15415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.InlinedGeneratorExpressionNode( 15435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node.pos, loop = exec_code, result_node = result_ref, 15445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr_scope = gen_expr_node.expr_scope, orig_func = 'sum', 15455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) has_local_scope = gen_expr_node.has_local_scope) 15465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_min(self, node, pos_args): 15485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._optimise_min_max(node, pos_args, '<') 15495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_max(self, node, pos_args): 15515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._optimise_min_max(node, pos_args, '>') 15525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _optimise_min_max(self, node, args, operator): 15545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace min(a,b,...) and max(a,b,...) by explicit comparison code. 15555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 15565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) <= 1: 15575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 1 and args[0].is_sequence_constructor: 15585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = args[0].args 15595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 15605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # leave this to Python 15615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 15625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cascaded_nodes = list(map(UtilNodes.ResultRefNode, args[1:])) 15645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_result = args[0] 15665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for arg_node in cascaded_nodes: 15675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_ref = UtilNodes.ResultRefNode(last_result) 15685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_result = ExprNodes.CondExprNode( 15695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_node.pos, 15705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) true_val = arg_node, 15715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) false_val = result_ref, 15725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test = ExprNodes.PrimaryCmpNode( 15735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_node.pos, 15745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1 = arg_node, 15755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator = operator, 15765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2 = result_ref, 15775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 15785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 15795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_result = UtilNodes.EvalWithTempExprNode(result_ref, last_result) 15805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for ref_node in cascaded_nodes[::-1]: 15825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_result = UtilNodes.EvalWithTempExprNode(ref_node, last_result) 15835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return last_result 15855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 15865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _DISABLED_handle_simple_function_tuple(self, node, pos_args): 15875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not pos_args: 15885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.TupleNode(node.pos, args=[], constant_result=()) 15895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # This is a bit special - for iterables (including genexps), 15905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Python actually overallocates and resizes a newly created 15915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # tuple incrementally while reading items, which we can't 15925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # easily do without explicit node support. Instead, we read 15935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # the items into a list and then copy them into a tuple of the 15945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # final size. This takes up to twice as much memory, but will 15955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # have to do until we have real support for genexps. 15965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = self._transform_list_set_genexpr(node, pos_args, Builtin.list_type) 15975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if result is not node: 15985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.AsTupleNode(node.pos, arg=result) 15995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_frozenset(self, node, pos_args): 16025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace frozenset([...]) by frozenset((...)) as tuples are more efficient. 16035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 16045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 16055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if pos_args[0].is_sequence_constructor and not pos_args[0].args: 16075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) del pos_args[0] 16085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(pos_args[0], ExprNodes.ListNode): 16095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos_args[0] = pos_args[0].as_tuple() 16105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_list(self, node, pos_args): 16135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not pos_args: 16145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.ListNode(node.pos, args=[], constant_result=[]) 16155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_list_set_genexpr(node, pos_args, Builtin.list_type) 16165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_set(self, node, pos_args): 16185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not pos_args: 16195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.SetNode(node.pos, args=[], constant_result=set()) 16205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._transform_list_set_genexpr(node, pos_args, Builtin.set_type) 16215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _transform_list_set_genexpr(self, node, pos_args, target_type): 16235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace set(genexpr) and list(genexpr) by a literal comprehension. 16245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 16255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) > 1: 16265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode): 16285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node = pos_args[0] 16305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = gen_expr_node.loop 16315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node) 16335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if yield_expression is None: 16345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append_node = ExprNodes.ComprehensionAppendNode( 16375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression.pos, 16385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = yield_expression) 16395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Visitor.recursively_replace_node(loop_node, yield_stat_node, append_node) 16415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) comp = ExprNodes.ComprehensionNode( 16435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 16445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) has_local_scope = True, 16455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr_scope = gen_expr_node.expr_scope, 16465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop = loop_node, 16475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append = append_node, 16485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type = target_type) 16495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append_node.target = comp 16505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return comp 16515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_dict(self, node, pos_args): 16535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace dict( (a,b) for ... ) by a literal { a:b for ... }. 16545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 16555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) == 0: 16565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.DictNode(node.pos, key_value_pairs=[], constant_result={}) 16575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) > 1: 16585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(pos_args[0], ExprNodes.GeneratorExpressionNode): 16605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gen_expr_node = pos_args[0] 16625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop_node = gen_expr_node.loop 16635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression, yield_stat_node = self._find_single_yield_expression(loop_node) 16655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if yield_expression is None: 16665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(yield_expression, ExprNodes.TupleNode): 16695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(yield_expression.args) != 2: 16715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append_node = ExprNodes.DictComprehensionAppendNode( 16745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) yield_expression.pos, 16755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) key_expr = yield_expression.args[0], 16765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value_expr = yield_expression.args[1]) 16775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Visitor.recursively_replace_node(loop_node, yield_stat_node, append_node) 16795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dictcomp = ExprNodes.ComprehensionNode( 16815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 16825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) has_local_scope = True, 16835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr_scope = gen_expr_node.expr_scope, 16845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) loop = loop_node, 16855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append = append_node, 16865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type = Builtin.dict_type) 16875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) append_node.target = dictcomp 16885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return dictcomp 16895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # specific handlers for general call nodes 16915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 16925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_general_function_dict(self, node, pos_args, kwargs): 16935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace dict(a=b,c=d,...) by the underlying keyword dict 16945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) construction which is done anyway. 16955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 16965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) > 0: 16975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 16985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(kwargs, ExprNodes.DictNode): 16995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return kwargs 17015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class InlineDefNodeCalls(Visitor.NodeRefCleanupMixin, Visitor.EnvTransform): 17045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.VisitorTransform.recurse_to_children 17055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def get_constant_value_node(self, name_node): 17075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name_node.cf_state is None: 17085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 17095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name_node.cf_state.cf_is_null: 17105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 17115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry = self.current_env().lookup(name_node.name) 17125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not entry or (not entry.cf_assignments 17135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or len(entry.cf_assignments) != 1): 17145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # not just a single assignment in all closures 17155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 17165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return entry.cf_assignments[0].rhs 17175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_SimpleCallNode(self, node): 17195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 17205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self.current_directives.get('optimize.inline_defnode_calls'): 17215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name = node.function 17235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not function_name.is_name: 17245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function = self.get_constant_value_node(function_name) 17265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(function, ExprNodes.PyCFunctionNode): 17275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inlined = ExprNodes.InlinedDefNodeCallNode( 17295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, function_name=function_name, 17305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function=function, args=node.args) 17315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if inlined.can_be_inlined(): 17325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.replace(node, inlined) 17335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class OptimizeBuiltinCalls(Visitor.MethodDispatcherTransform): 17375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Optimize some common methods calls and instantiation patterns 17385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for builtin types *after* the type analysis phase. 17395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Running after type analysis, this transform can only perform 17415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function replacements that do not alter the function return type 17425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) in a way that was not anticipated by the type analysis. 17435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### cleanup to avoid redundant coercions to/from Python types 17455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _visit_PyTypeTestNode(self, node): 17475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # disabled - appears to break assignments in some cases, and 17485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # also drops a None check, which might still be required 17495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Flatten redundant type checks after tree changes. 17505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) old_arg = node.arg 17525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 17535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if old_arg is node.arg or node.arg.type != node.type: 17545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.arg 17565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _visit_TypecastNode(self, node): 17585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # disabled - the user may have had a reason to put a type 17595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # cast, even if it looks redundant to Cython 17605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Drop redundant type casts. 17625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 17645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type == node.operand.type: 17655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.operand 17665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ExprStatNode(self, node): 17695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Drop useless coercions. 17715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 17735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.expr, ExprNodes.CoerceToPyTypeNode): 17745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.expr = node.expr.arg 17755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_CoerceToBooleanNode(self, node): 17785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Drop redundant conversion nodes after tree changes. 17795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 17815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = node.arg 17825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(arg, ExprNodes.PyTypeTestNode): 17835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = arg.arg 17845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(arg, ExprNodes.CoerceToPyTypeNode): 17855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type in (PyrexTypes.py_object_type, Builtin.bool_type): 17865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return arg.arg.coerce_to_boolean(self.current_env()) 17875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 17885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_CoerceFromPyTypeNode(self, node): 17905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Drop redundant conversion nodes after tree changes. 17915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 17925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Also, optimise away calls to Python's builtin int() and 17935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) float() if the result is going to be coerced back into a C 17945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type anyway. 17955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 17965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 17975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = node.arg 17985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not arg.type.is_pyobject: 17995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # no Python conversion left at all, just do a C coercion instead 18005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type == arg.type: 18015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return arg 18025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 18035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return arg.coerce_to(node.type, self.current_env()) 18045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(arg, ExprNodes.PyTypeTestNode): 18055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = arg.arg 18065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.is_literal: 18075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (node.type.is_int and isinstance(arg, ExprNodes.IntNode) or 18085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.type.is_float and isinstance(arg, ExprNodes.FloatNode) or 18095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.type.is_int and isinstance(arg, ExprNodes.BoolNode)): 18105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return arg.coerce_to(node.type, self.current_env()) 18115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(arg, ExprNodes.CoerceToPyTypeNode): 18125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type is PyrexTypes.py_object_type: 18135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type.assignable_from(arg.arg.type): 18145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # completely redundant C->Py->C coercion 18155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return arg.arg.coerce_to(node.type, self.current_env()) 18165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(arg, ExprNodes.SimpleCallNode): 18175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type.is_int or node.type.is_float: 18185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._optimise_numeric_cast_call(node, arg) 18195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(arg, ExprNodes.IndexNode) and not arg.is_buffer_access: 18205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_node = arg.index 18215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(index_node, ExprNodes.CoerceToPyTypeNode): 18225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_node = index_node.arg 18235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if index_node.type.is_int: 18245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._optimise_int_indexing(node, arg, index_node) 18255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 18265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyBytes_GetItemInt_func_type = PyrexTypes.CFuncType( 18285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_char_type, [ 18295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("bytes", Builtin.bytes_type, None), 18305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_py_ssize_t_type, None), 18315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("check_bounds", PyrexTypes.c_int_type, None), 18325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 18335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = "((char)-1)", 18345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_check = True) 18355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _optimise_int_indexing(self, coerce_node, arg, index_node): 18375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) env = self.current_env() 18385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound_check_bool = env.directives['boundscheck'] and 1 or 0 18395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.base.type is Builtin.bytes_type: 18405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if coerce_node.type in (PyrexTypes.c_char_type, PyrexTypes.c_uchar_type): 18415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # bytes[index] -> char 18425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound_check_node = ExprNodes.IntNode( 18435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) coerce_node.pos, value=str(bound_check_bool), 18445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=bound_check_bool) 18455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = ExprNodes.PythonCapiCallNode( 18465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) coerce_node.pos, "__Pyx_PyBytes_GetItemInt", 18475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyBytes_GetItemInt_func_type, 18485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[ 18495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg.base.as_none_safe_node("'NoneType' object is not subscriptable"), 18505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_node.coerce_to(PyrexTypes.c_py_ssize_t_type, env), 18515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bound_check_node, 18525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 18535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=True, 18545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=UtilityCode.load_cached( 18555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'bytes_index', 'StringTools.c')) 18565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if coerce_node.type is not PyrexTypes.c_char_type: 18575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = node.coerce_to(coerce_node.type, env) 18585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 18595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return coerce_node 18605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _optimise_numeric_cast_call(self, node, arg): 18625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function = arg.function 18635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(function, ExprNodes.NameNode) \ 18645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or not function.type.is_builtin_type \ 18655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or not isinstance(arg.arg_tuple, ExprNodes.TupleNode): 18665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 18675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = arg.arg_tuple.args 18685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) != 1: 18695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 18705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_arg = args[0] 18715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(func_arg, ExprNodes.CoerceToPyTypeNode): 18725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_arg = func_arg.arg 18735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif func_arg.type.is_pyobject: 18745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # play safe: Python conversion might work on all sorts of things 18755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 18765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if function.name == 'int': 18775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if func_arg.type.is_int or node.type.is_int: 18785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if func_arg.type == node.type: 18795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return func_arg 18805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type.assignable_from(func_arg.type) or func_arg.type.is_float: 18815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.TypecastNode( 18825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, operand=func_arg, type=node.type) 18835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif function.name == 'float': 18845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if func_arg.type.is_float or node.type.is_float: 18855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if func_arg.type == node.type: 18865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return func_arg 18875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type.assignable_from(func_arg.type) or func_arg.type.is_float: 18885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.TypecastNode( 18895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, operand=func_arg, type=node.type) 18905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 18915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 18925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _error_wrong_arg_count(self, function_name, node, args, expected=None): 18935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not expected: # None or 0 18945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = '' 18955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(expected, basestring) or expected > 1: 18965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = '...' 18975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expected == 1: 18985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = 'x' 18995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 19005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_str = '' 19015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if expected is not None: 19025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expected_str = 'expected %s, ' % expected 19035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 19045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expected_str = '' 19055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error(node.pos, "%s(%s) called with wrong number of args, %sfound %d" % ( 19065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name, arg_str, expected_str, len(args))) 19075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### generic fallbacks 19095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_function(self, node, function_name, function, arg_list, kwargs): 19115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_method(self, node, type_name, attr_name, function, 19145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_list, is_unbound_method, kwargs): 19155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 19165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Try to inject C-API calls for unbound method calls to builtin types. 19175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) While the method declarations in Builtin.py already handle this, we 19185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) can additionally resolve bound and unbound methods here that were 19195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assigned to variables ahead of time. 19205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 19215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if kwargs: 19225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not function or not function.is_attribute or not function.obj.is_name: 19245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # cannot track unbound method calls over more than one indirection as 19255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # the names might have been reassigned in the meantime 19265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_entry = self.current_env().lookup(type_name) 19285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not type_entry: 19295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method = ExprNodes.AttributeNode( 19315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.function.pos, 19325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) obj=ExprNodes.NameNode( 19335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function.pos, 19345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name=type_name, 19355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry=type_entry, 19365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=type_entry.type), 19375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) attribute=attr_name, 19385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_called=True).analyse_as_unbound_cmethod_node(self.current_env()) 19395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if method is None: 19405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = node.args 19425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if args is None and node.arg_tuple: 19435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = node.arg_tuple.args 19445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) call_node = ExprNodes.SimpleCallNode( 19455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 19465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function=method, 19475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=args) 19485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not is_unbound_method: 19495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) call_node.self = function.obj 19505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) call_node.analyse_c_function_call(self.current_env()) 19515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) call_node.analysed = True 19525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return call_node.coerce_to(node.type, self.current_env()) 19535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### builtin types 19555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyDict_Copy_func_type = PyrexTypes.CFuncType( 19575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.dict_type, [ 19585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("dict", Builtin.dict_type, None) 19595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 19605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_dict(self, node, function, pos_args): 19625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace dict(some_dict) by PyDict_Copy(some_dict). 19635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 19645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 19655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = pos_args[0] 19675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type is Builtin.dict_type: 19685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = arg.as_none_safe_node("'NoneType' is not iterable") 19695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 19705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "PyDict_Copy", self.PyDict_Copy_func_type, 19715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [arg], 19725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp 19735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 19745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyList_AsTuple_func_type = PyrexTypes.CFuncType( 19775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.tuple_type, [ 19785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("list", Builtin.list_type, None) 19795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 19805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_tuple(self, node, function, pos_args): 19825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace tuple([...]) by a call to PyList_AsTuple. 19835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 19845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 19855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = pos_args[0] 19875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type is Builtin.tuple_type and not arg.may_be_none(): 19885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return arg 19895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type is not Builtin.list_type: 19905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 19915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos_args[0] = arg.as_none_safe_node( 19925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "'NoneType' object is not iterable") 19935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 19945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 19955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "PyList_AsTuple", self.PyList_AsTuple_func_type, 19965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = pos_args, 19975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp 19985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 19995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PySet_New_func_type = PyrexTypes.CFuncType( 20015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.set_type, [ 20025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None) 20035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 20045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_set(self, node, function, pos_args): 20065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 20075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 20085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if pos_args[0].is_sequence_constructor: 20095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # We can optimise set([x,y,z]) safely into a set literal, 20105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # but only if we create all items before adding them - 20115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # adding an item may raise an exception if it is not 20125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # hashable, but creating the later items may have 20135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # side-effects. 20145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [] 20155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = [] 20165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for arg in pos_args[0].args: 20175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not arg.is_simple(): 20185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = UtilNodes.LetRefNode(arg) 20195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(arg) 20205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(arg) 20215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = ExprNodes.SetNode(node.pos, is_temp=1, args=args) 20225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for temp in temps[::-1]: 20235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = UtilNodes.EvalWithTempExprNode(temp, result) 20245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return result 20255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 20265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # PySet_New(it) is better than a generic Python call to set(it) 20275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 20285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "PySet_New", 20295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PySet_New_func_type, 20305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=pos_args, 20315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 20325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=UtilityCode.load_cached('pyset_compat', 'Builtins.c'), 20335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) py_name="set") 20345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyFrozenSet_New_func_type = PyrexTypes.CFuncType( 20365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.frozenset_type, [ 20375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("it", PyrexTypes.py_object_type, None) 20385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 20395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_frozenset(self, node, function, pos_args): 20415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not pos_args: 20425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos_args = [ExprNodes.NullNode(node.pos)] 20435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(pos_args) > 1: 20445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 20455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif pos_args[0].type is Builtin.frozenset_type and not pos_args[0].may_be_none(): 20465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return pos_args[0] 20475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # PyFrozenSet_New(it) is better than a generic Python call to frozenset(it) 20485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 20495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_PyFrozenSet_New", 20505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyFrozenSet_New_func_type, 20515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=pos_args, 20525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 20535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=UtilityCode.load_cached('pyfrozenset_new', 'Builtins.c'), 20545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) py_name="frozenset") 20555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyObject_AsDouble_func_type = PyrexTypes.CFuncType( 20575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_double_type, [ 20585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None), 20595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 20605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = "((double)-1)", 20615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_check = True) 20625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_float(self, node, function, pos_args): 20645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform float() into either a C type cast or a faster C 20655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function call. 20665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 20675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Note: this requires the float() function to be typed as 20685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # returning a C 'double' 20695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) == 0: 20705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.FloatNode( 20715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, value="0.0", constant_result=0.0 20725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to(Builtin.float_type, self.current_env()) 20735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(pos_args) != 1: 20745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('float', node, pos_args, '0 or 1') 20755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 20765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_arg = pos_args[0] 20775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(func_arg, ExprNodes.CoerceToPyTypeNode): 20785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_arg = func_arg.arg 20795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if func_arg.type is PyrexTypes.c_double_type: 20805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return func_arg 20815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type.assignable_from(func_arg.type) or func_arg.type.is_numeric: 20825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.TypecastNode( 20835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, operand=func_arg, type=node.type) 20845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 20855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_PyObject_AsDouble", 20865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyObject_AsDouble_func_type, 20875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = pos_args, 20885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp, 20895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = load_c_utility('pyobject_as_double'), 20905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) py_name = "float") 20915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyNumber_Int_func_type = PyrexTypes.CFuncType( 20935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 20945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("o", PyrexTypes.py_object_type, None) 20955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 20965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 20975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_int(self, node, function, pos_args): 20985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform int() into a faster C function call. 20995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 21005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) == 0: 21015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode(node, value="0", constant_result=0, 21025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.py_object_type) 21035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(pos_args) != 1: 21045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node # int(x, base) 21055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_arg = pos_args[0] 21065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(func_arg, ExprNodes.CoerceToPyTypeNode): 21075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node # handled in visit_CoerceFromPyTypeNode() 21085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if func_arg.type.is_pyobject and node.type.is_pyobject: 21095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 21105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "PyNumber_Int", self.PyNumber_Int_func_type, 21115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=pos_args, is_temp=True) 21125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 21135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_bool(self, node, function, pos_args): 21155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Transform bool(x) into a type coercion to a boolean. 21165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 21175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) == 0: 21185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.BoolNode( 21195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value=False, constant_result=False 21205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to(Builtin.bool_type, self.current_env()) 21215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(pos_args) != 1: 21225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('bool', node, pos_args, '0 or 1') 21235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 21245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 21255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # => !!<bint>(x) to make sure it's exactly 0 or 1 21265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand = pos_args[0].coerce_to_boolean(self.current_env()) 21275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand = ExprNodes.NotNode(node.pos, operand = operand) 21285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand = ExprNodes.NotNode(node.pos, operand = operand) 21295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # coerce back to Python object as that's the result we are expecting 21305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return operand.coerce_to_pyobject(self.current_env()) 21315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### builtin functions 21335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_strlen_func_type = PyrexTypes.CFuncType( 21355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_size_t_type, [ 21365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("bytes", PyrexTypes.c_char_ptr_type, None) 21375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 21385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_Py_UNICODE_strlen_func_type = PyrexTypes.CFuncType( 21405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_size_t_type, [ 21415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("unicode", PyrexTypes.c_py_unicode_ptr_type, None) 21425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 21435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyObject_Size_func_type = PyrexTypes.CFuncType( 21455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ssize_t_type, [ 21465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None) 21475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 21485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value="-1") 21495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _map_to_capi_len_function = { 21515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.unicode_type : "__Pyx_PyUnicode_GET_LENGTH", 21525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.bytes_type : "PyBytes_GET_SIZE", 21535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.list_type : "PyList_GET_SIZE", 21545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.tuple_type : "PyTuple_GET_SIZE", 21555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.dict_type : "PyDict_Size", 21565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.set_type : "PySet_Size", 21575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.frozenset_type : "PySet_Size", 21585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.get 21595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _ext_types_with_pysize = set(["cpython.array.array"]) 21615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 21625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_len(self, node, function, pos_args): 21635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace len(char*) by the equivalent call to strlen(), 21645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) len(Py_UNICODE) by the equivalent Py_UNICODE_strlen() and 21655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) len(known_builtin_type) by an equivalent C-API call. 21665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 21675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 21685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('len', node, pos_args, 1) 21695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 21705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = pos_args[0] 21715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(arg, ExprNodes.CoerceToPyTypeNode): 21725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = arg.arg 21735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.type.is_string: 21745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = ExprNodes.PythonCapiCallNode( 21755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "strlen", self.Pyx_strlen_func_type, 21765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [arg], 21775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp, 21785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached("IncludeStringH", "StringTools.c")) 21795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif arg.type.is_pyunicode_ptr: 21805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = ExprNodes.PythonCapiCallNode( 21815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_Py_UNICODE_strlen", self.Pyx_Py_UNICODE_strlen_func_type, 21825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [arg], 21835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp) 21845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif arg.type.is_pyobject: 21855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cfunc_name = self._map_to_capi_len_function(arg.type) 21865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cfunc_name is None: 21875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg_type = arg.type 21885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ((arg_type.is_extension_type or arg_type.is_builtin_type) 21895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and arg_type.entry.qualified_name in self._ext_types_with_pysize): 21905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cfunc_name = 'Py_SIZE' 21915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 21925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 21935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = arg.as_none_safe_node( 21945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "object of type 'NoneType' has no len()") 21955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = ExprNodes.PythonCapiCallNode( 21965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, cfunc_name, self.PyObject_Size_func_type, 21975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = [arg], 21985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp) 21995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif arg.type.is_unicode_char: 22005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode(node.pos, value='1', constant_result=1, 22015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=node.type) 22025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 22035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 22045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type not in (PyrexTypes.c_size_t_type, PyrexTypes.c_py_ssize_t_type): 22055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = new_node.coerce_to(node.type, self.current_env()) 22065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_node 22075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_Type_func_type = PyrexTypes.CFuncType( 22095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.type_type, [ 22105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("object", PyrexTypes.py_object_type, None) 22115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 22125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_type(self, node, function, pos_args): 22145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace type(o) by a macro call to Py_TYPE(o). 22155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 22165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 22175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 22185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = ExprNodes.PythonCapiCallNode( 22195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "Py_TYPE", self.Pyx_Type_func_type, 22205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = pos_args, 22215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = False) 22225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.CastNode(node, PyrexTypes.py_object_type) 22235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Py_type_check_func_type = PyrexTypes.CFuncType( 22255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_bint_type, [ 22265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("arg", PyrexTypes.py_object_type, None) 22275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 22285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_isinstance(self, node, function, pos_args): 22305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace isinstance() checks against builtin types by the 22315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding C-API call. 22325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 22335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 2: 22345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 22355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg, types = pos_args 22365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temp = None 22375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(types, ExprNodes.TupleNode): 22385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) types = types.args 22395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.is_attribute or not arg.is_simple(): 22405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = temp = UtilNodes.ResultRefNode(arg) 22415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif types.type is Builtin.type_type: 22425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) types = [types] 22435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 22445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 22455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tests = [] 22475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test_nodes = [] 22485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) env = self.current_env() 22495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for test_type_node in types: 22505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) builtin_type = None 22515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if test_type_node.is_name: 22525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if test_type_node.entry: 22535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry = env.lookup(test_type_node.entry.name) 22545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if entry and entry.type and entry.type.is_builtin_type: 22555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) builtin_type = entry.type 22565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if builtin_type is Builtin.type_type: 22575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # all types have type "type", but there's only one 'type' 22585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if entry.name != 'type' or not ( 22595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) entry.scope and entry.scope.is_builtin_scope): 22605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) builtin_type = None 22615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if builtin_type is not None: 22625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_check_function = entry.type.type_check_function(exact=False) 22635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if type_check_function in tests: 22645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 22655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tests.append(type_check_function) 22665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_check_args = [arg] 22675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif test_type_node.type is Builtin.type_type: 22685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_check_function = '__Pyx_TypeCheck' 22695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_check_args = [arg, test_type_node] 22705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 22715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 22725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test_nodes.append( 22735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.PythonCapiCallNode( 22745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test_type_node.pos, type_check_function, self.Py_type_check_func_type, 22755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = type_check_args, 22765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = True, 22775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) )) 22785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def join_with_or(a,b, make_binop_node=ExprNodes.binop_node): 22805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or_node = make_binop_node(node.pos, 'or', a, b) 22815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or_node.type = PyrexTypes.c_bint_type 22825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or_node.is_temp = True 22835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return or_node 22845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test_node = reduce(join_with_or, test_nodes).coerce_to(node.type, env) 22865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if temp is not None: 22875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) test_node = UtilNodes.EvalWithTempExprNode(temp, test_node) 22885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return test_node 22895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 22905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_function_ord(self, node, function, pos_args): 22915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Unpack ord(Py_UNICODE) and ord('X'). 22925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 22935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(pos_args) != 1: 22945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 22955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg = pos_args[0] 22965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(arg, ExprNodes.CoerceToPyTypeNode): 22975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.arg.type.is_unicode_char: 22985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.TypecastNode( 22995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg.pos, operand=arg.arg, type=PyrexTypes.c_int_type 23005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to(node.type, self.current_env()) 23015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(arg, ExprNodes.UnicodeNode): 23025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(arg.value) == 1: 23035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode( 23045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg.pos, type=PyrexTypes.c_int_type, 23055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value=str(ord(arg.value)), 23065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=ord(arg.value) 23075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to(node.type, self.current_env()) 23085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(arg, ExprNodes.StringNode): 23095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if arg.unicode_value and len(arg.unicode_value) == 1 \ 23105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and ord(arg.unicode_value) <= 255: # Py2/3 portability 23115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode( 23125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg.pos, type=PyrexTypes.c_int_type, 23135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value=str(ord(arg.unicode_value)), 23145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=ord(arg.unicode_value) 23155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to(node.type, self.current_env()) 23165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 23175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### special methods 23195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_tp_new_func_type = PyrexTypes.CFuncType( 23215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 23225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("type", PyrexTypes.py_object_type, None), 23235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None), 23245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 23255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_tp_new_kwargs_func_type = PyrexTypes.CFuncType( 23275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 23285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("type", PyrexTypes.py_object_type, None), 23295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("args", Builtin.tuple_type, None), 23305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("kwargs", Builtin.dict_type, None), 23315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 23325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_any_slot__new__(self, node, function, args, 23345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_unbound_method, kwargs=None): 23355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace 'exttype.__new__(exttype, ...)' by a call to exttype->tp_new() 23365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 23375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) obj = function.obj 23385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not is_unbound_method or len(args) < 1: 23395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 23405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_arg = args[0] 23415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not obj.is_name or not type_arg.is_name: 23425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # play safe 23435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 23445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if obj.type != Builtin.type_type or type_arg.type != Builtin.type_type: 23455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # not a known type, play safe 23465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 23475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not type_arg.type_entry or not obj.type_entry: 23485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if obj.name != type_arg.name: 23495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 23505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # otherwise, we know it's a type and we know it's the same 23515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # type for both - that should do 23525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif type_arg.type_entry != obj.type_entry: 23535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # different types - may or may not lead to an error at runtime 23545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 23555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args_tuple = ExprNodes.TupleNode(node.pos, args=args[1:]) 23575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args_tuple = args_tuple.analyse_types( 23585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.current_env(), skip_children=True) 23595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if type_arg.type_entry: 23615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ext_type = type_arg.type_entry.type 23625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (ext_type.is_extension_type and ext_type.typeobj_cname and 23635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ext_type.scope.global_scope() == self.current_env().global_scope()): 23645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # known type in current module 23655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__') 23665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) slot_func_cname = TypeSlots.get_slot_function(ext_type.scope, tp_slot) 23675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if slot_func_cname: 23685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cython_scope = self.context.cython_scope 23695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyTypeObjectPtr = PyrexTypes.CPtrType( 23705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cython_scope.lookup('PyTypeObject').type) 23715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pyx_tp_new_kwargs_func_type = PyrexTypes.CFuncType( 23725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 23735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("type", PyTypeObjectPtr, None), 23745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("args", PyrexTypes.py_object_type, None), 23755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("kwargs", PyrexTypes.py_object_type, None), 23765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 23775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_arg = ExprNodes.CastNode(type_arg, PyTypeObjectPtr) 23795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not kwargs: 23805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kwargs = ExprNodes.NullNode(node.pos, type=PyrexTypes.py_object_type) # hack? 23815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 23825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, slot_func_cname, 23835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pyx_tp_new_kwargs_func_type, 23845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[type_arg, args_tuple, kwargs], 23855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=True) 23865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 23875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # arbitrary variable, needs a None check for safety 23885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_arg = type_arg.as_none_safe_node( 23895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "object.__new__(X): X is not a type object (NoneType)") 23905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 23915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached('tp_new', 'ObjectHandling.c') 23925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if kwargs: 23935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 23945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_tp_new_kwargs", self.Pyx_tp_new_kwargs_func_type, 23955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[type_arg, args_tuple, kwargs], 23965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=utility_code, 23975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp 23985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 23995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 24005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 24015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_tp_new", self.Pyx_tp_new_func_type, 24025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[type_arg, args_tuple], 24035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=utility_code, 24045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp 24055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 24065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### methods of builtin types 24085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyObject_Append_func_type = PyrexTypes.CFuncType( 24105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_returncode_type, [ 24115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), 24125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("item", PyrexTypes.py_object_type, None), 24135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 24145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value="-1") 24155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_object_append(self, node, function, args, is_unbound_method): 24175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Optimistic optimisation as X.append() is almost always 24185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) referring to a list. 24195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 24205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) != 2 or node.result_is_used: 24215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 24225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 24245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_PyObject_Append", self.PyObject_Append_func_type, 24255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=args, 24265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none=False, 24275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 24285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_is_used=False, 24295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=load_c_utility('append') 24305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 24315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyByteArray_Append_func_type = PyrexTypes.CFuncType( 24335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_returncode_type, [ 24345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("bytearray", PyrexTypes.py_object_type, None), 24355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("value", PyrexTypes.c_int_type, None), 24365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 24375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value="-1") 24385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyByteArray_AppendObject_func_type = PyrexTypes.CFuncType( 24405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_returncode_type, [ 24415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("bytearray", PyrexTypes.py_object_type, None), 24425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("value", PyrexTypes.py_object_type, None), 24435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 24445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value="-1") 24455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_bytearray_append(self, node, function, args, is_unbound_method): 24475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) != 2: 24485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 24495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_name = "__Pyx_PyByteArray_Append" 24505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_type = self.PyByteArray_Append_func_type 24515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = unwrap_coerced_node(args[1]) 24535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value.type.is_int or isinstance(value, ExprNodes.IntNode): 24545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.coerce_to(PyrexTypes.c_int_type, self.current_env()) 24555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached("ByteArrayAppend", "StringTools.c") 24565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif value.is_string_literal: 24575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not value.can_coerce_to_char_literal(): 24585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 24595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.coerce_to(PyrexTypes.c_char_type, self.current_env()) 24605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached("ByteArrayAppend", "StringTools.c") 24615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif value.type.is_pyobject: 24625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_name = "__Pyx_PyByteArray_AppendObject" 24635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_type = self.PyByteArray_AppendObject_func_type 24645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached("ByteArrayAppendObject", "StringTools.c") 24655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 24665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 24675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = ExprNodes.PythonCapiCallNode( 24695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, func_name, func_type, 24705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[args[0], value], 24715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none=False, 24725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 24735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=utility_code, 24745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 24755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.result_is_used: 24765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = new_node.coerce_to(node.type, self.current_env()) 24775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_node 24785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyObject_Pop_func_type = PyrexTypes.CFuncType( 24805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 24815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), 24825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 24835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyObject_PopIndex_func_type = PyrexTypes.CFuncType( 24855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 24865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("list", PyrexTypes.py_object_type, None), 24875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("index", PyrexTypes.c_long_type, None), 24885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 24895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_list_pop(self, node, function, args, is_unbound_method): 24915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._handle_simple_method_object_pop( 24925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, is_list=True) 24935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 24945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_object_pop(self, node, function, args, is_unbound_method, is_list=False): 24955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Optimistic optimisation as X.pop([n]) is almost always 24965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) referring to a list. 24975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 24985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not args: 24995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 25005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = args[:] 25015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_list: 25025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_name = 'List' 25035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args[0] = args[0].as_none_safe_node( 25045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "'NoneType' object has no attribute '%s'", 25055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error="PyExc_AttributeError", 25065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) format_args=['pop']) 25075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 25085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_name = 'Object' 25095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 1: 25105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 25115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_Py%s_Pop" % type_name, 25125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyObject_Pop_func_type, 25135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=args, 25145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none=True, 25155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 25165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=load_c_utility('pop'), 25175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 25185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(args) == 2: 25195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index = unwrap_coerced_node(args[1]) 25205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_list or isinstance(index, ExprNodes.IntNode): 25215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index = index.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) 25225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if index.type.is_int: 25235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) widest = PyrexTypes.widest_numeric_type( 25245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index.type, PyrexTypes.c_py_ssize_t_type) 25255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if widest == PyrexTypes.c_py_ssize_t_type: 25265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args[1] = index 25275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 25285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, "__Pyx_Py%s_PopIndex" % type_name, 25295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyObject_PopIndex_func_type, 25305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=args, 25315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none=True, 25325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 25335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=load_c_utility("pop_index"), 25345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 25355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 25375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) single_param_func_type = PyrexTypes.CFuncType( 25395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_returncode_type, [ 25405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("obj", PyrexTypes.py_object_type, None), 25415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 25425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = "-1") 25435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_list_sort(self, node, function, args, is_unbound_method): 25455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Call PyList_Sort() instead of the 0-argument l.sort(). 25465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 25475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) != 1: 25485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 25495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 25505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, "PyList_Sort", self.single_param_func_type, 25515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'sort', is_unbound_method, args).coerce_to(node.type, self.current_env) 25525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_PyDict_GetItem_func_type = PyrexTypes.CFuncType( 25545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 25555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("dict", PyrexTypes.py_object_type, None), 25565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("key", PyrexTypes.py_object_type, None), 25575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("default", PyrexTypes.py_object_type, None), 25585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 25595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_dict_get(self, node, function, args, is_unbound_method): 25615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace dict.get() by a call to PyDict_GetItem(). 25625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 25635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 2: 25645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.NoneNode(node.pos)) 25655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(args) != 3: 25665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('dict.get', node, args, "2 or 3") 25675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 25685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 25705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 25715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "__Pyx_PyDict_GetItemDefault", self.Pyx_PyDict_GetItem_func_type, 25725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'get', is_unbound_method, args, 25735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none = True, 25745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = load_c_utility("dict_getitem_default")) 25755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Pyx_PyDict_SetDefault_func_type = PyrexTypes.CFuncType( 25775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.py_object_type, [ 25785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("dict", PyrexTypes.py_object_type, None), 25795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("key", PyrexTypes.py_object_type, None), 25805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("default", PyrexTypes.py_object_type, None), 25815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("is_safe_type", PyrexTypes.c_int_type, None), 25825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 25835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 25845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_dict_setdefault(self, node, function, args, is_unbound_method): 25855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace dict.setdefault() by calls to PyDict_GetItem() and PyDict_SetItem(). 25865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 25875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 2: 25885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.NoneNode(node.pos)) 25895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif len(args) != 3: 25905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('dict.setdefault', node, args, "2 or 3") 25915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 25925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) key_type = args[1].type 25935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if key_type.is_builtin_type: 25945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_safe_type = int(key_type.name in 25955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'str bytes unicode float int long bool') 25965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif key_type is PyrexTypes.py_object_type: 25975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_safe_type = -1 # don't know 25985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 25995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_safe_type = 0 # definitely not 26005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.IntNode( 26015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value=str(is_safe_type), constant_result=is_safe_type)) 26025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 26045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 26055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "__Pyx_PyDict_SetDefault", self.Pyx_PyDict_SetDefault_func_type, 26065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'setdefault', is_unbound_method, args, 26075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none=True, 26085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=load_c_utility('dict_setdefault')) 26095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### unicode type methods 26125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_uchar_predicate_func_type = PyrexTypes.CFuncType( 26145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_bint_type, [ 26155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None), 26165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 26175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_unicode_predicate(self, node, function, args, is_unbound_method): 26195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_unbound_method or len(args) != 1: 26205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 26215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ustring = args[0] 26225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(ustring, ExprNodes.CoerceToPyTypeNode) or \ 26235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not ustring.arg.type.is_unicode_char: 26245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 26255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uchar = ustring.arg 26265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name = function.attribute 26275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if method_name == 'istitle': 26285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # istitle() doesn't directly map to Py_UNICODE_ISTITLE() 26295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = UtilityCode.load_cached( 26305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "py_unicode_istitle", "StringTools.c") 26315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name = '__Pyx_Py_UNICODE_ISTITLE' 26325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 26335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = None 26345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name = 'Py_UNICODE_%s' % method_name.upper() 26355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_call = self._substitute_method_call( 26365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 26375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name, self.PyUnicode_uchar_predicate_func_type, 26385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name, is_unbound_method, [uchar], 26395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = utility_code) 26405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type.is_pyobject: 26415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_call = func_call.coerce_to_pyobject(self.current_env) 26425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return func_call 26435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isalnum = _inject_unicode_predicate 26455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isalpha = _inject_unicode_predicate 26465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isdecimal = _inject_unicode_predicate 26475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isdigit = _inject_unicode_predicate 26485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_islower = _inject_unicode_predicate 26495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isnumeric = _inject_unicode_predicate 26505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isspace = _inject_unicode_predicate 26515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_istitle = _inject_unicode_predicate 26525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_isupper = _inject_unicode_predicate 26535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_uchar_conversion_func_type = PyrexTypes.CFuncType( 26555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ucs4_type, [ 26565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("uchar", PyrexTypes.c_py_ucs4_type, None), 26575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 26585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_unicode_character_conversion(self, node, function, args, is_unbound_method): 26605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_unbound_method or len(args) != 1: 26615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 26625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ustring = args[0] 26635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(ustring, ExprNodes.CoerceToPyTypeNode) or \ 26645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not ustring.arg.type.is_unicode_char: 26655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 26665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) uchar = ustring.arg 26675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name = function.attribute 26685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name = 'Py_UNICODE_TO%s' % method_name.upper() 26695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_call = self._substitute_method_call( 26705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 26715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) function_name, self.PyUnicode_uchar_conversion_func_type, 26725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name, is_unbound_method, [uchar]) 26735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type.is_pyobject: 26745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_call = func_call.coerce_to_pyobject(self.current_env) 26755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return func_call 26765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_lower = _inject_unicode_character_conversion 26785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_upper = _inject_unicode_character_conversion 26795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_unicode_title = _inject_unicode_character_conversion 26805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_Splitlines_func_type = PyrexTypes.CFuncType( 26825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.list_type, [ 26835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None), 26845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("keepends", PyrexTypes.c_bint_type, None), 26855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 26865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_splitlines(self, node, function, args, is_unbound_method): 26885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.splitlines(...) by a direct call to the 26895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding C-API function. 26905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 26915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) not in (1,2): 26925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('unicode.splitlines', node, args, "1 or 2") 26935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 26945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_bint_default_argument(node, args, 1, False) 26955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 26965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 26975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 26985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "PyUnicode_Splitlines", self.PyUnicode_Splitlines_func_type, 26995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'splitlines', is_unbound_method, args) 27005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_Split_func_type = PyrexTypes.CFuncType( 27025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.list_type, [ 27035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None), 27045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("sep", PyrexTypes.py_object_type, None), 27055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("maxsplit", PyrexTypes.c_py_ssize_t_type, None), 27065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ] 27075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 27085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_split(self, node, function, args, is_unbound_method): 27105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.split(...) by a direct call to the 27115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding C-API function. 27125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 27135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) not in (1,2,3): 27145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('unicode.split', node, args, "1-3") 27155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 27165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) < 2: 27175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.NullNode(node.pos)) 27185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 27195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 2, PyrexTypes.c_py_ssize_t_type, "-1") 27205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 27225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 27235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "PyUnicode_Split", self.PyUnicode_Split_func_type, 27245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'split', is_unbound_method, args) 27255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyString_Tailmatch_func_type = PyrexTypes.CFuncType( 27275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_bint_type, [ 27285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("str", PyrexTypes.py_object_type, None), # bytes/str/unicode 27295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None), 27305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None), 27315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("end", PyrexTypes.c_py_ssize_t_type, None), 27325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("direction", PyrexTypes.c_int_type, None), 27335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 27345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = '-1') 27355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_endswith(self, node, function, args, is_unbound_method): 27375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 27385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'unicode', 'endswith', 27395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unicode_tailmatch_utility_code, +1) 27405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_startswith(self, node, function, args, is_unbound_method): 27425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 27435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'unicode', 'startswith', 27445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unicode_tailmatch_utility_code, -1) 27455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_tailmatch(self, node, function, args, is_unbound_method, type_name, 27475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name, utility_code, direction): 27485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.startswith(...) and unicode.endswith(...) 27495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) by a direct call to the corresponding C-API function. 27505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 27515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) not in (2,3,4): 27525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('%s.%s' % (type_name, method_name), node, args, "2-4") 27535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 27545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 27555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 2, PyrexTypes.c_py_ssize_t_type, "0") 27565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 27575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 3, PyrexTypes.c_py_ssize_t_type, "PY_SSIZE_T_MAX") 27585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.IntNode( 27595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value=str(direction), type=PyrexTypes.c_int_type)) 27605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_call = self._substitute_method_call( 27625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, 27635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "__Pyx_Py%s_Tailmatch" % type_name.capitalize(), 27645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyString_Tailmatch_func_type, 27655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name, is_unbound_method, args, 27665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = utility_code) 27675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return method_call.coerce_to(Builtin.bool_type, self.current_env()) 27685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_Find_func_type = PyrexTypes.CFuncType( 27705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ssize_t_type, [ 27715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None), 27725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None), 27735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None), 27745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("end", PyrexTypes.c_py_ssize_t_type, None), 27755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("direction", PyrexTypes.c_int_type, None), 27765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 27775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = '-2') 27785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_find(self, node, function, args, is_unbound_method): 27805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_unicode_find( 27815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'find', +1) 27825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_rfind(self, node, function, args, is_unbound_method): 27845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_unicode_find( 27855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'rfind', -1) 27865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 27875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_unicode_find(self, node, function, args, is_unbound_method, 27885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name, direction): 27895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.find(...) and unicode.rfind(...) by a 27905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) direct call to the corresponding C-API function. 27915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 27925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) not in (2,3,4): 27935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('unicode.%s' % method_name, node, args, "2-4") 27945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 27955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 27965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 2, PyrexTypes.c_py_ssize_t_type, "0") 27975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 27985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 3, PyrexTypes.c_py_ssize_t_type, "PY_SSIZE_T_MAX") 27995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.IntNode( 28005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value=str(direction), type=PyrexTypes.c_int_type)) 28015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_call = self._substitute_method_call( 28035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, "PyUnicode_Find", self.PyUnicode_Find_func_type, 28045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_name, is_unbound_method, args) 28055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return method_call.coerce_to_pyobject(self.current_env()) 28065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_Count_func_type = PyrexTypes.CFuncType( 28085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.c_py_ssize_t_type, [ 28095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None), 28105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None), 28115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None), 28125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("end", PyrexTypes.c_py_ssize_t_type, None), 28135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ], 28145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exception_value = '-1') 28155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_count(self, node, function, args, is_unbound_method): 28175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.count(...) by a direct call to the 28185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding C-API function. 28195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 28205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) not in (2,3,4): 28215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('unicode.count', node, args, "2-4") 28225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 28235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 28245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 2, PyrexTypes.c_py_ssize_t_type, "0") 28255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 28265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 3, PyrexTypes.c_py_ssize_t_type, "PY_SSIZE_T_MAX") 28275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) method_call = self._substitute_method_call( 28295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, "PyUnicode_Count", self.PyUnicode_Count_func_type, 28305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'count', is_unbound_method, args) 28315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return method_call.coerce_to_pyobject(self.current_env()) 28325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_Replace_func_type = PyrexTypes.CFuncType( 28345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.unicode_type, [ 28355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("str", Builtin.unicode_type, None), 28365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("substring", PyrexTypes.py_object_type, None), 28375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("replstr", PyrexTypes.py_object_type, None), 28385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("maxcount", PyrexTypes.c_py_ssize_t_type, None), 28395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 28405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_replace(self, node, function, args, is_unbound_method): 28425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.replace(...) by a direct call to the 28435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding C-API function. 28445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 28455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) not in (3,4): 28465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('unicode.replace', node, args, "3-4") 28475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 28485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._inject_int_default_argument( 28495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, args, 3, PyrexTypes.c_py_ssize_t_type, "-1") 28505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 28525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, "PyUnicode_Replace", self.PyUnicode_Replace_func_type, 28535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'replace', is_unbound_method, args) 28545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_AsEncodedString_func_type = PyrexTypes.CFuncType( 28565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.bytes_type, [ 28575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("obj", Builtin.unicode_type, None), 28585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("encoding", PyrexTypes.c_char_ptr_type, None), 28595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None), 28605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 28615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_AsXyzString_func_type = PyrexTypes.CFuncType( 28635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.bytes_type, [ 28645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("obj", Builtin.unicode_type, None), 28655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 28665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _special_encodings = ['UTF8', 'UTF16', 'Latin1', 'ASCII', 28685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'unicode_escape', 'raw_unicode_escape'] 28695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _special_codecs = [ (name, codecs.getencoder(name)) 28715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name in _special_encodings ] 28725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_unicode_encode(self, node, function, args, is_unbound_method): 28745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace unicode.encode(...) by a direct C-API call to the 28755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding codec. 28765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 28775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) < 1 or len(args) > 3: 28785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('unicode.encode', node, args, '1-3') 28795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 28805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = args[0] 28825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 1: 28845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) null_node = ExprNodes.NullNode(node.pos) 28855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 28865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, "PyUnicode_AsEncodedString", 28875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyUnicode_AsEncodedString_func_type, 28885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'encode', is_unbound_method, [string_node, null_node, null_node]) 28895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parameters = self._unpack_encoding_and_error_mode(node.pos, args) 28915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if parameters is None: 28925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 28935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding, encoding_node, error_handling, error_handling_node = parameters 28945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 28955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if encoding and isinstance(string_node, ExprNodes.UnicodeNode): 28965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # constant, so try to do the encoding at compile time 28975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 28985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = string_node.value.encode(encoding, error_handling) 28995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except: 29005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # well, looks like we can't 29015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 29025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 29035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = BytesLiteral(value) 29045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value.encoding = encoding 29055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.BytesNode( 29065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node.pos, value=value, type=Builtin.bytes_type) 29075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if encoding and error_handling == 'strict': 29095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # try to find a specific encoder function 29105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec_name = self._find_special_codec_name(encoding) 29115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if codec_name is not None: 29125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encode_function = "PyUnicode_As%sString" % codec_name 29135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 29145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, encode_function, 29155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyUnicode_AsXyzString_func_type, 29165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'encode', is_unbound_method, [string_node]) 29175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._substitute_method_call( 29195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, "PyUnicode_AsEncodedString", 29205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.PyUnicode_AsEncodedString_func_type, 29215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'encode', is_unbound_method, 29225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [string_node, encoding_node, error_handling_node]) 29235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyUnicode_DecodeXyz_func_ptr_type = PyrexTypes.CPtrType(PyrexTypes.CFuncType( 29255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.unicode_type, [ 29265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("string", PyrexTypes.c_char_ptr_type, None), 29275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("size", PyrexTypes.c_py_ssize_t_type, None), 29285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None), 29295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ])) 29305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _decode_c_string_func_type = PyrexTypes.CFuncType( 29325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.unicode_type, [ 29335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("string", PyrexTypes.c_char_ptr_type, None), 29345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None), 29355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("stop", PyrexTypes.c_py_ssize_t_type, None), 29365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("encoding", PyrexTypes.c_char_ptr_type, None), 29375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None), 29385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("decode_func", PyUnicode_DecodeXyz_func_ptr_type, None), 29395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 29405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _decode_bytes_func_type = PyrexTypes.CFuncType( 29425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.unicode_type, [ 29435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("string", PyrexTypes.py_object_type, None), 29445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None), 29455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("stop", PyrexTypes.c_py_ssize_t_type, None), 29465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("encoding", PyrexTypes.c_char_ptr_type, None), 29475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None), 29485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("decode_func", PyUnicode_DecodeXyz_func_ptr_type, None), 29495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 29505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _decode_cpp_string_func_type = None # lazy init 29525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_bytes_decode(self, node, function, args, is_unbound_method): 29545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace char*.decode() by a direct C-API call to the 29555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) corresponding codec, possibly resolving a slice on the char*. 29565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 29575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not (1 <= len(args) <= 3): 29585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._error_wrong_arg_count('bytes.decode', node, args, '1-3') 29595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 29605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # normalise input nodes 29625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = args[0] 29635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = stop = None 29645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(string_node, ExprNodes.SliceIndexNode): 29655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) index_node = string_node 29665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = index_node.base 29675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start, stop = index_node.start, index_node.stop 29685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not start or start.constant_result == 0: 29695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = None 29705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(string_node, ExprNodes.CoerceToPyTypeNode): 29715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = string_node.arg 29725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_type = string_node.type 29745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if string_type in (Builtin.bytes_type, Builtin.bytearray_type): 29755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_unbound_method: 29765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = string_node.as_none_safe_node( 29775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "descriptor '%s' requires a '%s' object but received a 'NoneType'", 29785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) format_args=['decode', string_type.name]) 29795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 29805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = string_node.as_none_safe_node( 29815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "'NoneType' object has no attribute '%s'", 29825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error="PyExc_AttributeError", 29835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) format_args=['decode']) 29845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not string_type.is_string and not string_type.is_cpp_string: 29855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # nothing to optimise here 29865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 29875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parameters = self._unpack_encoding_and_error_mode(node.pos, args) 29895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if parameters is None: 29905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 29915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding, encoding_node, error_handling, error_handling_node = parameters 29925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 29935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not start: 29945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = ExprNodes.IntNode(node.pos, value='0', constant_result=0) 29955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not start.type.is_int: 29965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = start.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) 29975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if stop and not stop.type.is_int: 29985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = stop.coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) 29995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # try to find a specific encoder function 30015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec_name = None 30025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if encoding is not None: 30035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) codec_name = self._find_special_codec_name(encoding) 30045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if codec_name is not None: 30055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) decode_function = ExprNodes.RawCNameExprNode( 30065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, type=self.PyUnicode_DecodeXyz_func_ptr_type, 30075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cname="PyUnicode_Decode%s" % codec_name) 30085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding_node = ExprNodes.NullNode(node.pos) 30095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 30105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) decode_function = ExprNodes.NullNode(node.pos) 30115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # build the helper function call 30135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps = [] 30145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if string_type.is_string: 30155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # C string 30165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not stop: 30175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # use strlen() to find the string length, just as CPython would 30185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not string_node.is_name: 30195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node = UtilNodes.LetRefNode(string_node) # used twice 30205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) temps.append(string_node) 30215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = ExprNodes.PythonCapiCallNode( 30225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) string_node.pos, "strlen", self.Pyx_strlen_func_type, 30235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[string_node], 30245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=False, 30255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=UtilityCode.load_cached("IncludeStringH", "StringTools.c"), 30265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ).coerce_to(PyrexTypes.c_py_ssize_t_type, self.current_env()) 30275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) helper_func_type = self._decode_c_string_func_type 30285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code_name = 'decode_c_string' 30295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif string_type.is_cpp_string: 30305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # C++ std::string 30315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not stop: 30325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = ExprNodes.IntNode(node.pos, value='PY_SSIZE_T_MAX', 30335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=ExprNodes.not_a_constant) 30345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._decode_cpp_string_func_type is None: 30355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # lazy init to reuse the C++ string type 30365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._decode_cpp_string_func_type = PyrexTypes.CFuncType( 30375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Builtin.unicode_type, [ 30385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("string", string_type, None), 30395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("start", PyrexTypes.c_py_ssize_t_type, None), 30405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("stop", PyrexTypes.c_py_ssize_t_type, None), 30415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("encoding", PyrexTypes.c_char_ptr_type, None), 30425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("errors", PyrexTypes.c_char_ptr_type, None), 30435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyrexTypes.CFuncTypeArg("decode_func", self.PyUnicode_DecodeXyz_func_ptr_type, None), 30445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ]) 30455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) helper_func_type = self._decode_cpp_string_func_type 30465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code_name = 'decode_cpp_string' 30475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 30485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # Python bytes/bytearray object 30495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not stop: 30505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = ExprNodes.IntNode(node.pos, value='PY_SSIZE_T_MAX', 30515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=ExprNodes.not_a_constant) 30525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) helper_func_type = self._decode_bytes_func_type 30535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if string_type is Builtin.bytes_type: 30545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code_name = 'decode_bytes' 30555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 30565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code_name = 'decode_bytearray' 30575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = ExprNodes.PythonCapiCallNode( 30595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, '__Pyx_%s' % utility_code_name, helper_func_type, 30605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args=[string_node, start, stop, encoding_node, error_handling_node, decode_function], 30615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp=node.is_temp, 30625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=UtilityCode.load_cached(utility_code_name, 'StringTools.c'), 30635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 30645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for temp in temps[::-1]: 30665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = UtilNodes.EvalWithTempExprNode(temp, node) 30675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 30685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _handle_simple_method_bytearray_decode = _handle_simple_method_bytes_decode 30705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _find_special_codec_name(self, encoding): 30725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 30735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) requested_codec = codecs.getencoder(encoding) 30745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except LookupError: 30755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 30765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, codec in self._special_codecs: 30775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if codec == requested_codec: 30785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '_' in name: 30795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = ''.join([s.capitalize() 30805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for s in name.split('_')]) 30815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return name 30825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 30835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _unpack_encoding_and_error_mode(self, pos, args): 30855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) null_node = ExprNodes.NullNode(pos) 30865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) >= 2: 30885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding, encoding_node = self._unpack_string_and_cstring_node(args[1]) 30895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if encoding_node is None: 30905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 30915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 30925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = None 30935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding_node = null_node 30945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 30955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == 3: 30965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_handling, error_handling_node = self._unpack_string_and_cstring_node(args[2]) 30975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if error_handling_node is None: 30985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 30995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if error_handling == 'strict': 31005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_handling_node = null_node 31015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 31025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_handling = 'strict' 31035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error_handling_node = null_node 31045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (encoding, encoding_node, error_handling, error_handling_node) 31065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _unpack_string_and_cstring_node(self, node): 31085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node, ExprNodes.CoerceToPyTypeNode): 31095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = node.arg 31105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node, ExprNodes.UnicodeNode): 31115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = node.value 31125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = ExprNodes.BytesNode( 31135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value=BytesLiteral(encoding.utf8encode()), 31145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_char_ptr_type) 31155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(node, (ExprNodes.StringNode, ExprNodes.BytesNode)): 31165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = node.value.decode('ISO-8859-1') 31175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = ExprNodes.BytesNode( 31185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, value=node.value, type=PyrexTypes.c_char_ptr_type) 31195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type is Builtin.bytes_type: 31205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = None 31215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = node.coerce_to(PyrexTypes.c_char_ptr_type, self.current_env()) 31225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type.is_string: 31235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = None 31245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 31255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) encoding = node = None 31265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return encoding, node 31275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_str_endswith(self, node, function, args, is_unbound_method): 31295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 31305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'str', 'endswith', 31315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) str_tailmatch_utility_code, +1) 31325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_str_startswith(self, node, function, args, is_unbound_method): 31345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 31355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'str', 'startswith', 31365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) str_tailmatch_utility_code, -1) 31375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_bytes_endswith(self, node, function, args, is_unbound_method): 31395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 31405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'bytes', 'endswith', 31415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_tailmatch_utility_code, +1) 31425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_bytes_startswith(self, node, function, args, is_unbound_method): 31445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 31455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'bytes', 'startswith', 31465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_tailmatch_utility_code, -1) 31475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ''' # disabled for now, enable when we consider it worth it (see StringTools.c) 31495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_bytearray_endswith(self, node, function, args, is_unbound_method): 31505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 31515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'bytearray', 'endswith', 31525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_tailmatch_utility_code, +1) 31535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_simple_method_bytearray_startswith(self, node, function, args, is_unbound_method): 31555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._inject_tailmatch( 31565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node, function, args, is_unbound_method, 'bytearray', 'startswith', 31575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bytes_tailmatch_utility_code, -1) 31585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ''' 31595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ### helpers 31615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _substitute_method_call(self, node, function, name, func_type, 31635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) attr_name, is_unbound_method, args=(), 31645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code=None, is_temp=None, 31655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none=ExprNodes.PythonCapiCallNode.may_return_none): 31665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = list(args) 31675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if args and not args[0].is_literal: 31685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self_arg = args[0] 31695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_unbound_method: 31705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self_arg = self_arg.as_none_safe_node( 31715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "descriptor '%s' requires a '%s' object but received a 'NoneType'", 31725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) format_args=[attr_name, function.obj.name]) 31735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 31745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self_arg = self_arg.as_none_safe_node( 31755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "'NoneType' object has no attribute '%s'", 31765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) error = "PyExc_AttributeError", 31775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) format_args = [attr_name]) 31785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args[0] = self_arg 31795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_temp is None: 31805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = node.is_temp 31815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.PythonCapiCallNode( 31825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, name, func_type, 31835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = args, 31845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) is_temp = is_temp, 31855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) utility_code = utility_code, 31865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) may_return_none = may_return_none, 31875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result_is_used = node.result_is_used, 31885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ) 31895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_int_default_argument(self, node, args, arg_index, type, default_value): 31915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert len(args) >= arg_index 31925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == arg_index: 31935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.IntNode(node.pos, value=str(default_value), 31945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=type, constant_result=default_value)) 31955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 31965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args[arg_index] = args[arg_index].coerce_to(type, self.current_env()) 31975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 31985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _inject_bint_default_argument(self, node, args, arg_index, default_value): 31995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert len(args) >= arg_index 32005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) == arg_index: 32015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_value = bool(default_value) 32025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args.append(ExprNodes.BoolNode(node.pos, value=default_value, 32035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=default_value)) 32045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 32055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args[arg_index] = args[arg_index].coerce_to_boolean(self.current_env()) 32065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)unicode_tailmatch_utility_code = UtilityCode.load_cached('unicode_tailmatch', 'StringTools.c') 32095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bytes_tailmatch_utility_code = UtilityCode.load_cached('bytes_tailmatch', 'StringTools.c') 32105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)str_tailmatch_utility_code = UtilityCode.load_cached('str_tailmatch', 'StringTools.c') 32115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ConstantFolding(Visitor.VisitorTransform, SkipDeclarations): 32145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Calculate the result of constant expressions to store it in 32155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ``expr_node.constant_result``, and replace trivial cases by their 32165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant result. 32175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) General rules: 32195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - We calculate float constants to make them available to the 32215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) compiler, but we do not aggregate them into a single literal 32225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node to prevent any loss of precision. 32235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - We recursively calculate constants from non-literal nodes to 32255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) make them available to the compiler, but we only aggregate 32265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) literal nodes at each step. Non-literal nodes are never merged 32275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) into a single node. 32285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 32295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, reevaluate=False): 32315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 32325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) The reevaluate argument specifies whether constant values that were 32335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) previously computed should be recomputed. 32345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 32355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) super(ConstantFolding, self).__init__() 32365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.reevaluate = reevaluate 32375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _calculate_const(self, node): 32395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (not self.reevaluate and 32405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.constant_result is not ExprNodes.constant_value_not_set): 32415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 32425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # make sure we always set the value 32445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) not_a_constant = ExprNodes.not_a_constant 32455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.constant_result = not_a_constant 32465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # check if all children are constant 32485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) children = self.visitchildren(node) 32495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for child_result in children.values(): 32505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if type(child_result) is list: 32515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for child in child_result: 32525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if getattr(child, 'constant_result', not_a_constant) is not_a_constant: 32535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 32545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif getattr(child_result, 'constant_result', not_a_constant) is not_a_constant: 32555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 32565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # now try to calculate the real constant value 32585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 32595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.calculate_constant_result() 32605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# if node.constant_result is not ExprNodes.not_a_constant: 32615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)# print node.__class__.__name__, node.constant_result 32625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except (ValueError, TypeError, KeyError, IndexError, AttributeError, ArithmeticError): 32635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # ignore all 'normal' errors here => no constant result 32645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 32655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except Exception: 32665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # this looks like a real error 32675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) import traceback, sys 32685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) traceback.print_exc(file=sys.stdout) 32695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NODE_TYPE_ORDER = [ExprNodes.BoolNode, ExprNodes.CharNode, 32715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ExprNodes.IntNode, ExprNodes.FloatNode] 32725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _widest_node_class(self, *nodes): 32745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 32755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.NODE_TYPE_ORDER[ 32765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) max(map(self.NODE_TYPE_ORDER.index, map(type, nodes)))] 32775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except ValueError: 32785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 32795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _bool_node(self, node, value): 32815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = bool(value) 32825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.BoolNode(node.pos, value=value, constant_result=value) 32835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ExprNode(self, node): 32855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 32865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 32875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 32885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_UnopNode(self, node): 32895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 32905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.has_constant_result(): 32915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operator == '!': 32925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._handle_NotNode(node) 32935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 32945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.operand.is_literal: 32955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 32965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operator == '!': 32975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._bool_node(node, node.constant_result) 32985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif isinstance(node.operand, ExprNodes.BoolNode): 32995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode(node.pos, value=str(int(node.constant_result)), 33005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=PyrexTypes.c_int_type, 33015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=int(node.constant_result)) 33025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.operator == '+': 33035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._handle_UnaryPlusNode(node) 33045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.operator == '-': 33055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._handle_UnaryMinusNode(node) 33065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) _negate_operator = { 33095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'in': 'not_in', 33105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'not_in': 'in', 33115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'is': 'is_not', 33125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'is_not': 'is' 33135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }.get 33145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_NotNode(self, node): 33165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand = node.operand 33175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(operand, ExprNodes.PrimaryCmpNode): 33185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator = self._negate_operator(operand.operator) 33195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if operator: 33205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = copy.copy(operand) 33215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.operator = operator 33225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = self.visit_PrimaryCmpNode(node) 33235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_UnaryMinusNode(self, node): 33265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _negate(value): 33275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value.startswith('-'): 33285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value[1:] 33295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 33305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = '-' + value 33315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return value 33325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node_type = node.operand.type 33345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.operand, ExprNodes.FloatNode): 33355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # this is a safe operation 33365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.FloatNode(node.pos, value=_negate(node.operand.value), 33375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=node_type, 33385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=node.constant_result) 33395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node_type.is_int and node_type.signed or \ 33405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) isinstance(node.operand, ExprNodes.IntNode) and node_type.is_pyobject: 33415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.IntNode(node.pos, value=_negate(node.operand.value), 33425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type=node_type, 33435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) longness=node.operand.longness, 33445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=node.constant_result) 33455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _handle_UnaryPlusNode(self, node): 33485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (node.operand.has_constant_result() and 33495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.constant_result == node.operand.constant_result): 33505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.operand 33515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_BoolBinopNode(self, node): 33545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 33555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.operand1.has_constant_result(): 33565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operand1.constant_result: 33585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operator == 'and': 33595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.operand2 33605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 33615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.operand1 33625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 33635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operator == 'and': 33645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.operand1 33655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 33665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.operand2 33675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_BinopNode(self, node): 33695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 33705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.constant_result is ExprNodes.not_a_constant: 33715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.constant_result, float): 33735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1, operand2 = node.operand1, node.operand2 33755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not operand1.is_literal or not operand2.is_literal: 33765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # now inject a new constant node with the calculated value 33795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 33805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type1, type2 = operand1.type, operand2.type 33815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if type1 is None or type2 is None: 33825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except AttributeError: 33845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if type1.is_numeric and type2.is_numeric: 33875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) widest_type = PyrexTypes.widest_numeric_type(type1, type2) 33885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 33895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) widest_type = PyrexTypes.py_object_type 33905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 33915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_class = self._widest_node_class(operand1, operand2) 33925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if target_class is None: 33935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 33945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif target_class is ExprNodes.BoolNode and node.operator in '+-//<<%**>>': 33955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # C arithmetic results in at least an int type 33965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_class = ExprNodes.IntNode 33975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif target_class is ExprNodes.CharNode and node.operator in '+-//<<%**>>&|^': 33985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # C arithmetic results in at least an int type 33995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) target_class = ExprNodes.IntNode 34005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if target_class is ExprNodes.IntNode: 34025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned = getattr(operand1, 'unsigned', '') and \ 34035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) getattr(operand2, 'unsigned', '') 34045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) longness = "LL"[:max(len(getattr(operand1, 'longness', '')), 34055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) len(getattr(operand2, 'longness', '')))] 34065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = ExprNodes.IntNode(pos=node.pos, 34075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned=unsigned, longness=longness, 34085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value=str(int(node.constant_result)), 34095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=int(node.constant_result)) 34105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # IntNode is smart about the type it chooses, so we just 34115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # make sure we were not smarter this time 34125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if widest_type.is_pyobject or new_node.type.is_pyobject: 34135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node.type = PyrexTypes.py_object_type 34145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node.type = PyrexTypes.widest_numeric_type(widest_type, new_node.type) 34165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if target_class is ExprNodes.BoolNode: 34185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node_value = node.constant_result 34195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node_value = str(node.constant_result) 34215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new_node = target_class(pos=node.pos, type = widest_type, 34225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = node_value, 34235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result = node.constant_result) 34245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return new_node 34255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_MulNode(self, node): 34275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 34285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.operand1.is_sequence_constructor: 34295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._calculate_constant_seq(node, node.operand1, node.operand2) 34305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.operand1, ExprNodes.IntNode) and \ 34315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.operand2.is_sequence_constructor: 34325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._calculate_constant_seq(node, node.operand2, node.operand1) 34335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.visit_BinopNode(node) 34345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _calculate_constant_seq(self, node, sequence_node, factor): 34365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if factor.constant_result != 1 and sequence_node.args: 34375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(factor.constant_result, (int, long)) and factor.constant_result <= 0: 34385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) del sequence_node.args[:] 34395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sequence_node.mult_factor = None 34405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif sequence_node.mult_factor is not None: 34415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (isinstance(factor.constant_result, (int, long)) and 34425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) isinstance(sequence_node.mult_factor.constant_result, (int, long))): 34435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = sequence_node.mult_factor.constant_result * factor.constant_result 34445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sequence_node.mult_factor = ExprNodes.IntNode( 34455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sequence_node.mult_factor.pos, 34465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value=str(value), constant_result=value) 34475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # don't know if we can combine the factors, so don't 34495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.visit_BinopNode(node) 34505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sequence_node.mult_factor = factor 34525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return sequence_node 34535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_PrimaryCmpNode(self, node): 34555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # calculate constant partial results in the comparison cascade 34565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node, ['operand1']) 34575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) left_node = node.operand1 34585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node = node 34595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while cmp_node is not None: 34605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(cmp_node, ['operand2']) 34615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) right_node = cmp_node.operand2 34625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node.constant_result = not_a_constant 34635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if left_node.has_constant_result() and right_node.has_constant_result(): 34645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 34655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node.calculate_cascaded_constant_result(left_node.constant_result) 34665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except (ValueError, TypeError, KeyError, IndexError, AttributeError, ArithmeticError): 34675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass # ignore all 'normal' errors here => no constant result 34685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) left_node = right_node 34695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node = cmp_node.cascade 34705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.cascade: 34725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.has_constant_result(): 34735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._bool_node(node, node.constant_result) 34745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 34755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # collect partial cascades: [[value, CmpNode...], [value, CmpNode, ...], ...] 34775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cascades = [[node.operand1]] 34785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) final_false_result = [] 34795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def split_cascades(cmp_node): 34815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cmp_node.has_constant_result(): 34825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not cmp_node.constant_result: 34835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # False => short-circuit 34845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) final_false_result.append(self._bool_node(cmp_node, False)) 34855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 34865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # True => discard and start new cascade 34885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cascades.append([cmp_node.operand2]) 34895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 34905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # not constant => append to current cascade 34915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cascades[-1].append(cmp_node) 34925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if cmp_node.cascade: 34935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) split_cascades(cmp_node.cascade) 34945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) split_cascades(node) 34965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 34975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_nodes = [] 34985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for cascade in cascades: 34995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(cascade) < 2: 35005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 35015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node = cascade[1] 35025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pcmp_node = ExprNodes.PrimaryCmpNode( 35035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_node.pos, 35045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1=cascade[0], 35055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator=cmp_node.operator, 35065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2=cmp_node.operand2, 35075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=not_a_constant) 35085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_nodes.append(pcmp_node) 35095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_cmp_node = pcmp_node 35115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for cmp_node in cascade[2:]: 35125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_cmp_node.cascade = cmp_node 35135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_cmp_node = cmp_node 35145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_cmp_node.cascade = None 35155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if final_false_result: 35175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # last cascade was constant False 35185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cmp_nodes.append(final_false_result[0]) 35195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not cmp_nodes: 35205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # only constants, but no False result 35215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._bool_node(node, True) 35225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = cmp_nodes[0] 35235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(cmp_nodes) == 1: 35245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.has_constant_result(): 35255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self._bool_node(node, node.constant_result) 35265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 35275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for cmp_node in cmp_nodes[1:]: 35285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node = ExprNodes.BoolBinopNode( 35295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, 35305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand1=node, 35315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operator='and', 35325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) operand2=cmp_node, 35335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) constant_result=not_a_constant) 35345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 35355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_CondExprNode(self, node): 35375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 35385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.test.has_constant_result(): 35395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 35405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.test.constant_result: 35415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.true_val 35425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 35435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.false_val 35445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_IfStatNode(self, node): 35465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 35475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # eliminate dead code based on constant condition results 35485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if_clauses = [] 35495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for if_clause in node.if_clauses: 35505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) condition = if_clause.condition 35515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if condition.has_constant_result(): 35525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if condition.constant_result: 35535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # always true => subsequent clauses can safely be dropped 35545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.else_clause = if_clause.body 35555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 35565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # else: false => drop clause 35575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 35585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # unknown result => normal runtime evaluation 35595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if_clauses.append(if_clause) 35605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if if_clauses: 35615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.if_clauses = if_clauses 35625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 35635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.else_clause: 35645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.else_clause 35655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 35665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Nodes.StatListNode(node.pos, stats=[]) 35675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_SliceIndexNode(self, node): 35695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._calculate_const(node) 35705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # normalise start/stop values 35715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.start is None or node.start.constant_result is None: 35725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = node.start = None 35735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 35745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = node.start.constant_result 35755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.stop is None or node.stop.constant_result is None: 35765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = node.stop = None 35775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 35785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) stop = node.stop.constant_result 35795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # cut down sliced constant sequences 35805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.constant_result is not not_a_constant: 35815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base = node.base 35825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if base.is_sequence_constructor and base.mult_factor is None: 35835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base.args = base.args[start:stop] 35845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return base 35855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif base.is_string_literal: 35865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base = base.as_sliced_node(start, stop) 35875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if base is not None: 35885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return base 35895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 35905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 35915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ComprehensionNode(self, node): 35925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 35935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(node.loop, Nodes.StatListNode) and not node.loop.stats: 35945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # loop was pruned already => transform into literal 35955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.type is Builtin.list_type: 35965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.ListNode( 35975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, args=[], constant_result=[]) 35985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type is Builtin.set_type: 35995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.SetNode( 36005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, args=[], constant_result=set()) 36015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif node.type is Builtin.dict_type: 36025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ExprNodes.DictNode( 36035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.pos, key_value_pairs=[], constant_result={}) 36045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ForInStatNode(self, node): 36075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sequence = node.iterator.sequence 36095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(sequence, ExprNodes.SequenceNode): 36105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not sequence.args: 36115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.else_clause: 36125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.else_clause 36135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 36145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # don't break list comprehensions 36155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return Nodes.StatListNode(node.pos, stats=[]) 36165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # iterating over a list literal? => tuples are more efficient 36175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(sequence, ExprNodes.ListNode): 36185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.iterator.sequence = sequence.as_tuple() 36195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_WhileStatNode(self, node): 36225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.condition and node.condition.has_constant_result(): 36245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.condition.constant_result: 36255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.condition = None 36265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.else_clause = None 36275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 36285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.else_clause 36295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_ExprStatNode(self, node): 36325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(node.expr, ExprNodes.ExprNode): 36345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # ParallelRangeTransform does this ... 36355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # drop unused constant expressions 36375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.expr.has_constant_result(): 36385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return None 36395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # in the future, other nodes can have their own handler method here 36425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # that can replace them with a constant result node 36435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visit_Node = Visitor.VisitorTransform.recurse_to_children 36455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class FinalOptimizePhase(Visitor.CythonTransform): 36485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 36495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) This visitor handles several commuting optimizations, and is run 36505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) just before the C code generation phase. 36515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) The optimizations currently implemented in this class are: 36535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - eliminate None assignment and refcounting for first assignment. 36545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - isinstance -> typecheck for cdef types 36555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) - eliminate checks for None and/or types that became redundant after tree changes 36565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 36575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_SingleAssignmentNode(self, node): 36585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Avoid redundant initialisation of local variables before their 36595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first assignment. 36605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 36615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.first: 36635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs = node.lhs 36645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lhs.lhs_of_first_assignment = True 36655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_SimpleCallNode(self, node): 36685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Replace generic calls to isinstance(x, type) by a more efficient 36695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type check. 36705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 36715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.function.type.is_cfunction and isinstance(node.function, ExprNodes.NameNode): 36735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.function.name == 'isinstance' and len(node.args) == 2: 36745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type_arg = node.args[1] 36755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if type_arg.type.is_builtin_type and type_arg.type.name == 'type': 36765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cython_scope = self.context.cython_scope 36775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.function.entry = cython_scope.lookup('PyObject_TypeCheck') 36785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.function.type = node.function.entry.type 36795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PyTypeObjectPtr = PyrexTypes.CPtrType(cython_scope.lookup('PyTypeObject').type) 36805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr) 36815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_PyTypeTestNode(self, node): 36845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Remove tests for alternatively allowed None values from 36855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) type tests when we know that the argument cannot be None 36865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) anyway. 36875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 36885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.notnone: 36905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.arg.may_be_none(): 36915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.notnone = True 36925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 36935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 36945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_NoneCheckNode(self, node): 36955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Remove None checks from expressions that definitely do not 36965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) carry a None value. 36975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 36985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 36995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not node.arg.may_be_none(): 37005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node.arg 37015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 37025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 37035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ConsolidateOverflowCheck(Visitor.CythonTransform): 37045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 37055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) This class facilitates the sharing of overflow checking among all nodes 37065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) of a nested arithmetic expression. For example, given the expression 37075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) a*b + c, where a, b, and x are all possibly overflowing ints, the entire 37085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sequence will be evaluated and the overflow bit checked only at the end. 37095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 37105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) overflow_bit_node = None 37115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 37125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_Node(self, node): 37135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.overflow_bit_node is not None: 37145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) saved = self.overflow_bit_node 37155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.overflow_bit_node = None 37165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 37175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.overflow_bit_node = saved 37185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 37195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 37205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 37215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 37225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def visit_NumBinopNode(self, node): 37235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if node.overflow_check and node.overflow_fold: 37245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) top_level_overflow = self.overflow_bit_node is None 37255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if top_level_overflow: 37265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.overflow_bit_node = node 37275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 37285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.overflow_bit_node = self.overflow_bit_node 37295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) node.overflow_check = False 37305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 37315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if top_level_overflow: 37325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.overflow_bit_node = None 37335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 37345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.visitchildren(node) 37355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return node 3736