diff options
49 files changed, 293 insertions, 106 deletions
diff --git a/.travis.yml b/.travis.yml index f0b5b561b6..e6c12b9677 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ before_script: - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded - sudo apt-get update -qq - - sudo apt-get install -y python3.3 python3 gcc-4.7 gcc-arm-none-eabi qemu-system + - sudo apt-get install -y python3.3 python3 gcc-4.7 gcc-arm-none-eabi qemu-system mingw32 script: - make -C unix CC=gcc-4.7 @@ -15,6 +15,8 @@ script: - make -C bare-arm - make -C qemu-arm - make -C stmhal + - make -C windows CROSS_COMPILE=i586-mingw32msvc- + - (cd tests && MICROPY_CPYTHON3=python3.3 ./run-tests) after_failure: diff --git a/py/builtin.c b/py/builtin.c index 8d5779e42c..7f0d2a4d9f 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -462,6 +462,21 @@ STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr); +STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) { + assert(MP_OBJ_IS_QSTR(attr_in)); + + mp_obj_t dest[2]; + // TODO: https://docs.python.org/3.3/library/functions.html?highlight=hasattr#hasattr + // explicitly says "This is implemented by calling getattr(object, name) and seeing + // whether it raises an AttributeError or not.", so we should explicitly wrap this + // in nlr_push and handle exception. + mp_load_method_maybe(object_in, MP_OBJ_QSTR_VALUE(attr_in), dest); + + return MP_BOOL(dest[0] != MP_OBJ_NULL); +} + +MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr); + // These two are defined in terms of MicroPython API functions right away MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_globals_get); MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_locals_get); diff --git a/py/builtin.h b/py/builtin.h index baf444a208..2929c1018a 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -41,6 +41,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_exec_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_getattr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_globals_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hasattr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hex_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_id_obj); 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/builtintables.c b/py/builtintables.c index a1888a6e97..133c14a269 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -90,6 +90,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_exec), (mp_obj_t)&mp_builtin_exec_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_getattr), (mp_obj_t)&mp_builtin_getattr_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_globals), (mp_obj_t)&mp_builtin_globals_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_hasattr), (mp_obj_t)&mp_builtin_hasattr_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_hash), (mp_obj_t)&mp_builtin_hash_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_hex), (mp_obj_t)&mp_builtin_hex_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_id), (mp_obj_t)&mp_builtin_id_obj }, 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/modstruct.c b/py/modstruct.c index 68c5ce9baa..95a282e2ec 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) { @@ -67,9 +86,23 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { machine_uint_t size; for (size = 0; *fmt; fmt++) { uint align; - int sz = mp_binary_get_size(fmt_type, *fmt, &align); + 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,11 +154,33 @@ 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; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, -1, struct_pack); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); STATIC const mp_map_elem_t mp_module_struct_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_struct) }, @@ -213,8 +213,8 @@ STATIC uint mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, uint jlen, const mpz *idig = *jdig & *kdig; } - for (; jlen > 0; --jlen, ++idig) { - *idig = 0; + // remove trailing zeros + for (; idig > oidig && *idig == 0; --idig) { } return idig - oidig; @@ -357,7 +357,12 @@ 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) { - return type->unary_op(MP_UNARY_OP_LEN, o_in); + 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; } else { return MP_OBJ_NULL; } diff --git a/py/objarray.c b/py/objarray.c index b394d77461..81ab57139a 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 diff --git a/py/objbool.c b/py/objbool.c index 179ab76596..e31e7a2a42 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -49,12 +49,14 @@ STATIC void bool_print(void (*print)(void *env, const char *fmt, ...), void *env } STATIC mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { - case 0: return mp_const_false; - case 1: if (mp_obj_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } - default: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bool takes at most 1 argument, %d given", n_args)); + case 0: + return mp_const_false; + case 1: + default: // must be 0 or 1 + if (mp_obj_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } } } diff --git a/py/objcomplex.c b/py/objcomplex.c index 1caa49ede4..18e0edc519 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -34,6 +34,7 @@ #include "obj.h" #include "parsenum.h" #include "runtime0.h" +#include "runtime.h" #if MICROPY_ENABLE_FLOAT @@ -74,7 +75,7 @@ STATIC void complex_print(void (*print)(void *env, const char *fmt, ...), void * } STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 2, false); switch (n_args) { case 0: @@ -94,7 +95,8 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); } - case 2: { + case 2: + default: { mp_float_t real, imag; if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { mp_obj_complex_get(args[0], &real, &imag); @@ -112,9 +114,6 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const } return mp_obj_new_complex(real, imag); } - - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "complex takes at most 2 arguments, %d given", n_args)); } } diff --git a/py/objfloat.c b/py/objfloat.c index 5260fadc1c..e27942143d 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -37,6 +37,7 @@ #include "obj.h" #include "parsenum.h" #include "runtime0.h" +#include "runtime.h" #if MICROPY_ENABLE_FLOAT @@ -66,13 +67,14 @@ STATIC void float_print(void (*print)(void *env, const char *fmt, ...), void *en } STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: return mp_obj_new_float(0); case 1: + default: if (MP_OBJ_IS_STR(args[0])) { // a string, parse it uint l; @@ -85,9 +87,6 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m // something else, try to cast it to a float return mp_obj_new_float(mp_obj_get_float(args[0])); } - - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "float takes at most 1 argument, %d given", n_args)); } } diff --git a/py/objfun.c b/py/objfun.c index 732009376d..7915ddad0f 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 diff --git a/py/objgenerator.c b/py/objgenerator.c index fb8366bae5..de2ecdd488 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 diff --git a/py/objint.c b/py/objint.c index 73b4c5d0be..d1d99a253f 100644 --- a/py/objint.c +++ b/py/objint.c @@ -46,7 +46,7 @@ // This dispatcher function is expected to be independent of the implementation of long int STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 2, false); switch (n_args) { case 0: @@ -67,16 +67,13 @@ STATIC mp_obj_t mp_obj_int_make_new(mp_obj_t type_in, uint n_args, uint n_kw, co } case 2: - { + default: { // should be a string, parse it // TODO proper error checking of argument types uint l; const char *s = mp_obj_str_get_data(args[0], &l); return mp_parse_num_integer(s, l, mp_obj_get_int(args[1])); } - - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "int takes at most 2 arguments, %d given", n_args)); } } diff --git a/py/objint_longlong.c b/py/objint_longlong.c index f648615a73..fe35d54a48 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 diff --git a/py/objlist.c b/py/objlist.c index 9e30ebb4aa..0ef685daeb 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -69,7 +69,7 @@ STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { } STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: @@ -77,15 +77,12 @@ STATIC mp_obj_t list_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp return mp_obj_new_list(0, NULL); case 1: - { + default: { // make list from iterable // TODO: optimize list/tuple mp_obj_t list = mp_obj_new_list(0, NULL); return list_extend_from_iter(list, args[0]); } - - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "list takes at most 1 argument, %d given", n_args)); } } 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/objproperty.c b/py/objproperty.c index 439cb9ad8a..b4f2e7d490 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -42,13 +42,10 @@ typedef struct _mp_obj_property_t { } mp_obj_property_t; STATIC mp_obj_t property_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 4, false); mp_obj_property_t *o = m_new_obj(mp_obj_property_t); o->base.type = &mp_type_property; - if (n_args >= 5) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "property takes at most 4 arguments")); - } if (n_args >= 4) { // doc ignored } diff --git a/py/objset.c b/py/objset.c index 4198dac18f..a6f1fe7339 100644 --- a/py/objset.c +++ b/py/objset.c @@ -121,15 +121,19 @@ STATIC void set_print(void (*print)(void *env, const char *fmt, ...), void *env, STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { - case 0: - // return a new, empty set - return mp_obj_new_set(0, NULL); + case 0: { + // create a new, empty set + mp_obj_set_t *set = mp_obj_new_set(0, NULL); + // set actual set/frozenset type + set->base.type = type_in; + return set; + } case 1: - { + default: { // can only be 0 or 1 arg // 1 argument, an iterable from which we make a new set mp_obj_set_t *set = mp_obj_new_set(0, NULL); mp_obj_t iterable = mp_getiter(args[0]); @@ -141,9 +145,6 @@ STATIC mp_obj_t set_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_ set->base.type = type_in; return set; } - - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "set takes at most 1 argument, %d given", n_args)); } } diff --git a/py/objstr.c b/py/objstr.c index 33bfcc3756..3a4b0b97f3 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 @@ -332,6 +333,7 @@ STATIC mp_obj_t str_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) { } STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { + mp_obj_type_t *type = mp_obj_get_type(self_in); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { // load @@ -341,10 +343,9 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (!mp_seq_get_fast_slice_indexes(self_len, index, &start, &stop)) { assert(0); } - return mp_obj_new_str(self_data + start, stop - start, false); + return str_new(type, self_data + start, stop - start); } #endif - mp_obj_type_t *type = mp_obj_get_type(self_in); uint index_val = mp_get_index(type, self_len, index, false); if (type == &mp_type_bytes) { return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self_data[index_val]); @@ -357,7 +358,8 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { - assert(MP_OBJ_IS_STR(self_in)); + assert(is_str_or_bytes(self_in)); + const mp_obj_type_t *self_type = mp_obj_get_type(self_in); // get separation string GET_STR_DATA_LEN(self_in, sep_str, sep_len); @@ -379,8 +381,9 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { // count required length int required_len = 0; for (int i = 0; i < seq_len; i++) { - if (!MP_OBJ_IS_STR(seq_items[i])) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "join expected a list of str's")); + if (mp_obj_get_type(seq_items[i]) != self_type) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, + "join expects a list of str/bytes objects consistent with self object")); } if (i > 0) { required_len += sep_len; @@ -391,7 +394,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { // make joined string byte *data; - mp_obj_t joined_str = mp_obj_str_builder_start(mp_obj_get_type(self_in), required_len, &data); + mp_obj_t joined_str = mp_obj_str_builder_start(self_type, required_len, &data); for (int i = 0; i < seq_len; i++) { if (i > 0) { memcpy(data, sep_str, sep_len); @@ -409,6 +412,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { #define is_ws(c) ((c) == ' ' || (c) == '\t') STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) { + const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); machine_int_t splits = -1; mp_obj_t sep = mp_const_none; if (n_args > 1) { @@ -430,7 +434,7 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) { while (s < top && splits != 0) { const byte *start = s; while (s < top && !is_ws(*s)) s++; - mp_obj_list_append(res, mp_obj_new_str(start, s - start, false)); + mp_obj_list_append(res, str_new(self_type, start, s - start)); if (s >= top) { break; } @@ -441,7 +445,7 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) { } if (s < top) { - mp_obj_list_append(res, mp_obj_new_str(s, top - s, false)); + mp_obj_list_append(res, str_new(self_type, s, top - s)); } } else { @@ -465,7 +469,7 @@ STATIC mp_obj_t str_split(uint n_args, const mp_obj_t *args) { } s++; } - mp_obj_list_append(res, mp_obj_new_str(start, s - start, false)); + mp_obj_list_append(res, str_new(self_type, start, s - start)); if (s >= top) { break; } diff --git a/py/objtuple.c b/py/objtuple.c index 1ec75239bd..44ee95dd96 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -57,14 +57,15 @@ void mp_obj_tuple_print(void (*print)(void *env, const char *fmt, ...), void *en } STATIC mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { case 0: // return a empty tuple return mp_const_empty_tuple; - case 1: { + case 1: + default: { // 1 argument, an iterable from which we make a new tuple if (MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) { return args[0]; @@ -91,9 +92,6 @@ STATIC mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, return tuple; } - - default: - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "tuple takes at most 1 argument, %d given", n_args)); } } diff --git a/py/objtype.c b/py/objtype.c index c579477db7..4827595bbe 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 @@ -540,7 +541,7 @@ STATIC void type_print(void (*print)(void *env, const char *fmt, ...), void *env } STATIC mp_obj_t type_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 1, 3, false); switch (n_args) { case 1: diff --git a/py/objzip.c b/py/objzip.c index 8f8946264d..97a14eb870 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -40,7 +40,7 @@ typedef struct _mp_obj_zip_t { } mp_obj_zip_t; STATIC mp_obj_t zip_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { - // TODO check n_kw == 0 + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false); mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args); o->base.type = &mp_type_zip; diff --git a/py/qstrdefs.h b/py/qstrdefs.h index 13476b3be8..1679d8b39c 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -142,6 +142,7 @@ Q(float) Q(from_bytes) Q(getattr) Q(globals) +Q(hasattr) Q(hash) Q(hex) Q(%#x) diff --git a/py/runtime.c b/py/runtime.c index a2de2d75b1..7c89ec4e2e 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 @@ -884,9 +884,14 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { } mp_obj_t mp_getiter(mp_obj_t o_in) { + assert(o_in); mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->getiter != NULL) { - return type->getiter(o_in); + mp_obj_t iter = type->getiter(o_in); + if (iter == MP_OBJ_NULL) { + goto not_iterable; + } + return iter; } else { // check for __iter__ method mp_obj_t dest[2]; @@ -901,6 +906,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in) { return mp_obj_new_getitem_iter(dest); } else { // object not iterable +not_iterable: nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in))); } } 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..1af2ad27ef 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 diff --git a/py/showbc.c b/py/showbc.c index 48d5328c20..91b7572db9 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -404,14 +404,10 @@ void mp_bytecode_print2(const byte *ip, int len) { printf("STORE_MAP"); break; - /* case MP_BC_MAP_ADD: DECODE_UINT; - // I think it's guaranteed by the compiler that sp[unum + 1] is a map - rt_store_map(sp[unum + 1], sp[0], sp[1]); - sp += 2; + printf("MAP_ADD " UINT_FMT, unum); break; - */ case MP_BC_BUILD_SET: DECODE_UINT; diff --git a/py/stream.c b/py/stream.c index 9eb438b538..599582b510 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 @@ -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 @@ -663,6 +664,7 @@ unwind_jump: ENTRY(MP_BC_FOR_ITER): DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward save_sp = sp; + assert(TOP()); obj1 = mp_iternext_allow_raise(TOP()); if (obj1 == MP_OBJ_STOP_ITERATION) { --sp; // pop the exhausted iterator diff --git a/tests/basics/frozenset1.py b/tests/basics/frozenset1.py index 02a5bf8c56..00694581f0 100644 --- a/tests/basics/frozenset1.py +++ b/tests/basics/frozenset1.py @@ -7,6 +7,9 @@ except NameError: import sys sys.exit() +s = frozenset() +print(s) + s = frozenset({1}) print(s) diff --git a/tests/basics/hasattr1.py b/tests/basics/hasattr1.py new file mode 100644 index 0000000000..b1c4b5ceb6 --- /dev/null +++ b/tests/basics/hasattr1.py @@ -0,0 +1,29 @@ +class A: + + var = 132 + + def __init__(self): + self.var2 = 34 + + def meth(self, i): + return 42 + i + + +a = A() +print(hasattr(a, "var")) +print(hasattr(a, "var2")) +print(hasattr(a, "meth")) +print(hasattr(a, "_none_such")) +print(hasattr(list, "foo")) + +class C: + + def __getattr__(self, attr): + if attr == "exists": + return attr + raise AttributeError + +c = C() +print(hasattr(c, "exists")) +# TODO +#print(hasattr(c, "doesnt_exist")) 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-join.py b/tests/basics/string-join.py index 275a804c64..49bbfc5ca0 100644 --- a/tests/basics/string-join.py +++ b/tests/basics/string-join.py @@ -10,3 +10,15 @@ print(''.join('')) print(''.join('abc')) print(','.join('abc')) print(','.join('abc' for i in range(5))) + +print(b','.join([b'abc', b'123'])) + +try: + print(b','.join(['abc', b'123'])) +except TypeError: + print("TypeError") + +try: + print(','.join([b'abc', b'123'])) +except TypeError: + print("TypeError") diff --git a/tests/basics/string-slice.py b/tests/basics/string-slice.py index 7538ae5700..89853d3437 100644 --- a/tests/basics/string-slice.py +++ b/tests/basics/string-slice.py @@ -30,3 +30,6 @@ print("123"[-1000000:]) # No IndexError! print(""[1:1]) print(""[-1:-1]) + +# bytes +print(b"123"[0:2]) diff --git a/tests/basics/string_split.py b/tests/basics/string_split.py index 398a115397..9ee9e5960a 100644 --- a/tests/basics/string_split.py +++ b/tests/basics/string_split.py @@ -26,3 +26,5 @@ print("abcabc".split("bc")) print("abcabc".split("bc", 0)) print("abcabc".split("bc", 1)) print("abcabc".split("bc", 2)) + +print(b"abcabc".split(b"bc", 2)) 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/unix/main.c b/unix/main.c index 5ac776fbc3..23dd4be631 100644 --- a/unix/main.c +++ b/unix/main.c @@ -233,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) { @@ -338,6 +338,9 @@ int main(int argc, char **argv) { 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); } 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/modsocket.c b/unix/modsocket.c index 72aee95eab..08d0d56b60 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..a0a627d57e 100644 --- a/unix/mpconfigport.h +++ b/unix/mpconfigport.h @@ -52,9 +52,21 @@ 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 }, \ // type definitions for the specific machine diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h index 0a1e313cb8..974c454d39 100644 --- a/windows/mpconfigport.h +++ b/windows/mpconfigport.h @@ -41,6 +41,8 @@ #define MICROPY_ENABLE_LEXER_UNIX (1) #define MICROPY_ENABLE_MOD_CMATH (1) #define MICROPY_MOD_SYS_STDFILES (1) +#define MICROPY_MOD_SYS_EXIT (1) +#define MICROPY_ENABLE_FROZENSET (1) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_PORT_INIT_FUNC init() |