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(
# 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,
"""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,
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)
# 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),
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',
# 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.
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,
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',
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',
"""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',
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,
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',
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)