diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/builtinimport.c | 1 | ||||
-rw-r--r-- | py/compile.c | 2 | ||||
-rw-r--r-- | py/compile.h | 2 | ||||
-rw-r--r-- | py/emitglue.c | 25 | ||||
-rw-r--r-- | py/emitglue.h | 3 | ||||
-rw-r--r-- | py/lexer.c | 22 | ||||
-rw-r--r-- | py/modio.c | 13 | ||||
-rw-r--r-- | py/modstruct.c | 84 | ||||
-rw-r--r-- | py/mpconfig.h | 8 | ||||
-rw-r--r-- | py/mpz.c | 13 | ||||
-rw-r--r-- | py/obj.c | 17 | ||||
-rw-r--r-- | py/obj.h | 33 | ||||
-rw-r--r-- | py/objarray.c | 7 | ||||
-rw-r--r-- | py/objbool.c | 2 | ||||
-rw-r--r-- | py/objcomplex.c | 4 | ||||
-rw-r--r-- | py/objdict.c | 10 | ||||
-rw-r--r-- | py/objexcept.c | 15 | ||||
-rw-r--r-- | py/objfloat.c | 4 | ||||
-rw-r--r-- | py/objfun.c | 7 | ||||
-rw-r--r-- | py/objgenerator.c | 7 | ||||
-rw-r--r-- | py/objint.c | 8 | ||||
-rw-r--r-- | py/objint.h | 4 | ||||
-rw-r--r-- | py/objint_longlong.c | 9 | ||||
-rw-r--r-- | py/objint_mpz.c | 16 | ||||
-rw-r--r-- | py/objlist.c | 10 | ||||
-rw-r--r-- | py/objmap.c | 6 | ||||
-rw-r--r-- | py/objnamedtuple.c | 1 | ||||
-rw-r--r-- | py/objnone.c | 2 | ||||
-rw-r--r-- | py/objset.c | 4 | ||||
-rw-r--r-- | py/objstr.c | 104 | ||||
-rw-r--r-- | py/objstr.h | 1 | ||||
-rw-r--r-- | py/objstringio.c | 33 | ||||
-rw-r--r-- | py/objtuple.c | 11 | ||||
-rw-r--r-- | py/objtype.c | 124 | ||||
-rw-r--r-- | py/qstrdefs.h | 4 | ||||
-rw-r--r-- | py/runtime.c | 12 | ||||
-rw-r--r-- | py/runtime.h | 2 | ||||
-rw-r--r-- | py/sequence.c | 5 | ||||
-rw-r--r-- | py/stream.c | 10 | ||||
-rw-r--r-- | py/vm.c | 1 |
40 files changed, 422 insertions, 224 deletions
diff --git a/py/builtinimport.c b/py/builtinimport.c index e6bb7586c..e758158a6 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/compile.c b/py/compile.c index 36ffa928e..cdd3a5b03 100644 --- a/py/compile.c +++ b/py/compile.c @@ -1147,7 +1147,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_ qstr attr = MP_PARSE_NODE_LEAF_ARG(name_nodes[1]); if (attr == MP_QSTR_bytecode) { - *emit_options = MP_EMIT_OPT_BYTE_CODE; + *emit_options = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE } else if (attr == MP_QSTR_native) { *emit_options = MP_EMIT_OPT_NATIVE_PYTHON; diff --git a/py/compile.h b/py/compile.h index 460637897..52c42aff4 100644 --- a/py/compile.h +++ b/py/compile.h @@ -27,7 +27,7 @@ // These must fit in 8 bits; see scope.h enum { MP_EMIT_OPT_NONE, - MP_EMIT_OPT_BYTE_CODE, + MP_EMIT_OPT_BYTECODE, MP_EMIT_OPT_NATIVE_PYTHON, MP_EMIT_OPT_VIPER, MP_EMIT_OPT_ASM_THUMB, diff --git a/py/emitglue.c b/py/emitglue.c index 7265a206a..528c3bd36 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -49,24 +49,6 @@ #define DEBUG_OP_printf(...) (void)0 #endif -#ifdef WRITE_CODE -FILE *fp_write_code = NULL; -#endif - -void mp_emit_glue_init(void) { -#ifdef WRITE_CODE - fp_write_code = fopen("out-code", "wb"); -#endif -} - -void mp_emit_glue_deinit(void) { -#ifdef WRITE_CODE - if (fp_write_code != NULL) { - fclose(fp_write_code); - } -#endif -} - mp_raw_code_t *mp_emit_glue_new_raw_code(void) { mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1); rc->kind = MP_CODE_RESERVED; @@ -123,10 +105,9 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void DEBUG_printf("\n"); #ifdef WRITE_CODE - if (fp_write_code != NULL) { - fwrite(fun_data, len, 1, fp_write_code); - fflush(fp_write_code); - } + FILE *fp_write_code = fopen("out-code", "wb"); + fwrite(fun_data, len, 1, fp_write_code); + fclose(fp_write_code); #endif #endif } diff --git a/py/emitglue.h b/py/emitglue.h index 43bfb5e08..c6cbb6283 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -52,9 +52,6 @@ typedef struct _mp_code_t { }; } mp_raw_code_t; -void mp_emit_glue_init(void); -void mp_emit_glue_deinit(void); - mp_raw_code_t *mp_emit_glue_new_raw_code(void); void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, uint len, uint n_pos_args, uint n_kwonly_args, qstr *arg_names, uint scope_flags); diff --git a/py/lexer.c b/py/lexer.c index f736ef303..e2dfea78c 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -64,6 +64,13 @@ struct _mp_lexer_t { mp_token_t tok_cur; }; +// debug flag for __debug__ constant +STATIC mp_token_kind_t mp_debug_value; + +void mp_set_debug(bool value) { + mp_debug_value = value ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE; +} + // TODO replace with a call to a standard function bool str_strn_equal(const char *str, const char *strn, int len) { uint i = 0; @@ -303,7 +310,7 @@ STATIC const char *tok_kw[] = { "while", "with", "yield", - NULL, + "__debug__", }; STATIC int hex_digit(unichar c) { @@ -687,9 +694,18 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs // check for keywords if (tok->kind == MP_TOKEN_NAME) { - for (int i = 0; tok_kw[i] != NULL; i++) { + // We check for __debug__ here and convert it to its value. This is so + // the parser gives a syntax error on, eg, x.__debug__. Otherwise, we + // need to check for this special token in many places in the compiler. + // TODO improve speed of these string comparisons + //for (int i = 0; tok_kw[i] != NULL; i++) { + for (int i = 0; i < ARRAY_SIZE(tok_kw); i++) { if (str_strn_equal(tok_kw[i], tok->str, tok->len)) { - tok->kind = MP_TOKEN_KW_FALSE + i; + if (i == ARRAY_SIZE(tok_kw) - 1) { + tok->kind = mp_debug_value; + } else { + tok->kind = MP_TOKEN_KW_FALSE + i; + } break; } } diff --git a/py/modio.c b/py/modio.c index 892d493c9..b1f0d880a 100644 --- a/py/modio.c +++ b/py/modio.c @@ -32,13 +32,24 @@ #if MICROPY_ENABLE_MOD_IO +extern const mp_obj_type_t mp_type_fileio; +extern const mp_obj_type_t mp_type_textio; + STATIC const mp_map_elem_t mp_module_io_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_io) }, // Note: mp_builtin_open_obj should be defined by port, it's not // part of the core. { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_BytesIO), (mp_obj_t)&mp_type_stringio }, + #if MICROPY_MOD_IO_FILEIO + { MP_OBJ_NEW_QSTR(MP_QSTR_FileIO), (mp_obj_t)&mp_type_fileio }, + #endif + #if MICROPY_CPYTHON_COMPAT + { MP_OBJ_NEW_QSTR(MP_QSTR_TextIOWrapper), (mp_obj_t)&mp_type_textio }, + #endif { MP_OBJ_NEW_QSTR(MP_QSTR_StringIO), (mp_obj_t)&mp_type_stringio }, + #if MICROPY_IO_BYTESIO + { MP_OBJ_NEW_QSTR(MP_QSTR_BytesIO), (mp_obj_t)&mp_type_bytesio }, + #endif }; STATIC const mp_obj_dict_t mp_module_io_globals = { diff --git a/py/modstruct.c b/py/modstruct.c index b53dd5183..19cf9cfd6 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +35,7 @@ #include "objtuple.h" #include "objstr.h" #include "binary.h" +#include "parsenum.h" #if MICROPY_ENABLE_MOD_STRUCT @@ -56,9 +58,26 @@ STATIC char get_fmt_type(const char **fmt) { return t; } +STATIC machine_uint_t get_fmt_num(const char **p) { + const char *num = *p; + uint len = 1; + while (unichar_isdigit(*++num)) { + len++; + } + machine_uint_t val = (machine_uint_t)MP_OBJ_SMALL_INT_VALUE(mp_parse_num_integer(*p, len, 10)); + *p = num; + return val; +} + STATIC uint calcsize_items(const char *fmt) { - // TODO - return strlen(fmt); + uint cnt = 0; + while (*fmt) { + // TODO supports size spec only for "s" + if (!unichar_isdigit(*fmt++)) { + cnt++; + } + } + return cnt; } STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { @@ -66,10 +85,24 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { char fmt_type = get_fmt_type(&fmt); machine_uint_t size; for (size = 0; *fmt; fmt++) { - uint align; - int sz = mp_binary_get_size(fmt_type, *fmt, &align); + uint align = 1; + machine_uint_t cnt = 1; + if (unichar_isdigit(*fmt)) { + cnt = get_fmt_num(&fmt); + } + if (cnt > 1) { + // TODO: count spec support only for string len + assert(*fmt == 's'); + } + + machine_uint_t sz; + if (*fmt == 's') { + sz = cnt; + } else { + sz = (machine_uint_t)mp_binary_get_size(fmt_type, *fmt, &align); + } // TODO - assert(sz != -1); + assert(sz != (machine_uint_t)-1); // Apply alignment size = (size + align - 1) & ~(align - 1); size += sz; @@ -89,7 +122,22 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) { byte *p = bufinfo.buf; for (uint i = 0; i < size; i++) { - mp_obj_t item = mp_binary_get_val(fmt_type, *fmt++, &p); + machine_uint_t sz = 1; + if (unichar_isdigit(*fmt)) { + sz = get_fmt_num(&fmt); + } + if (sz > 1) { + // TODO: size spec support only for string len + assert(*fmt == 's'); + } + mp_obj_t item; + if (*fmt == 's') { + item = mp_obj_new_bytes(p, sz); + p += sz; + fmt++; + } else { + item = mp_binary_get_val(fmt_type, *fmt++, &p); + } res->items[i] = item; } return res; @@ -106,7 +154,29 @@ STATIC mp_obj_t struct_pack(uint n_args, mp_obj_t *args) { memset(p, 0, size); for (uint i = 1; i < n_args; i++) { - mp_binary_set_val(fmt_type, *fmt++, args[i], &p); + machine_uint_t sz = 1; + if (unichar_isdigit(*fmt)) { + sz = get_fmt_num(&fmt); + } + if (sz > 1) { + // TODO: size spec support only for string len + assert(*fmt == 's'); + } + + if (*fmt == 's') { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[i], &bufinfo, MP_BUFFER_READ); + machine_uint_t to_copy = sz; + if (bufinfo.len < to_copy) { + to_copy = bufinfo.len; + } + memcpy(p, bufinfo.buf, to_copy); + memset(p + to_copy, 0, sz - to_copy); + p += sz; + fmt++; + } else { + mp_binary_set_val(fmt_type, *fmt++, args[i], &p); + } } return res; } diff --git a/py/mpconfig.h b/py/mpconfig.h index 76cd1091c..445fc78b0 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -225,6 +225,14 @@ typedef double mp_float_t; #define MICROPY_ENABLE_MOD_IO (1) #endif +#ifndef MICROPY_MOD_IO_FILEIO +#define MICROPY_MOD_IO_FILEIO (0) +#endif + +#ifndef MICROPY_IO_BYTESIO +#define MICROPY_IO_BYTESIO (1) +#endif + // Whether to provide "struct" module #ifndef MICROPY_ENABLE_MOD_STRUCT #define MICROPY_ENABLE_MOD_STRUCT (1) @@ -207,17 +207,15 @@ STATIC uint mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz STATIC uint mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz_dig_t *kdig, uint klen) { mpz_dig_t *oidig = idig; - jlen -= klen; - for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { *idig = *jdig & *kdig; } - for (; jlen > 0; --jlen, ++idig) { - *idig = 0; + // remove trailing zeros + for (--idig; idig >= oidig && *idig == 0; --idig) { } - return idig - oidig; + return idig + 1 - oidig; } /* computes i = j | k @@ -898,14 +896,15 @@ void mpz_sub_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { can have dest, lhs, rhs the same */ void mpz_and_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs) { - if (mpn_cmp(lhs->dig, lhs->len, rhs->dig, rhs->len) < 0) { + // make sure lhs has the most digits + if (lhs->len < rhs->len) { const mpz_t *temp = lhs; lhs = rhs; rhs = temp; } if (lhs->neg == rhs->neg) { - mpz_need_dig(dest, lhs->len); + mpz_need_dig(dest, rhs->len); dest->len = mpn_and(dest->dig, lhs->dig, lhs->len, rhs->dig, rhs->len); } else { mpz_need_dig(dest, lhs->len); @@ -122,7 +122,7 @@ int mp_obj_is_true(mp_obj_t arg) { mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg); - if (result != MP_OBJ_NOT_SUPPORTED) { + if (result != MP_OBJ_NULL) { return result == mp_const_true; } } @@ -212,7 +212,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); - if (r != MP_OBJ_NOT_SUPPORTED) { + if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } @@ -222,7 +222,7 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { return false; } -machine_int_t mp_obj_get_int(mp_obj_t arg) { +machine_int_t mp_obj_get_int(mp_const_obj_t arg) { // This function essentially performs implicit type conversion to int // Note that Python does NOT provide implicit type conversion from // float to int in the core expression language, try some_list[1.0]. @@ -242,7 +242,7 @@ machine_int_t mp_obj_get_int(mp_obj_t arg) { // returns false if arg is not of integral type // returns true and sets *value if it is of integral type // can throw OverflowError if arg is of integral type, but doesn't fit in a machine_int_t -bool mp_obj_get_int_maybe(mp_obj_t arg, machine_int_t *value) { +bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value) { if (arg == mp_const_false) { *value = 0; } else if (arg == mp_const_true) { @@ -357,12 +357,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { } else { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { - mp_obj_t val = type->unary_op(MP_UNARY_OP_LEN, o_in); - // TODO: Here's the case of having MP_OBJ_NOT_SUPPORTED is confusing - if (val == MP_OBJ_NOT_SUPPORTED) { - return MP_OBJ_NULL; - } - return val; + return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } @@ -373,7 +368,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(base); if (type->subscr != NULL) { mp_obj_t ret = type->subscr(base, index, value); - if (ret != MP_OBJ_NOT_SUPPORTED) { + if (ret != MP_OBJ_NULL) { return ret; } // TODO: call base classes here? @@ -52,8 +52,7 @@ typedef struct _mp_obj_base_t mp_obj_base_t; // These fake objects are used to indicate certain things in arguments or return // values, and should only be used when explicitly allowed. // -// - MP_OBJ_NULL : used to indicate the absence of an object. -// - MP_OBJ_NOT_SUPPORTED : a return value that indicates an unsupported operation. +// - MP_OBJ_NULL : used to indicate the absence of an object, or unsupported operation. // - MP_OBJ_STOP_ITERATION : used instead of throwing a StopIteration, for efficiency. // - MP_OBJ_SENTINEL : used for various internal purposes where one needs // an object which is unique from all other objects, including MP_OBJ_NULL. @@ -63,14 +62,12 @@ typedef struct _mp_obj_base_t mp_obj_base_t; #if NDEBUG #define MP_OBJ_NULL ((mp_obj_t)0) -#define MP_OBJ_NOT_SUPPORTED ((mp_obj_t)0) #define MP_OBJ_STOP_ITERATION ((mp_obj_t)0) #define MP_OBJ_SENTINEL ((mp_obj_t)4) #else #define MP_OBJ_NULL ((mp_obj_t)0) -#define MP_OBJ_NOT_SUPPORTED ((mp_obj_t)4) -#define MP_OBJ_STOP_ITERATION ((mp_obj_t)8) -#define MP_OBJ_SENTINEL ((mp_obj_t)12) +#define MP_OBJ_STOP_ITERATION ((mp_obj_t)4) +#define MP_OBJ_SENTINEL ((mp_obj_t)8) #endif // These macros check for small int, qstr or object, and access small int and qstr values @@ -158,7 +155,7 @@ typedef enum _mp_map_lookup_kind_t { MP_MAP_LOOKUP_REMOVE_IF_FOUND, // 2 } mp_map_lookup_kind_t; -static inline bool MP_MAP_SLOT_IS_FILLED(mp_map_t *map, machine_uint_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); } +static inline bool MP_MAP_SLOT_IS_FILLED(const mp_map_t *map, machine_uint_t pos) { return ((map)->table[pos].key != MP_OBJ_NULL && (map)->table[pos].key != MP_OBJ_SENTINEL); } void mp_map_init(mp_map_t *map, int n); void mp_map_init_fixed_table(mp_map_t *map, int n, const mp_obj_t *table); @@ -177,7 +174,7 @@ typedef struct _mp_set_t { mp_obj_t *table; } mp_set_t; -static inline bool MP_SET_SLOT_IS_FILLED(mp_set_t *set, machine_uint_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); } +static inline bool MP_SET_SLOT_IS_FILLED(const mp_set_t *set, machine_uint_t pos) { return ((set)->table[pos] != MP_OBJ_NULL && (set)->table[pos] != MP_OBJ_SENTINEL); } void mp_set_init(mp_set_t *set, int n); mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); @@ -246,6 +243,7 @@ typedef struct _mp_stream_p_t { machine_int_t (*read)(mp_obj_t obj, void *buf, machine_uint_t size, int *errcode); machine_int_t (*write)(mp_obj_t obj, const void *buf, machine_uint_t size, int *errcode); // add seek() ? + int is_bytes : 1; } mp_stream_p_t; struct _mp_obj_type_t { @@ -255,15 +253,15 @@ struct _mp_obj_type_t { mp_make_new_fun_t make_new; // to make an instance of the type mp_call_fun_t call; - mp_unary_op_fun_t unary_op; // can return MP_OBJ_NOT_SUPPORTED if op not supported - mp_binary_op_fun_t binary_op; // can return MP_OBJ_NOT_SUPPORTED if op not supported + mp_unary_op_fun_t unary_op; // can return MP_OBJ_NULL if op not supported + mp_binary_op_fun_t binary_op; // can return MP_OBJ_NULL if op not supported mp_load_attr_fun_t load_attr; mp_store_attr_fun_t store_attr; // if value is MP_OBJ_NULL, then delete that attribute mp_subscr_fun_t subscr; // implements load, store, delete subscripting // value=MP_OBJ_NULL means delete, value=MP_OBJ_SENTINEL means load, else store - // can return MP_OBJ_NOT_SUPPORTED + // can return MP_OBJ_NULL if op not supported mp_fun_1_t getiter; mp_fun_1_t iternext; // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() (with no args) @@ -321,6 +319,7 @@ extern const mp_obj_type_t mp_type_staticmethod; extern const mp_obj_type_t mp_type_classmethod; extern const mp_obj_type_t mp_type_property; extern const mp_obj_type_t mp_type_stringio; +extern const mp_obj_type_t mp_type_bytesio; // Exceptions extern const mp_obj_type_t mp_type_BaseException; @@ -422,8 +421,8 @@ bool mp_obj_is_callable(mp_obj_t o_in); machine_int_t mp_obj_hash(mp_obj_t o_in); bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2); -machine_int_t mp_obj_get_int(mp_obj_t arg); -bool mp_obj_get_int_maybe(mp_obj_t arg, machine_int_t *value); +machine_int_t mp_obj_get_int(mp_const_obj_t arg); +bool mp_obj_get_int_maybe(mp_const_obj_t arg, machine_int_t *value); #if MICROPY_ENABLE_FLOAT mp_float_t mp_obj_get_float(mp_obj_t self_in); void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); @@ -450,7 +449,7 @@ machine_int_t mp_obj_int_get(mp_obj_t self_in); mp_float_t mp_obj_int_as_float(mp_obj_t self_in); #endif // Will raise exception if value doesn't fit into machine_int_t -machine_int_t mp_obj_int_get_checked(mp_obj_t self_in); +machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in); // exception #define mp_obj_is_native_exception_instance(o) (mp_obj_get_type(o)->make_new == mp_obj_exception_make_new) @@ -481,11 +480,11 @@ typedef struct _mp_obj_float_t { mp_float_t value; } mp_obj_float_t; mp_float_t mp_obj_float_get(mp_obj_t self_in); -mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NOT_SUPPORTED +mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported // complex void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag); -mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NOT_SUPPORTED +mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_imag, mp_obj_t rhs_in); // can return MP_OBJ_NULL if op not supported #endif // tuple @@ -538,7 +537,7 @@ typedef struct _mp_obj_fun_native_t { // need this so we can define const object bool mp_obj_fun_prepare_simple_args(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args, uint *out_args1_len, const mp_obj_t **out_args1, uint *out_args2_len, const mp_obj_t **out_args2); -const char *mp_obj_fun_get_name(mp_obj_t fun); +const char *mp_obj_fun_get_name(mp_const_obj_t fun); const char *mp_obj_code_get_name(const byte *code_info); mp_obj_t mp_identity(mp_obj_t self); diff --git a/py/objarray.c b/py/objarray.c index b394d7746..d973a4c56 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -139,7 +140,7 @@ STATIC mp_obj_t array_unary_op(int op, mp_obj_t o_in) { switch (op) { case MP_UNARY_OP_BOOL: return MP_BOOL(o->len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(o->len); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -165,7 +166,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value // TODO implement // TODO: confirmed that both bytearray and array.array support // slice deletion - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } else { mp_obj_array_t *o = self_in; if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) { @@ -173,7 +174,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value // Only getting a slice is suported so far, not assignment // TODO: confirmed that both bytearray and array.array support // slice assignment (incl. of different size) - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } machine_uint_t start, stop; if (!mp_seq_get_fast_slice_indexes(o->len, index_in, &start, &stop)) { diff --git a/py/objbool.c b/py/objbool.c index e31e7a2a4..4fe7a1934 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -76,7 +76,7 @@ STATIC mp_obj_t bool_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (MP_BINARY_OP_OR <= op && op <= MP_BINARY_OP_NOT_EQUAL) { return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_is_true(lhs_in)), rhs_in); } - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } const mp_obj_type_t mp_type_bool = { diff --git a/py/objcomplex.c b/py/objcomplex.c index 18e0edc51..80a13c6d8 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -123,7 +123,7 @@ STATIC mp_obj_t complex_unary_op(int op, mp_obj_t o_in) { case MP_UNARY_OP_BOOL: return MP_BOOL(o->real != 0 || o->imag != 0); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -233,7 +233,7 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im case MP_BINARY_OP_EQUAL: return MP_BOOL(lhs_real == rhs_real && lhs_imag == rhs_imag); default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } return mp_obj_new_complex(lhs_real, lhs_imag); } diff --git a/py/objdict.c b/py/objdict.c index 9d4ebb627..f41eacd93 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -103,7 +103,7 @@ STATIC mp_obj_t dict_unary_op(int op, mp_obj_t self_in) { switch (op) { case MP_UNARY_OP_BOOL: return MP_BOOL(self->map.used != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->map.used); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -140,7 +140,7 @@ STATIC mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } default: // op not supported - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; } } @@ -463,13 +463,13 @@ STATIC void dict_view_print(void (*print)(void *env, const char *fmt, ...), void } STATIC mp_obj_t dict_view_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { - /* only supported for the 'keys' kind until sets and dicts are refactored */ + // only supported for the 'keys' kind until sets and dicts are refactored mp_obj_dict_view_t *o = lhs_in; if (o->kind != MP_DICT_VIEW_KEYS) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } if (op != MP_BINARY_OP_IN) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } return dict_binary_op(op, o->dict, rhs_in); } diff --git a/py/objexcept.c b/py/objexcept.c index 7f5f9c73d..0006554a8 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -120,12 +120,27 @@ STATIC void exception_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } +STATIC mp_obj_t exc___init__(uint n_args, const mp_obj_t *args) { + mp_obj_exception_t *self = args[0]; + mp_obj_t argst = mp_obj_new_tuple(n_args - 1, args + 1); + self->args = argst; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exc___init___obj, 1, MP_OBJ_FUN_ARGS_MAX, exc___init__); + +STATIC const mp_map_elem_t exc_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&exc___init___obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(exc_locals_dict, exc_locals_dict_table); + const mp_obj_type_t mp_type_BaseException = { { &mp_type_type }, .name = MP_QSTR_BaseException, .print = mp_obj_exception_print, .make_new = mp_obj_exception_make_new, .load_attr = exception_load_attr, + .locals_dict = (mp_obj_t)&exc_locals_dict, }; #define MP_DEFINE_EXCEPTION_BASE(base_name) \ diff --git a/py/objfloat.c b/py/objfloat.c index e27942143..6732f3121 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -96,7 +96,7 @@ STATIC mp_obj_t float_unary_op(int op, mp_obj_t o_in) { case MP_UNARY_OP_BOOL: return MP_BOOL(o->value != 0); case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-o->value); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -165,7 +165,7 @@ mp_obj_t mp_obj_float_binary_op(int op, mp_float_t lhs_val, mp_obj_t rhs_in) { case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(lhs_val >= rhs_val); default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } return mp_obj_new_float(lhs_val); } diff --git a/py/objfun.c b/py/objfun.c index 732009376..26dfe0b2e 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -58,7 +59,7 @@ STATIC mp_obj_t fun_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // we don't even need to check for 2nd arg type. return MP_BOOL(lhs_in == rhs_in); } - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } STATIC mp_obj_t fun_native_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { @@ -153,8 +154,8 @@ const char *mp_obj_code_get_name(const byte *code_info) { return qstr_str(block_name); } -const char *mp_obj_fun_get_name(mp_obj_t fun_in) { - mp_obj_fun_bc_t *fun = fun_in; +const char *mp_obj_fun_get_name(mp_const_obj_t fun_in) { + const mp_obj_fun_bc_t *fun = fun_in; const byte *code_info = fun->bytecode; return mp_obj_code_get_name(code_info); } diff --git a/py/objgenerator.c b/py/objgenerator.c index fb8366bae..8180185b9 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -98,10 +99,6 @@ void gen_instance_print(void (*print)(void *env, const char *fmt, ...), void *en print(env, "<generator object '%s' at %p>", mp_obj_code_get_name(self->code_info), self_in); } -mp_obj_t gen_instance_getiter(mp_obj_t self_in) { - return self_in; -} - mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance)); mp_obj_gen_instance_t *self = self_in; @@ -250,7 +247,7 @@ const mp_obj_type_t mp_type_gen_instance = { { &mp_type_type }, .name = MP_QSTR_generator, .print = gen_instance_print, - .getiter = gen_instance_getiter, + .getiter = mp_identity, .iternext = gen_instance_iternext, .locals_dict = (mp_obj_t)&gen_instance_locals_dict, }; diff --git a/py/objint.c b/py/objint.c index d1d99a253..a3b355400 100644 --- a/py/objint.c +++ b/py/objint.c @@ -129,7 +129,7 @@ STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) // // The resulting formatted string will be returned from this function and the // formatted size will be in *fmt_size. -char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in, +char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { fmt_int_t num; if (MP_OBJ_IS_SMALL_INT(self_in)) { @@ -216,7 +216,7 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) { // This is called for operations on SMALL_INT that are not handled by mp_unary_op mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } // This is called for operations on SMALL_INT that are not handled by mp_binary_op @@ -258,7 +258,7 @@ machine_int_t mp_obj_int_get(mp_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } -machine_int_t mp_obj_int_get_checked(mp_obj_t self_in) { +machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return MP_OBJ_SMALL_INT_VALUE(self_in); } @@ -285,7 +285,7 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(int op, mp_obj_t lhs_in, mp_obj_t rhs_ return mp_binary_op(op, rhs_in, lhs_in); } } - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } // this is a classmethod diff --git a/py/objint.h b/py/objint.h index 0ea19d0dd..1d12cffae 100644 --- a/py/objint.h +++ b/py/objint.h @@ -34,9 +34,9 @@ typedef struct _mp_obj_int_t { } mp_obj_int_t; void mp_obj_int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind); -char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in, +char *mp_obj_int_formatted(char **buf, int *buf_size, int *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); -char *mp_obj_int_formatted_impl(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in, +char *mp_obj_int_formatted_impl(char **buf, int *buf_size, int *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); bool mp_obj_int_is_positive(mp_obj_t self_in); mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index f648615a7..1e0167b46 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -63,7 +64,7 @@ mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) { case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: return mp_obj_new_int_from_ll(-o->val); case MP_UNARY_OP_INVERT: return mp_obj_new_int_from_ll(~o->val); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -76,7 +77,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) { lhs_val = ((mp_obj_int_t*)lhs_in)->val; } else { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } if (MP_OBJ_IS_SMALL_INT(rhs_in)) { @@ -134,7 +135,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return MP_BOOL(lhs_val == rhs_val); default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } @@ -185,7 +186,7 @@ machine_int_t mp_obj_int_get(mp_obj_t self_in) { } } -machine_int_t mp_obj_int_get_checked(mp_obj_t self_in) { +machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { // TODO: Check overflow return mp_obj_int_get(self_in); } diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 8e72782d6..2df3232e9 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -58,10 +58,10 @@ STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) { // formatted size will be in *fmt_size. // // This particular routine should only be called for the mpz representation of the int. -char *mp_obj_int_formatted_impl(char **buf, int *buf_size, int *fmt_size, mp_obj_t self_in, +char *mp_obj_int_formatted_impl(char **buf, int *buf_size, int *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); - mp_obj_int_t *self = self_in; + const mp_obj_int_t *self = self_in; uint needed_size = mpz_as_str_size_formatted(&self->mpz, base, prefix, comma); if (needed_size > *buf_size) { @@ -90,7 +90,7 @@ mp_obj_t mp_obj_int_unary_op(int op, mp_obj_t o_in) { case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return o2; } case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return o2; } - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -108,7 +108,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { zlhs = &((mp_obj_int_t*)lhs_in)->mpz; } else { // unsupported type - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; } // if rhs is small int, then lhs was not (otherwise mp_binary_op handles it) @@ -213,7 +213,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { break; default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } return res; @@ -233,7 +233,7 @@ mp_obj_t mp_obj_int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return MP_BOOL(cmp == 0); default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } } @@ -284,11 +284,11 @@ machine_int_t mp_obj_int_get(mp_obj_t self_in) { } } -machine_int_t mp_obj_int_get_checked(mp_obj_t self_in) { +machine_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { if (MP_OBJ_IS_SMALL_INT(self_in)) { return MP_OBJ_SMALL_INT_VALUE(self_in); } else { - mp_obj_int_t *self = self_in; + const mp_obj_int_t *self = self_in; machine_int_t value; if (mpz_as_int_checked(&self->mpz, &value)) { return value; diff --git a/py/objlist.c b/py/objlist.c index 0ef685dae..ee7492692 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -103,7 +103,7 @@ STATIC mp_obj_t list_unary_op(int op, mp_obj_t self_in) { switch (op) { case MP_UNARY_OP_BOOL: return MP_BOOL(self->len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -112,7 +112,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { switch (op) { case MP_BINARY_OP_ADD: { if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } mp_obj_list_t *p = rhs; mp_obj_list_t *s = list_new(o->len + p->len); @@ -121,7 +121,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } case MP_BINARY_OP_INPLACE_ADD: { if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } list_extend(lhs, rhs); return o; @@ -129,7 +129,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_MULTIPLY: { machine_int_t n; if (!mp_obj_get_int_maybe(rhs, &n)) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } mp_obj_list_t *s = list_new(o->len * n); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); @@ -143,7 +143,7 @@ STATIC mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { return MP_BOOL(list_cmp_helper(op, lhs, rhs)); default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } diff --git a/py/objmap.c b/py/objmap.c index 232e611bd..6e5c79017 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -56,10 +56,6 @@ STATIC mp_obj_t map_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_ return o; } -STATIC mp_obj_t map_getiter(mp_obj_t self_in) { - return self_in; -} - STATIC mp_obj_t map_iternext(mp_obj_t self_in) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_map)); mp_obj_map_t *self = self_in; @@ -80,6 +76,6 @@ const mp_obj_type_t mp_type_map = { { &mp_type_type }, .name = MP_QSTR_map, .make_new = map_make_new, - .getiter = map_getiter, + .getiter = mp_identity, .iternext = map_iternext, }; diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 212cf131c..a55dd643b 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/py/objnone.c b/py/objnone.c index bb4e7e560..165c8e5a4 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -44,7 +44,7 @@ STATIC void none_print(void (*print)(void *env, const char *fmt, ...), void *env STATIC mp_obj_t none_unary_op(int op, mp_obj_t o_in) { switch (op) { case MP_UNARY_OP_BOOL: return mp_const_false; - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } diff --git a/py/objset.c b/py/objset.c index a6f1fe733..32c194db1 100644 --- a/py/objset.c +++ b/py/objset.c @@ -475,7 +475,7 @@ STATIC mp_obj_t set_unary_op(int op, mp_obj_t self_in) { switch (op) { case MP_UNARY_OP_BOOL: return MP_BOOL(self->set.used != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT((machine_int_t)self->set.used); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -514,7 +514,7 @@ STATIC mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { return MP_BOOL(elem != NULL); } default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } diff --git a/py/objstr.c b/py/objstr.c index 79ad891d0..61fda12a3 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,6 +38,7 @@ #include "runtime.h" #include "pfenv.h" #include "objstr.h" +#include "objlist.h" STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, uint n_args, const mp_obj_t *args); const mp_obj_t mp_const_empty_bytes; @@ -52,7 +54,7 @@ const mp_obj_t mp_const_empty_bytes; STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str); STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str); -STATIC mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len); +mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len); STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); STATIC NORETURN void arg_type_mixup(); @@ -294,7 +296,7 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_MULTIPLY: { if (!MP_OBJ_IS_SMALL_INT(rhs_in)) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } int n = MP_OBJ_SMALL_INT_VALUE(rhs_in); byte *data; @@ -326,9 +328,20 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { GET_STR_DATA_LEN(rhs_in, rhs_data, rhs_len); return MP_BOOL(mp_seq_cmp_bytes(op, lhs_data, lhs_len, rhs_data, rhs_len)); } + if (lhs_type == &mp_type_bytes) { + mp_buffer_info_t bufinfo; + if (!mp_get_buffer(rhs_in, &bufinfo, MP_BUFFER_READ)) { + goto uncomparable; + } + return MP_BOOL(mp_seq_cmp_bytes(op, lhs_data, lhs_len, bufinfo.buf, bufinfo.len)); + } +uncomparable: + if (op == MP_BINARY_OP_EQUAL) { + return mp_const_false; + } } - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { @@ -352,7 +365,7 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { return mp_obj_new_str(self_data + index_val, 1, true); } } else { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } @@ -482,6 +495,69 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) { return res; } +STATIC mp_obj_t str_rsplit(uint n_args, const mp_obj_t *args) { + if (n_args < 3) { + // If we don't have split limit, it doesn't matter from which side + // we split. + return str_split(n_args, args); + } + const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); + mp_obj_t sep = args[1]; + GET_STR_DATA_LEN(args[0], s, len); + + machine_int_t splits = mp_obj_get_int(args[2]); + machine_int_t org_splits = splits; + // Preallocate list to the max expected # of elements, as we + // will fill it from the end. + mp_obj_list_t *res = mp_obj_new_list(splits + 1, NULL); + int idx = splits; + + if (sep == mp_const_none) { + // TODO + assert(0); + } else { + uint sep_len; + const char *sep_str = mp_obj_str_get_data(sep, &sep_len); + + if (sep_len == 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator")); + } + + const byte *beg = s; + const byte *last = s + len; + for (;;) { + s = last - sep_len; + for (;;) { + if (splits == 0 || s < beg) { + break; + } else if (memcmp(s, sep_str, sep_len) == 0) { + break; + } + s--; + } + if (s < beg || splits == 0) { + res->items[idx] = str_new(self_type, beg, last - beg); + break; + } + res->items[idx--] = str_new(self_type, s + sep_len, last - s - sep_len); + last = s; + if (splits > 0) { + splits--; + } + } + if (idx != 0) { + // We split less parts than split limit, now go cleanup surplus + int used = org_splits + 1 - idx; + memcpy(res->items, &res->items[idx], used * sizeof(mp_obj_t)); + mp_seq_clear(res->items, used, res->alloc, sizeof(*res->items)); + res->len = used; + } + } + + return res; +} + + STATIC mp_obj_t str_finder(uint n_args, const mp_obj_t *args, machine_int_t direction, bool is_index) { assert(2 <= n_args && n_args <= 4); assert(MP_OBJ_IS_STR(args[0])); @@ -530,13 +606,17 @@ STATIC mp_obj_t str_rindex(uint n_args, const mp_obj_t *args) { } // TODO: (Much) more variety in args -STATIC mp_obj_t str_startswith(mp_obj_t self_in, mp_obj_t arg) { - GET_STR_DATA_LEN(self_in, str, str_len); - GET_STR_DATA_LEN(arg, prefix, prefix_len); - if (prefix_len > str_len) { +STATIC mp_obj_t str_startswith(uint n_args, const mp_obj_t *args) { + GET_STR_DATA_LEN(args[0], str, str_len); + GET_STR_DATA_LEN(args[1], prefix, prefix_len); + uint index_val = 0; + if (n_args > 2) { + index_val = mp_get_index(&mp_type_str, str_len, args[2], true); + } + if (prefix_len + index_val > str_len) { return mp_const_false; } - return MP_BOOL(memcmp(str, prefix, prefix_len) == 0); + return MP_BOOL(memcmp(str + index_val, prefix, prefix_len) == 0); } enum { LSTRIP, RSTRIP, STRIP }; @@ -1459,7 +1539,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex); STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_startswith_obj, str_startswith); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip); @@ -1482,6 +1563,7 @@ STATIC const mp_map_elem_t str_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_rindex), (mp_obj_t)&str_rindex_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_join), (mp_obj_t)&str_join_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_split), (mp_obj_t)&str_split_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_rsplit), (mp_obj_t)&str_rsplit_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_startswith), (mp_obj_t)&str_startswith_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_strip), (mp_obj_t)&str_strip_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_lstrip), (mp_obj_t)&str_lstrip_obj }, @@ -1545,7 +1627,7 @@ mp_obj_t mp_obj_str_builder_end(mp_obj_t o_in) { return o; } -STATIC mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len) { +mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len) { mp_obj_str_t *o = m_new_obj(mp_obj_str_t); o->base.type = type; o->len = len; diff --git a/py/objstr.h b/py/objstr.h index 019f56f7b..c0ef701a8 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -36,3 +36,4 @@ typedef struct _mp_obj_str_t { #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str}; mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args); +mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len); diff --git a/py/objstringio.c b/py/objstringio.c index 880d4e117..a1a765f89 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,6 +35,7 @@ #include "obj.h" #include "runtime.h" #include "stream.h" +#include "objstr.h" #if MICROPY_ENABLE_MOD_IO @@ -46,7 +48,7 @@ typedef struct _mp_obj_stringio_t { STATIC void stringio_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_stringio_t *self = self_in; - print(env, "<io.StringIO 0x%x>", self->vstr); + print(env, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self->vstr); } STATIC machine_int_t stringio_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) { @@ -77,9 +79,11 @@ STATIC machine_int_t stringio_write(mp_obj_t o_in, const void *buf, machine_uint return size; } +#define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes) + STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) { mp_obj_stringio_t *self = self_in; - return mp_obj_new_str((byte*)self->vstr->buf, self->vstr->len, false); + return str_new(STREAM_TO_CONTENT_TYPE(self), (byte*)self->vstr->buf, self->vstr->len); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue); @@ -96,16 +100,16 @@ mp_obj_t stringio___exit__(uint n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio___exit__); -STATIC mp_obj_stringio_t *stringio_new() { +STATIC mp_obj_stringio_t *stringio_new(mp_obj_t type_in) { mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t); - o->base.type = &mp_type_stringio; + o->base.type = type_in; o->vstr = vstr_new(); o->pos = 0; return o; } STATIC mp_obj_t stringio_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - mp_obj_stringio_t *o = stringio_new(); + mp_obj_stringio_t *o = stringio_new(type_in); if (n_args > 0) { mp_buffer_info_t bufinfo; @@ -135,6 +139,12 @@ STATIC const mp_stream_p_t stringio_stream_p = { .write = stringio_write, }; +STATIC const mp_stream_p_t bytesio_stream_p = { + .read = stringio_read, + .write = stringio_write, + .is_bytes = true, +}; + const mp_obj_type_t mp_type_stringio = { { &mp_type_type }, .name = MP_QSTR_StringIO, @@ -146,4 +156,17 @@ const mp_obj_type_t mp_type_stringio = { .locals_dict = (mp_obj_t)&stringio_locals_dict, }; +#if MICROPY_IO_BYTESIO +const mp_obj_type_t mp_type_bytesio = { + { &mp_type_type }, + .name = MP_QSTR_BytesIO, + .print = stringio_print, + .make_new = stringio_make_new, + .getiter = mp_identity, + .iternext = mp_stream_unbuffered_iter, + .stream_p = &bytesio_stream_p, + .locals_dict = (mp_obj_t)&stringio_locals_dict, +}; +#endif + #endif diff --git a/py/objtuple.c b/py/objtuple.c index 44ee95dd9..46515378f 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -120,7 +120,7 @@ mp_obj_t mp_obj_tuple_unary_op(int op, mp_obj_t self_in) { switch (op) { case MP_UNARY_OP_BOOL: return MP_BOOL(self->len != 0); case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len); - default: return MP_OBJ_NOT_SUPPORTED; + default: return MP_OBJ_NULL; // op not supported } } @@ -129,7 +129,7 @@ mp_obj_t mp_obj_tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { 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_NOT_SUPPORTED; + 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); @@ -138,7 +138,7 @@ mp_obj_t mp_obj_tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { } case MP_BINARY_OP_MULTIPLY: { if (!MP_OBJ_IS_SMALL_INT(rhs)) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } int n = MP_OBJ_SMALL_INT_VALUE(rhs); mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL); @@ -153,8 +153,7 @@ mp_obj_t mp_obj_tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { return MP_BOOL(tuple_cmp_helper(op, lhs, rhs)); default: - // op not supported - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } @@ -176,7 +175,7 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { uint index_value = mp_get_index(self->base.type, self->len, index, false); return self->items[index_value]; } else { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } diff --git a/py/objtype.c b/py/objtype.c index 5f3e1db5d..2e1c56416 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -48,8 +49,10 @@ /******************************************************************************/ // instance object +#define is_instance_type(type) ((type)->make_new == instance_make_new) #define is_native_type(type) ((type)->make_new != instance_make_new) STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args); +STATIC void instance_convert_return_attr(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest); STATIC mp_obj_t mp_obj_new_instance(mp_obj_t class, uint subobjs) { mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs); @@ -119,10 +122,10 @@ STATIC void mp_obj_class_lookup(mp_obj_instance_t *o, const mp_obj_type_t *type, if (elem != NULL) { dest[0] = elem->value; if (o != MP_OBJ_NULL && is_native_type(type)) { - dest[1] = o->subobj[0]; + instance_convert_return_attr(o->subobj[0], type, elem->value, dest); + } else { + instance_convert_return_attr(o, type, elem->value, dest); } - // TODO: Sensibly, we should call instance_convert_return_attr() here, - // instead of multiple places later. Also, this code duplicates runtime.c much. return; } } @@ -215,38 +218,56 @@ STATIC mp_obj_t instance_make_new(mp_obj_t self_in, uint n_args, uint n_kw, cons mp_obj_instance_t *o = mp_obj_new_instance(self_in, num_native_bases); - // look for __init__ function + // look for __new__ function mp_obj_t init_fn[2] = {MP_OBJ_NULL}; - mp_obj_class_lookup(NULL, self, MP_QSTR___init__, offsetof(mp_obj_type_t, make_new), init_fn); + mp_obj_class_lookup(NULL, self, MP_QSTR___new__, offsetof(mp_obj_type_t, make_new), init_fn); + mp_obj_t new_ret = o; if (init_fn[0] == MP_OBJ_SENTINEL) { // Native type's constructor is what wins - it gets all our arguments, // and none Python classes are initialized at all. o->subobj[0] = native_base->make_new((mp_obj_type_t*)native_base, n_args, n_kw, args); } else if (init_fn[0] != MP_OBJ_NULL) { - // We need to default-initialize any native subobjs first - if (num_native_bases > 0) { - o->subobj[0] = native_base->make_new((mp_obj_type_t*)native_base, 0, 0, NULL); - } - // now call Python class __init__ function with all args - mp_obj_t init_ret; + // now call Python class __new__ function with all args if (n_args == 0 && n_kw == 0) { - init_ret = mp_call_function_n_kw(init_fn[0], 1, 0, (mp_obj_t*)(void*)&o); + new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, (mp_obj_t*)(void*)&self_in); } else { mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw); - args2[0] = o; + args2[0] = self_in; memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); - init_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2); + new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2); m_del(mp_obj_t, args2, 1 + n_args + 2 * n_kw); } + + } + + // https://docs.python.org/3.4/reference/datamodel.html#object.__new__ + // "If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked." + if (mp_obj_get_type(new_ret) != self_in) { + return new_ret; + } + + o = new_ret; + + // now call Python class __init__ function with all args + init_fn[0] = init_fn[1] = NULL; + mp_obj_class_lookup(o, self, MP_QSTR___init__, 0, init_fn); + if (init_fn[0] != MP_OBJ_NULL) { + mp_obj_t init_ret; + if (n_args == 0 && n_kw == 0) { + init_ret = mp_call_method_n_kw(0, 0, init_fn); + } else { + mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw); + args2[0] = init_fn[0]; + args2[1] = init_fn[1]; + memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); + init_ret = mp_call_method_n_kw(n_args, n_kw, args2); + m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw); + } if (init_ret != mp_const_none) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); } - } else { - if (n_args != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object() takes no parameters")); - } } return o; @@ -266,7 +287,7 @@ STATIC mp_obj_t instance_unary_op(int op, mp_obj_t self_in) { qstr op_name = unary_op_method_name[op]; /* Still try to lookup native slot if (op_name == 0) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; } */ mp_obj_t member[2] = {MP_OBJ_NULL}; @@ -276,7 +297,7 @@ STATIC mp_obj_t instance_unary_op(int op, mp_obj_t self_in) { } else if (member[0] != MP_OBJ_NULL) { return mp_call_function_1(member[0], self_in); } else { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } @@ -324,7 +345,7 @@ STATIC const qstr binary_op_method_name[] = { // and put the result in the dest[] array for a possible method call. // Conversion means dealing with static/class methods, callables, and values. // see http://docs.python.org/3.3/howto/descriptor.html -STATIC void instance_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_t *dest) { +STATIC void instance_convert_return_attr(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest) { assert(dest[1] == NULL); if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { // return just the function @@ -332,7 +353,7 @@ STATIC void instance_convert_return_attr(mp_obj_t self, mp_obj_t member, mp_obj_ } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { // return a bound method, with self being the type of this object dest[0] = ((mp_obj_static_class_method_t*)member)->fun; - dest[1] = mp_obj_get_type(self); + dest[1] = (mp_obj_t)type; } else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) { // Don't try to bind types dest[0] = member; @@ -353,26 +374,24 @@ STATIC mp_obj_t instance_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { qstr op_name = binary_op_method_name[op]; /* Still try to lookup native slot if (op_name == 0) { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; } */ - mp_obj_t member[2] = {MP_OBJ_NULL}; - mp_obj_class_lookup(lhs, lhs->base.type, op_name, offsetof(mp_obj_type_t, binary_op), member); - if (member[0] == MP_OBJ_SENTINEL) { + mp_obj_t dest[3] = {MP_OBJ_NULL}; + mp_obj_class_lookup(lhs, lhs->base.type, op_name, offsetof(mp_obj_type_t, binary_op), dest); + if (dest[0] == MP_OBJ_SENTINEL) { return mp_binary_op(op, lhs->subobj[0], rhs_in); - } else if (member[0] != MP_OBJ_NULL) { - mp_obj_t dest[3]; - dest[1] = MP_OBJ_NULL; - instance_convert_return_attr(lhs_in, member[0], dest); + } else if (dest[0] != MP_OBJ_NULL) { dest[2] = rhs_in; return mp_call_method_n_kw(1, 0, dest); } else { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // logic: look in obj members then class locals (TODO check this against CPython) + assert(is_instance_type(mp_obj_get_type(self_in))); mp_obj_instance_t *self = self_in; mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); @@ -386,9 +405,8 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_class_lookup(self, self->base.type, attr, 0, dest); mp_obj_t member = dest[0]; if (member != MP_OBJ_NULL) { - if (0) { #if MICROPY_ENABLE_PROPERTY - } else if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { + if (MP_OBJ_IS_TYPE(member, &mp_type_property)) { // object member is a property // delegate the store to the property // TODO should this be part of instance_convert_return_attr? @@ -399,15 +417,8 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); // TODO should we convert the returned value using instance_convert_return_attr? } -#endif - } else { - // not a property - // if we don't yet have bound method (supposedly from native base), go - // try to convert own attrs. - if (dest[1] == MP_OBJ_NULL) { - instance_convert_return_attr(self_in, member, dest); - } } +#endif return; } @@ -488,7 +499,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value return mp_const_none; } } else { - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } @@ -515,7 +526,6 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) { mp_obj_class_lookup(self, self->base.type, MP_QSTR___getitem__, 0, member); if (member[0] != MP_OBJ_NULL) { // __getitem__ exists, create an iterator - instance_convert_return_attr(self_in, member[0], member); return mp_obj_new_getitem_iter(member); } return MP_OBJ_NULL; @@ -583,24 +593,7 @@ STATIC void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { return; } #endif - mp_obj_t member[2] = {MP_OBJ_NULL}; - mp_obj_class_lookup(NULL, self, attr, 0, member); - if (member[0] != MP_OBJ_NULL) { - // check if the methods are functions, static or class methods - // see http://docs.python.org/3.3/howto/descriptor.html - if (MP_OBJ_IS_TYPE(member[0], &mp_type_staticmethod)) { - // return just the function - dest[0] = ((mp_obj_static_class_method_t*)member[0])->fun; - } else if (MP_OBJ_IS_TYPE(member[0], &mp_type_classmethod)) { - // return a bound method, with self being this class - dest[0] = ((mp_obj_static_class_method_t*)member[0])->fun; - dest[1] = self_in; - } else { - // return just the function - // TODO need to wrap in a type check for the first argument; eg list.append(1,1) needs to throw an exception - dest[0] = member[0]; - } - } + mp_obj_class_lookup(NULL, self, attr, 0, dest); } STATIC bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { @@ -639,7 +632,7 @@ STATIC mp_obj_t type_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { return MP_BOOL(lhs_in == rhs_in); default: - return MP_OBJ_NOT_SUPPORTED; + return MP_OBJ_NULL; // op not supported } } @@ -741,12 +734,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_tuple_get(type->bases_tuple, &len, &items); for (uint i = 0; i < len; i++) { assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type)); - mp_obj_t member[2] = {MP_OBJ_NULL}; - mp_obj_class_lookup(self->obj, (mp_obj_type_t*)items[i], attr, 0, member); - if (member[0] != MP_OBJ_NULL) { - instance_convert_return_attr(self->obj, member[0], dest); - return; - } + mp_obj_class_lookup(self->obj, (mp_obj_type_t*)items[i], attr, 0, dest); } } diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 1679d8b39..cffb64d5e 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -34,6 +34,7 @@ Q(__class__) Q(__doc__) Q(__import__) Q(__init__) +Q(__new__) Q(__locals__) Q(__main__) Q(__module__) @@ -236,6 +237,7 @@ Q(find) Q(rfind) Q(rindex) Q(split) +Q(rsplit) Q(startswith) Q(replace) Q(partition) @@ -352,6 +354,8 @@ Q(io) Q(readall) Q(readline) Q(readlines) +Q(FileIO) +Q(TextIOWrapper) Q(StringIO) Q(BytesIO) Q(getvalue) diff --git a/py/runtime.c b/py/runtime.c index 8852b7d80..ea75280ce 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -69,12 +69,13 @@ const mp_obj_module_t mp_module___main__ = { }; void mp_init(void) { - // call port specific initialization if any + // call port specific initialization if any #ifdef MICROPY_PORT_INIT_FUNC MICROPY_PORT_INIT_FUNC; #endif - mp_emit_glue_init(); + // __debug__ enabled by default + mp_set_debug(true); // init global module stuff mp_module_init(); @@ -90,7 +91,6 @@ void mp_init(void) { void mp_deinit(void) { //mp_obj_dict_free(&dict_main); mp_module_deinit(); - mp_emit_glue_deinit(); // call port specific deinitialization if any #ifdef MICROPY_PORT_INIT_FUNC @@ -200,7 +200,7 @@ mp_obj_t mp_unary_op(int op, mp_obj_t arg) { mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(op, arg); - if (result != MP_OBJ_NOT_SUPPORTED) { + if (result != MP_OBJ_NULL) { return result; } } @@ -439,7 +439,7 @@ mp_obj_t mp_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_type_t *type = mp_obj_get_type(rhs); if (type->binary_op != NULL) { mp_obj_t res = type->binary_op(op, rhs, lhs); - if (res != MP_OBJ_NOT_SUPPORTED) { + if (res != MP_OBJ_NULL) { return res; } } @@ -467,7 +467,7 @@ generic_binary_op: type = mp_obj_get_type(lhs); if (type->binary_op != NULL) { mp_obj_t result = type->binary_op(op, lhs, rhs); - if (result != MP_OBJ_NOT_SUPPORTED) { + if (result != MP_OBJ_NULL) { return result; } } diff --git a/py/runtime.h b/py/runtime.h index 910a48544..a5d674303 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -54,6 +54,8 @@ typedef struct _mp_arg_t { void mp_init(void); void mp_deinit(void); +void mp_set_debug(bool value); // sets the value of __debug__; see lexer.c + void mp_arg_check_num(uint n_args, uint n_kw, uint n_args_min, uint n_args_max, bool takes_kw); void mp_arg_parse_all(uint n_pos, const mp_obj_t *pos, mp_map_t *kws, uint n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); void mp_arg_parse_all_kw_array(uint n_pos, uint n_kw, const mp_obj_t *args, uint n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); diff --git a/py/sequence.c b/py/sequence.c index 91162fc09..966adaac0 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -99,6 +100,10 @@ bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, u } uint min_len = len1 < len2 ? len1 : len2; int res = memcmp(data1, data2, min_len); + if (op == MP_BINARY_OP_EQUAL) { + // If we are checking for equality, here're the answer + return res == 0; + } if (res < 0) { return false; } diff --git a/py/stream.c b/py/stream.c index 9eb438b53..b1a64cdcf 100644 --- a/py/stream.c +++ b/py/stream.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,6 +32,7 @@ #include "misc.h" #include "qstr.h" #include "obj.h" +#include "objstr.h" #include "stream.h" #if MICROPY_STREAMS_NON_BLOCK #include <errno.h> @@ -52,6 +54,8 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in); #define is_nonblocking_error(errno) (0) #endif +#define STREAM_CONTENT_TYPE(stream) (((stream)->is_bytes) ? &mp_type_bytes : &mp_type_str) + STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) { @@ -77,7 +81,7 @@ STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) { } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } else { - mp_obj_t s = mp_obj_new_str(buf, out_sz, false); // will reallocate to use exact size + mp_obj_t s = str_new(STREAM_CONTENT_TYPE(o->type->stream_p), buf, out_sz); // will reallocate to use exact size m_free(buf, sz); return s; } @@ -154,7 +158,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { } } - mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, total_size, false); + mp_obj_t s = str_new(STREAM_CONTENT_TYPE(o->type->stream_p), (byte*)vstr->buf, total_size); vstr_free(vstr); return s; } @@ -203,7 +207,7 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { } } // TODO need a string creation API that doesn't copy the given data - mp_obj_t ret = mp_obj_new_str((byte*)vstr->buf, vstr->len, false); + mp_obj_t ret = str_new(STREAM_CONTENT_TYPE(o->type->stream_p), (byte*)vstr->buf, vstr->len); vstr_free(vstr); return ret; } @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2014 Paul Sokolovsky * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal |