コード例 #1
0
    def test_runtime_subtype(self) -> None:
        # right type to check with
        r = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive])

        # using the exact same fields
        r1 = RStruct("Foo", ["a", "b"], [bool_rprimitive, int_rprimitive])

        # names different
        r2 = RStruct("Bar", ["c", "b"], [bool_rprimitive, int_rprimitive])

        # name different
        r3 = RStruct("Baz", ["a", "b"], [bool_rprimitive, int_rprimitive])

        # type different
        r4 = RStruct("FooBar", ["a", "b"], [bool_rprimitive, int32_rprimitive])

        # number of types different
        r5 = RStruct("FooBarBaz", ["a", "b", "c"],
                     [bool_rprimitive, int_rprimitive, bool_rprimitive])

        assert is_runtime_subtype(r1, r) is True
        assert is_runtime_subtype(r2, r) is False
        assert is_runtime_subtype(r3, r) is False
        assert is_runtime_subtype(r4, r) is False
        assert is_runtime_subtype(r5, r) is False
コード例 #2
0
ファイル: test_struct.py プロジェクト: suned/mypy
    def test_runtime_subtype(self) -> None:
        # right type to check with
        info = StructInfo("Foo", ["a", "b"],
                    [bool_rprimitive, int_rprimitive])
        r = RStruct(info)

        # using the same StructInfo
        r1 = RStruct(info)

        # names different
        info2 = StructInfo("Bar", ["c", "b"],
                    [bool_rprimitive, int_rprimitive])
        r2 = RStruct(info2)

        # name different
        info3 = StructInfo("Baz", ["a", "b"],
                    [bool_rprimitive, int_rprimitive])
        r3 = RStruct(info3)

        # type different
        info4 = StructInfo("FooBar", ["a", "b"],
                    [bool_rprimitive, int32_rprimitive])
        r4 = RStruct(info4)

        # number of types different
        info5 = StructInfo("FooBarBaz", ["a", "b", "c"],
                    [bool_rprimitive, int_rprimitive, bool_rprimitive])
        r5 = RStruct(info5)

        assert is_runtime_subtype(r1, r) is True
        assert is_runtime_subtype(r2, r) is False
        assert is_runtime_subtype(r3, r) is False
        assert is_runtime_subtype(r4, r) is False
        assert is_runtime_subtype(r5, r) is False
コード例 #3
0
ファイル: ll_builder.py プロジェクト: meghachauhan04/mypy
 def matching_primitive_op(self,
                           candidates: List[OpDescription],
                           args: List[Value],
                           line: int,
                           result_type: Optional[RType] = None) -> Optional[Value]:
     # Find the highest-priority primitive op that matches.
     matching = None  # type: Optional[OpDescription]
     for desc in candidates:
         if len(desc.arg_types) != len(args):
             continue
         if all(is_subtype(actual.type, formal)
                for actual, formal in zip(args, desc.arg_types)):
             if matching:
                 assert matching.priority != desc.priority, 'Ambiguous:\n1) %s\n2) %s' % (
                     matching, desc)
                 if desc.priority > matching.priority:
                     matching = desc
             else:
                 matching = desc
     if matching:
         target = self.primitive_op(matching, args, line)
         if result_type and not is_runtime_subtype(target.type, result_type):
             if is_none_rprimitive(result_type):
                 # Special case None return. The actual result may actually be a bool
                 # and so we can't just coerce it.
                 target = self.none()
             else:
                 target = self.coerce(target, result_type, line)
         return target
     return None
コード例 #4
0
ファイル: ll_builder.py プロジェクト: meghachauhan04/mypy
    def coerce(self, src: Value, target_type: RType, line: int, force: bool = False) -> Value:
        """Generate a coercion/cast from one type to other (only if needed).

        For example, int -> object boxes the source int; int -> int emits nothing;
        object -> int unboxes the object. All conversions preserve object value.

        If force is true, always generate an op (even if it is just an assignment) so
        that the result will have exactly target_type as the type.

        Returns the register with the converted value (may be same as src).
        """
        if src.type.is_unboxed and not target_type.is_unboxed:
            return self.box(src)
        if ((src.type.is_unboxed and target_type.is_unboxed)
                and not is_runtime_subtype(src.type, target_type)):
            # To go from one unboxed type to another, we go through a boxed
            # in-between value, for simplicity.
            tmp = self.box(src)
            return self.unbox_or_cast(tmp, target_type, line)
        if ((not src.type.is_unboxed and target_type.is_unboxed)
                or not is_subtype(src.type, target_type)):
            return self.unbox_or_cast(src, target_type, line)
        elif force:
            tmp = self.alloc_temp(target_type)
            self.add(Assign(tmp, src))
            return tmp
        return src
コード例 #5
0
ファイル: ll_builder.py プロジェクト: liux-n/mypy
 def call_c(self,
            desc: CFunctionDescription,
            args: List[Value],
            line: int,
            result_type: Optional[RType] = None) -> Value:
     # handle void function via singleton RVoid instance
     coerced = []
     # coerce fixed number arguments
     for i in range(min(len(args), len(desc.arg_types))):
         formal_type = desc.arg_types[i]
         arg = args[i]
         arg = self.coerce(arg, formal_type, line)
         coerced.append(arg)
     # coerce any var_arg
     var_arg_idx = -1
     if desc.var_arg_type is not None:
         var_arg_idx = len(desc.arg_types)
         for i in range(len(desc.arg_types), len(args)):
             arg = args[i]
             arg = self.coerce(arg, desc.var_arg_type, line)
             coerced.append(arg)
     target = self.add(
         CallC(desc.c_function_name, coerced, desc.return_type, desc.steals,
               desc.error_kind, line, var_arg_idx))
     if result_type and not is_runtime_subtype(target.type, result_type):
         if is_none_rprimitive(result_type):
             # Special case None return. The actual result may actually be a bool
             # and so we can't just coerce it.
             target = self.none()
         else:
             target = self.coerce(target, result_type, line)
     return target
コード例 #6
0
 def call_c(self,
            desc: CFunctionDescription,
            args: List[Value],
            line: int,
            result_type: Optional[RType] = None) -> Value:
     # handle void function via singleton RVoid instance
     coerced = []
     # coerce fixed number arguments
     for i in range(min(len(args), len(desc.arg_types))):
         formal_type = desc.arg_types[i]
         arg = args[i]
         arg = self.coerce(arg, formal_type, line)
         coerced.append(arg)
     # reorder args if necessary
     if desc.ordering is not None:
         assert desc.var_arg_type is None
         coerced = [coerced[i] for i in desc.ordering]
     # coerce any var_arg
     var_arg_idx = -1
     if desc.var_arg_type is not None:
         var_arg_idx = len(desc.arg_types)
         for i in range(len(desc.arg_types), len(args)):
             arg = args[i]
             arg = self.coerce(arg, desc.var_arg_type, line)
             coerced.append(arg)
     # add extra integer constant if any
     for item in desc.extra_int_constants:
         val, typ = item
         extra_int_constant = self.add(LoadInt(val, line, rtype=typ))
         coerced.append(extra_int_constant)
     target = self.add(
         CallC(desc.c_function_name, coerced, desc.return_type, desc.steals,
               desc.is_borrowed, desc.error_kind, line, var_arg_idx))
     if desc.truncated_type is None:
         result = target
     else:
         truncate = self.add(
             Truncate(target, desc.return_type, desc.truncated_type))
         result = truncate
     if result_type and not is_runtime_subtype(result.type, result_type):
         if is_none_rprimitive(result_type):
             # Special case None return. The actual result may actually be a bool
             # and so we can't just coerce it.
             result = self.none()
         else:
             result = self.coerce(target, result_type, line)
     return result
コード例 #7
0
ファイル: ir_builder.py プロジェクト: anygitdata/ubn-nltest
    def add_bool_branch(self, value: Value, true: BasicBlock,
                        false: BasicBlock) -> None:
        if is_runtime_subtype(value.type, int_rprimitive):
            zero = self.add(LoadInt(0))
            value = self.binary_op(value, zero, '!=', value.line)
        elif is_same_type(value.type, list_rprimitive):
            length = self.primitive_op(list_len_op, [value], value.line)
            zero = self.add(LoadInt(0))
            value = self.binary_op(length, zero, '!=', value.line)
        elif (isinstance(value.type, RInstance)
              and value.type.class_ir.is_ext_class
              and value.type.class_ir.has_method('__bool__')):
            # Directly call the __bool__ method on classes that have it.
            value = self.gen_method_call(value, '__bool__', [],
                                         bool_rprimitive, value.line)
        else:
            value_type = optional_value_type(value.type)
            if value_type is not None:
                is_none = self.binary_op(value, self.none_object(), 'is not',
                                         value.line)
                branch = Branch(is_none, true, false, Branch.BOOL_EXPR)
                self.add(branch)
                always_truthy = False
                if isinstance(value_type, RInstance):
                    # check whether X.__bool__ is always just the default (object.__bool__)
                    if (not value_type.class_ir.has_method('__bool__') and
                            value_type.class_ir.is_method_final('__bool__')):
                        always_truthy = True

                if not always_truthy:
                    # Optional[X] where X may be falsey and requires a check
                    branch.true = BasicBlock()
                    self.activate_block(branch.true)
                    # unbox_or_cast instead of coerce because we want the
                    # type to change even if it is a subtype.
                    remaining = self.unbox_or_cast(value, value_type,
                                                   value.line)
                    self.add_bool_branch(remaining, true, false)
                return
            elif not is_same_type(value.type, bool_rprimitive):
                value = self.primitive_op(bool_op, [value], value.line)
        self.add(Branch(value, true, false, Branch.BOOL_EXPR))
コード例 #8
0
 def call_c(self,
            desc: CFunctionDescription,
            args: List[Value],
            line: int,
            result_type: Optional[RType] = None) -> Value:
     # handle void function via singleton RVoid instance
     coerced = []
     for i, arg in enumerate(args):
         formal_type = desc.arg_types[i]
         arg = self.coerce(arg, formal_type, line)
         coerced.append(arg)
     target = self.add(CallC(desc.c_function_name, coerced, desc.return_type, desc.steals,
                             desc.error_kind, line))
     if result_type and not is_runtime_subtype(target.type, result_type):
         if is_none_rprimitive(result_type):
             # Special case None return. The actual result may actually be a bool
             # and so we can't just coerce it.
             target = self.none()
         else:
             target = self.coerce(target, result_type, line)
     return target
コード例 #9
0
 def test_bool(self) -> None:
     assert not is_runtime_subtype(bool_rprimitive, bit_rprimitive)
     assert not is_runtime_subtype(bool_rprimitive, int_rprimitive)