Ejemplo n.º 1
0
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
    mp_obj_tuple_t *o = lhs;
    switch (op) {
        case MP_BINARY_OP_ADD: {
            if (!mp_obj_is_subclass_fast(mp_obj_get_type(rhs), (mp_obj_t)&mp_type_tuple)) {
                return MP_OBJ_NULL; // op not supported
            }
            mp_obj_tuple_t *p = rhs;
            mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL);
            mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
            return s;
        }
        case MP_BINARY_OP_MULTIPLY: {
            mp_int_t n;
            if (!mp_obj_get_int_maybe(rhs, &n)) {
                return MP_OBJ_NULL; // op not supported
            }
            if (n <= 0) {
                return mp_const_empty_tuple;
            }
            mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL);
            mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
            return s;
        }
        case MP_BINARY_OP_EQUAL:
        case MP_BINARY_OP_LESS:
        case MP_BINARY_OP_LESS_EQUAL:
        case MP_BINARY_OP_MORE:
        case MP_BINARY_OP_MORE_EQUAL:
            return MP_BOOL(tuple_cmp_helper(op, lhs, rhs));

        default:
            return MP_OBJ_NULL; // op not supported
    }
}
Ejemplo n.º 2
0
STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
    mp_obj_list_t *o = lhs;
    switch (op) {
        case MP_BINARY_OP_SUBSCR:
        {
#if MICROPY_ENABLE_SLICE
            if (MP_OBJ_IS_TYPE(rhs, &mp_type_slice)) {
                machine_uint_t start, stop;
                if (!m_seq_get_fast_slice_indexes(o->len, rhs, &start, &stop)) {
                    assert(0);
                }
                mp_obj_list_t *res = list_new(stop - start);
                m_seq_copy(res->items, o->items + start, res->len, mp_obj_t);
                return res;
            }
#endif
            uint index = mp_get_index(o->base.type, o->len, rhs, false);
            return o->items[index];
        }
        case MP_BINARY_OP_ADD:
        {
            if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
                return NULL;
            }
            mp_obj_list_t *p = rhs;
            mp_obj_list_t *s = list_new(o->len + p->len);
            m_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
            return s;
        }
        case MP_BINARY_OP_INPLACE_ADD:
        {
            if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
                return NULL;
            }
            list_extend(lhs, rhs);
            return o;
        }
        case MP_BINARY_OP_MULTIPLY: {
            machine_int_t n;
            if (!mp_obj_get_int_maybe(rhs, &n)) {
                return NULL;
            }
            mp_obj_list_t *s = list_new(o->len * n);
            mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
            return s;
        }
        case MP_BINARY_OP_EQUAL:
        case MP_BINARY_OP_LESS:
        case MP_BINARY_OP_LESS_EQUAL:
        case MP_BINARY_OP_MORE:
        case MP_BINARY_OP_MORE_EQUAL:
            return MP_BOOL(list_cmp_helper(op, lhs, rhs));
        case MP_BINARY_OP_NOT_EQUAL:
            return MP_BOOL(!list_cmp_helper(MP_BINARY_OP_EQUAL, lhs, rhs));

        default:
            // op not supported
            return NULL;
    }
}
Ejemplo n.º 3
0
// Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or
// be capped to the first/last character of the string, depending on is_slice.
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
                             mp_obj_t index, bool is_slice) {
    (void)type;
    mp_int_t i;
    // Copied from mp_get_index; I don't want bounds checking, just give me
    // the integer as-is. (I can't bounds-check without scanning the whole
    // string; an out-of-bounds index will be caught in the loops below.)
    if (MP_OBJ_IS_SMALL_INT(index)) {
        i = MP_OBJ_SMALL_INT_VALUE(index);
    } else if (!mp_obj_get_int_maybe(index, &i)) {
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "string indices must be integers, not %s", mp_obj_get_type_str(index)));
    }
    const byte *s, *top = self_data + self_len;
    if (i < 0)
    {
        // Negative indexing is performed by counting from the end of the string.
        for (s = top - 1; i; --s) {
            if (s < self_data) {
                if (is_slice) {
                    return self_data;
                }
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
            }
            if (!UTF8_IS_CONT(*s)) {
                ++i;
            }
        }
        ++s;
    } else if (!i) {
        return self_data; // Shortcut - str[0] is its base pointer
    } else {
        // Positive indexing, correspondingly, counts from the start of the string.
        // It's assumed that negative indexing will generally be used with small
        // absolute values (eg str[-1], not str[-1000000]), which means it'll be
        // more efficient this way.
        for (s = self_data; true; ++s) {
            if (s >= top) {
                if (is_slice) {
                    return top;
                }
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "string index out of range"));
            }
            while (UTF8_IS_CONT(*s)) {
                ++s;
            }
            if (!i--) {
                return s;
            }
        }
    }
    return s;
}
Ejemplo n.º 4
0
STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) {
    mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs);
    switch (op) {
        case MP_BINARY_OP_ADD: {
            if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
                return MP_OBJ_NULL; // op not supported
            }
            mp_obj_list_t *p = MP_OBJ_TO_PTR(rhs);
            mp_obj_list_t *s = list_new(o->len + p->len);
            mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
            return MP_OBJ_FROM_PTR(s);
        }
        case MP_BINARY_OP_INPLACE_ADD: {
            list_extend(lhs, rhs);
            return lhs;
        }
        case MP_BINARY_OP_MULTIPLY: {
            mp_int_t n;
            if (!mp_obj_get_int_maybe(rhs, &n)) {
                return MP_OBJ_NULL; // op not supported
            }
            if (n < 0) {
                n = 0;
            }
            mp_obj_list_t *s = list_new(o->len * n);
            mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
            return MP_OBJ_FROM_PTR(s);
        }
        case MP_BINARY_OP_EQUAL:
        case MP_BINARY_OP_LESS:
        case MP_BINARY_OP_LESS_EQUAL:
        case MP_BINARY_OP_MORE:
        case MP_BINARY_OP_MORE_EQUAL: {
            if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
                if (op == MP_BINARY_OP_EQUAL) {
                    return mp_const_false;
                }
                return MP_OBJ_NULL; // op not supported
            }

            mp_obj_list_t *another = MP_OBJ_TO_PTR(rhs);
            bool res = mp_seq_cmp_objs(op, o->items, o->len, another->items, another->len);
            return mp_obj_new_bool(res);
        }

        default:
            return MP_OBJ_NULL; // op not supported
    }
}
Ejemplo n.º 5
0
// If exc is SystemExit, return value where FORCED_EXIT bit set,
// and lower 8 bits are SystemExit value. For all other exceptions,
// return 1.
STATIC int handle_uncaught_exception(mp_obj_t exc) {
    // check for SystemExit
    if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) {
        // None is an exit value of 0; an int is its value; anything else is 1
        mp_obj_t exit_val = mp_obj_exception_get_value(exc);
        mp_int_t val = 0;
        if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) {
            val = 1;
        }
        return FORCED_EXIT | (val & 255);
    }

    // Report all other exceptions
    mp_obj_print_exception(&mp_stderr_print, exc);
    return 1;
}
Ejemplo n.º 6
0
STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
    mp_obj_list_t *o = lhs;
    switch (op) {
    case MP_BINARY_OP_ADD: {
        if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
            return MP_OBJ_NULL; // op not supported
        }
        mp_obj_list_t *p = rhs;
        mp_obj_list_t *s = list_new(o->len + p->len);
        mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
        return s;
    }
    case MP_BINARY_OP_INPLACE_ADD: {
        if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
            return MP_OBJ_NULL; // op not supported
        }
        list_extend(lhs, rhs);
        return o;
    }
    case MP_BINARY_OP_MULTIPLY: {
        mp_int_t n;
        if (!mp_obj_get_int_maybe(rhs, &n)) {
            return MP_OBJ_NULL; // op not supported
        }
        if (n < 0) {
            n = 0;
        }
        mp_obj_list_t *s = list_new(o->len * n);
        mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
        return s;
    }
    case MP_BINARY_OP_EQUAL:
    case MP_BINARY_OP_LESS:
    case MP_BINARY_OP_LESS_EQUAL:
    case MP_BINARY_OP_MORE:
    case MP_BINARY_OP_MORE_EQUAL:
        return MP_BOOL(list_cmp_helper(op, lhs, rhs));

    default:
        return MP_OBJ_NULL; // op not supported
    }
}
Ejemplo n.º 7
0
// is_slice determines whether the index is a slice index
size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice) {
    mp_int_t i;
    if (MP_OBJ_IS_SMALL_INT(index)) {
        i = MP_OBJ_SMALL_INT_VALUE(index);
    } else if (!mp_obj_get_int_maybe(index, &i)) {
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            mp_raise_TypeError("indices must be integers");
        } else {
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                "%q indices must be integers, not %s",
                type->name, mp_obj_get_type_str(index)));
        }
    }

    if (i < 0) {
        i += len;
    }
    if (is_slice) {
        if (i < 0) {
            i = 0;
        } else if ((mp_uint_t)i > len) {
            i = len;
        }
    } else {
        if (i < 0 || (mp_uint_t)i >= len) {
            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                mp_raise_msg(&mp_type_IndexError, "index out of range");
            } else {
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError,
                    "%q index out of range", type->name));
            }
        }
    }

    // By this point 0 <= i <= len and so fits in a size_t
    return (size_t)i;
}
Ejemplo n.º 8
0
// is_slice determines whether the index is a slice index
mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice) {
    mp_int_t i;
    if (MP_OBJ_IS_SMALL_INT(index)) {
        i = MP_OBJ_SMALL_INT_VALUE(index);
    } else if (!mp_obj_get_int_maybe(index, &i)) {
        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                "indices must be integers"));
        } else {
            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
                "%s indices must be integers, not %s",
                qstr_str(type->name), mp_obj_get_type_str(index)));
        }
    }

    if (i < 0) {
        i += len;
    }
    if (is_slice) {
        if (i < 0) {
            i = 0;
        } else if (i > len) {
            i = len;
        }
    } else {
        if (i < 0 || i >= len) {
            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "index out of range"));
            } else {
                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError,
                    "%s index out of range", qstr_str(type->name)));
            }
        }
    }
    return i;
}
Ejemplo n.º 9
0
// returns standard error codes: 0 for success, 1 for all other errors
STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
    if (lex == NULL) {
        return 1;
    }

    if (0) {
        // just tokenise
        while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) {
            mp_token_show(mp_lexer_cur(lex));
            mp_lexer_to_next(lex);
        }
        mp_lexer_free(lex);
        return 0;
    }

    mp_parse_error_kind_t parse_error_kind;
    mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind);

    if (pn == MP_PARSE_NODE_NULL) {
        // parse error
        mp_parse_show_exception(lex, parse_error_kind);
        mp_lexer_free(lex);
        return 1;
    }

    qstr source_name = mp_lexer_source_name(lex);
    #if MICROPY_PY___FILE__
    if (input_kind == MP_PARSE_FILE_INPUT) {
        mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
    }
    #endif
    mp_lexer_free(lex);

    /*
    printf("----------------\n");
    mp_parse_node_print(pn, 0);
    printf("----------------\n");
    */

    mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl);

    if (module_fun == mp_const_none) {
        // compile error
        return 1;
    }

    if (compile_only) {
        return 0;
    }

    // execute it
    nlr_buf_t nlr;
    if (nlr_push(&nlr) == 0) {
        mp_call_function_0(module_fun);
        nlr_pop();
        return 0;
    } else {
        // uncaught exception
        // check for SystemExit
        mp_obj_t exc = (mp_obj_t)nlr.ret_val;
        if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) {
            mp_obj_t exit_val = mp_obj_exception_get_value(exc);
            mp_int_t val;
            if (!mp_obj_get_int_maybe(exit_val, &val)) {
                val = 0;
            }
            exit(val);
        }
        mp_obj_print_exception((mp_obj_t)nlr.ret_val);
        return 1;
    }
}
Ejemplo n.º 10
0
// Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or
// be capped to the first/last character of the string, depending on is_slice.
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
                             mp_obj_t index, bool is_slice) {
    // All str functions also handle bytes objects, and they call str_index_to_ptr(),
    // so it must handle bytes.
    if (type == &mp_type_bytes) {
        // Taken from objstr.c:str_index_to_ptr()
        size_t index_val = mp_get_index(type, self_len, index, is_slice);
        return self_data + index_val;
    }

    mp_int_t i;
    // Copied from mp_get_index; I don't want bounds checking, just give me
    // the integer as-is. (I can't bounds-check without scanning the whole
    // string; an out-of-bounds index will be caught in the loops below.)
    if (MP_OBJ_IS_SMALL_INT(index)) {
        i = MP_OBJ_SMALL_INT_VALUE(index);
    } else if (!mp_obj_get_int_maybe(index, &i)) {
        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "string indices must be integers, not %s", mp_obj_get_type_str(index)));
    }
    const byte *s, *top = self_data + self_len;
    if (i < 0)
    {
        // Negative indexing is performed by counting from the end of the string.
        for (s = top - 1; i; --s) {
            if (s < self_data) {
                if (is_slice) {
                    return self_data;
                }
                mp_raise_msg(&mp_type_IndexError, "string index out of range");
            }
            if (!UTF8_IS_CONT(*s)) {
                ++i;
            }
        }
        ++s;
    } else {
        // Positive indexing, correspondingly, counts from the start of the string.
        // It's assumed that negative indexing will generally be used with small
        // absolute values (eg str[-1], not str[-1000000]), which means it'll be
        // more efficient this way.
        s = self_data;
        while (1) {
            // First check out-of-bounds
            if (s >= top) {
                if (is_slice) {
                    return top;
                }
                mp_raise_msg(&mp_type_IndexError, "string index out of range");
            }
            // Then check completion
            if (i-- == 0) {
                break;
            }
            // Then skip UTF-8 char
            ++s;
            while (UTF8_IS_CONT(*s)) {
                ++s;
            }
        }
    }
    return s;
}