Example #1
0
    error_kind=ERR_NEVER)

# del obj.attr
py_delattr_op = c_function_op(
    name='builtins.delattr',
    arg_types=[object_rprimitive, object_rprimitive],
    return_type=c_int_rprimitive,
    c_function_name='PyObject_DelAttr',
    error_kind=ERR_NEG_INT)

# Call callable object with N positional arguments: func(arg1, ..., argN)
# Arguments are (func, arg1, ..., argN).
py_call_op = c_custom_op(
    arg_types=[],
    return_type=object_rprimitive,
    c_function_name='PyObject_CallFunctionObjArgs',
    error_kind=ERR_MAGIC,
    var_arg_type=object_rprimitive,
    extra_int_constants=[(0, pointer_rprimitive)])

# Call callable object with positional + keyword args: func(*args, **kwargs)
# Arguments are (func, *args tuple, **kwargs dict).
py_call_with_kwargs_op = c_custom_op(
    arg_types=[object_rprimitive, object_rprimitive, object_rprimitive],
    return_type=object_rprimitive,
    c_function_name='PyObject_Call',
    error_kind=ERR_MAGIC)

# Call method with positional arguments: obj.method(arg1, ...)
# Arguments are (object, attribute name, arg1, ...).
py_method_call_op = c_custom_op(
Example #2
0
# Get the 'builtins.list' type object.
load_address_op(name='builtins.list',
                type=object_rprimitive,
                src='PyList_Type')

# list(obj)
to_list = c_function_op(
    name='builtins.list',
    arg_types=[object_rprimitive],
    return_type=list_rprimitive,
    c_function_name='PySequence_List',
    error_kind=ERR_MAGIC,
)

new_list_op = c_custom_op(arg_types=[c_pyssize_t_rprimitive],
                          return_type=list_rprimitive,
                          c_function_name='PyList_New',
                          error_kind=ERR_MAGIC)

# list[index] (for an integer index)
list_get_item_op = c_method_op(name='__getitem__',
                               arg_types=[list_rprimitive, int_rprimitive],
                               return_type=object_rprimitive,
                               c_function_name='CPyList_GetItem',
                               error_kind=ERR_MAGIC)

# Version with no int bounds check for when it is known to be short
c_method_op(name='__getitem__',
            arg_types=[list_rprimitive, short_int_rprimitive],
            return_type=object_rprimitive,
            c_function_name='CPyList_GetItemShort',
            error_kind=ERR_MAGIC,
Example #3
0
"""Exception-related primitive ops."""

from mypyc.ir.ops import ERR_NEVER, ERR_FALSE, ERR_ALWAYS
from mypyc.ir.rtypes import object_rprimitive, void_rtype, exc_rtuple, bit_rprimitive
from mypyc.primitives.registry import c_custom_op

# If the argument is a class, raise an instance of the class. Otherwise, assume
# that the argument is an exception object, and raise it.
raise_exception_op = c_custom_op(arg_types=[object_rprimitive],
                                 return_type=void_rtype,
                                 c_function_name='CPy_Raise',
                                 error_kind=ERR_ALWAYS)

# Raise StopIteration exception with the specified value (which can be NULL).
set_stop_iteration_value = c_custom_op(
    arg_types=[object_rprimitive],
    return_type=void_rtype,
    c_function_name='CPyGen_SetStopIterationValue',
    error_kind=ERR_ALWAYS)

# Raise exception with traceback.
# Arguments are (exception type, exception value, traceback).
raise_exception_with_tb_op = c_custom_op(
    arg_types=[object_rprimitive, object_rprimitive, object_rprimitive],
    return_type=void_rtype,
    c_function_name='CPyErr_SetObjectAndTraceback',
    error_kind=ERR_ALWAYS)

# Reraise the currently raised exception.
reraise_exception_op = c_custom_op(arg_types=[],
                                   return_type=void_rtype,
Example #4
0
for i in range(len(str_split_types)):
    c_method_op(name='split',
                arg_types=str_split_types[0:i + 1],
                return_type=list_rprimitive,
                c_function_name=str_split_functions[i],
                extra_int_constants=str_split_constants[i],
                error_kind=ERR_MAGIC)

# str1 += str2
#
# PyUnicodeAppend makes an effort to reuse the LHS when the refcount
# is 1. This is super dodgy but oh well, the interpreter does it.
c_binary_op(name='+=',
            arg_types=[str_rprimitive, str_rprimitive],
            return_type=str_rprimitive,
            c_function_name='CPyStr_Append',
            error_kind=ERR_MAGIC,
            steals=[True, False])

unicode_compare = c_custom_op(arg_types=[str_rprimitive, str_rprimitive],
                              return_type=c_int_rprimitive,
                              c_function_name='PyUnicode_Compare',
                              error_kind=ERR_NEVER)

# str[begin:end]
str_slice_op = c_custom_op(
    arg_types=[str_rprimitive, int_rprimitive, int_rprimitive],
    return_type=object_rprimitive,
    c_function_name='CPyStr_GetSlice',
    error_kind=ERR_MAGIC)
Example #5
0
# Description for building int logical ops
# For each field:
# binary_op_variant: identify which BinaryIntOp to use when operands are short integers
# c_func_description: the C function to call when operands are tagged integers
# c_func_negated: whether to negate the C function call's result
# c_func_swap_operands: whether to swap lhs and rhs when call the function
IntLogicalOpDescrption = NamedTuple(
    'IntLogicalOpDescrption', [('binary_op_variant', int),
                               ('c_func_description', CFunctionDescription),
                               ('c_func_negated', bool),
                               ('c_func_swap_operands', bool)])

# description for equal operation on two boxed tagged integers
int_equal_ = c_custom_op(arg_types=[int_rprimitive, int_rprimitive],
                         return_type=bool_rprimitive,
                         c_function_name='CPyTagged_IsEq_',
                         error_kind=ERR_NEVER)

int_less_than_ = c_custom_op(arg_types=[int_rprimitive, int_rprimitive],
                             return_type=bool_rprimitive,
                             c_function_name='CPyTagged_IsLt_',
                             error_kind=ERR_NEVER)

# provide mapping from textual op to short int's op variant and boxed int's description
# note these are not complete implementations
int_logical_op_mapping = {
    '==': IntLogicalOpDescrption(BinaryIntOp.EQ, int_equal_, False, False),
    '!=': IntLogicalOpDescrption(BinaryIntOp.NEQ, int_equal_, True, False),
    '<': IntLogicalOpDescrption(BinaryIntOp.SLT, int_less_than_, False, False),
    '<=': IntLogicalOpDescrption(BinaryIntOp.SLE, int_less_than_, True, True),
    '>': IntLogicalOpDescrption(BinaryIntOp.SGT, int_less_than_, False, True),
Example #6
0
            truncated_type=bool_rprimitive,
            ordering=[1, 0])

# dict1.update(dict2)
dict_update_op = c_method_op(name='update',
                             arg_types=[dict_rprimitive, dict_rprimitive],
                             return_type=c_int_rprimitive,
                             c_function_name='CPyDict_Update',
                             error_kind=ERR_NEG_INT,
                             priority=2)

# Operation used for **value in dict displays.
# This is mostly like dict.update(obj), but has customized error handling.
dict_update_in_display_op = c_custom_op(
    arg_types=[dict_rprimitive, dict_rprimitive],
    return_type=c_int_rprimitive,
    c_function_name='CPyDict_UpdateInDisplay',
    error_kind=ERR_NEG_INT)

# dict.update(obj)
c_method_op(name='update',
            arg_types=[dict_rprimitive, object_rprimitive],
            return_type=c_int_rprimitive,
            c_function_name='CPyDict_UpdateFromAny',
            error_kind=ERR_NEG_INT)

# dict.get(key, default)
c_method_op(name='get',
            arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive],
            return_type=object_rprimitive,
            c_function_name='CPyDict_Get',
Example #7
0
# Get the boxed NotImplemented object
not_implemented_op = load_address_op(name='builtins.NotImplemented',
                                     type=object_rprimitive,
                                     src='_Py_NotImplementedStruct')

# id(obj)
c_function_op(name='builtins.id',
              arg_types=[object_rprimitive],
              return_type=int_rprimitive,
              c_function_name='CPyTagged_Id',
              error_kind=ERR_NEVER)

# Return the result of obj.__await()__ or obj.__iter__() (if no __await__ exists)
coro_op = c_custom_op(arg_types=[object_rprimitive],
                      return_type=object_rprimitive,
                      c_function_name='CPy_GetCoro',
                      error_kind=ERR_MAGIC)

# Do obj.send(value), or a next(obj) if second arg is None.
# (This behavior is to match the PEP 380 spec for yield from.)
# Like next_raw_op, don't swallow StopIteration,
# but also don't propagate an error.
# Can return NULL: see next_op.
send_op = c_custom_op(arg_types=[object_rprimitive, object_rprimitive],
                      return_type=object_rprimitive,
                      c_function_name='CPyIter_Send',
                      error_kind=ERR_NEVER)

# This is sort of unfortunate but oh well: yield_from_except performs most of the
# error handling logic in `yield from` operations. It returns a bool and a value.
# If the bool is true, then a StopIteration was received and we should return.
Example #8
0
            arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive],
            return_type=object_rprimitive,
            c_function_name='CPyDict_Get',
            error_kind=ERR_MAGIC)

# dict.get(key)
method_op(
    name='get',
    arg_types=[dict_rprimitive, object_rprimitive],
    result_type=object_rprimitive,
    error_kind=ERR_MAGIC,
    emit=simple_emit('{dest} = CPyDict_Get({args[0]}, {args[1]}, Py_None);'))

# Construct an empty dictionary.
dict_new_op = c_custom_op(arg_types=[],
                          return_type=dict_rprimitive,
                          c_function_name='PyDict_New',
                          error_kind=ERR_MAGIC)

# Construct a dictionary from keys and values.
# Positional argument is the number of key-value pairs
# Variable arguments are (key1, value1, ..., keyN, valueN).
dict_build_op = c_custom_op(arg_types=[c_pyssize_t_rprimitive],
                            return_type=dict_rprimitive,
                            c_function_name='CPyDict_Build',
                            error_kind=ERR_MAGIC,
                            var_arg_type=object_rprimitive)

# Construct a dictionary from another dictionary.
c_function_op(name='builtins.dict',
              arg_types=[dict_rprimitive],
              return_type=dict_rprimitive,
Example #9
0
# Get the boxed NotImplemented object
not_implemented_op = load_address_op(name='builtins.NotImplemented',
                                     type=object_rprimitive,
                                     src='_Py_NotImplementedStruct')

# id(obj)
c_function_op(name='builtins.id',
              arg_types=[object_rprimitive],
              return_type=int_rprimitive,
              c_function_name='CPyTagged_Id',
              error_kind=ERR_NEVER)

# Return the result of obj.__await()__ or obj.__iter__() (if no __await__ exists)
coro_op = c_custom_op(arg_types=[object_rprimitive],
                      return_type=object_rprimitive,
                      c_function_name='CPy_GetCoro',
                      error_kind=ERR_MAGIC)

# Do obj.send(value), or a next(obj) if second arg is None.
# (This behavior is to match the PEP 380 spec for yield from.)
# Like next_raw_op, don't swallow StopIteration,
# but also don't propagate an error.
# Can return NULL: see next_op.
send_op = c_custom_op(arg_types=[object_rprimitive, object_rprimitive],
                      return_type=object_rprimitive,
                      c_function_name='CPyIter_Send',
                      error_kind=ERR_NEVER)

# This is sort of unfortunate but oh well: yield_from_except performs most of the
# error handling logic in `yield from` operations. It returns a bool and a value.
# If the bool is true, then a StopIteration was received and we should return.
Example #10
0
    c_method_op, c_function_op, c_custom_op
)


# tuple[index] (for an int index)
tuple_get_item_op = c_method_op(
    name='__getitem__',
    arg_types=[tuple_rprimitive, int_rprimitive],
    return_type=object_rprimitive,
    c_function_name='CPySequenceTuple_GetItem',
    error_kind=ERR_MAGIC)

# Construct a boxed tuple from items: (item1, item2, ...)
new_tuple_op = c_custom_op(
    arg_types=[c_pyssize_t_rprimitive],
    return_type=tuple_rprimitive,
    c_function_name='PyTuple_Pack',
    error_kind=ERR_MAGIC,
    var_arg_type=object_rprimitive)

# Construct tuple from a list.
list_tuple_op = c_function_op(
    name='builtins.tuple',
    arg_types=[list_rprimitive],
    return_type=tuple_rprimitive,
    c_function_name='PyList_AsTuple',
    error_kind=ERR_MAGIC,
    priority=2)

# Construct tuple from an arbitrary (iterable) object.
c_function_op(
    name='builtins.tuple',
Example #11
0
    emit=call_emit('PyObject_Call'))

# Call method with positional arguments: obj.method(arg1, ...)
# Arguments are (object, attribute name, arg1, ...).
py_method_call_op = custom_op(
    arg_types=[object_rprimitive],
    result_type=object_rprimitive,
    is_var_arg=True,
    error_kind=ERR_MAGIC,
    format_str='{dest} = py_method_call({comma_args})',
    emit=simple_emit(
        '{dest} = CPyObject_CallMethodObjArgs({comma_args}, NULL);'))

# len(obj)
generic_len_op = c_custom_op(arg_types=[object_rprimitive],
                             return_type=int_rprimitive,
                             c_function_name='CPyObject_Size',
                             error_kind=ERR_NEVER)

# iter(obj)
iter_op = c_function_op(name='builtins.iter',
                        arg_types=[object_rprimitive],
                        return_type=object_rprimitive,
                        c_function_name='PyObject_GetIter',
                        error_kind=ERR_MAGIC)
# next(iterator)
#
# Although the error_kind is set to be ERR_NEVER, this can actually
# return NULL, and thus it must be checked using Branch.IS_ERROR.
next_op = c_custom_op(arg_types=[object_rprimitive],
                      return_type=object_rprimitive,
                      c_function_name='PyIter_Next',
Example #12
0
"""Exception-related primitive ops."""

from mypyc.ir.ops import ERR_NEVER, ERR_FALSE, ERR_ALWAYS
from mypyc.ir.rtypes import bool_rprimitive, object_rprimitive, void_rtype, exc_rtuple
from mypyc.primitives.registry import (simple_emit, call_emit, call_void_emit,
                                       call_and_fail_emit, custom_op,
                                       c_custom_op)

# If the argument is a class, raise an instance of the class. Otherwise, assume
# that the argument is an exception object, and raise it.
raise_exception_op = c_custom_op(arg_types=[object_rprimitive],
                                 return_type=void_rtype,
                                 c_function_name='CPy_Raise',
                                 error_kind=ERR_ALWAYS)

# Raise StopIteration exception with the specified value (which can be NULL).
set_stop_iteration_value = custom_op(
    arg_types=[object_rprimitive],
    result_type=bool_rprimitive,
    error_kind=ERR_FALSE,
    format_str='set_stop_iteration_value({args[0]}); {dest} = 0',
    emit=call_and_fail_emit('CPyGen_SetStopIterationValue'))

# Raise exception with traceback.
# Arguments are (exception type, exception value, traceback).
raise_exception_with_tb_op = custom_op(
    arg_types=[object_rprimitive, object_rprimitive, object_rprimitive],
    result_type=bool_rprimitive,
    error_kind=ERR_FALSE,
    format_str=
    'raise_exception_with_tb({args[0]}, {args[1]}, {args[2]}); {dest} = 0',
Example #13
0
from mypyc.ir.ops import ERR_MAGIC
from mypyc.ir.rtypes import (tuple_rprimitive, int_rprimitive, list_rprimitive,
                             object_rprimitive, c_pyssize_t_rprimitive)
from mypyc.primitives.registry import c_method_op, c_function_op, c_custom_op

# tuple[index] (for an int index)
tuple_get_item_op = c_method_op(name='__getitem__',
                                arg_types=[tuple_rprimitive, int_rprimitive],
                                return_type=object_rprimitive,
                                c_function_name='CPySequenceTuple_GetItem',
                                error_kind=ERR_MAGIC)

# Construct a boxed tuple from items: (item1, item2, ...)
new_tuple_op = c_custom_op(arg_types=[c_pyssize_t_rprimitive],
                           return_type=tuple_rprimitive,
                           c_function_name='PyTuple_Pack',
                           error_kind=ERR_MAGIC,
                           var_arg_type=object_rprimitive)

# Construct tuple from a list.
list_tuple_op = c_function_op(name='builtins.tuple',
                              arg_types=[list_rprimitive],
                              return_type=tuple_rprimitive,
                              c_function_name='PyList_AsTuple',
                              error_kind=ERR_MAGIC,
                              priority=2)

# Construct tuple from an arbitrary (iterable) object.
c_function_op(name='builtins.tuple',
              arg_types=[object_rprimitive],
              return_type=tuple_rprimitive,
Example #14
0
    error_kind=ERR_MAGIC)

# Version with no int bounds check for when it is known to be short
c_method_op(
    name='__getitem__',
    arg_types=[list_rprimitive, short_int_rprimitive],
    return_type=object_rprimitive,
    c_function_name='CPyList_GetItemShort',
    error_kind=ERR_MAGIC,
    priority=2)

# This is unsafe because it assumes that the index is a non-negative short integer
# that is in-bounds for the list.
list_get_item_unsafe_op = c_custom_op(
    arg_types=[list_rprimitive, short_int_rprimitive],
    return_type=object_rprimitive,
    c_function_name='CPyList_GetItemUnsafe',
    error_kind=ERR_NEVER)

# list[index] = obj
list_set_item_op = c_method_op(
    name='__setitem__',
    arg_types=[list_rprimitive, int_rprimitive, object_rprimitive],
    return_type=bool_rprimitive,
    c_function_name='CPyList_SetItem',
    error_kind=ERR_FALSE,
    steals=[False, False, True])

# list.append(obj)
list_append_op = c_method_op(
    name='append',
Example #15
0
str_split_constants = [[(0, pointer_rprimitive), (-1, c_int_rprimitive)],
                       [(-1, c_int_rprimitive)],
                       []] \
                       # type: List[List[Tuple[int, RType]]]
for i in range(len(str_split_types)):
    c_method_op(
        name='split',
        arg_types=str_split_types[0:i+1],
        return_type=list_rprimitive,
        c_function_name=str_split_functions[i],
        extra_int_constants=str_split_constants[i],
        error_kind=ERR_MAGIC)

# str1 += str2
#
# PyUnicodeAppend makes an effort to reuse the LHS when the refcount
# is 1. This is super dodgy but oh well, the interpreter does it.
c_binary_op(name='+=',
            arg_types=[str_rprimitive, str_rprimitive],
            return_type=str_rprimitive,
            c_function_name='CPyStr_Append',
            error_kind=ERR_MAGIC,
            steals=[True, False])


unicode_compare = c_custom_op(
    arg_types=[str_rprimitive, str_rprimitive],
    return_type=c_int_rprimitive,
    c_function_name='PyUnicode_Compare',
    error_kind=ERR_NEVER)