예제 #1
0
def add_non_ext_class_attr(builder: IRBuilder,
                           non_ext: NonExtClassInfo,
                           lvalue: NameExpr,
                           stmt: AssignmentStmt,
                           cdef: ClassDef,
                           attr_to_cache: List[Tuple[Lvalue, RType]]) -> None:
    """Add a class attribute to __annotations__ of a non-extension class.

    If the attribute is initialized with a value, also add it to __dict__.
    """
    # We populate __annotations__ because dataclasses uses it to determine
    # which attributes to compute on.
    # TODO: Maybe generate more precise types for annotations
    key = builder.load_str(lvalue.name)
    typ = builder.add(LoadAddress(type_object_op.type, type_object_op.src, stmt.line))
    builder.call_c(dict_set_item_op, [non_ext.anns, key, typ], stmt.line)

    # Only add the attribute to the __dict__ if the assignment is of the form:
    # x: type = value (don't add attributes of the form 'x: type' to the __dict__).
    if not isinstance(stmt.rvalue, TempNode):
        rvalue = builder.accept(stmt.rvalue)
        builder.add_to_non_ext_dict(non_ext, lvalue.name, rvalue, stmt.line)
        # We cache enum attributes to speed up enum attribute lookup since they
        # are final.
        if (
            cdef.info.bases
            and cdef.info.bases[0].type.fullname == 'enum.Enum'
            # Skip "_order_" and "__order__", since Enum will remove it
            and lvalue.name not in ('_order_', '__order__')
        ):
            # Enum values are always boxed, so use object_rprimitive.
            attr_to_cache.append((lvalue, object_rprimitive))
예제 #2
0
파일: function.py 프로젝트: wesleyks/mypy
def transform_decorator(builder: IRBuilder, dec: Decorator) -> None:
    func_ir, func_reg = gen_func_item(
        builder,
        dec.func,
        dec.func.name,
        builder.mapper.fdef_to_sig(dec.func)
    )

    if dec.func in builder.nested_fitems:
        assert func_reg is not None
        decorated_func = load_decorated_func(builder, dec.func, func_reg)
        builder.assign(get_func_target(builder, dec.func), decorated_func, dec.func.line)
        func_reg = decorated_func
    else:
        # Obtain the the function name in order to construct the name of the helper function.
        name = dec.func.fullname.split('.')[-1]
        helper_name = decorator_helper_name(name)

        # Load the callable object representing the non-decorated function, and decorate it.
        orig_func = builder.load_global_str(helper_name, dec.line)
        decorated_func = load_decorated_func(builder, dec.func, orig_func)

        # Set the callable object representing the decorated function as a global.
        builder.call_c(dict_set_item_op,
                    [builder.load_globals_dict(),
                    builder.load_static_unicode(dec.func.name), decorated_func],
                    decorated_func.line)

    builder.functions.append(func_ir)
예제 #3
0
def dict_methods_fast_path(
        builder: IRBuilder, expr: CallExpr, callee: RefExpr) -> Optional[Value]:
    """Specialize a common case when list() is called on a dictionary
    view method call.

    For example:
        foo = list(bar.keys())
    """
    if not (len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]):
        return None
    arg = expr.args[0]
    if not (isinstance(arg, CallExpr) and not arg.args
            and isinstance(arg.callee, MemberExpr)):
        return None
    base = arg.callee.expr
    attr = arg.callee.name
    rtype = builder.node_type(base)
    if not (is_dict_rprimitive(rtype) and attr in ('keys', 'values', 'items')):
        return None

    obj = builder.accept(base)
    # Note that it is not safe to use fast methods on dict subclasses,
    # so the corresponding helpers in CPy.h fallback to (inlined)
    # generic logic.
    if attr == 'keys':
        return builder.call_c(dict_keys_op, [obj], expr.line)
    elif attr == 'values':
        return builder.call_c(dict_values_op, [obj], expr.line)
    else:
        return builder.call_c(dict_items_op, [obj], expr.line)
예제 #4
0
def _visit_display(builder: IRBuilder,
                   items: List[Expression],
                   constructor_op: Callable[[List[Value], int], Value],
                   append_op: CFunctionDescription,
                   extend_op: CFunctionDescription,
                   line: int,
                   is_list: bool
                   ) -> Value:
    accepted_items = []
    for item in items:
        if isinstance(item, StarExpr):
            accepted_items.append((True, builder.accept(item.expr)))
        else:
            accepted_items.append((False, builder.accept(item)))

    result: Union[Value, None] = None
    initial_items = []
    for starred, value in accepted_items:
        if result is None and not starred and is_list:
            initial_items.append(value)
            continue

        if result is None:
            result = constructor_op(initial_items, line)

        builder.call_c(extend_op if starred else append_op, [result, value], line)

    if result is None:
        result = constructor_op(initial_items, line)

    return result
예제 #5
0
def transform_import(builder: IRBuilder, node: Import) -> None:
    if node.is_mypy_only:
        return
    globals = builder.load_globals_dict()
    for node_id, as_name in node.ids:
        builder.gen_import(node_id, node.line)

        # Update the globals dict with the appropriate module:
        # * For 'import foo.bar as baz' we add 'foo.bar' with the name 'baz'
        # * For 'import foo.bar' we add 'foo' with the name 'foo'
        # Typically we then ignore these entries and access things directly
        # via the module static, but we will use the globals version for modules
        # that mypy couldn't find, since it doesn't analyze module references
        # from those properly.

        # Miscompiling imports inside of functions, like below in import from.
        if as_name:
            name = as_name
            base = node_id
        else:
            base = name = node_id.split('.')[0]

        # Python 3.7 has a nice 'PyImport_GetModule' function that we can't use :(
        mod_dict = builder.call_c(get_module_dict_op, [], node.line)
        obj = builder.call_c(
            dict_get_item_op,
            [mod_dict, builder.load_static_unicode(base)], node.line)
        builder.gen_method_call(globals,
                                '__setitem__',
                                [builder.load_static_unicode(name), obj],
                                result_type=None,
                                line=node.line)
예제 #6
0
파일: statement.py 프로젝트: sthagen/mypy
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):
        if isinstance(target.obj_type, RInstance):
            cl = target.obj_type.class_ir
            if not cl.is_deletable(target.attr):
                builder.error('"{}" cannot be deleted'.format(target.attr),
                              line)
                builder.note(
                    'Using "__deletable__ = ' +
                    '[\'<attr>\']" in the class body enables "del obj.<attr>"',
                    line)
        key = builder.load_str(target.attr)
        builder.call_c(py_delattr_op, [target.obj, key], 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)
예제 #7
0
def transform_assert_stmt(builder: IRBuilder, a: AssertStmt) -> None:
    if builder.options.strip_asserts:
        return
    cond = builder.accept(a.expr)
    ok_block, error_block = BasicBlock(), BasicBlock()
    builder.add_bool_branch(cond, ok_block, error_block)
    builder.activate_block(error_block)
    if a.msg is None:
        # Special case (for simpler generated code)
        builder.add(
            RaiseStandardError(RaiseStandardError.ASSERTION_ERROR, None,
                               a.line))
    elif isinstance(a.msg, StrExpr):
        # Another special case
        builder.add(
            RaiseStandardError(RaiseStandardError.ASSERTION_ERROR, a.msg.value,
                               a.line))
    else:
        # The general case -- explicitly construct an exception instance
        message = builder.accept(a.msg)
        exc_type = builder.load_module_attr_by_fullname(
            'builtins.AssertionError', a.line)
        exc = builder.py_call(exc_type, [message], a.line)
        builder.call_c(raise_exception_op, [exc], a.line)
    builder.add(Unreachable())
    builder.activate_block(ok_block)
예제 #8
0
def add_non_ext_class_attr_ann(
    builder: IRBuilder,
    non_ext: NonExtClassInfo,
    lvalue: NameExpr,
    stmt: AssignmentStmt,
    get_type_info: Optional[Callable[[AssignmentStmt],
                                     Optional[TypeInfo]]] = None
) -> None:
    """Add a class attribute to __annotations__ of a non-extension class."""
    typ: Optional[Value] = None
    if get_type_info is not None:
        type_info = get_type_info(stmt)
        if type_info:
            typ = load_type(builder, type_info, stmt.line)

    if typ is None:
        # FIXME: if get_type_info is not provided, don't fall back to stmt.type?
        ann_type = get_proper_type(stmt.type)
        if isinstance(ann_type, Instance):
            typ = load_type(builder, ann_type.type, stmt.line)
        else:
            typ = builder.add(
                LoadAddress(type_object_op.type, type_object_op.src,
                            stmt.line))

    key = builder.load_str(lvalue.name)
    builder.call_c(dict_set_item_op, [non_ext.anns, key, typ], stmt.line)
예제 #9
0
파일: expression.py 프로젝트: xw0329/mypy
def _visit_display(builder: IRBuilder, items: List[Expression],
                   constructor_op: OpDescription,
                   append_op: CFunctionDescription,
                   extend_op: CFunctionDescription, line: int) -> Value:
    accepted_items = []
    for item in items:
        if isinstance(item, StarExpr):
            accepted_items.append((True, builder.accept(item.expr)))
        else:
            accepted_items.append((False, builder.accept(item)))

    result = None  # type: Union[Value, None]
    initial_items = []
    for starred, value in accepted_items:
        if result is None and not starred and constructor_op.is_var_arg:
            initial_items.append(value)
            continue

        if result is None:
            result = builder.primitive_op(constructor_op, initial_items, line)

        builder.call_c(extend_op if starred else append_op, [result, value],
                       line)

    if result is None:
        result = builder.primitive_op(constructor_op, initial_items, line)

    return result
예제 #10
0
def transform_decorator(builder: IRBuilder, dec: Decorator) -> None:
    func_ir, func_reg = gen_func_item(builder, dec.func, dec.func.name,
                                      builder.mapper.fdef_to_sig(dec.func))
    decorated_func: Optional[Value] = None
    if func_reg:
        decorated_func = load_decorated_func(builder, dec.func, func_reg)
        builder.assign(get_func_target(builder, dec.func), decorated_func,
                       dec.func.line)
        func_reg = decorated_func
    # If the prebuild pass didn't put this function in the function to decorators map (for example
    # if this is a registered singledispatch implementation with no other decorators), we should
    # treat this function as a regular function, not a decorated function
    elif dec.func in builder.fdefs_to_decorators:
        # Obtain the the function name in order to construct the name of the helper function.
        name = dec.func.fullname.split('.')[-1]

        # Load the callable object representing the non-decorated function, and decorate it.
        orig_func = builder.load_global_str(name, dec.line)
        decorated_func = load_decorated_func(builder, dec.func, orig_func)

    if decorated_func is not None:
        # Set the callable object representing the decorated function as a global.
        builder.call_c(dict_set_item_op, [
            builder.load_globals_dict(),
            builder.load_str(dec.func.name), decorated_func
        ], decorated_func.line)

    maybe_insert_into_registry_dict(builder, dec.func)

    builder.functions.append(func_ir)
예제 #11
0
def setup_non_ext_dict(builder: IRBuilder,
                       cdef: ClassDef,
                       metaclass: Value,
                       bases: Value) -> Value:
    """Initialize the class dictionary for a non-extension class.

    This class dictionary is passed to the metaclass constructor.
    """
    # Check if the metaclass defines a __prepare__ method, and if so, call it.
    has_prepare = builder.call_c(py_hasattr_op,
                                [metaclass,
                                builder.load_str('__prepare__')], cdef.line)

    non_ext_dict = Register(dict_rprimitive)

    true_block, false_block, exit_block, = BasicBlock(), BasicBlock(), BasicBlock()
    builder.add_bool_branch(has_prepare, true_block, false_block)

    builder.activate_block(true_block)
    cls_name = builder.load_str(cdef.name)
    prepare_meth = builder.py_get_attr(metaclass, '__prepare__', cdef.line)
    prepare_dict = builder.py_call(prepare_meth, [cls_name, bases], cdef.line)
    builder.assign(non_ext_dict, prepare_dict, cdef.line)
    builder.goto(exit_block)

    builder.activate_block(false_block)
    builder.assign(non_ext_dict, builder.call_c(dict_new_op, [], cdef.line), cdef.line)
    builder.goto(exit_block)
    builder.activate_block(exit_block)

    return non_ext_dict
예제 #12
0
def convert_expr(builder: IRBuilder, format_ops: List[FormatOp],
                 exprs: List[Expression], line: int) -> Optional[List[Value]]:
    """Convert expressions into string literals with the guidance
    of FormatOps."""
    if len(format_ops) != len(exprs):
        return None

    converted = []
    for x, format_op in zip(exprs, format_ops):
        node_type = builder.node_type(x)
        if format_op == FormatOp.STR:
            if is_str_rprimitive(node_type):
                var_str = builder.accept(x)
            elif is_int_rprimitive(node_type) or is_short_int_rprimitive(
                    node_type):
                var_str = builder.call_c(int_to_str_op, [builder.accept(x)],
                                         line)
            else:
                var_str = builder.call_c(str_op, [builder.accept(x)], line)
        elif format_op == FormatOp.INT:
            if is_int_rprimitive(node_type) or is_short_int_rprimitive(
                    node_type):
                var_str = builder.call_c(int_to_str_op, [builder.accept(x)],
                                         line)
            else:
                return None
        else:
            return None
        converted.append(var_str)
    return converted
예제 #13
0
def transform_raise_stmt(builder: IRBuilder, s: RaiseStmt) -> None:
    if s.expr is None:
        builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
        builder.add(Unreachable())
        return

    exc = builder.accept(s.expr)
    builder.call_c(raise_exception_op, [exc], s.line)
    builder.add(Unreachable())
예제 #14
0
def maybe_insert_into_registry_dict(builder: IRBuilder,
                                    fitem: FuncDef) -> None:
    line = fitem.line
    is_singledispatch_main_func = fitem in builder.singledispatch_impls
    # dict of singledispatch_func to list of register_types (fitem is the function to register)
    to_register: DefaultDict[FuncDef, List[TypeInfo]] = defaultdict(list)
    for main_func, impls in builder.singledispatch_impls.items():
        for dispatch_type, impl in impls:
            if fitem == impl:
                to_register[main_func].append(dispatch_type)

    if not to_register and not is_singledispatch_main_func:
        return

    if is_singledispatch_main_func:
        main_func_name = singledispatch_main_func_name(fitem.name)
        main_func_obj = load_func(builder, main_func_name, fitem.fullname,
                                  line)

        loaded_object_type = builder.load_module_attr_by_fullname(
            'builtins.object', line)
        registry_dict = builder.builder.make_dict(
            [(loaded_object_type, main_func_obj)], line)

        dispatch_func_obj = builder.load_global_str(fitem.name, line)
        builder.call_c(
            py_setattr_op,
            [dispatch_func_obj,
             builder.load_str('registry'), registry_dict], line)

    for singledispatch_func, types in to_register.items():
        # TODO: avoid recomputing the native IDs for all the functions every time we find a new
        # function
        native_ids = get_native_impl_ids(builder, singledispatch_func)
        if fitem not in native_ids:
            to_insert = load_func(builder, fitem.name, fitem.fullname, line)
        else:
            current_id = native_ids[fitem]
            load_literal = LoadLiteral(current_id, object_rprimitive)
            to_insert = builder.add(load_literal)
        # TODO: avoid reloading the registry here if we just created it
        dispatch_func_obj = load_func(builder, singledispatch_func.name,
                                      singledispatch_func.fullname, line)
        registry = load_singledispatch_registry(builder, dispatch_func_obj,
                                                line)
        for typ in types:
            loaded_type = load_type(builder, typ, line)
            builder.call_c(dict_set_item_op,
                           [registry, loaded_type, to_insert], line)
        dispatch_cache = builder.builder.get_attr(dispatch_func_obj,
                                                  'dispatch_cache',
                                                  dict_rprimitive, line)
        builder.gen_method_call(dispatch_cache, 'clear', [], None, line)
예제 #15
0
def finish_non_ext_dict(builder: IRBuilder, non_ext: NonExtClassInfo, line: int) -> None:
    # Add __annotations__ to the class dict.
    builder.call_c(dict_set_item_op,
                [non_ext.dict, builder.load_str('__annotations__'),
                non_ext.anns], -1)

    # We add a __doc__ attribute so if the non-extension class is decorated with the
    # dataclass decorator, dataclass will not try to look for __text_signature__.
    # https://github.com/python/cpython/blob/3.7/Lib/dataclasses.py#L957
    filler_doc_str = 'mypyc filler docstring'
    builder.add_to_non_ext_dict(
        non_ext, '__doc__', builder.load_str(filler_doc_str), line)
    builder.add_to_non_ext_dict(
        non_ext, '__module__', builder.load_str(builder.module_name), line)
예제 #16
0
def generate_singledispatch_callable_class_ctor(builder: IRBuilder) -> None:
    """Create an __init__ that sets registry and dispatch_cache to empty dicts"""
    line = -1
    class_ir = builder.fn_info.callable_class.ir
    with builder.enter_method(class_ir, '__init__', bool_rprimitive):
        empty_dict = builder.call_c(dict_new_op, [], line)
        builder.add(SetAttr(builder.self(), 'registry', empty_dict, line))
        cache_dict = builder.call_c(dict_new_op, [], line)
        dispatch_cache_str = builder.load_str('dispatch_cache')
        # use the py_setattr_op instead of SetAttr so that it also gets added to our __dict__
        builder.call_c(py_setattr_op,
                       [builder.self(), dispatch_cache_str, cache_dict], line)
        # the generated C code seems to expect that __init__ returns a char, so just return 1
        builder.add(Return(Integer(1, bool_rprimitive, line), line))
예제 #17
0
def transform_generator_expr(builder: IRBuilder, o: GeneratorExpr) -> Value:
    if any(o.is_async):
        builder.error('async comprehensions are unimplemented', o.line)

    builder.warning('Treating generator comprehension as list', o.line)
    return builder.call_c(iter_op, [translate_list_comprehension(builder, o)],
                          o.line)
예제 #18
0
def transform_import_from(builder: IRBuilder, node: ImportFrom) -> None:
    if node.is_mypy_only:
        return

    module_state = builder.graph[builder.module_name]
    if module_state.ancestors is not None and module_state.ancestors:
        module_package = module_state.ancestors[0]
    elif builder.module_path.endswith("__init__.py"):
        module_package = builder.module_name
    else:
        module_package = ''

    id = importlib.util.resolve_name('.' * node.relative + node.id, module_package)

    globals = builder.load_globals_dict()
    imported_names = [name for name, _ in node.names]
    module = builder.gen_import_from(id, globals, imported_names, node.line)

    # Copy everything into our module's dict.
    # Note that we miscompile import from inside of functions here,
    # since that case *shouldn't* load it into the globals dict.
    # This probably doesn't matter much and the code runs basically right.
    for name, maybe_as_name in node.names:
        as_name = maybe_as_name or name
        obj = builder.call_c(import_from_op,
                             [module, builder.load_str(id),
                              builder.load_str(name), builder.load_str(as_name)],
                             node.line)
        builder.gen_method_call(
            globals, '__setitem__', [builder.load_str(as_name), obj],
            result_type=None, line=node.line)
예제 #19
0
def dataclass_non_ext_info(builder: IRBuilder, cdef: ClassDef) -> Optional[NonExtClassInfo]:
    """Set up a NonExtClassInfo to track dataclass attributes.

    In addition to setting up a normal extension class for dataclasses,
    we also collect its class attributes like a non-extension class so
    that we can hand them to the dataclass decorator.
    """
    if is_dataclass(cdef):
        return NonExtClassInfo(
            builder.call_c(dict_new_op, [], cdef.line),
            builder.add(TupleSet([], cdef.line)),
            builder.call_c(dict_new_op, [], cdef.line),
            builder.add(LoadAddress(type_object_op.type, type_object_op.src, cdef.line))
        )
    else:
        return None
예제 #20
0
def try_finally_entry_blocks(builder: IRBuilder, err_handler: BasicBlock,
                             return_entry: BasicBlock, main_entry: BasicBlock,
                             finally_block: BasicBlock,
                             ret_reg: Optional[Register]) -> Value:
    old_exc = builder.alloc_temp(exc_rtuple)

    # Entry block for non-exceptional flow
    builder.activate_block(main_entry)
    if ret_reg:
        builder.add(
            Assign(ret_reg,
                   builder.add(LoadErrorValue(builder.ret_types[-1]))))
    builder.goto(return_entry)

    builder.activate_block(return_entry)
    builder.add(Assign(old_exc, builder.add(LoadErrorValue(exc_rtuple))))
    builder.goto(finally_block)

    # Entry block for errors
    builder.activate_block(err_handler)
    if ret_reg:
        builder.add(
            Assign(ret_reg,
                   builder.add(LoadErrorValue(builder.ret_types[-1]))))
    builder.add(Assign(old_exc, builder.call_c(error_catch_op, [], -1)))
    builder.goto(finally_block)

    return old_exc
예제 #21
0
def add_get_to_callable_class(builder: IRBuilder, fn_info: FuncInfo) -> None:
    """Generate the '__get__' method for a callable class."""
    line = fn_info.fitem.line
    with builder.enter_method(fn_info.callable_class.ir,
                              '__get__',
                              object_rprimitive,
                              fn_info,
                              self_type=object_rprimitive):
        instance = builder.add_argument('instance', object_rprimitive)
        builder.add_argument('owner', object_rprimitive)

        # If accessed through the class, just return the callable
        # object. If accessed through an object, create a new bound
        # instance method object.
        instance_block, class_block = BasicBlock(), BasicBlock()
        comparison = builder.translate_is_op(builder.read(instance),
                                             builder.none_object(), 'is', line)
        builder.add_bool_branch(comparison, class_block, instance_block)

        builder.activate_block(class_block)
        builder.add(Return(builder.self()))

        builder.activate_block(instance_block)
        builder.add(
            Return(
                builder.call_c(
                    method_new_op,
                    [builder.self(), builder.read(instance)], line)))
예제 #22
0
def translate_super_method_call(builder: IRBuilder, expr: CallExpr,
                                callee: SuperExpr) -> Value:
    if callee.info is None or (len(callee.call.args) != 0
                               and len(callee.call.args) != 2):
        return translate_call(builder, expr, callee)

    # We support two-argument super but only when it is super(CurrentClass, self)
    # TODO: We could support it when it is a parent class in many cases?
    if len(callee.call.args) == 2:
        self_arg = callee.call.args[1]
        if (not isinstance(self_arg, NameExpr)
                or not isinstance(self_arg.node, Var)
                or not self_arg.node.is_self):
            return translate_call(builder, expr, callee)

        typ_arg = callee.call.args[0]
        if (not isinstance(typ_arg, NameExpr)
                or not isinstance(typ_arg.node, TypeInfo)
                or callee.info is not typ_arg.node):
            return translate_call(builder, expr, callee)

    ir = builder.mapper.type_to_ir[callee.info]
    # Search for the method in the mro, skipping ourselves. We
    # determine targets of super calls to native methods statically.
    for base in ir.mro[1:]:
        if callee.name in base.method_decls:
            break
    else:
        if (ir.is_ext_class and ir.builtin_base is None
                and not ir.inherits_python and callee.name == '__init__'
                and len(expr.args) == 0):
            # Call translates to object.__init__(self), which is a
            # no-op, so omit the call.
            return builder.none()
        return translate_call(builder, expr, callee)

    decl = base.method_decl(callee.name)
    arg_values = [builder.accept(arg) for arg in expr.args]
    arg_kinds, arg_names = expr.arg_kinds[:], expr.arg_names[:]

    if decl.kind != FUNC_STATICMETHOD:
        # Grab first argument
        vself: Value = builder.self()
        if decl.kind == FUNC_CLASSMETHOD:
            vself = builder.call_c(type_op, [vself], expr.line)
        elif builder.fn_info.is_generator:
            # For generator classes, the self target is the 6th value
            # in the symbol table (which is an ordered dict). This is sort
            # of ugly, but we can't search by name since the 'self' parameter
            # could be named anything, and it doesn't get added to the
            # environment indexes.
            self_targ = list(builder.symtables[-1].values())[6]
            vself = builder.read(self_targ, builder.fn_info.fitem.line)
        arg_values.insert(0, vself)
        arg_kinds.insert(0, ARG_POS)
        arg_names.insert(0, None)

    return builder.builder.call(decl, arg_values, arg_kinds, arg_names,
                                expr.line)
예제 #23
0
def transform_with(builder: IRBuilder,
                   expr: Expression,
                   target: Optional[Lvalue],
                   body: GenFunc,
                   line: int) -> None:
    # This is basically a straight transcription of the Python code in PEP 343.
    # I don't actually understand why a bunch of it is the way it is.
    # We could probably optimize the case where the manager is compiled by us,
    # but that is not our common case at all, so.
    mgr_v = builder.accept(expr)
    typ = builder.call_c(type_op, [mgr_v], line)
    exit_ = builder.maybe_spill(builder.py_get_attr(typ, '__exit__', line))
    value = builder.py_call(
        builder.py_get_attr(typ, '__enter__', line), [mgr_v], line
    )
    mgr = builder.maybe_spill(mgr_v)
    exc = builder.maybe_spill_assignable(builder.true())

    def try_body() -> None:
        if target:
            builder.assign(builder.get_assignment_target(target), value, line)
        body()

    def except_body() -> None:
        builder.assign(exc, builder.false(), line)
        out_block, reraise_block = BasicBlock(), BasicBlock()
        builder.add_bool_branch(
            builder.py_call(builder.read(exit_),
                            [builder.read(mgr)] + get_sys_exc_info(builder), line),
            out_block,
            reraise_block
        )
        builder.activate_block(reraise_block)
        builder.call_c(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
        builder.add(Unreachable())
        builder.activate_block(out_block)

    def finally_body() -> None:
        out_block, exit_block = BasicBlock(), BasicBlock()
        builder.add(
            Branch(builder.read(exc), exit_block, out_block, Branch.BOOL)
        )
        builder.activate_block(exit_block)
        none = builder.none_object()
        builder.py_call(
            builder.read(exit_), [builder.read(mgr), none, none, none], line
        )
        builder.goto_and_activate(out_block)

    transform_try_finally_stmt(
        builder,
        lambda: transform_try_except(builder,
                                     try_body,
                                     [(None, None, except_body)],
                                     None,
                                     line),
        finally_body
    )
예제 #24
0
파일: classdef.py 프로젝트: mobotyx/mypy
def find_non_ext_metaclass(builder: IRBuilder, cdef: ClassDef, bases: Value) -> Value:
    """Find the metaclass of a class from its defs and bases. """
    if cdef.metaclass:
        declared_metaclass = builder.accept(cdef.metaclass)
    else:
        declared_metaclass = builder.add(LoadAddress(type_object_op.type,
                                                     type_object_op.src, cdef.line))

    return builder.call_c(py_calc_meta_op, [declared_metaclass, bases], cdef.line)
예제 #25
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.call_c(py_delattr_op, [target.obj, key], 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)
예제 #26
0
def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value:
    # OK AND NOW THE FUN PART
    base_exprs = cdef.base_type_exprs + cdef.removed_base_type_exprs
    if base_exprs:
        bases = [builder.accept(x) for x in base_exprs]
        tp_bases = builder.new_tuple(bases, cdef.line)
    else:
        tp_bases = builder.add(
            LoadErrorValue(object_rprimitive, is_borrowed=True))
    modname = builder.load_static_unicode(builder.module_name)
    template = builder.add(
        LoadStatic(object_rprimitive, cdef.name + "_template",
                   builder.module_name, NAMESPACE_TYPE))
    # Create the class
    tp = builder.call_c(pytype_from_template_op, [template, tp_bases, modname],
                        cdef.line)
    # Immediately fix up the trait vtables, before doing anything with the class.
    ir = builder.mapper.type_to_ir[cdef.info]
    if not ir.is_trait and not ir.builtin_base:
        builder.add(
            Call(
                FuncDecl(cdef.name + '_trait_vtable_setup',
                         None, builder.module_name,
                         FuncSignature([], bool_rprimitive)), [], -1))
    # Populate a '__mypyc_attrs__' field containing the list of attrs
    builder.call_c(py_setattr_op, [
        tp,
        builder.load_static_unicode('__mypyc_attrs__'),
        create_mypyc_attrs_tuple(builder, builder.mapper.type_to_ir[cdef.info],
                                 cdef.line)
    ], cdef.line)

    # Save the class
    builder.add(InitStatic(tp, cdef.name, builder.module_name, NAMESPACE_TYPE))

    # Add it to the dict
    builder.call_c(dict_set_item_op, [
        builder.load_globals_dict(),
        builder.load_static_unicode(cdef.name),
        tp,
    ], cdef.line)

    return tp
예제 #27
0
def add_register_method_to_callable_class(builder: IRBuilder,
                                          fn_info: FuncInfo) -> None:
    line = -1
    with builder.enter_method(fn_info.callable_class.ir, 'register',
                              object_rprimitive):
        cls_arg = builder.add_argument('cls', object_rprimitive)
        func_arg = builder.add_argument('func', object_rprimitive,
                                        ArgKind.ARG_OPT)
        ret_val = builder.call_c(register_function,
                                 [builder.self(), cls_arg, func_arg], line)
        builder.add(Return(ret_val, line))
예제 #28
0
파일: expression.py 프로젝트: wesleyks/mypy
def transform_dictionary_comprehension(builder: IRBuilder, o: DictionaryComprehension) -> Value:
    d = builder.call_c(dict_new_op, [], o.line)
    loop_params = list(zip(o.indices, o.sequences, o.condlists))

    def gen_inner_stmts() -> None:
        k = builder.accept(o.key)
        v = builder.accept(o.value)
        builder.call_c(dict_set_item_op, [d, k, v], o.line)

    comprehension_helper(builder, loop_params, gen_inner_stmts, o.line)
    return d
예제 #29
0
def transform_slice_expr(builder: IRBuilder, expr: SliceExpr) -> Value:
    def get_arg(arg: Optional[Expression]) -> Value:
        if arg is None:
            return builder.none_object()
        else:
            return builder.accept(arg)

    args = [get_arg(expr.begin_index),
            get_arg(expr.end_index),
            get_arg(expr.stride)]
    return builder.call_c(new_slice_op, args, expr.line)
def unsafe_index(
    builder: IRBuilder, target: Value, index: Value, line: int
) -> Value:
    """Emit a potentially unsafe index into a target."""
    # This doesn't really fit nicely into any of our data-driven frameworks
    # since we want to use __getitem__ if we don't have an unsafe version,
    # so we just check manually.
    if is_list_rprimitive(target.type):
        return builder.call_c(list_get_item_unsafe_op, [target, index], line)
    else:
        return builder.gen_method_call(target, '__getitem__', [index], None, line)