'Replace generic calls to isinstance(x, type) by a more efficient type check.
Replace likely Python method calls by a specialised PyMethodCallNode.'

def visit_SimpleCallNode(self, node):

    self.visitchildren(node)
    function = node.function
    if (function.type.is_cfunction and function.is_name):
        if ((function.name == 'isinstance') and (len(node.args) == 2)):
            type_arg = node.args[1]
            if (type_arg.type.is_builtin_type and (type_arg.type.name == 'type')):
                cython_scope = self.context.cython_scope
                function.entry = cython_scope.lookup('PyObject_TypeCheck')
                function.type = function.entry.type
                PyTypeObjectPtr = PyrexTypes.CPtrType(cython_scope.lookup('PyTypeObject').type)
                node.args[1] = ExprNodes.CastNode(node.args[1], PyTypeObjectPtr)
    elif (self.current_directives.get('optimize.unpack_method_calls') and node.is_temp and function.type.is_pyobject):
        if (isinstance(node.arg_tuple, ExprNodes.TupleNode) and (not (node.arg_tuple.mult_factor or (node.arg_tuple.is_literal and node.arg_tuple.args)))):
            may_be_a_method = True
            if (function.type is Builtin.type_type):
                may_be_a_method = False
            elif function.is_attribute:
                if (function.entry and function.entry.type.is_cfunction):
                    may_be_a_method = False
            elif function.is_name:
                entry = function.entry
                if (entry.is_builtin or entry.type.is_cfunction):
                    may_be_a_method = False
                elif entry.cf_assignments:
                    non_method_nodes = (ExprNodes.PyCFunctionNode, ExprNodes.ClassNode, ExprNodes.Py3ClassNode)
                    may_be_a_method = any(((assignment.rhs and (not isinstance(assignment.rhs, non_method_nodes))) for assignment in entry.cf_assignments))
            if may_be_a_method:
                if (node.self and function.is_attribute and isinstance(function.obj, ExprNodes.CloneNode) and (function.obj.arg is node.self)):
                    function.obj = function.obj.arg
                node = self.replace(node, ExprNodes.PyMethodCallNode.from_node(node, function=function, arg_tuple=node.arg_tuple, type=node.type))
    return node
