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