Example #1
0
def _visit_display(builder: IRBuilder, items: List[Expression],
                   constructor_op: OpDescription, append_op: OpDescription,
                   extend_op: OpDescription, 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.primitive_op(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
Example #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)
Example #3
0
def transform_dict_expr(builder: IRBuilder, expr: DictExpr) -> Value:
    """First accepts all keys and values, then makes a dict out of them."""
    key_value_pairs = []
    for key_expr, value_expr in expr.items:
        key = builder.accept(key_expr) if key_expr is not None else None
        value = builder.accept(value_expr)
        key_value_pairs.append((key, value))

    return builder.builder.make_dict(key_value_pairs, expr.line)
Example #4
0
def translate_len(builder: IRBuilder, expr: CallExpr,
                  callee: RefExpr) -> Optional[Value]:
    # Special case builtins.len
    if (len(expr.args) == 1 and expr.arg_kinds == [ARG_POS]):
        expr_rtype = builder.node_type(expr.args[0])
        if isinstance(expr_rtype, RTuple):
            # len() of fixed-length tuple can be trivially determined statically,
            # though we still need to evaluate it.
            builder.accept(expr.args[0])
            return builder.add(LoadInt(len(expr_rtype.types)))
    return None
Example #5
0
def transform_block(builder: IRBuilder, block: Block) -> None:
    if not block.is_unreachable:
        for stmt in block.body:
            builder.accept(stmt)
    # Raise a RuntimeError if we hit a non-empty unreachable block.
    # Don't complain about empty unreachable blocks, since mypy inserts
    # those after `if MYPY`.
    elif block.body:
        builder.add(RaiseStandardError(RaiseStandardError.RUNTIME_ERROR,
                                       'Reached allegedly unreachable code!',
                                       block.line))
        builder.add(Unreachable())
Example #6
0
def translate_call(builder: IRBuilder, expr: CallExpr,
                   callee: Expression) -> Value:
    # The common case of calls is refexprs
    if isinstance(callee, RefExpr):
        return translate_refexpr_call(builder, expr, callee)

    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)
Example #7
0
def transform_if_stmt(builder: IRBuilder, stmt: IfStmt) -> None:
    if_body, next = BasicBlock(), BasicBlock()
    else_body = BasicBlock() if stmt.else_body else next

    # If statements are normalized
    assert len(stmt.expr) == 1

    builder.process_conditional(stmt.expr[0], if_body, else_body)
    builder.activate_block(if_body)
    builder.accept(stmt.body[0])
    builder.goto(next)
    if stmt.else_body:
        builder.activate_block(else_body)
        builder.accept(stmt.else_body)
        builder.goto(next)
    builder.activate_block(next)
Example #8
0
def add_non_ext_class_attr(builder: IRBuilder, non_ext: NonExtClassInfo, lvalue: NameExpr,
                           stmt: AssignmentStmt, cdef: ClassDef,
                           attr_to_cache: List[Lvalue]) -> None:
    """
    Add a class attribute to __annotations__ of a non-extension class. If the
    attribute is assigned to a value, it is also added 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_static_unicode(lvalue.name)
    typ = builder.primitive_op(type_object_op, [], stmt.line)
    builder.primitive_op(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__')
        ):
            attr_to_cache.append(lvalue)
Example #9
0
def transform_return_stmt(builder: IRBuilder, stmt: ReturnStmt) -> None:
    if stmt.expr:
        retval = builder.accept(stmt.expr)
    else:
        retval = builder.builder.none()
    retval = builder.coerce(retval, builder.ret_types[-1], stmt.line)
    builder.nonlocal_control[-1].gen_return(builder, retval, stmt.line)
Example #10
0
def translate_super_method_call(builder: IRBuilder, expr: CallExpr,
                                callee: SuperExpr) -> Value:
    if callee.info is None or callee.call.args:
        return translate_call(builder, expr, callee)
    ir = builder.mapper.type_to_ir[callee.info]
    # Search for the method in the mro, skipping ourselves.
    for base in ir.mro[1:]:
        if callee.name in base.method_decls:
            break
    else:
        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:
        vself = next(iter(builder.environment.indexes))  # grab first argument
        if decl.kind == FUNC_CLASSMETHOD:
            vself = builder.primitive_op(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.environment.symtable.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)
Example #11
0
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.primitive_op(type_object_op, [], cdef.line)

    return builder.primitive_op(py_calc_meta_op, [declared_metaclass, bases], cdef.line)
Example #12
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.primitive_op(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.primitive_op(true_op, [], -1))

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

    def except_body() -> None:
        builder.assign(exc, builder.primitive_op(false_op, [], -1), 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.primitive_op(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_EXPR)
        )
        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
    )
Example #13
0
def transform_raise_stmt(builder: IRBuilder, s: RaiseStmt) -> None:
    if s.expr is None:
        builder.primitive_op(reraise_exception_op, [], NO_TRACEBACK_LINE_NO)
        builder.add(Unreachable())
        return

    exc = builder.accept(s.expr)
    builder.primitive_op(raise_exception_op, [exc], s.line)
    builder.add(Unreachable())
Example #14
0
def translate_isinstance(builder: IRBuilder, expr: CallExpr,
                         callee: RefExpr) -> Optional[Value]:
    # Special case builtins.isinstance
    if (len(expr.args) == 2 and expr.arg_kinds == [ARG_POS, ARG_POS]
            and isinstance(expr.args[1], (RefExpr, TupleExpr))):
        irs = builder.flatten_classes(expr.args[1])
        if irs is not None:
            return builder.builder.isinstance_helper(
                builder.accept(expr.args[0]), irs, expr.line)
    return None
Example #15
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
Example #16
0
def transform_try_except_stmt(builder: IRBuilder, t: TryStmt) -> None:
    def body() -> None:
        builder.accept(t.body)

    # Work around scoping woes
    def make_handler(body: Block) -> GenFunc:
        return lambda: builder.accept(body)

    handlers = [(type, var, make_handler(body))
                for type, var, body in zip(t.types, t.vars, t.handlers)]
    else_body = (lambda: builder.accept(t.else_body)) if t.else_body else None
    transform_try_except(builder, body, handlers, else_body, t.line)
Example #17
0
def transform_operator_assignment_stmt(builder: IRBuilder, stmt: OperatorAssignmentStmt) -> None:
    """Operator assignment statement such as x += 1"""
    builder.disallow_class_assignments([stmt.lvalue], stmt.line)
    target = builder.get_assignment_target(stmt.lvalue)
    target_value = builder.read(target, stmt.line)
    rreg = builder.accept(stmt.rvalue)
    # the Python parser strips the '=' from operator assignment statements, so re-add it
    op = stmt.op + '='
    res = builder.binary_op(target_value, rreg, op, stmt.line)
    # usually operator assignments are done in-place
    # but when target doesn't support that we need to manually assign
    builder.assign(target, res, res.line)
Example #18
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)
Example #19
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.primitive_op(raise_exception_op, [exc], a.line)
    builder.add(Unreachable())
    builder.activate_block(ok_block)
Example #20
0
def transform_while_stmt(builder: IRBuilder, s: WhileStmt) -> None:
    body, next, top, else_block = BasicBlock(), BasicBlock(), BasicBlock(), BasicBlock()
    normal_loop_exit = else_block if s.else_body is not None else next

    builder.push_loop_stack(top, next)

    # Split block so that we get a handle to the top of the loop.
    builder.goto_and_activate(top)
    builder.process_conditional(s.expr, body, normal_loop_exit)

    builder.activate_block(body)
    builder.accept(s.body)
    # Add branch to the top at the end of the body.
    builder.goto(top)

    builder.pop_loop_stack()

    if s.else_body is not None:
        builder.activate_block(else_block)
        builder.accept(s.else_body)
        builder.goto(next)

    builder.activate_block(next)
Example #21
0
def transform_conditional_expr(builder: IRBuilder,
                               expr: ConditionalExpr) -> Value:
    if_body, else_body, next = BasicBlock(), BasicBlock(), BasicBlock()

    builder.process_conditional(expr.cond, if_body, else_body)
    expr_type = builder.node_type(expr)
    # Having actual Phi nodes would be really nice here!
    target = builder.alloc_temp(expr_type)

    builder.activate_block(if_body)
    true_value = builder.accept(expr.if_expr)
    true_value = builder.coerce(true_value, expr_type, expr.line)
    builder.add(Assign(target, true_value))
    builder.goto(next)

    builder.activate_block(else_body)
    false_value = builder.accept(expr.else_expr)
    false_value = builder.coerce(false_value, expr_type, expr.line)
    builder.add(Assign(target, false_value))
    builder.goto(next)

    builder.activate_block(next)

    return target
Example #22
0
def translate_next_call(builder: IRBuilder, expr: CallExpr,
                        callee: RefExpr) -> Optional[Value]:
    # Special case for calling next() on a generator expression, an
    # idiom that shows up some in mypy.
    #
    # For example, next(x for x in l if x.id == 12, None) will
    # generate code that searches l for an element where x.id == 12
    # and produce the first such object, or None if no such element
    # exists.
    if not (expr.arg_kinds in ([ARG_POS], [ARG_POS, ARG_POS])
            and isinstance(expr.args[0], GeneratorExpr)):
        return None

    gen = expr.args[0]

    retval = builder.alloc_temp(builder.node_type(expr))
    default_val = None
    if len(expr.args) > 1:
        default_val = builder.accept(expr.args[1])

    exit_block = BasicBlock()

    def gen_inner_stmts() -> None:
        # next takes the first element of the generator, so if
        # something gets produced, we are done.
        builder.assign(retval, builder.accept(gen.left_expr),
                       gen.left_expr.line)
        builder.goto(exit_block)

    loop_params = list(zip(gen.indices, gen.sequences, gen.condlists))
    builder.comprehension_helper(loop_params, gen_inner_stmts, gen.line)

    # Now we need the case for when nothing got hit. If there was
    # a default value, we produce it, and otherwise we raise
    # StopIteration.
    if default_val:
        builder.assign(retval, default_val, gen.left_expr.line)
        builder.goto(exit_block)
    else:
        builder.add(
            RaiseStandardError(RaiseStandardError.STOP_ITERATION, None,
                               expr.line))
        builder.add(Unreachable())

    builder.activate_block(exit_block)
    return retval
Example #23
0
def transform_tuple_expr(builder: IRBuilder, expr: TupleExpr) -> Value:
    if any(isinstance(item, StarExpr) for item in expr.items):
        # create a tuple of unknown length
        return _visit_tuple_display(builder, expr)

    # create a tuple of fixed length (RTuple)
    tuple_type = builder.node_type(expr)
    # When handling NamedTuple et. al we might not have proper type info,
    # so make some up if we need it.
    types = (tuple_type.types if isinstance(tuple_type, RTuple) else
             [object_rprimitive] * len(expr.items))

    items = []
    for item_expr, item_type in zip(expr.items, types):
        reg = builder.accept(item_expr)
        items.append(builder.coerce(reg, item_type, item_expr.line))
    return builder.add(TupleSet(items, expr.line))
Example #24
0
def transform_member_expr(builder: IRBuilder, expr: MemberExpr) -> Value:
    # First check if this is maybe a final attribute.
    final = builder.get_final_ref(expr)
    if final is not None:
        fullname, final_var, native = final
        value = builder.emit_load_final(final_var, fullname, final_var.name,
                                        native, builder.types[expr], expr.line)
        if value is not None:
            return value

    if isinstance(expr.node,
                  MypyFile) and expr.node.fullname in builder.imports:
        return builder.load_module(expr.node.fullname)

    obj = builder.accept(expr.expr)
    return builder.builder.get_attr(obj, expr.name, builder.node_type(expr),
                                    expr.line)
Example #25
0
def transform_try_stmt(builder: IRBuilder, t: TryStmt) -> None:
    # Our compilation strategy for try/except/else/finally is to
    # treat try/except/else and try/finally as separate language
    # constructs that we compile separately. When we have a
    # try/except/else/finally, we treat the try/except/else as the
    # body of a try/finally block.
    if t.finally_body:
        def transform_try_body() -> None:
            if t.handlers:
                transform_try_except_stmt(builder, t)
            else:
                builder.accept(t.body)
        body = t.finally_body

        transform_try_finally_stmt(builder, transform_try_body, lambda: builder.accept(body))
    else:
        transform_try_except_stmt(builder, t)
Example #26
0
def translate_refexpr_call(builder: IRBuilder, expr: CallExpr,
                           callee: RefExpr) -> Value:
    """Translate a non-method call."""

    # TODO: Allow special cases to have default args or named args. Currently they don't since
    # they check that everything in arg_kinds is ARG_POS.

    # If there is a specializer for this function, try calling it.
    if callee.fullname and (callee.fullname, None) in specializers:
        val = specializers[callee.fullname, None](builder, expr, callee)
        if val is not None:
            return val

    # Gen the argument values
    arg_values = [builder.accept(arg) for arg in expr.args]

    return builder.call_refexpr_with_args(expr, callee, arg_values)
Example #27
0
def transform_assignment_stmt(builder: IRBuilder, stmt: AssignmentStmt) -> None:
    assert len(stmt.lvalues) >= 1
    builder.disallow_class_assignments(stmt.lvalues, stmt.line)
    lvalue = stmt.lvalues[0]
    if stmt.type and isinstance(stmt.rvalue, TempNode):
        # This is actually a variable annotation without initializer. Don't generate
        # an assignment but we need to call get_assignment_target since it adds a
        # name binding as a side effect.
        builder.get_assignment_target(lvalue, stmt.line)
        return

    line = stmt.rvalue.line
    rvalue_reg = builder.accept(stmt.rvalue)
    if builder.non_function_scope() and stmt.is_final_def:
        builder.init_final_static(lvalue, rvalue_reg)
    for lvalue in stmt.lvalues:
        target = builder.get_assignment_target(lvalue)
        builder.assign(target, rvalue_reg, line)
Example #28
0
def transform_super_expr(builder: IRBuilder, o: SuperExpr) -> Value:
    # warning(builder, 'can not optimize super() expression', o.line)
    sup_val = builder.load_module_attr_by_fullname('builtins.super', o.line)
    if o.call.args:
        args = [builder.accept(arg) for arg in o.call.args]
    else:
        assert o.info is not None
        typ = builder.load_native_type_object(o.info.fullname)
        ir = builder.mapper.type_to_ir[o.info]
        iter_env = iter(builder.environment.indexes)
        vself = next(iter_env)  # grab first argument
        if builder.fn_info.is_generator:
            # grab sixth argument (see comment in translate_super_method_call)
            self_targ = list(builder.environment.symtable.values())[6]
            vself = builder.read(self_targ, builder.fn_info.fitem.line)
        elif not ir.is_ext_class:
            vself = next(
                iter_env)  # second argument is self if non_extension class
        args = [typ, vself]
    res = builder.py_call(sup_val, args, o.line)
    return builder.py_get_attr(res, o.name, o.line)
Example #29
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.primitive_op(new_tuple_op, 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.primitive_op(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.primitive_op(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.primitive_op(dict_set_item_op,
                      [
                          builder.load_globals_dict(),
                          builder.load_static_unicode(cdef.name),
                          tp,
                      ], cdef.line)

    return tp
Example #30
0
def transform_comparison_expr(builder: IRBuilder, e: ComparisonExpr) -> Value:
    # TODO: Don't produce an expression when used in conditional context

    # All of the trickiness here is due to support for chained conditionals
    # (`e1 < e2 > e3`, etc). `e1 < e2 > e3` is approximately equivalent to
    # `e1 < e2 and e2 > e3` except that `e2` is only evaluated once.
    expr_type = builder.node_type(e)

    # go(i, prev) generates code for `ei opi e{i+1} op{i+1} ... en`,
    # assuming that prev contains the value of `ei`.
    def go(i: int, prev: Value) -> Value:
        if i == len(e.operators) - 1:
            return transform_basic_comparison(
                builder, e.operators[i], prev,
                builder.accept(e.operands[i + 1]), e.line)

        next = builder.accept(e.operands[i + 1])
        return builder.builder.shortcircuit_helper(
            'and', expr_type, lambda: transform_basic_comparison(
                builder, e.operators[i], prev, next, e.line),
            lambda: go(i + 1, next), e.line)

    return go(0, builder.accept(e.operands[0]))