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.
        if (callee.name, receiver_typ) in specializers:
            val = specializers[callee.name, receiver_typ](builder, expr,
                                                          callee)
            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_index_expr(builder: IRBuilder, expr: IndexExpr) -> Value:
    base = builder.accept(expr.base)

    if isinstance(base.type, RTuple) and isinstance(expr.index, IntExpr):
        return builder.add(TupleGet(base, expr.index.value, expr.line))

    index_reg = builder.accept(expr.index)
    return builder.gen_method_call(base, '__getitem__', [index_reg],
                                   builder.node_type(expr), expr.line)
Esempio n. 3
0
def transform_del_item(builder: IRBuilder, target: AssignmentTarget, line: int) -> None:
    if isinstance(target, AssignmentTargetIndex):
        builder.gen_method_call(
            target.base,
            '__delitem__',
            [target.index],
            result_type=None,
            line=line
        )
    elif isinstance(target, AssignmentTargetAttr):
        key = builder.load_static_unicode(target.attr)
        builder.add(PrimitiveOp([target.obj, key], py_delattr_op, line))
    elif isinstance(target, AssignmentTargetRegister):
        # Delete a local by assigning an error value to it, which will
        # prompt the insertion of uninit checks.
        builder.add(Assign(target.register,
                           builder.add(LoadErrorValue(target.type, undefines=True))))
    elif isinstance(target, AssignmentTargetTuple):
        for subtarget in target.items:
            transform_del_item(builder, subtarget, line)
Esempio n. 4
0
def translate_safe_generator_call(builder: IRBuilder, expr: CallExpr,
                                  callee: RefExpr) -> Optional[Value]:
    # Special cases for things that consume iterators where we know we
    # can safely compile a generator into a list.
    if (len(expr.args) > 0 and expr.arg_kinds[0] == ARG_POS
            and isinstance(expr.args[0], GeneratorExpr)):
        if isinstance(callee, MemberExpr):
            return builder.gen_method_call(
                builder.accept(callee.expr), callee.name,
                ([builder.translate_list_comprehension(expr.args[0])] +
                 [builder.accept(arg) for arg in expr.args[1:]]),
                builder.node_type(expr), expr.line, expr.arg_kinds,
                expr.arg_names)
        else:
            return builder.call_refexpr_with_args(
                expr, callee,
                ([builder.translate_list_comprehension(expr.args[0])] +
                 [builder.accept(arg) for arg in expr.args[1:]]))
    return None