Example #1
0
    def emit_box(self,
                 src: str,
                 dest: str,
                 typ: RType,
                 declare_dest: bool = False,
                 can_borrow: bool = False) -> None:
        """Emit code for boxing a value of given type.

        Generate a simple assignment if no boxing is needed.

        The source reference count is stolen for the result (no need to decref afterwards).
        """
        # TODO: Always generate a new reference (if a reference type)
        if declare_dest:
            declaration = 'PyObject *'
        else:
            declaration = ''
        if is_int_rprimitive(typ) or is_short_int_rprimitive(typ):
            # Steal the existing reference if it exists.
            self.emit_line('{}{} = CPyTagged_StealAsObject({});'.format(
                declaration, dest, src))
        elif is_bool_rprimitive(typ):
            # N.B: bool is special cased to produce a borrowed value
            # after boxing, so we don't need to increment the refcount
            # when this comes directly from a Box op.
            self.emit_lines('{}{} = {} ? Py_True : Py_False;'.format(
                declaration, dest, src))
            if not can_borrow:
                self.emit_inc_ref(dest, object_rprimitive)
        elif is_none_rprimitive(typ):
            # N.B: None is special cased to produce a borrowed value
            # after boxing, so we don't need to increment the refcount
            # when this comes directly from a Box op.
            self.emit_lines('{}{} = Py_None;'.format(declaration, dest))
            if not can_borrow:
                self.emit_inc_ref(dest, object_rprimitive)
        elif isinstance(typ, RTuple):
            self.declare_tuple_struct(typ)
            self.emit_line('{}{} = PyTuple_New({});'.format(
                declaration, dest, len(typ.types)))
            self.emit_line('if (unlikely({} == NULL))'.format(dest))
            self.emit_line('    CPyError_OutOfMemory();')
            # TODO: Fail if dest is None
            for i in range(0, len(typ.types)):
                if not typ.is_unboxed:
                    self.emit_line('PyTuple_SET_ITEM({}, {}, {}.f{}'.format(
                        dest, i, src, i))
                else:
                    inner_name = self.temp_name()
                    self.emit_box('{}.f{}'.format(src, i),
                                  inner_name,
                                  typ.types[i],
                                  declare_dest=True)
                    self.emit_line('PyTuple_SET_ITEM({}, {}, {});'.format(
                        dest, i, inner_name))
        else:
            assert not typ.is_unboxed
            # Type is boxed -- trivially just assign.
            self.emit_line('{}{} = {};'.format(declaration, dest, src))
Example #2
0
 def visit_load_static(self, op: LoadStatic) -> None:
     dest = self.reg(op)
     prefix = self.PREFIX_MAP[op.namespace]
     name = self.emitter.static_name(op.identifier, op.module_name, prefix)
     if op.namespace == NAMESPACE_TYPE:
         name = '(PyObject *)&%s' % name
     if is_int_rprimitive(op.type):
         self.emit_line('%s = CPyTagged_FromObject(%s);' % (dest, name))
     else:
         self.emit_line('%s = %s;' % (dest, name))
Example #3
0
    def emit_dec_ref(self, dest: str, rtype: RType) -> None:
        """Decrement reference count of C expression `dest`.

        For composite unboxed structures (e.g. tuples) recursively
        decrement reference counts for each component.
        """
        if is_int_rprimitive(rtype):
            self.emit_line('CPyTagged_DecRef(%s);' % dest)
        elif isinstance(rtype, RTuple):
            for i, item_type in enumerate(rtype.types):
                self.emit_dec_ref('{}.f{}'.format(dest, i), item_type)
        elif not rtype.is_unboxed:
            self.emit_line('CPy_DECREF(%s);' % dest)
Example #4
0
 def visit_load_static(self, op: LoadStatic) -> None:
     dest = self.reg(op)
     prefix = self.PREFIX_MAP[op.namespace]
     name = self.emitter.static_name(op.identifier, op.module_name, prefix)
     if op.namespace == NAMESPACE_TYPE:
         name = '(PyObject *)%s' % name
     if is_int_rprimitive(op.type):
         self.emit_line('%s = CPyTagged_FromObject(%s);' % (dest, name))
     else:
         ann = ''
         if op.ann:
             s = repr(op.ann)
             if not any(x in s for x in ('/*', '*/', '\0')):
                 ann = ' /* %s */' % s
         self.emit_line('%s = %s;%s' % (dest, name, ann))
Example #5
0
    def emit_box(self,
                 src: str,
                 dest: str,
                 typ: RType,
                 declare_dest: bool = False) -> None:
        """Emit code for boxing a value of give type.

        Generate a simple assignment if no boxing is needed.

        The source reference count is stolen for the result (no need to decref afterwards).
        """
        # TODO: Always generate a new reference (if a reference type)
        if declare_dest:
            declaration = 'PyObject *'
        else:
            declaration = ''
        if is_int_rprimitive(typ):
            # Steal the existing reference if it exists.
            self.emit_line('{}{} = CPyTagged_StealAsObject({});'.format(
                declaration, dest, src))
        elif is_bool_rprimitive(typ):
            # TODO: The Py_RETURN macros return the correct PyObject * with reference count
            #       handling. Relevant here?
            self.emit_lines('{}{} = PyBool_FromLong({});'.format(
                declaration, dest, src))
        elif isinstance(typ, RTuple):
            self.declare_tuple_struct(typ)
            self.emit_line('{}{} = PyTuple_New({});'.format(
                declaration, dest, len(typ.types)))
            self.emit_line('if ({} == NULL)'.format(dest))
            self.emit_line('    CPyError_OutOfMemory();')
            # TODO: Fail if dest is None
            for i in range(0, len(typ.types)):
                if not typ.is_unboxed:
                    self.emit_line('PyTuple_SetItem({}, {}, {}.f{}'.format(
                        dest, i, src, i))
                else:
                    inner_name = self.temp_name()
                    self.emit_box('{}.f{}'.format(src, i),
                                  inner_name,
                                  typ.types[i],
                                  declare_dest=True)
                    self.emit_line('PyTuple_SetItem({}, {}, {});'.format(
                        dest, i, inner_name, i))
        else:
            assert not typ.is_unboxed
            # Type is boxed -- trivially just assign.
            self.emit_line('{}{} = {};'.format(declaration, dest, src))
Example #6
0
def generate_hash_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str:
    """Generates a wrapper for native __hash__ methods."""
    name = '{}{}{}'.format(DUNDER_PREFIX, fn.name,
                           cl.name_prefix(emitter.names))
    emitter.emit_line(
        'static Py_ssize_t {name}(PyObject *self) {{'.format(name=name))
    emitter.emit_line('{}retval = {}{}(self);'.format(
        emitter.ctype_spaced(fn.ret_type), NATIVE_PREFIX,
        fn.cname(emitter.names)))
    emitter.emit_error_check('retval', fn.ret_type, 'return -1;')
    if is_int_rprimitive(fn.ret_type):
        emitter.emit_line('Py_ssize_t val = CPyTagged_AsLongLong(retval);')
    else:
        emitter.emit_line('Py_ssize_t val = PyLong_AsLongLong(retval);')
    emitter.emit_line('if (PyErr_Occurred()) return -1;')
    # We can't return -1 from a hash function..
    emitter.emit_line('if (val == -1) return -2;')
    emitter.emit_line('return val;')
    emitter.emit_line('}')

    return name
Example #7
0
 def visit_rprimitive(self, left: RPrimitive) -> bool:
     if is_short_int_rprimitive(left) and is_int_rprimitive(self.right):
         return True
     return left is self.right
Example #8
0
    def emit_unbox(self,
                   src: str,
                   dest: str,
                   typ: RType,
                   custom_failure: Optional[str] = None,
                   declare_dest: bool = False,
                   borrow: bool = False,
                   optional: bool = False) -> None:
        """Emit code for unboxing a value of given type (from PyObject *).

        Evaluate C code in 'failure' if the value has an incompatible type.

        Always generate a new reference.

        Args:
            src: Name of source C variable
            dest: Name of target C variable
            typ: Type of value
            failure: What happens on error
            declare_dest: If True, also declare the variable 'dest'
            borrow: If True, create a borrowed reference
        """
        # TODO: Raise exception on failure.
        # TODO: Verify refcount handling.
        raise_exc = 'PyErr_SetString(PyExc_TypeError, "%s object expected");' % (
            self.pretty_name(typ))
        if custom_failure is not None:
            failure = [raise_exc, custom_failure]
        else:
            failure = [raise_exc, '%s = %s;' % (dest, self.c_error_value(typ))]
        if is_int_rprimitive(typ):
            if declare_dest:
                self.emit_line('CPyTagged {};'.format(dest))
            self.emit_arg_check(src, dest, typ,
                                '(PyLong_Check({}))'.format(src), optional)
            if borrow:
                self.emit_line(
                    '    {} = CPyTagged_BorrowFromObject({});'.format(
                        dest, src))
            else:
                self.emit_line('    {} = CPyTagged_FromObject({});'.format(
                    dest, src))
            self.emit_line('else {')
            self.emit_lines(*failure)
            self.emit_line('}')
        elif is_bool_rprimitive(typ):
            # Whether we are borrowing or not makes no difference.
            if declare_dest:
                self.emit_line('char {};'.format(dest))
            self.emit_arg_check(src, dest, typ,
                                '(!PyBool_Check({})) {{'.format(src), optional)
            self.emit_lines(*failure)
            self.emit_line('} else')
            conversion = 'PyObject_IsTrue({})'.format(src)
            self.emit_line('    {} = {};'.format(dest, conversion))
        elif isinstance(typ, RTuple):
            self.declare_tuple_struct(typ)
            if declare_dest:
                self.emit_line('{} {};'.format(self.ctype(typ), dest))
            # HACK: The error handling for unboxing tuples is busted
            # and instead of fixing it I am just wrapping it in the
            # cast code which I think is right. This is not good.
            if optional:
                self.emit_line('if ({} == NULL) {{'.format(src))
                self.emit_line('{} = {};'.format(dest,
                                                 self.c_error_value(typ)))
                self.emit_line('} else {')

            cast_temp = self.temp_name()
            self.emit_tuple_cast(src,
                                 cast_temp,
                                 typ,
                                 declare_dest=True,
                                 err='',
                                 src_type=None)
            self.emit_line('if ({} == NULL) {{'.format(cast_temp))

            # self.emit_arg_check(src, dest, typ,
            #     '(!PyTuple_Check({}) || PyTuple_Size({}) != {}) {{'.format(
            #         src, src, len(typ.types)), optional)
            self.emit_lines(*failure)  # TODO: Decrease refcount?
            self.emit_line('} else {')
            if not typ.types:
                self.emit_line('{}.empty_struct_error_flag = 0;'.format(dest))
            for i, item_type in enumerate(typ.types):
                temp = self.temp_name()
                self.emit_line(
                    'PyObject *{} = PyTuple_GetItem({}, {});'.format(
                        temp, src, i))
                temp2 = self.temp_name()
                # Unbox or check the item.
                if item_type.is_unboxed:
                    self.emit_unbox(temp,
                                    temp2,
                                    item_type,
                                    custom_failure,
                                    declare_dest=True,
                                    borrow=borrow)
                else:
                    if not borrow:
                        self.emit_inc_ref(temp, object_rprimitive)
                    self.emit_cast(temp, temp2, item_type, declare_dest=True)
                self.emit_line('{}.f{} = {};'.format(dest, i, temp2))
            self.emit_line('}')
            if optional:
                self.emit_line('}')

        else:
            assert False, 'Unboxing not implemented: %s' % typ
Example #9
0
    def emit_cast(self,
                  src: str,
                  dest: str,
                  typ: RType,
                  declare_dest: bool = False,
                  custom_message: Optional[str] = None,
                  optional: bool = False,
                  src_type: Optional[RType] = None) -> None:
        """Emit code for casting a value of given type.

        Somewhat strangely, this supports unboxed types but only
        operates on boxed versions.  This is necessary to properly
        handle types such as Optional[int] in compatability glue.

        Assign NULL (error value) to dest if the value has an incompatible type.

        Always copy/steal the reference in src.

        Args:
            src: Name of source C variable
            dest: Name of target C variable
            typ: Type of value
            declare_dest: If True, also declare the variable 'dest'

        """
        if custom_message is not None:
            err = custom_message
        else:
            err = 'PyErr_SetString(PyExc_TypeError, "{} object expected");'.format(
                self.pretty_name(typ))

        # Special case casting *from* optional
        if src_type and is_optional_type(
                src_type) and not is_object_rprimitive(typ):
            value_type = optional_value_type(src_type)
            assert value_type is not None
            if is_same_type(value_type, typ):
                if declare_dest:
                    self.emit_line('PyObject *{};'.format(dest))
                self.emit_arg_check(src, dest, typ,
                                    '({} != Py_None)'.format(src), optional)
                self.emit_lines('    {} = {};'.format(dest, src), 'else {',
                                err, '{} = NULL;'.format(dest), '}')
                return

        # TODO: Verify refcount handling.
        if (is_list_rprimitive(typ) or is_dict_rprimitive(typ)
                or is_set_rprimitive(typ) or is_float_rprimitive(typ)
                or is_str_rprimitive(typ) or is_int_rprimitive(typ)
                or is_bool_rprimitive(typ)):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            if is_list_rprimitive(typ):
                prefix = 'PyList'
            elif is_dict_rprimitive(typ):
                prefix = 'PyDict'
            elif is_set_rprimitive(typ):
                prefix = 'PySet'
            elif is_float_rprimitive(typ):
                prefix = 'CPyFloat'
            elif is_str_rprimitive(typ):
                prefix = 'PyUnicode'
            elif is_int_rprimitive(typ):
                prefix = 'PyLong'
            elif is_bool_rprimitive(typ):
                prefix = 'PyBool'
            else:
                assert False, prefix
            self.emit_arg_check(src, dest, typ,
                                '({}_Check({}))'.format(prefix, src), optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_tuple_rprimitive(typ):
            if declare_dest:
                self.emit_line('{} {};'.format(self.ctype(typ), dest))
            self.emit_arg_check(src, dest, typ,
                                '(PyTuple_Check({}))'.format(src), optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif isinstance(typ, RInstance):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            if typ.class_ir.children:
                check = '(PyObject_TypeCheck({}, {}))'.format(
                    src, self.type_struct_name(typ.class_ir))
            else:
                # If the class has no children, just check the type directly
                check = '(Py_TYPE({}) == {})'.format(
                    src, self.type_struct_name(typ.class_ir))
            self.emit_arg_check(src, dest, typ, check, optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_none_rprimitive(typ):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_arg_check(src, dest, typ, '({} == Py_None)'.format(src),
                                optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_object_rprimitive(typ):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_arg_check(src, dest, typ, '', optional)
            self.emit_line('{} = {};'.format(dest, src))
            if optional:
                self.emit_line('}')
        elif isinstance(typ, RUnion):
            self.emit_union_cast(src, dest, typ, declare_dest, err, optional,
                                 src_type)
        elif isinstance(typ, RTuple):
            assert not optional
            self.emit_tuple_cast(src, dest, typ, declare_dest, err, src_type)
        else:
            assert False, 'Cast not implemented: %s' % typ
Example #10
0
    def emit_cast(self,
                  src: str,
                  dest: str,
                  typ: RType,
                  declare_dest: bool = False,
                  custom_message: Optional[str] = None,
                  optional: bool = False,
                  src_type: Optional[RType] = None,
                  likely: bool = True) -> None:
        """Emit code for casting a value of given type.

        Somewhat strangely, this supports unboxed types but only
        operates on boxed versions.  This is necessary to properly
        handle types such as Optional[int] in compatibility glue.

        Assign NULL (error value) to dest if the value has an incompatible type.

        Always copy/steal the reference in src.

        Args:
            src: Name of source C variable
            dest: Name of target C variable
            typ: Type of value
            declare_dest: If True, also declare the variable 'dest'
            likely: If the cast is likely to succeed (can be False for unions)
        """
        if custom_message is not None:
            err = custom_message
        else:
            err = 'CPy_TypeError("{}", {});'.format(self.pretty_name(typ), src)

        # Special case casting *from* optional
        if src_type and is_optional_type(
                src_type) and not is_object_rprimitive(typ):
            value_type = optional_value_type(src_type)
            assert value_type is not None
            if is_same_type(value_type, typ):
                if declare_dest:
                    self.emit_line('PyObject *{};'.format(dest))
                check = '({} != Py_None)'
                if likely:
                    check = '(likely{})'.format(check)
                self.emit_arg_check(src, dest, typ, check.format(src),
                                    optional)
                self.emit_lines('    {} = {};'.format(dest, src), 'else {',
                                err, '{} = NULL;'.format(dest), '}')
                return

        # TODO: Verify refcount handling.
        if (is_list_rprimitive(typ) or is_dict_rprimitive(typ)
                or is_set_rprimitive(typ) or is_float_rprimitive(typ)
                or is_str_rprimitive(typ) or is_int_rprimitive(typ)
                or is_bool_rprimitive(typ)):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            if is_list_rprimitive(typ):
                prefix = 'PyList'
            elif is_dict_rprimitive(typ):
                prefix = 'PyDict'
            elif is_set_rprimitive(typ):
                prefix = 'PySet'
            elif is_float_rprimitive(typ):
                prefix = 'CPyFloat'
            elif is_str_rprimitive(typ):
                prefix = 'PyUnicode'
            elif is_int_rprimitive(typ):
                prefix = 'PyLong'
            elif is_bool_rprimitive(typ):
                prefix = 'PyBool'
            else:
                assert False, 'unexpected primitive type'
            check = '({}_Check({}))'
            if likely:
                check = '(likely{})'.format(check)
            self.emit_arg_check(src, dest, typ, check.format(prefix, src),
                                optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_tuple_rprimitive(typ):
            if declare_dest:
                self.emit_line('{} {};'.format(self.ctype(typ), dest))
            check = '(PyTuple_Check({}))'
            if likely:
                check = '(likely{})'.format(check)
            self.emit_arg_check(src, dest, typ, check.format(src), optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif isinstance(typ, RInstance):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            concrete = all_concrete_classes(typ.class_ir)
            n_types = len(concrete)
            # If there are too many concrete subclasses or we can't find any
            # (meaning the code ought to be dead), fall back to a normal typecheck.
            # Otherwise check all the subclasses.
            if n_types == 0 or n_types > FAST_ISINSTANCE_MAX_SUBCLASSES + 1:
                check = '(PyObject_TypeCheck({}, {}))'.format(
                    src, self.type_struct_name(typ.class_ir))
            else:
                full_str = '(Py_TYPE({src}) == {targets[0]})'
                for i in range(1, n_types):
                    full_str += ' || (Py_TYPE({src}) == {targets[%d]})' % i
                if n_types > 1:
                    full_str = '(%s)' % full_str
                check = full_str.format(
                    src=src,
                    targets=[self.type_struct_name(ir) for ir in concrete])
            if likely:
                check = '(likely{})'.format(check)
            self.emit_arg_check(src, dest, typ, check, optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_none_rprimitive(typ):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            check = '({} == Py_None)'
            if likely:
                check = '(likely{})'.format(check)
            self.emit_arg_check(src, dest, typ, check.format(src), optional)
            self.emit_lines('    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_object_rprimitive(typ):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_arg_check(src, dest, typ, '', optional)
            self.emit_line('{} = {};'.format(dest, src))
            if optional:
                self.emit_line('}')
        elif isinstance(typ, RUnion):
            self.emit_union_cast(src, dest, typ, declare_dest, err, optional,
                                 src_type)
        elif isinstance(typ, RTuple):
            assert not optional
            self.emit_tuple_cast(src, dest, typ, declare_dest, err, src_type)
        else:
            assert False, 'Cast not implemented: %s' % typ
Example #11
0
File: emit.py Project: kxing/mypyc
    def emit_cast(self,
                  src: str,
                  dest: str,
                  typ: RType,
                  declare_dest: bool = False,
                  custom_message: Optional[str] = None) -> None:
        """Emit code for casting a value of given type.

        Somewhat strangely, this supports unboxed types but only
        operates on boxed versions.  This is necessary to properly
        handle types such as Optional[int] in compatability glue.

        Assign NULL (error value) to dest if the value has an incompatible type.

        Always copy/steal the reference in src.

        Args:
            src: Name of source C variable
            dest: Name of target C variable
            typ: Type of value
            declare_dest: If True, also declare the variable 'dest'

        """
        if custom_message is not None:
            err = custom_message
        else:
            err = 'PyErr_SetString(PyExc_TypeError, "{} object expected");'.format(
                self.pretty_name(typ))
        # TODO: Verify refcount handling.
        if (is_list_rprimitive(typ) or is_dict_rprimitive(typ)
                or is_set_rprimitive(typ) or is_float_rprimitive(typ)
                or is_str_rprimitive(typ) or is_int_rprimitive(typ)
                or is_bool_rprimitive(typ)):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            if is_list_rprimitive(typ):
                prefix = 'PyList'
            elif is_dict_rprimitive(typ):
                prefix = 'PyDict'
            elif is_set_rprimitive(typ):
                prefix = 'PySet'
            elif is_float_rprimitive(typ):
                prefix = 'PyFloat'
            elif is_str_rprimitive(typ):
                prefix = 'PyUnicode'
            elif is_int_rprimitive(typ):
                prefix = 'PyLong'
            elif is_bool_rprimitive(typ):
                prefix = 'PyBool'
            else:
                assert False, prefix
            self.emit_lines('if ({}_Check({}))'.format(prefix, src),
                            '    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_tuple_rprimitive(typ):
            if declare_dest:
                self.emit_line('{} {};'.format(self.ctype(typ), dest))
            self.emit_lines('if (PyTuple_Check({}))'.format(src),
                            '    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif isinstance(typ, RInstance):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_lines(
                'if (PyObject_TypeCheck({}, &{}))'.format(
                    src, self.type_struct_name(typ.class_ir)),
                '    {} = {};'.format(dest, src), 'else {', err,
                '{} = NULL;'.format(dest), '}')
        elif is_none_rprimitive(typ):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_lines('if ({} == Py_None)'.format(src),
                            '    {} = {};'.format(dest, src), 'else {', err,
                            '{} = NULL;'.format(dest), '}')
        elif is_object_rprimitive(typ):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_line('{} = {};'.format(dest, src))
        elif isinstance(typ, ROptional):
            if declare_dest:
                self.emit_line('PyObject *{};'.format(dest))
            self.emit_lines('if ({} == Py_None)'.format(src),
                            '    {} = {};'.format(dest, src), 'else {')
            self.emit_cast(src, dest, typ.value_type, custom_message=err)
            self.emit_line('}')
        else:
            assert False, 'Cast not implemented: %s' % typ
Example #12
0
 def visit_rprimitive(self, left: RPrimitive) -> bool:
     if is_bool_rprimitive(left) and is_int_rprimitive(self.right):
         return True
     return isinstance(self.right, RPrimitive) and left.name == self.right.name