Esempio n. 1
0
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))
def int_binary_op(name: str,
                  c_function_name: str,
                  return_type: RType = int_rprimitive,
                  error_kind: int = ERR_NEVER) -> None:
    binary_op(name=name,
              arg_types=[int_rprimitive, int_rprimitive],
              return_type=return_type,
              c_function_name=c_function_name,
              error_kind=error_kind)
Esempio n. 3
0
def int_compare_op(op: str, c_func_name: str) -> None:
    int_binary_op(op, c_func_name, bool_rprimitive)
    # Generate a straight compare if we know both sides are short
    binary_op(op=op,
              arg_types=[short_int_rprimitive, short_int_rprimitive],
              result_type=bool_rprimitive,
              error_kind=ERR_NEVER,
              format_str='{dest} = {args[0]} %s {args[1]} :: short_int' % op,
              emit=simple_emit(
                  '{dest} = (Py_ssize_t){args[0]} %s (Py_ssize_t){args[1]};' % op),
              priority=2)
Esempio n. 4
0
                             c_function_name='CPyDict_GetItem',
                             error_kind=ERR_MAGIC)

# dict[key] = value
dict_set_item_op = method_op(
    name='__setitem__',
    arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive],
    return_type=c_int_rprimitive,
    c_function_name='CPyDict_SetItem',
    error_kind=ERR_NEG_INT)

# key in dict
binary_op(name='in',
          arg_types=[object_rprimitive, dict_rprimitive],
          return_type=c_int_rprimitive,
          c_function_name='PyDict_Contains',
          error_kind=ERR_NEG_INT,
          truncated_type=bool_rprimitive,
          ordering=[1, 0])

# dict1.update(dict2)
dict_update_op = 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 = custom_op(
Esempio n. 5
0
# Get the 'str' type object.
load_address_op(name='builtins.str',
                type=object_rprimitive,
                src='PyUnicode_Type')

# str(obj)
str_op = function_op(name='builtins.str',
                     arg_types=[object_rprimitive],
                     return_type=str_rprimitive,
                     c_function_name='PyObject_Str',
                     error_kind=ERR_MAGIC)

# str1 + str2
binary_op(name='+',
          arg_types=[str_rprimitive, str_rprimitive],
          return_type=str_rprimitive,
          c_function_name='PyUnicode_Concat',
          error_kind=ERR_MAGIC)

# str1 += str2
#
# PyUnicode_Append makes an effort to reuse the LHS when the refcount
# is 1. This is super dodgy but oh well, the interpreter does it.
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 = custom_op(arg_types=[str_rprimitive, str_rprimitive],
Esempio n. 6
0
            error_kind=ERR_MAGIC,
            steals=[True, False])


def emit_str_compare(
        comparison: str) -> Callable[[EmitterInterface, List[str], str], None]:
    def emit(emitter: EmitterInterface, args: List[str], dest: str) -> None:
        temp = emitter.temp_name()
        emitter.emit_declaration('int %s;' % temp)
        emitter.emit_lines(
            '%s = PyUnicode_Compare(%s, %s);' % (temp, args[0], args[1]),
            'if (%s == -1 && PyErr_Occurred())' % temp, '    %s = 2;' % dest,
            'else', '    %s = (%s %s);' % (dest, temp, comparison))

    return emit


# str1 == str2
binary_op(op='==',
          arg_types=[str_rprimitive, str_rprimitive],
          result_type=bool_rprimitive,
          error_kind=ERR_MAGIC,
          emit=emit_str_compare('== 0'))

# str1 != str2
binary_op(op='!=',
          arg_types=[str_rprimitive, str_rprimitive],
          result_type=bool_rprimitive,
          error_kind=ERR_MAGIC,
          emit=emit_str_compare('!= 0'))
Esempio n. 7
0
                     ('<<=', 'PyNumber_InPlaceLshift'),
                     ('>>=', 'PyNumber_InPlaceRshift'),
                     ('&=', 'PyNumber_InPlaceAnd'),
                     ('^=', 'PyNumber_InPlaceXor'),
                     ('|=', 'PyNumber_InPlaceOr')]:
    c_binary_op(name=op,
                arg_types=[object_rprimitive, object_rprimitive],
                return_type=object_rprimitive,
                c_function_name=funcname,
                error_kind=ERR_MAGIC,
                priority=0)

binary_op(op='**',
          arg_types=[object_rprimitive, object_rprimitive],
          result_type=object_rprimitive,
          error_kind=ERR_MAGIC,
          emit=simple_emit(
              '{dest} = PyNumber_Power({args[0]}, {args[1]}, Py_None);'),
          priority=0)

c_binary_op(name='in',
            arg_types=[object_rprimitive, object_rprimitive],
            return_type=c_int_rprimitive,
            c_function_name='PySequence_Contains',
            error_kind=ERR_NEG_INT,
            truncated_type=bool_rprimitive,
            ordering=[1, 0],
            priority=0)

# Unary operations
Esempio n. 8
0
          arg_types=[list_rprimitive, object_rprimitive],
          return_type=c_int_rprimitive,
          c_function_name='CPyList_Remove',
          error_kind=ERR_NEG_INT)

# list.index(obj)
method_op(name='index',
          arg_types=[list_rprimitive, object_rprimitive],
          return_type=int_rprimitive,
          c_function_name='CPyList_Index',
          error_kind=ERR_MAGIC)

# list * int
binary_op(name='*',
          arg_types=[list_rprimitive, int_rprimitive],
          return_type=list_rprimitive,
          c_function_name='CPySequence_Multiply',
          error_kind=ERR_MAGIC)

# int * list
binary_op(name='*',
          arg_types=[int_rprimitive, list_rprimitive],
          return_type=list_rprimitive,
          c_function_name='CPySequence_RMultiply',
          error_kind=ERR_MAGIC)

# list[begin:end]
list_slice_op = custom_op(
    arg_types=[list_rprimitive, int_rprimitive, int_rprimitive],
    return_type=object_rprimitive,
    c_function_name='CPyList_GetSlice',
Esempio n. 9
0
    result_type=object_rprimitive,
    error_kind=ERR_MAGIC,
    emit=call_emit('CPyDict_GetItem'))

# dict[key] = value
dict_set_item_op = method_op(
    name='__setitem__',
    arg_types=[dict_rprimitive, object_rprimitive, object_rprimitive],
    result_type=bool_rprimitive,
    error_kind=ERR_FALSE,
    emit=call_negative_bool_emit('CPyDict_SetItem'))

# key in dict
binary_op(op='in',
          arg_types=[object_rprimitive, dict_rprimitive],
          result_type=bool_rprimitive,
          error_kind=ERR_MAGIC,
          format_str='{dest} = {args[0]} in {args[1]} :: dict',
          emit=negative_int_emit('{dest} = PyDict_Contains({args[1]}, {args[0]});'))

# dict1.update(dict2)
dict_update_op = method_op(
    name='update',
    arg_types=[dict_rprimitive, dict_rprimitive],
    result_type=bool_rprimitive,
    error_kind=ERR_FALSE,
    emit=call_negative_bool_emit('CPyDict_Update'),
    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 = custom_op(
Esempio n. 10
0
            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',
            error_kind=ERR_MAGIC)

# str[index] (for an int index)
method_op(name='__getitem__',
          arg_types=[str_rprimitive, int_rprimitive],
          result_type=str_rprimitive,
          error_kind=ERR_MAGIC,
Esempio n. 11
0
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]});'))

str_split_types = [str_rprimitive, str_rprimitive,
                   int_rprimitive]  # type: List[RType]
str_split_emits = [simple_emit('{dest} = PyUnicode_Split({args[0]}, NULL, -1);'),
                   simple_emit('{dest} = PyUnicode_Split({args[0]}, {args[1]}, -1);'),
                   simple_emit('{dest} = CPyStr_Split({args[0]}, {args[1]}, {args[2]});')] \
                   # type: List[EmitCallback]
Esempio n. 12
0
# bytes(obj)
function_op(
    name='builtins.bytes',
    arg_types=[RUnion([list_rprimitive, dict_rprimitive, str_rprimitive])],
    return_type=bytes_rprimitive,
    c_function_name='PyBytes_FromObject',
    error_kind=ERR_MAGIC)

# bytearray(obj)
function_op(name='builtins.bytearray',
            arg_types=[object_rprimitive],
            return_type=bytes_rprimitive,
            c_function_name='PyByteArray_FromObject',
            error_kind=ERR_MAGIC)

# bytes + bytes
# bytearray + bytearray
binary_op(name='+',
          arg_types=[bytes_rprimitive, bytes_rprimitive],
          return_type=bytes_rprimitive,
          c_function_name='CPyBytes_Concat',
          error_kind=ERR_MAGIC,
          steals=[True, False])

# bytes.join(obj)
method_op(name='join',
          arg_types=[bytes_rprimitive, object_rprimitive],
          return_type=bytes_rprimitive,
          c_function_name='CPyBytes_Join',
          error_kind=ERR_MAGIC)
Esempio n. 13
0
                priority=0)

for op, funcname in [('+', 'PyNumber_Add'),
                     ('-', 'PyNumber_Subtract'),
                     ('*', 'PyNumber_Multiply'),
                     ('//', 'PyNumber_FloorDivide'),
                     ('/', 'PyNumber_TrueDivide'),
                     ('%', 'PyNumber_Remainder'),
                     ('<<', 'PyNumber_Lshift'),
                     ('>>', 'PyNumber_Rshift'),
                     ('&', 'PyNumber_And'),
                     ('^', 'PyNumber_Xor'),
                     ('|', 'PyNumber_Or')]:
    binary_op(op=op,
              arg_types=[object_rprimitive, object_rprimitive],
              result_type=object_rprimitive,
              error_kind=ERR_MAGIC,
              emit=call_emit(funcname),
              priority=0)

for op, funcname in [('+=', 'PyNumber_InPlaceAdd'),
                     ('-=', 'PyNumber_InPlaceSubtract'),
                     ('*=', 'PyNumber_InPlaceMultiply'),
                     ('@=', 'PyNumber_InPlaceMatrixMultiply'),
                     ('//=', 'PyNumber_InPlaceFloorDivide'),
                     ('/=', 'PyNumber_InPlaceTrueDivide'),
                     ('%=', 'PyNumber_InPlaceRemainder'),
                     ('<<=', 'PyNumber_InPlaceLshift'),
                     ('>>=', 'PyNumber_InPlaceRshift'),
                     ('&=', 'PyNumber_InPlaceAnd'),
                     ('^=', 'PyNumber_InPlaceXor'),
                     ('|=', 'PyNumber_InPlaceOr')]:
Esempio n. 14
0
# Binary operations

for op, opid in [
    ('==', 2),  # PY_EQ
    ('!=', 3),  # PY_NE
    ('<', 0),  # PY_LT
    ('<=', 1),  # PY_LE
    ('>', 4),  # PY_GT
    ('>=', 5)
]:  # PY_GE
    # The result type is 'object' since that's what PyObject_RichCompare returns.
    binary_op(name=op,
              arg_types=[object_rprimitive, object_rprimitive],
              return_type=object_rprimitive,
              c_function_name='PyObject_RichCompare',
              error_kind=ERR_MAGIC,
              extra_int_constants=[(opid, c_int_rprimitive)],
              priority=0)

for op, funcname in [('+', 'PyNumber_Add'), ('-', 'PyNumber_Subtract'),
                     ('*', 'PyNumber_Multiply'),
                     ('//', 'PyNumber_FloorDivide'),
                     ('/', 'PyNumber_TrueDivide'), ('%', 'PyNumber_Remainder'),
                     ('<<', 'PyNumber_Lshift'), ('>>', 'PyNumber_Rshift'),
                     ('&', 'PyNumber_And'), ('^', 'PyNumber_Xor'),
                     ('|', 'PyNumber_Or')]:
    binary_op(name=op,
              arg_types=[object_rprimitive, object_rprimitive],
              return_type=object_rprimitive,
              c_function_name=funcname,
Esempio n. 15
0
                     arg_types=[list_rprimitive, int_rprimitive],
                     result_type=object_rprimitive,
                     error_kind=ERR_MAGIC,
                     emit=call_emit('CPyList_Pop'))

# list.count(obj)
method_op(name='count',
          arg_types=[list_rprimitive, object_rprimitive],
          result_type=short_int_rprimitive,
          error_kind=ERR_MAGIC,
          emit=call_emit('CPyList_Count'))

# list * int
binary_op(op='*',
          arg_types=[list_rprimitive, int_rprimitive],
          result_type=list_rprimitive,
          error_kind=ERR_MAGIC,
          format_str='{dest} = {args[0]} * {args[1]} :: list',
          emit=call_emit("CPySequence_Multiply"))

# int * list
binary_op(op='*',
          arg_types=[int_rprimitive, list_rprimitive],
          result_type=list_rprimitive,
          error_kind=ERR_MAGIC,
          format_str='{dest} = {args[0]} * {args[1]} :: list',
          emit=call_emit("CPySequence_RMultiply"))


def emit_len(emitter: EmitterInterface, args: List[str], dest: str) -> None:
    temp = emitter.temp_name()
    emitter.emit_declaration('Py_ssize_t %s;' % temp)
Esempio n. 16
0
                       "%s = PySequence_Repeat(%s, %s);" % (dest, lst, temp))


def emit_multiply(emitter: EmitterInterface, args: List[str],
                  dest: str) -> None:
    emit_multiply_helper(emitter, dest, args[0], args[1])


def emit_multiply_reversed(emitter: EmitterInterface, args: List[str],
                           dest: str) -> None:
    emit_multiply_helper(emitter, dest, args[1], args[0])


binary_op(op='*',
          arg_types=[list_rprimitive, int_rprimitive],
          result_type=list_rprimitive,
          error_kind=ERR_MAGIC,
          format_str='{dest} = {args[0]} * {args[1]} :: list',
          emit=emit_multiply)

binary_op(op='*',
          arg_types=[int_rprimitive, list_rprimitive],
          result_type=list_rprimitive,
          error_kind=ERR_MAGIC,
          format_str='{dest} = {args[0]} * {args[1]} :: list',
          emit=emit_multiply_reversed)


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]))