summaryrefslogtreecommitdiff
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/builtinimport.c1
-rw-r--r--py/compile.c2
-rw-r--r--py/compile.h2
-rw-r--r--py/emitglue.c25
-rw-r--r--py/emitglue.h3
-rw-r--r--py/lexer.c22
-rw-r--r--py/modio.c13
-rw-r--r--py/modstruct.c84
-rw-r--r--py/mpconfig.h8
-rw-r--r--py/mpz.c13
-rw-r--r--py/obj.c17
-rw-r--r--py/obj.h33
-rw-r--r--py/objarray.c7
-rw-r--r--py/objbool.c2
-rw-r--r--py/objcomplex.c4
-rw-r--r--py/objdict.c10
-rw-r--r--py/objexcept.c15
-rw-r--r--py/objfloat.c4
-rw-r--r--py/objfun.c7
-rw-r--r--py/objgenerator.c7
-rw-r--r--py/objint.c8
-rw-r--r--py/objint.h4
-rw-r--r--py/objint_longlong.c9
-rw-r--r--py/objint_mpz.c16
-rw-r--r--py/objlist.c10
-rw-r--r--py/objmap.c6
-rw-r--r--py/objnamedtuple.c1
-rw-r--r--py/objnone.c2
-rw-r--r--py/objset.c4
-rw-r--r--py/objstr.c104
-rw-r--r--py/objstr.h1
-rw-r--r--py/objstringio.c33
-rw-r--r--py/objtuple.c11
-rw-r--r--py/objtype.c124
-rw-r--r--py/qstrdefs.h4
-rw-r--r--py/runtime.c12
-rw-r--r--py/runtime.h2
-rw-r--r--py/sequence.c5
-rw-r--r--py/stream.c10
-rw-r--r--py/vm.c1
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)
diff --git a/py/mpz.c b/py/mpz.c
index 8eed283f0..9e60fc50d 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -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);
diff --git a/py/obj.c b/py/obj.c
index 437346b62..f8b5ee34d 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -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?
diff --git a/py/obj.h b/py/obj.h
index b34581c8b..2df597de7 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -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;
}
diff --git a/py/vm.c b/py/vm.c
index 52e057ec1..123f52028 100644
--- a/py/vm.c
+++ b/py/vm.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