) # These int constructors produce object_rprimitives that then need to be unboxed # I guess unboxing ourselves would save a check and branch though? # For ordinary calls to int() we use a name_ref to the type name_ref_op('builtins.int', result_type=object_rprimitive, error_kind=ERR_NEVER, emit=simple_emit('{dest} = (PyObject *)&PyLong_Type;'), is_borrowed=True) # Convert from a float. We could do a bit better directly. func_op(name='builtins.int', arg_types=[float_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyLong_FromFloat'), priority=1) def int_binary_op(op: str, c_func_name: str, result_type: RType = int_rprimitive, error_kind: int = ERR_NEVER) -> None: binary_op(op=op, arg_types=[int_rprimitive, int_rprimitive], result_type=result_type, error_kind=error_kind, format_str='{dest} = {args[0]} %s {args[1]} :: int' % op, emit=call_emit(c_func_name))
"""Primitive set (and frozenset) ops.""" from mypyc.primitives.registry import (func_op, method_op, binary_op, simple_emit, negative_int_emit, call_negative_bool_emit, c_function_op, c_method_op) from mypyc.ir.ops import ERR_MAGIC, ERR_FALSE, ERR_NEVER, ERR_NEG_INT, EmitterInterface from mypyc.ir.rtypes import (object_rprimitive, bool_rprimitive, set_rprimitive, int_rprimitive, c_int_rprimitive) from typing import List # Construct an empty set. new_set_op = func_op(name='builtins.set', arg_types=[], result_type=set_rprimitive, error_kind=ERR_MAGIC, emit=simple_emit('{dest} = PySet_New(NULL);')) # set(obj) c_function_op(name='builtins.set', arg_types=[object_rprimitive], return_type=set_rprimitive, c_function_name='PySet_New', error_kind=ERR_MAGIC) # frozenset(obj) c_function_op(name='builtins.frozenset', arg_types=[object_rprimitive], return_type=object_rprimitive, c_function_name='PyFrozenSet_New', error_kind=ERR_MAGIC)
# Construct a dictionary from keys and values. # Arguments are (key1, value1, ..., keyN, valueN). new_dict_op = custom_op( name='builtins.dict', arg_types=[object_rprimitive], is_var_arg=True, result_type=dict_rprimitive, format_str='{dest} = {{{colon_args}}}', error_kind=ERR_MAGIC, emit=emit_new_dict) # Construct a dictionary from another dictionary. func_op( name='builtins.dict', arg_types=[dict_rprimitive], result_type=dict_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PyDict_Copy'), priority=2) # Generic one-argument dict constructor: dict(obj) func_op( name='builtins.dict', arg_types=[object_rprimitive], result_type=dict_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyDict_FromAny')) def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: temp = emitter.temp_name()
bool_rprimitive, int_rprimitive, list_rprimitive) from mypyc.primitives.registry import (func_op, binary_op, simple_emit, name_ref_op, method_op, call_emit, name_emit, c_method_op) # Get the 'str' type object. name_ref_op('builtins.str', result_type=object_rprimitive, error_kind=ERR_NEVER, emit=name_emit('&PyUnicode_Type', target_type='PyObject *'), is_borrowed=True) # str(obj) func_op(name='builtins.str', arg_types=[object_rprimitive], result_type=str_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PyObject_Str')) # str1 + str2 binary_op(op='+', arg_types=[str_rprimitive, str_rprimitive], result_type=str_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PyUnicode_Concat')) # str.join(obj) c_method_op(name='join', arg_types=[str_rprimitive, object_rprimitive], return_type=str_rprimitive, c_function_name='PyUnicode_Join',
is_borrowed=True) # isinstance(obj, cls) c_function_op(name='builtins.isinstance', arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, c_function_name='PyObject_IsInstance', error_kind=ERR_NEG_INT, truncated_type=bool_rprimitive) # Faster isinstance(obj, cls) that only works with native classes and doesn't perform # type checking of the type argument. fast_isinstance_op = func_op( 'builtins.isinstance', arg_types=[object_rprimitive, object_rprimitive], result_type=bool_rprimitive, error_kind=ERR_NEVER, emit=simple_emit( '{dest} = PyObject_TypeCheck({args[0]}, (PyTypeObject *){args[1]});'), priority=0) # Exact type check that doesn't consider subclasses: type(obj) is cls type_is_op = custom_op( name='type_is', arg_types=[object_rprimitive, object_rprimitive], result_type=bool_rprimitive, error_kind=ERR_NEVER, emit=simple_emit( '{dest} = Py_TYPE({args[0]}) == (PyTypeObject *){args[1]};')) # bool(obj) with unboxed result bool_op = func_op('builtins.bool',
from typing import List, Callable from mypyc.ops import ERR_MAGIC, ERR_NEVER, EmitterInterface, EmitCallback from mypyc.rtypes import (RType, object_rprimitive, str_rprimitive, bool_rprimitive, int_rprimitive, list_rprimitive) from mypyc.primitives.registry import func_op, binary_op, simple_emit, name_ref_op, method_op name_ref_op('builtins.str', result_type=object_rprimitive, error_kind=ERR_NEVER, emit=simple_emit('{dest} = (PyObject *)&PyUnicode_Type;'), is_borrowed=True) func_op(name='builtins.str', arg_types=[object_rprimitive], result_type=str_rprimitive, error_kind=ERR_MAGIC, emit=simple_emit('{dest} = PyObject_Str({args[0]});')) binary_op(op='+', arg_types=[str_rprimitive, str_rprimitive], result_type=str_rprimitive, error_kind=ERR_MAGIC, emit=simple_emit('{dest} = PyUnicode_Concat({args[0]}, {args[1]});')) method_op(name='join', arg_types=[str_rprimitive, object_rprimitive], result_type=str_rprimitive, error_kind=ERR_MAGIC, emit=simple_emit('{dest} = PyUnicode_Join({args[0]}, {args[1]});'))
# These int constructors produce object_rprimitives that then need to be unboxed # I guess unboxing ourselves would save a check and branch though? # Get the type object for 'builtins.int'. # For ordinary calls to int() we use a name_ref to the type name_ref_op('builtins.int', result_type=object_rprimitive, error_kind=ERR_NEVER, emit=name_emit('&PyLong_Type', target_type='PyObject *'), is_borrowed=True) # Convert from a float to int. We could do a bit better directly. func_op( name='builtins.int', arg_types=[float_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyLong_FromFloat'), priority=1) # int(string) func_op( name='builtins.int', arg_types=[str_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyLong_FromStr'), priority=1) # int(string, base) func_op(
is_borrowed=True) # isinstance(obj, cls) c_function_op(name='builtins.isinstance', arg_types=[object_rprimitive, object_rprimitive], return_type=c_int_rprimitive, c_function_name='PyObject_IsInstance', error_kind=ERR_NEG_INT, truncated_type=bool_rprimitive) # Faster isinstance(obj, cls) that only works with native classes and doesn't perform # type checking of the type argument. fast_isinstance_op = func_op( 'builtins.isinstance', arg_types=[object_rprimitive, object_rprimitive], result_type=bool_rprimitive, error_kind=ERR_NEVER, emit=simple_emit( '{dest} = PyObject_TypeCheck({args[0]}, (PyTypeObject *){args[1]});'), priority=0) # Exact type check that doesn't consider subclasses: type(obj) is cls type_is_op = custom_op( name='type_is', arg_types=[object_rprimitive, object_rprimitive], result_type=bool_rprimitive, error_kind=ERR_NEVER, emit=simple_emit( '{dest} = Py_TYPE({args[0]}) == (PyTypeObject *){args[1]};')) # bool(obj) with unboxed result bool_op = c_function_op(name='builtins.bool',
result_type=list_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyDict_Items')) def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: temp = emitter.temp_name() emitter.emit_declaration('Py_ssize_t %s;' % temp) emitter.emit_line('%s = PyDict_Size(%s);' % (temp, args[0])) emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) # len(dict) func_op(name='builtins.len', arg_types=[dict_rprimitive], result_type=int_rprimitive, error_kind=ERR_NEVER, emit=emit_len) # PyDict_Next() fast iteration dict_key_iter_op = custom_op( name='key_iter', arg_types=[dict_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyDict_GetKeysIter'), ) dict_value_iter_op = custom_op( name='value_iter', arg_types=[dict_rprimitive],
error_kind=ERR_MAGIC) # list * int c_binary_op(name='*', arg_types=[list_rprimitive, int_rprimitive], return_type=list_rprimitive, c_function_name='CPySequence_Multiply', error_kind=ERR_MAGIC) # int * list c_binary_op(name='*', arg_types=[int_rprimitive, list_rprimitive], return_type=list_rprimitive, c_function_name='CPySequence_RMultiply', error_kind=ERR_MAGIC) def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: temp = emitter.temp_name() emitter.emit_declaration('Py_ssize_t %s;' % temp) emitter.emit_line('%s = PyList_GET_SIZE(%s);' % (temp, args[0])) emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) # len(list) list_len_op = func_op(name='builtins.len', arg_types=[list_rprimitive], result_type=short_int_rprimitive, error_kind=ERR_NEVER, emit=emit_len)
error_kind=ERR_FALSE, emit=call_negative_bool_emit('PyObject_SetItem'), priority=0) # del obj1[obj2] method_op('__delitem__', arg_types=[object_rprimitive, object_rprimitive], result_type=bool_rprimitive, error_kind=ERR_FALSE, emit=call_negative_bool_emit('PyObject_DelItem'), priority=0) # hash(obj) func_op( name='builtins.hash', arg_types=[object_rprimitive], result_type=int_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyObject_Hash')) # getattr(obj, attr) py_getattr_op = func_op( name='builtins.getattr', arg_types=[object_rprimitive, object_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPyObject_GetAttr') ) # getattr(obj, attr, default) func_op( name='builtins.getattr',
ellipsis_op = custom_op(name='...', arg_types=[], result_type=object_rprimitive, error_kind=ERR_NEVER, emit=name_emit('Py_Ellipsis'), is_borrowed=True) not_implemented_op = name_ref_op(name='builtins.NotImplemented', result_type=object_rprimitive, error_kind=ERR_NEVER, emit=name_emit('Py_NotImplemented'), is_borrowed=True) func_op(name='builtins.id', arg_types=[object_rprimitive], result_type=int_rprimitive, error_kind=ERR_NEVER, emit=call_emit('CPyTagged_Id')) iter_op = func_op(name='builtins.iter', arg_types=[object_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PyObject_GetIter')) coro_op = custom_op(name='get_coroutine_obj', arg_types=[object_rprimitive], result_type=object_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('CPy_GetCoro'))
name_emit, call_emit, call_negative_bool_emit, ) # Get the 'builtins.list' type object. name_ref_op('builtins.list', result_type=object_rprimitive, error_kind=ERR_NEVER, emit=name_emit('&PyList_Type', target_type='PyObject *'), is_borrowed=True) # list(obj) to_list = func_op(name='builtins.list', arg_types=[object_rprimitive], result_type=list_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PySequence_List')) def emit_new(emitter: EmitterInterface, args: List[str], dest: str) -> None: # TODO: This would be better split into multiple smaller ops. emitter.emit_line('%s = PyList_New(%d); ' % (dest, len(args))) emitter.emit_line('if (likely(%s != NULL)) {' % dest) for i, arg in enumerate(args): emitter.emit_line('PyList_SET_ITEM(%s, %s, %s);' % (dest, i, arg)) emitter.emit_line('}') # Construct a list from values: [item1, item2, ....] new_list_op = custom_op(arg_types=[object_rprimitive],
error_kind=ERR_MAGIC, steals=False, format_str='{dest} = ({comma_args}) :: tuple', emit=simple_emit('{dest} = PyTuple_Pack({num_args}{pre_comma_args});')) def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None: temp = emitter.temp_name() emitter.emit_declaration('Py_ssize_t %s;' % temp) emitter.emit_line('%s = PyTuple_GET_SIZE(%s);' % (temp, args[0])) emitter.emit_line('%s = CPyTagged_ShortFromSsize_t(%s);' % (dest, temp)) tuple_len_op = func_op( name='builtins.len', arg_types=[tuple_rprimitive], result_type=int_rprimitive, error_kind=ERR_NEVER, emit=emit_len) list_tuple_op = func_op( name='builtins.tuple', arg_types=[list_rprimitive], result_type=tuple_rprimitive, error_kind=ERR_MAGIC, emit=call_emit('PyList_AsTuple'), priority=2) func_op( name='builtins.tuple', arg_types=[object_rprimitive],