summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-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
-rw-r--r--qemu-arm/mpconfigport.h1
-rw-r--r--stmhal/dac.c8
-rw-r--r--stmhal/file.c8
-rw-r--r--stmhal/modpyb.c18
-rw-r--r--stmhal/modstm.c2
-rw-r--r--stmhal/qstrdefsport.h1
-rw-r--r--stmhal/usb.c7
-rw-r--r--stmhal/usb.h1
-rw-r--r--tests/basics/bytes_compare.py2
-rw-r--r--tests/basics/bytes_compare2.py7
-rw-r--r--tests/basics/int-big-and.py8
-rw-r--r--tests/basics/int-long.py12
-rw-r--r--tests/basics/string_rsplit.py42
-rw-r--r--tests/basics/string_startswith.py6
-rw-r--r--tests/basics/struct1.py5
-rw-r--r--tests/basics/subclass-native2-list.py26
-rw-r--r--tests/basics/subclass-native2-tuple.py21
-rw-r--r--tests/basics/subclass-native2.py37
-rw-r--r--unix/Makefile1
-rw-r--r--unix/file.c73
-rw-r--r--unix/main.c45
-rw-r--r--unix/modffi.c1
-rw-r--r--unix/modos.c87
-rw-r--r--unix/modsocket.c1
-rw-r--r--unix/mpconfigport.h19
-rw-r--r--unix/qstrdefsport.h3
-rw-r--r--windows/Makefile3
67 files changed, 776 insertions, 315 deletions
diff --git a/py/builtinimport.c b/py/builtinimport.c
index e6bb7586c8..e758158a64 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 36ffa928ee..cdd3a5b030 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 4606378976..52c42aff4f 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 7265a206a8..528c3bd36c 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 43bfb5e08a..c6cbb6283d 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 f736ef3030..e2dfea78c8 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 892d493c95..b1f0d880ae 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 b53dd51836..19cf9cfd6c 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 76cd1091cb..445fc78b04 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 8eed283f04..9e60fc50d0 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 437346b62d..f8b5ee34d9 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 b34581c8bf..2df597de75 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 b394d77461..d973a4c563 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 e31e7a2a42..4fe7a19341 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 18e0edc519..80a13c6d8f 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 9d4ebb6279..f41eacd939 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 7f5f9c73d2..0006554a85 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 e27942143d..6732f31215 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 732009376d..26dfe0b2e2 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 fb8366bae5..8180185b94 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 d1d99a253f..a3b3554008 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 0ea19d0ddb..1d12cffae0 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 f648615a73..1e0167b464 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 8e72782d66..2df3232e9c 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 0ef685daeb..ee74926923 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 232e611bd2..6e5c79017d 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 212cf131c8..a55dd643b0 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 bb4e7e5608..165c8e5a43 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 a6f1fe7339..32c194db12 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 79ad891d05..61fda12a3f 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 019f56f7b3..c0ef701a83 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 880d4e1177..a1a765f89c 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 44ee95dd96..46515378f0 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 5f3e1db5d3..2e1c56416e 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 1679d8b39c..cffb64d5ef 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 8852b7d80d..ea75280ce4 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 910a485446..a5d6743034 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 91162fc099..966adaac03 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 9eb438b538..b1a64cdcf5 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 52e057ec1e..123f520280 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
diff --git a/qemu-arm/mpconfigport.h b/qemu-arm/mpconfigport.h
index 7f4c378901..76663ccabe 100644
--- a/qemu-arm/mpconfigport.h
+++ b/qemu-arm/mpconfigport.h
@@ -14,6 +14,7 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_PATH_MAX (512)
+#define MICROPY_ENABLE_MOD_IO (0)
// type definitions for the specific machine
diff --git a/stmhal/dac.c b/stmhal/dac.c
index f0f723f853..81ce993a8c 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -62,7 +62,7 @@
/// # create a buffer containing a sine-wave
/// buf = bytearray(100)
/// for i in range(len(buf)):
-/// buf[i] = 128 + 127 * math.sin(2 * math.pi * i / len(buf))
+/// buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf)))
///
/// # output the sine-wave at 400Hz
/// dac = DAC(1)
@@ -295,7 +295,11 @@ mp_obj_t pyb_dac_write_timed(uint n_args, const mp_obj_t *args, mp_map_t *kw_arg
DMA_Handle.Init.PeriphBurst = DMA_PBURST_SINGLE;
HAL_DMA_Init(&DMA_Handle);
- __HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle);
+ if (self->dac_channel == DAC_CHANNEL_1) {
+ __HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle);
+ } else {
+ __HAL_LINKDMA(&DAC_Handle, DMA_Handle2, DMA_Handle);
+ }
DAC_Handle.Instance = DAC;
DAC_Handle.State = HAL_DAC_STATE_RESET;
diff --git a/stmhal/file.c b/stmhal/file.c
index 93bd49e669..3fea956530 100644
--- a/stmhal/file.c
+++ b/stmhal/file.c
@@ -41,7 +41,7 @@ typedef struct _pyb_file_obj_t {
} pyb_file_obj_t;
void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
- printf("<io.FileIO %p>", self_in);
+ printf("<io.%s %p>", mp_obj_get_type_str(self_in), self_in);
}
STATIC machine_int_t file_read(mp_obj_t self_in, void *buf, machine_uint_t size, int *errcode) {
@@ -94,7 +94,7 @@ STATIC const mp_stream_p_t file_obj_stream_p = {
.write = file_write,
};
-STATIC const mp_obj_type_t file_obj_type = {
+const mp_obj_type_t mp_type_textio = {
{ &mp_type_type },
.name = MP_QSTR_FileIO,
.make_new = file_obj_make_new,
@@ -113,7 +113,7 @@ STATIC mp_obj_t file_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, cons
mode = mp_obj_str_get_str(args[1]);
}
pyb_file_obj_t *self = m_new_obj_with_finaliser(pyb_file_obj_t);
- self->base.type = &file_obj_type;
+ self->base.type = &mp_type_textio;
if (mode[0] == 'r') {
// open for reading
FRESULT res = f_open(&self->fp, filename, FA_READ);
@@ -138,7 +138,7 @@ STATIC mp_obj_t file_obj_make_new(mp_obj_t type_in, uint n_args, uint n_kw, cons
// Factory function for I/O stream classes
STATIC mp_obj_t pyb_io_open(uint n_args, const mp_obj_t *args) {
// TODO: analyze mode and buffering args and instantiate appropriate type
- return file_obj_make_new((mp_obj_t)&file_obj_type, n_args, 0, args);
+ return file_obj_make_new((mp_obj_t)&mp_type_textio, n_args, 0, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, pyb_io_open);
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 81dc921173..7ec25038bf 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -62,6 +62,23 @@
///
/// The `pyb` module contains specific functions related to the pyboard.
+/// \function bootloader()
+/// Activate the bootloader without BOOT* pins.
+STATIC NORETURN mp_obj_t pyb_bootloader(void) {
+ pyb_usb_dev_stop();
+ storage_flush();
+
+ HAL_RCC_DeInit();
+ HAL_DeInit();
+
+ __HAL_REMAPMEMORY_SYSTEMFLASH();
+ __set_MSP(*((uint32_t*) 0x00000000));
+ ((void (*)(void)) *((uint32_t*) 0x00000004))();
+
+ while (1);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_bootloader_obj, pyb_bootloader);
+
/// \function info([dump_alloc_table])
/// Print out lots of information about the board.
STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
@@ -302,6 +319,7 @@ MP_DECLARE_CONST_FUN_OBJ(pyb_usb_mode_obj); // defined in main.c
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&pyb_bootloader_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&pyb_unique_id_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
diff --git a/stmhal/modstm.c b/stmhal/modstm.c
index e645af1229..520c8e51bd 100644
--- a/stmhal/modstm.c
+++ b/stmhal/modstm.c
@@ -81,7 +81,7 @@ STATIC mp_obj_t stm_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
stm_mem_obj_t *self = self_in;
if (value == MP_OBJ_NULL) {
// delete
- return MP_OBJ_NOT_SUPPORTED;
+ return MP_OBJ_NULL; // op not supported
} else if (value == MP_OBJ_SENTINEL) {
// load
uint32_t addr = get_read_addr(index, self->elem_size);
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h
index c2cf6840df..d822a542f0 100644
--- a/stmhal/qstrdefsport.h
+++ b/stmhal/qstrdefsport.h
@@ -29,6 +29,7 @@
Q(help)
Q(pyb)
Q(unique_id)
+Q(bootloader)
Q(info)
Q(sd_test)
Q(present)
diff --git a/stmhal/usb.c b/stmhal/usb.c
index fd8cbb95a1..ef7e8a62eb 100644
--- a/stmhal/usb.c
+++ b/stmhal/usb.c
@@ -75,6 +75,13 @@ void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) {
#endif
}
+void pyb_usb_dev_stop(void) {
+ if (dev_is_enabled) {
+ USBD_Stop(&hUSBDDevice);
+ dev_is_enabled = 0;
+ }
+}
+
bool usb_vcp_is_enabled(void) {
return dev_is_enabled;
}
diff --git a/stmhal/usb.h b/stmhal/usb.h
index 8b8562ce6d..3bd30ba92c 100644
--- a/stmhal/usb.h
+++ b/stmhal/usb.h
@@ -42,6 +42,7 @@ typedef enum {
} usb_storage_medium_t;
void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium);
+void pyb_usb_dev_stop(void);
bool usb_vcp_is_enabled(void);
bool usb_vcp_is_connected(void);
void usb_vcp_set_interrupt_char(int c);
diff --git a/tests/basics/bytes_compare.py b/tests/basics/bytes_compare.py
index 3804844feb..292267ba75 100644
--- a/tests/basics/bytes_compare.py
+++ b/tests/basics/bytes_compare.py
@@ -49,3 +49,5 @@ print(b"1" <= b"10")
print(b"1" <= b"1/")
print(b"10" <= b"1")
print(b"1/" <= b"1")
+
+print(b'o' == b'\n')
diff --git a/tests/basics/bytes_compare2.py b/tests/basics/bytes_compare2.py
new file mode 100644
index 0000000000..769d76b119
--- /dev/null
+++ b/tests/basics/bytes_compare2.py
@@ -0,0 +1,7 @@
+import array
+
+print(b"1" == 1)
+print(b"123" == bytearray(b"123"))
+print(b"123" == "123")
+# CPyhon gives False here
+#print(b"\x01\x02\x03" == array.array("B", [1, 2, 3]))
diff --git a/tests/basics/int-big-and.py b/tests/basics/int-big-and.py
new file mode 100644
index 0000000000..75fbd52884
--- /dev/null
+++ b/tests/basics/int-big-and.py
@@ -0,0 +1,8 @@
+print(0 & (1 << 80))
+print(0 & (1 << 80) == 0)
+print(bool(0 & (1 << 80)))
+
+#a = 0xfffffffffffffffffffffffffffff
+#print(a & (1 << 80))
+#print((a & (1 << 80)) >> 80)
+#print((a & (1 << 80)) >> 80 == 1)
diff --git a/tests/basics/int-long.py b/tests/basics/int-long.py
index 3567e08b2d..a22075d1f9 100644
--- a/tests/basics/int-long.py
+++ b/tests/basics/int-long.py
@@ -11,7 +11,7 @@ print(b - a)
#print(a * b)
print(a // b)
print(a % b)
-print(a & b)
+print("&", a & b)
print(a | b)
print(a ^ b)
print(a << 3)
@@ -32,7 +32,7 @@ print(a)
a |= b
print(a)
a &= b
-print(a)
+print("&=", a)
a <<= 5
print(a)
a >>= 1
@@ -44,3 +44,11 @@ b = a
a += 1
print(a)
print(b)
+
+# Bitwise ops on 64-bit
+
+a = 0x1ffffffffffffffff
+b = 0x10000000000000000
+print("&", a & b)
+print(a | b)
+print(a ^ b)
diff --git a/tests/basics/string_rsplit.py b/tests/basics/string_rsplit.py
new file mode 100644
index 0000000000..cc6c0fd062
--- /dev/null
+++ b/tests/basics/string_rsplit.py
@@ -0,0 +1,42 @@
+# default separator (whitespace)
+print("a b".rsplit())
+#print(" a b ".rsplit(None))
+#print(" a b ".rsplit(None, 1))
+#print(" a b ".rsplit(None, 2))
+#print(" a b c ".rsplit(None, 1))
+#print(" a b c ".rsplit(None, 0))
+#print(" a b c ".rsplit(None, -1))
+
+# empty separator should fail
+try:
+ "abc".rsplit('')
+except ValueError:
+ print("ValueError")
+
+# non-empty separator
+print("abc".rsplit("a"))
+print("abc".rsplit("b"))
+print("abc".rsplit("c"))
+print("abc".rsplit("z"))
+print("abc".rsplit("ab"))
+print("abc".rsplit("bc"))
+print("abc".rsplit("abc"))
+print("abc".rsplit("abcd"))
+print("abcabc".rsplit("bc"))
+print("abcabc".rsplit("bc", 0))
+print("abcabc".rsplit("bc", 1))
+print("abcabc".rsplit("bc", 2))
+
+print("10/11/12".rsplit("/", 1))
+print("10/11/12".rsplit("/", 2))
+print("10/11/12".rsplit("/", 3))
+print("10/11/12".rsplit("/", 4))
+print("10/11/12".rsplit("/", 5))
+
+print("/*10/*11/*12/*".rsplit("/*", 1))
+print("/*10/*11/*12/*".rsplit("/*", 2))
+print("/*10/*11/*12/*".rsplit("/*", 3))
+print("/*10/*11/*12/*".rsplit("/*", 4))
+print("/*10/*11/*12/*".rsplit("/*", 5))
+
+print(b"abcabc".rsplit(b"bc", 2))
diff --git a/tests/basics/string_startswith.py b/tests/basics/string_startswith.py
index 99d653efbb..5cf730c03c 100644
--- a/tests/basics/string_startswith.py
+++ b/tests/basics/string_startswith.py
@@ -3,3 +3,9 @@ print("foobar".startswith("Foo"))
print("foobar".startswith("foo1"))
print("foobar".startswith("foobar"))
print("foobar".startswith(""))
+
+print("1foobar".startswith("foo", 1))
+print("1foo".startswith("foo", 1))
+print("1foo".startswith("1foo", 1))
+print("1fo".startswith("foo", 1))
+print("1fo".startswith("foo", 10))
diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py
index 3a05c85f0b..b114a789b5 100644
--- a/tests/basics/struct1.py
+++ b/tests/basics/struct1.py
@@ -16,3 +16,8 @@ print(struct.pack(">b", 1))
print(struct.pack("<bI", -128, 256))
print(struct.pack(">bI", -128, 256))
+
+print(struct.calcsize("100sI"))
+print(struct.calcsize("97sI"))
+print(struct.unpack("<6sH", b"foo\0\0\0\x12\x34"))
+print(struct.pack("<6sH", b"foo", 10000))
diff --git a/tests/basics/subclass-native2-list.py b/tests/basics/subclass-native2-list.py
new file mode 100644
index 0000000000..9ad0b77ef6
--- /dev/null
+++ b/tests/basics/subclass-native2-list.py
@@ -0,0 +1,26 @@
+class Base1:
+ def __init__(self, *args):
+ print("Base1.__init__", args)
+
+class Clist1(Base1, list):
+ pass
+
+a = Clist1()
+print(len(a))
+# Not compliant - list assignment should happen in list.__init__, which is not called
+# because there's Base1.__init__, but we assign in list.__new__
+#a = Clist1([1, 2, 3])
+#print(len(a))
+
+print("---")
+
+class Clist2(list, Base1):
+ pass
+
+# Not compliant - should call list.__init__, but we don't have it
+#a = Clist2()
+#print(len(a))
+
+# Not compliant - should call list.__init__, but we don't have it
+#a = Clist2([1, 2, 3])
+#print(len(a))
diff --git a/tests/basics/subclass-native2-tuple.py b/tests/basics/subclass-native2-tuple.py
new file mode 100644
index 0000000000..9eb69e1575
--- /dev/null
+++ b/tests/basics/subclass-native2-tuple.py
@@ -0,0 +1,21 @@
+class Base1:
+ def __init__(self, *args):
+ print("Base1.__init__", args)
+
+class Ctuple1(Base1, tuple):
+ pass
+
+a = Ctuple1()
+print(len(a))
+a = Ctuple1([1, 2, 3])
+print(len(a))
+
+print("---")
+
+class Ctuple2(tuple, Base1):
+ pass
+
+a = Ctuple2()
+print(len(a))
+a = Ctuple2([1, 2, 3])
+print(len(a))
diff --git a/tests/basics/subclass-native2.py b/tests/basics/subclass-native2.py
deleted file mode 100644
index 749bf969cf..0000000000
--- a/tests/basics/subclass-native2.py
+++ /dev/null
@@ -1,37 +0,0 @@
-class Base1:
- def __init__(self, *args):
- print("Base1.__init__",args)
-
-class Clist1(Base1, list):
- pass
-
-class Ctuple1(Base1, tuple):
- pass
-
-a = Clist1()
-print(len(a))
-a = Clist1([1, 2, 3])
-print(len(a))
-
-a = Ctuple1()
-print(len(a))
-a = Ctuple1([1, 2, 3])
-# TODO: Faults
-#print(len(a))
-
-print("---")
-
-class Clist2(list, Base1):
- pass
-
-class Ctuple2(tuple, Base1):
- pass
-a = Clist2()
-print(len(a))
-a = Clist2([1, 2, 3])
-print(len(a))
-
-#a = Ctuple2()
-#print(len(a))
-#a = Ctuple2([1, 2, 3])
-#print(len(a))
diff --git a/unix/Makefile b/unix/Makefile
index ba2180fe58..b336892a42 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -68,6 +68,7 @@ SRC_C = \
input.c \
file.c \
modsocket.c \
+ modos.c \
$(SRC_MOD)
# Must be the last file
diff --git a/unix/file.c b/unix/file.c
index ada841ea2c..7f45ac4a33 100644
--- a/unix/file.c
+++ b/unix/file.c
@@ -54,11 +54,12 @@ void check_fd_is_open(const mp_obj_fdfile_t *o) {
#define check_fd_is_open(o)
#endif
-STATIC const mp_obj_type_t rawfile_type;
+extern const mp_obj_type_t mp_type_fileio;
+extern const mp_obj_type_t mp_type_textio;
STATIC void fdfile_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
mp_obj_fdfile_t *self = self_in;
- print(env, "<io.FileIO %d>", self->fd);
+ print(env, "<io.%s %d>", mp_obj_get_type_str(self), self->fd);
}
STATIC machine_int_t fdfile_read(mp_obj_t o_in, void *buf, machine_uint_t size, int *errcode) {
@@ -103,23 +104,10 @@ STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_fileno_obj, fdfile_fileno);
-STATIC mp_obj_fdfile_t *fdfile_new(int fd) {
- mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
- o->base.type = &rawfile_type;
- o->fd = fd;
- return o;
-}
-
STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
- o->base.type = type_in;
-
- if (MP_OBJ_IS_SMALL_INT(args[0])) {
- o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]);
- return o;
- }
+ mp_const_obj_t type = type_in;
- const char *fname = mp_obj_str_get_str(args[0]);
const char *mode_s;
if (n_args > 1) {
mode_s = mp_obj_str_get_str(args[1]);
@@ -143,14 +131,32 @@ STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const
case '+':
mode |= O_RDWR;
break;
+ #if MICROPY_MOD_IO_FILEIO
+ // If we don't have io.FileIO, then files are in text mode implicitly
+ case 'b':
+ type = &mp_type_fileio;
+ break;
+ case 't':
+ type = &mp_type_textio;
+ break;
+ #endif
}
}
+ o->base.type = type;
+
+ if (MP_OBJ_IS_SMALL_INT(args[0])) {
+ o->fd = MP_OBJ_SMALL_INT_VALUE(args[0]);
+ return o;
+ }
+
+ const char *fname = mp_obj_str_get_str(args[0]);
int fd = open(fname, mode, 0644);
if (fd == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT((machine_int_t)errno)));
}
- return fdfile_new(fd);
+ o->fd = fd;
+ return o;
}
STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
@@ -167,29 +173,48 @@ STATIC const mp_map_elem_t rawfile_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table);
-STATIC const mp_stream_p_t rawfile_stream_p = {
+#if MICROPY_MOD_IO_FILEIO
+STATIC const mp_stream_p_t fileio_stream_p = {
.read = fdfile_read,
.write = fdfile_write,
+ .is_bytes = true,
};
-STATIC const mp_obj_type_t rawfile_type = {
+const mp_obj_type_t mp_type_fileio = {
{ &mp_type_type },
.name = MP_QSTR_FileIO,
.print = fdfile_print,
.make_new = fdfile_make_new,
.getiter = mp_identity,
.iternext = mp_stream_unbuffered_iter,
- .stream_p = &rawfile_stream_p,
+ .stream_p = &fileio_stream_p,
+ .locals_dict = (mp_obj_t)&rawfile_locals_dict,
+};
+#endif
+
+STATIC const mp_stream_p_t textio_stream_p = {
+ .read = fdfile_read,
+ .write = fdfile_write,
+};
+
+const mp_obj_type_t mp_type_textio = {
+ { &mp_type_type },
+ .name = MP_QSTR_TextIOWrapper,
+ .print = fdfile_print,
+ .make_new = fdfile_make_new,
+ .getiter = mp_identity,
+ .iternext = mp_stream_unbuffered_iter,
+ .stream_p = &textio_stream_p,
.locals_dict = (mp_obj_t)&rawfile_locals_dict,
};
// Factory function for I/O stream classes
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args) {
// TODO: analyze mode and buffering args and instantiate appropriate type
- return fdfile_make_new((mp_obj_t)&rawfile_type, n_args, 0, args);
+ return fdfile_make_new((mp_obj_t)&mp_type_textio, n_args, 0, args);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_open_obj, 1, 2, mp_builtin_open);
-const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&rawfile_type}, .fd = STDIN_FILENO };
-const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&rawfile_type}, .fd = STDOUT_FILENO };
-const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&rawfile_type}, .fd = STDERR_FILENO };
+const mp_obj_fdfile_t mp_sys_stdin_obj = { .base = {&mp_type_textio}, .fd = STDIN_FILENO };
+const mp_obj_fdfile_t mp_sys_stdout_obj = { .base = {&mp_type_textio}, .fd = STDOUT_FILENO };
+const mp_obj_fdfile_t mp_sys_stderr_obj = { .base = {&mp_type_textio}, .fd = STDERR_FILENO };
diff --git a/unix/main.c b/unix/main.c
index de296142b3..23dd4be631 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -69,9 +69,10 @@ void microsocket_init();
void time_init();
void ffi_init();
-STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
+// returns standard error codes: 0 for success, 1 for all other errors
+STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) {
if (lex == NULL) {
- return;
+ return 1;
}
if (0) {
@@ -81,7 +82,7 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
mp_lexer_to_next(lex);
}
mp_lexer_free(lex);
- return;
+ return 0;
}
mp_parse_error_kind_t parse_error_kind;
@@ -91,7 +92,7 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
// parse error
mp_parse_show_exception(lex, parse_error_kind);
mp_lexer_free(lex);
- return;
+ return 1;
}
qstr source_name = mp_lexer_source_name(lex);
@@ -107,11 +108,11 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
if (module_fun == mp_const_none) {
// compile error
- return;
+ return 1;
}
if (compile_only) {
- return;
+ return 0;
}
// execute it
@@ -119,9 +120,11 @@ STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
if (nlr_push(&nlr) == 0) {
mp_call_function_0(module_fun);
nlr_pop();
+ return 0;
} else {
// uncaught exception
mp_obj_print_exception((mp_obj_t)nlr.ret_val);
+ return 1;
}
}
@@ -165,14 +168,14 @@ STATIC void do_repl(void) {
}
}
-STATIC void do_file(const char *file) {
+STATIC int do_file(const char *file) {
mp_lexer_t *lex = mp_lexer_new_from_file(file);
- execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false);
+ return execute_from_lexer(lex, MP_PARSE_FILE_INPUT, false);
}
-STATIC void do_str(const char *str) {
+STATIC int do_str(const char *str) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, str, strlen(str), false);
- execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false);
+ return execute_from_lexer(lex, MP_PARSE_SINGLE_INPUT, false);
}
int usage(char **argv) {
@@ -230,7 +233,7 @@ void pre_process_options(int argc, char **argv) {
} else if (strcmp(argv[a + 1], "compile-only") == 0) {
compile_only = true;
} else if (strcmp(argv[a + 1], "emit=bytecode") == 0) {
- emit_opt = MP_EMIT_OPT_BYTE_CODE;
+ emit_opt = MP_EMIT_OPT_BYTECODE;
} else if (strcmp(argv[a + 1], "emit=native") == 0) {
emit_opt = MP_EMIT_OPT_NATIVE_PYTHON;
} else if (strcmp(argv[a + 1], "emit=viper") == 0) {
@@ -321,20 +324,23 @@ int main(int argc, char **argv) {
printf(" peak %d\n", m_get_peak_bytes_allocated());
*/
- bool executed = false;
+ const int NOTHING_EXECUTED = -2;
+ int ret = NOTHING_EXECUTED;
for (int a = 1; a < argc; a++) {
if (argv[a][0] == '-') {
if (strcmp(argv[a], "-c") == 0) {
if (a + 1 >= argc) {
return usage(argv);
}
- do_str(argv[a + 1]);
- executed = true;
+ ret = do_str(argv[a + 1]);
a += 1;
} else if (strcmp(argv[a], "-X") == 0) {
a += 1;
} else if (strcmp(argv[a], "-v") == 0) {
mp_verbose_flag++;
+ } else if (strcmp(argv[a], "-O") == 0) {
+ // optimisation; sets __debug__ to False
+ mp_set_debug(false);
} else {
return usage(argv);
}
@@ -344,7 +350,8 @@ int main(int argc, char **argv) {
fprintf(stderr, "%s: can't open file '%s': [Errno %d] ", argv[0], argv[1], errno);
perror("");
// CPython exits with 2 in such case
- exit(2);
+ ret = 2;
+ break;
}
// Set base dir of the script as first entry in sys.path
@@ -355,20 +362,20 @@ int main(int argc, char **argv) {
for (int i = a; i < argc; i++) {
mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i])));
}
- do_file(argv[a]);
- executed = true;
+ ret = do_file(argv[a]);
break;
}
}
- if (!executed) {
+ if (ret == NOTHING_EXECUTED) {
do_repl();
+ ret = 0;
}
mp_deinit();
//printf("total bytes = %d\n", m_get_total_bytes_allocated());
- return 0;
+ return ret;
}
STATIC mp_obj_t mp_sys_exit(uint n_args, const mp_obj_t *args) {
diff --git a/unix/modffi.c b/unix/modffi.c
index aa26297d60..4ac9fef5aa 100644
--- a/unix/modffi.c
+++ b/unix/modffi.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/unix/modos.c b/unix/modos.c
new file mode 100644
index 0000000000..d4951661da
--- /dev/null
+++ b/unix/modos.c
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * 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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "misc.h"
+#include "mpconfig.h"
+#include "nlr.h"
+#include "qstr.h"
+#include "obj.h"
+#include "runtime.h"
+#include "objtuple.h"
+
+#define RAISE_ERRNO(err_flag, error_val) \
+ { if (err_flag == -1) \
+ { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT((machine_int_t)error_val))); } }
+
+STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) {
+ struct stat sb;
+ const char *path = mp_obj_str_get_str(path_in);
+
+ int res = stat(path, &sb);
+ RAISE_ERRNO(res, errno);
+
+ mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
+ t->items[0] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_mode);
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino);
+ t->items[2] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_dev);
+ t->items[3] = MP_OBJ_NEW_SMALL_INT(sb.st_nlink);
+ t->items[4] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_uid);
+ t->items[5] = MP_OBJ_NEW_SMALL_INT((machine_int_t)sb.st_gid);
+ t->items[6] = MP_OBJ_NEW_SMALL_INT(sb.st_size);
+ t->items[7] = MP_OBJ_NEW_SMALL_INT(sb.st_atime);
+ t->items[8] = MP_OBJ_NEW_SMALL_INT(sb.st_mtime);
+ t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.st_ctime);
+ return t;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat);
+
+STATIC const mp_map_elem_t mp_module_os_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR__os) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&mod_os_stat_obj },
+};
+
+STATIC const mp_obj_dict_t mp_module_os_globals = {
+ .base = {&mp_type_dict},
+ .map = {
+ .all_keys_are_qstrs = 1,
+ .table_is_fixed_array = 1,
+ .used = ARRAY_SIZE(mp_module_os_globals_table),
+ .alloc = ARRAY_SIZE(mp_module_os_globals_table),
+ .table = (mp_map_elem_t*)mp_module_os_globals_table,
+ },
+};
+
+const mp_obj_module_t mp_module_os = {
+ .base = { &mp_type_module },
+ .name = MP_QSTR__os,
+ .globals = (mp_obj_dict_t*)&mp_module_os_globals,
+};
diff --git a/unix/modsocket.c b/unix/modsocket.c
index 131d9285e4..5192c02438 100644
--- a/unix/modsocket.c
+++ b/unix/modsocket.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/unix/mpconfigport.h b/unix/mpconfigport.h
index 4f347f4e02..6cac4f4cc7 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -45,17 +45,32 @@
#define MICROPY_MOD_SYS_EXIT (1)
#define MICROPY_MOD_SYS_STDFILES (1)
#define MICROPY_ENABLE_MOD_CMATH (1)
+#define MICROPY_MOD_IO_FILEIO (1)
// Define to MICROPY_ERROR_REPORTING_DETAILED to get function, etc.
// names in exception messages (may require more RAM).
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
+extern const struct _mp_obj_module_t mp_module_os;
extern const struct _mp_obj_module_t mp_module_time;
extern const struct _mp_obj_module_t mp_module_socket;
extern const struct _mp_obj_module_t mp_module_ffi;
+
+#if MICROPY_MOD_FFI
+#define MICROPY_MOD_FFI_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_ffi), (mp_obj_t)&mp_module_ffi },
+#else
+#define MICROPY_MOD_FFI_DEF
+#endif
+#if MICROPY_MOD_TIME
+#define MICROPY_MOD_TIME_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_time },
+#else
+#define MICROPY_MOD_TIME_DEF
+#endif
+
#define MICROPY_EXTRA_BUILTIN_MODULES \
- { MP_OBJ_NEW_QSTR(MP_QSTR_ffi), (mp_obj_t)&mp_module_ffi }, \
- { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_time }, \
+ MICROPY_MOD_FFI_DEF \
+ MICROPY_MOD_TIME_DEF \
{ MP_OBJ_NEW_QSTR(MP_QSTR_microsocket), (mp_obj_t)&mp_module_socket }, \
+ { MP_OBJ_NEW_QSTR(MP_QSTR__os), (mp_obj_t)&mp_module_os }, \
// type definitions for the specific machine
diff --git a/unix/qstrdefsport.h b/unix/qstrdefsport.h
index 55a82ec067..de0b3d8fae 100644
--- a/unix/qstrdefsport.h
+++ b/unix/qstrdefsport.h
@@ -33,6 +33,9 @@ Q(makefile)
Q(FileIO)
+Q(_os)
+Q(stat)
+
Q(ffi)
Q(ffimod)
Q(ffifunc)
diff --git a/windows/Makefile b/windows/Makefile
index 8fcc0b5815..a188979bd5 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -17,6 +17,9 @@ INC += -I$(BUILD)
# compiler settings
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT)
LDFLAGS = $(LDFLAGS_MOD) -lm
+ifeq ($(CROSS_COMPILE),i686-w64-mingw32-)
+CFLAGS += -D__USE_MINGW_ANSI_STDIO=1
+endif
# Debugging/Optimization
ifdef DEBUG