Esempio n. 1
0
def translate_method_call(builder: IRBuilder, expr: CallExpr,
                          callee: MemberExpr) -> Value:
    """Generate IR for an arbitrary call of form e.m(...).

    This can also deal with calls to module-level functions.
    """
    if builder.is_native_ref_expr(callee):
        # Call to module-level native function or such
        return translate_call(builder, expr, callee)
    elif (isinstance(callee.expr, RefExpr)
          and isinstance(callee.expr.node, TypeInfo)
          and callee.expr.node in builder.mapper.type_to_ir and
          builder.mapper.type_to_ir[callee.expr.node].has_method(callee.name)):
        # Call a method via the *class*
        assert isinstance(callee.expr.node, TypeInfo)
        ir = builder.mapper.type_to_ir[callee.expr.node]
        decl = ir.method_decl(callee.name)
        args = []
        arg_kinds, arg_names = expr.arg_kinds[:], expr.arg_names[:]
        # Add the class argument for class methods in extension classes
        if decl.kind == FUNC_CLASSMETHOD and ir.is_ext_class:
            args.append(
                builder.load_native_type_object(callee.expr.node.fullname))
            arg_kinds.insert(0, ARG_POS)
            arg_names.insert(0, None)
        args += [builder.accept(arg) for arg in expr.args]

        if ir.is_ext_class:
            return builder.builder.call(decl, args, arg_kinds, arg_names,
                                        expr.line)
        else:
            obj = builder.accept(callee.expr)
            return builder.gen_method_call(obj, callee.name, args,
                                           builder.node_type(expr), expr.line,
                                           expr.arg_kinds, expr.arg_names)

    elif builder.is_module_member_expr(callee):
        # Fall back to a PyCall for non-native module calls
        function = builder.accept(callee)
        args = [builder.accept(arg) for arg in expr.args]
        return builder.py_call(function,
                               args,
                               expr.line,
                               arg_kinds=expr.arg_kinds,
                               arg_names=expr.arg_names)
    else:
        receiver_typ = builder.node_type(callee.expr)

        # If there is a specializer for this method name/type, try calling it.
        # We would return the first successful one.
        val = apply_method_specialization(builder, expr, callee, receiver_typ)
        if val is not None:
            return val

        obj = builder.accept(callee.expr)
        args = [builder.accept(arg) for arg in expr.args]
        return builder.gen_method_call(obj, callee.name, args,
                                       builder.node_type(expr), expr.line,
                                       expr.arg_kinds, expr.arg_names)
Esempio n. 2
0
def transform_call_expr(builder: IRBuilder, expr: CallExpr) -> Value:
    if isinstance(expr.analyzed, CastExpr):
        return translate_cast_expr(builder, expr.analyzed)

    callee = expr.callee
    if isinstance(callee, IndexExpr) and isinstance(callee.analyzed, TypeApplication):
        callee = callee.analyzed.expr  # Unwrap type application

    if isinstance(callee, MemberExpr):
        return apply_method_specialization(builder, expr, callee) or \
               translate_method_call(builder, expr, callee)
    elif isinstance(callee, SuperExpr):
        return translate_super_method_call(builder, expr, callee)
    else:
        return translate_call(builder, expr, callee)