Merge remote-tracking branch 'upstream/master' into containment

This commit is contained in:
John R. Lenton 2014-01-13 00:41:12 +00:00
commit 13e64f0660
64 changed files with 1633 additions and 250 deletions

3
.gitignore vendored
View File

@ -19,3 +19,6 @@
######################
*.swp
# Build directory
######################
build/

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 90 KiB

View File

@ -32,13 +32,13 @@
inkscape:window-height="1086"
id="namedview127"
showgrid="false"
inkscape:zoom="1.1668212"
inkscape:cx="347.36024"
inkscape:cy="357.11268"
inkscape:zoom="5.4082024"
inkscape:cx="367.53099"
inkscape:cy="675.33912"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="layer6" />
inkscape:current-layer="layer4" />
<defs
id="defs4">
<linearGradient
@ -693,6 +693,12 @@
d="m 197.35296,637.05028 26.22631,-36.06117 193.41902,1.96697 -36.06117,45.24038 -89.82511,-9.83486 7.21224,-15.08013 -43.27341,3.93395 z"
id="path5039"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="m 344.52579,102.27483 15.42653,-40.280383 23.99682,-15.426528 17.14059,9.427323 3.42812,11.998411 28.28197,-6.856235 14.56949,21.425734 0.85703,38.566318 -13.71247,30.85306 -21.42573,9.42732 -20.5687,-12.85544 -20.56871,8.57029 -24.98883,-23.71207 z"
id="path3253"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccccccc" />
</g>
<g
inkscape:groupmode="layer"

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -1316,7 +1316,7 @@ void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
int l_end = comp_next_label(comp);
c_if_cond(comp, pns->nodes[0], true, l_end);
EMIT(load_id, MP_QSTR_AssertionError);
EMIT(load_global, MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
// assertion message
compile_node(comp, pns->nodes[1]);

View File

@ -45,10 +45,7 @@ static void emit_pass1_load_id(emit_t *emit, qstr qstr) {
bool added;
id_info_t *id = scope_find_or_add_id(emit->scope, qstr, &added);
if (added) {
if (qstr == MP_QSTR_AssertionError) {
// TODO how much of a hack is this?
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
} else if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) {
if (strcmp(qstr_str(qstr), "super") == 0 && emit->scope->kind == SCOPE_FUNCTION) {
// special case, super is a global, and also counts as use of __class__
id->kind = ID_INFO_KIND_GLOBAL_EXPLICIT;
id_info_t *id2 = scope_find_local_in_parent(emit->scope, emit->qstr___class__);

View File

@ -8,15 +8,8 @@
#if MICROPY_ENABLE_GC
// a machine word is big enough to hold a pointer
/*
#define BYTES_PER_WORD (8)
typedef unsigned long machine_uint_t;
*/
typedef unsigned char byte;
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
#define WORDS_PER_BLOCK (4)
#define BYTES_PER_BLOCK (WORDS_PER_BLOCK * BYTES_PER_WORD)
#define STACK_SIZE (64) // tunable; minimum is 1

View File

@ -299,8 +299,15 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
// backslash (outside string literals) must appear just before a physical newline
next_char(lex);
if (!is_physical_newline(lex)) {
// TODO SyntaxError
assert(0);
// SyntaxError: unexpected character after line continuation character
tok->src_name = lex->name;
tok->src_line = lex->line;
tok->src_column = lex->column;
tok->kind = MP_TOKEN_BAD_LINE_CONTINUATION;
vstr_reset(&lex->vstr);
tok->str = vstr_str(&lex->vstr);
tok->len = 0;
return;
} else {
next_char(lex);
}

View File

@ -10,19 +10,20 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_INVALID,
MP_TOKEN_DEDENT_MISMATCH,
MP_TOKEN_LONELY_STRING_OPEN,
MP_TOKEN_BAD_LINE_CONTINUATION,
MP_TOKEN_NEWLINE, // 4
MP_TOKEN_INDENT, // 5
MP_TOKEN_DEDENT, // 6
MP_TOKEN_NEWLINE, // 5
MP_TOKEN_INDENT, // 6
MP_TOKEN_DEDENT, // 7
MP_TOKEN_NAME, // 7
MP_TOKEN_NAME, // 8
MP_TOKEN_NUMBER,
MP_TOKEN_STRING,
MP_TOKEN_BYTES,
MP_TOKEN_ELLIPSIS,
MP_TOKEN_KW_FALSE, // 12
MP_TOKEN_KW_FALSE, // 13
MP_TOKEN_KW_NONE,
MP_TOKEN_KW_TRUE,
MP_TOKEN_KW_AND,
@ -31,7 +32,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_KW_BREAK,
MP_TOKEN_KW_CLASS,
MP_TOKEN_KW_CONTINUE,
MP_TOKEN_KW_DEF, // 21
MP_TOKEN_KW_DEF, // 22
MP_TOKEN_KW_DEL,
MP_TOKEN_KW_ELIF,
MP_TOKEN_KW_ELSE,
@ -41,7 +42,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_KW_FROM,
MP_TOKEN_KW_GLOBAL,
MP_TOKEN_KW_IF,
MP_TOKEN_KW_IMPORT, // 31
MP_TOKEN_KW_IMPORT, // 32
MP_TOKEN_KW_IN,
MP_TOKEN_KW_IS,
MP_TOKEN_KW_LAMBDA,
@ -51,12 +52,12 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_KW_PASS,
MP_TOKEN_KW_RAISE,
MP_TOKEN_KW_RETURN,
MP_TOKEN_KW_TRY, // 41
MP_TOKEN_KW_TRY, // 42
MP_TOKEN_KW_WHILE,
MP_TOKEN_KW_WITH,
MP_TOKEN_KW_YIELD,
MP_TOKEN_OP_PLUS, // 45
MP_TOKEN_OP_PLUS, // 46
MP_TOKEN_OP_MINUS,
MP_TOKEN_OP_STAR,
MP_TOKEN_OP_DBL_STAR,
@ -66,7 +67,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_OP_LESS,
MP_TOKEN_OP_DBL_LESS,
MP_TOKEN_OP_MORE,
MP_TOKEN_OP_DBL_MORE, // 55
MP_TOKEN_OP_DBL_MORE, // 56
MP_TOKEN_OP_AMPERSAND,
MP_TOKEN_OP_PIPE,
MP_TOKEN_OP_CARET,
@ -76,7 +77,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_OP_DBL_EQUAL,
MP_TOKEN_OP_NOT_EQUAL,
MP_TOKEN_DEL_PAREN_OPEN, // 64
MP_TOKEN_DEL_PAREN_OPEN, // 65
MP_TOKEN_DEL_PAREN_CLOSE,
MP_TOKEN_DEL_BRACKET_OPEN,
MP_TOKEN_DEL_BRACKET_CLOSE,
@ -86,7 +87,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_DEL_COLON,
MP_TOKEN_DEL_PERIOD,
MP_TOKEN_DEL_SEMICOLON,
MP_TOKEN_DEL_AT, // 74
MP_TOKEN_DEL_AT, // 75
MP_TOKEN_DEL_EQUAL,
MP_TOKEN_DEL_PLUS_EQUAL,
MP_TOKEN_DEL_MINUS_EQUAL,
@ -96,7 +97,7 @@ typedef enum _mp_token_kind_t {
MP_TOKEN_DEL_PERCENT_EQUAL,
MP_TOKEN_DEL_AMPERSAND_EQUAL,
MP_TOKEN_DEL_PIPE_EQUAL,
MP_TOKEN_DEL_CARET_EQUAL, // 84
MP_TOKEN_DEL_CARET_EQUAL, // 85
MP_TOKEN_DEL_DBL_MORE_EQUAL,
MP_TOKEN_DEL_DBL_LESS_EQUAL,
MP_TOKEN_DEL_DBL_STAR_EQUAL,

View File

@ -132,28 +132,45 @@ void mp_set_init(mp_set_t *set, int n) {
set->table = m_new0(mp_obj_t, set->alloc);
}
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) {
int hash = mp_obj_hash(index);
assert(set->alloc); /* FIXME: if alloc is ever 0 when doing a lookup, this'll fail: */
int pos = hash % set->alloc;
static void mp_set_rehash(mp_set_t *set) {
int old_alloc = set->alloc;
mp_obj_t *old_table = set->table;
set->alloc = get_doubling_prime_greater_or_equal_to(set->alloc + 1);
set->used = 0;
set->table = m_new0(mp_obj_t, set->alloc);
for (int i = 0; i < old_alloc; i++) {
if (old_table[i] != NULL) {
mp_set_lookup(set, old_table[i], true);
}
}
m_del(mp_obj_t, old_table, old_alloc);
}
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) {
int hash;
int pos;
if (set->alloc == 0) {
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
mp_set_rehash(set);
} else {
return NULL;
}
}
if (lookup_kind & MP_MAP_LOOKUP_FIRST) {
hash = 0;
pos = 0;
} else {
hash = mp_obj_hash(index);;
pos = hash % set->alloc;
}
for (;;) {
mp_obj_t elem = set->table[pos];
if (elem == MP_OBJ_NULL) {
// not in table
if (add_if_not_found) {
if (lookup_kind & MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
if (set->used + 1 >= set->alloc) {
// not enough room in table, rehash it
int old_alloc = set->alloc;
mp_obj_t *old_table = set->table;
set->alloc = get_doubling_prime_greater_or_equal_to(set->alloc + 1);
set->used = 0;
set->table = m_new(mp_obj_t, set->alloc);
for (int i = 0; i < old_alloc; i++) {
if (old_table[i] != NULL) {
mp_set_lookup(set, old_table[i], true);
}
}
m_del(mp_obj_t, old_table, old_alloc);
mp_set_rehash(set);
// restart the search for the new element
pos = hash % set->alloc;
} else {
@ -161,11 +178,17 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) {
set->table[pos] = index;
return index;
}
} else if (lookup_kind & MP_MAP_LOOKUP_FIRST) {
pos++;
} else {
return MP_OBJ_NULL;
}
} else if (mp_obj_equal(elem, index)) {
} else if (lookup_kind & MP_MAP_LOOKUP_FIRST || mp_obj_equal(elem, index)) {
// found it
if (lookup_kind & MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
set->used--;
set->table[pos] = NULL;
}
return elem;
} else {
// not yet found, keep searching in this table
@ -173,3 +196,13 @@ mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found) {
}
}
}
void mp_set_clear(mp_set_t *set) {
set->used = 0;
machine_uint_t a = set->alloc;
set->alloc = 0;
set->table = m_renew(mp_obj_t, set->table, a, set->alloc);
for (uint i=0; i<set->alloc; i++) {
set->table[i] = NULL;
}
}

View File

@ -19,9 +19,10 @@ typedef struct _mp_set_t {
} mp_set_t;
typedef enum _mp_map_lookup_kind_t {
MP_MAP_LOOKUP,
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND,
MP_MAP_LOOKUP_REMOVE_IF_FOUND,
MP_MAP_LOOKUP, // 0
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND, // 1
MP_MAP_LOOKUP_REMOVE_IF_FOUND, // 2
MP_MAP_LOOKUP_FIRST = 4,
} mp_map_lookup_kind_t;
int get_doubling_prime_greater_or_equal_to(int x);
@ -31,4 +32,5 @@ mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
void mp_map_clear(mp_map_t *map);
void mp_set_init(mp_set_t *set, int n);
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, bool add_if_not_found);
mp_obj_t mp_set_lookup(mp_set_t *set, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
void mp_set_clear(mp_set_t *set);

View File

@ -62,6 +62,18 @@
#define MICROPY_ENABLE_LEXER_UNIX (0)
#endif
// Long int implementation
#define MICROPY_LONGINT_IMPL_NONE (0)
#define MICROPY_LONGINT_IMPL_LONGLONG (1)
#ifndef MICROPY_LONGINT_IMPL
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#endif
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
typedef long long mp_longint_impl_t;
#endif
// Whether to support float and complex types
#ifndef MICROPY_ENABLE_FLOAT
#define MICROPY_ENABLE_FLOAT (0)
@ -76,6 +88,11 @@
/*****************************************************************************/
/* Miscellaneous settings */
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
// machine_int_t value with most significant bit set
#define WORD_MSBIT_HIGH (1 << (BYTES_PER_WORD * 8 - 1))
// printf format spec to use for machine_int_t and friends
#ifndef INT_FMT
#ifdef __LP64__

View File

@ -117,6 +117,13 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
} else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) {
return mp_obj_str_get(o1) == mp_obj_str_get(o2);
} else {
mp_obj_base_t *o = o1;
if (o->type->binary_op != NULL) {
mp_obj_t r = o->type->binary_op(RT_COMPARE_OP_EQUAL, o1, o2);
if (r != MP_OBJ_NULL) {
return r == mp_const_true ? true : false;
}
}
// TODO: Debugging helper
printf("Equality for '%s' and '%s' types not yet implemented\n", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2));
assert(0);
@ -231,7 +238,7 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
}
}
// may return NULL
// may return MP_OBJ_NULL
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
mp_small_int_t len = 0;
if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
@ -249,7 +256,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
} else if (MP_OBJ_IS_TYPE(o_in, &dict_type)) {
len = mp_obj_dict_len(o_in);
} else {
return NULL;
return MP_OBJ_NULL;
}
return MP_OBJ_NEW_SMALL_INT(len);
}

View File

@ -34,6 +34,8 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
// - xxxx...xx10: a qstr, bits 2 and above are the value
// - xxxx...xx00: a pointer to an mp_obj_base_t
// In SMALL_INT, next-to-highest bits is used as sign, so both must match for value in range
#define MP_OBJ_FITS_SMALL_INT(n) ((((n) ^ ((n) << 1)) & WORD_MSBIT_HIGH) == 0)
#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
@ -59,6 +61,15 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, n_args_max, (mp_fun_var_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, 0, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name)
// These macros are used to declare and define constant staticmethond and classmethod objects
// You can put "static" in front of the definitions to make them local
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_staticmethod_t obj_name
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_classmethod_t obj_name
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_staticmethod_t obj_name = {{&mp_type_staticmethod}, fun_name}
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_classmethod_t obj_name = {{&mp_type_classmethod}, fun_name}
// Need to declare this here so we are not dependent on map.h
struct _mp_map_t;
struct _mp_map_elem_t;
@ -187,6 +198,8 @@ mp_obj_t mp_obj_new_none(void);
mp_obj_t mp_obj_new_bool(bool value);
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
mp_obj_t mp_obj_new_int(machine_int_t value);
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value);
mp_obj_t mp_obj_new_int_from_long_str(const char *s);
mp_obj_t mp_obj_new_str(qstr qstr);
#if MICROPY_ENABLE_FLOAT
mp_obj_t mp_obj_new_float(mp_float_t val);
@ -316,3 +329,18 @@ extern const mp_obj_type_t gen_instance_type;
extern const mp_obj_type_t module_type;
mp_obj_t mp_obj_new_module(qstr module_name);
struct _mp_map_t *mp_obj_module_get_globals(mp_obj_t self_in);
// staticmethod and classmethod types; defined here so we can make const versions
extern const mp_obj_type_t mp_type_staticmethod;
extern const mp_obj_type_t mp_type_classmethod;
typedef struct _mp_obj_staticmethod_t {
mp_obj_base_t base;
mp_obj_t fun;
} mp_obj_staticmethod_t;
typedef struct _mp_obj_classmethod_t {
mp_obj_base_t base;
mp_obj_t fun;
} mp_obj_classmethod_t;

View File

@ -145,6 +145,35 @@ static mp_obj_t dict_copy(mp_obj_t self_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
// this is a classmethod
static mp_obj_t dict_fromkeys(int n_args, const mp_obj_t *args) {
assert(2 <= n_args && n_args <= 3);
mp_obj_t iter = rt_getiter(args[1]);
mp_obj_t len = mp_obj_len_maybe(iter);
mp_obj_t value = mp_const_none;
mp_obj_t next = NULL;
mp_obj_dict_t *self = NULL;
if (n_args > 2) {
value = args[2];
}
if (len == MP_OBJ_NULL) {
/* object's type doesn't have a __len__ slot */
self = mp_obj_new_dict(0);
} else {
self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
}
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
}
return self;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys);
static MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, (const mp_obj_t)&dict_fromkeys_fun_obj);
static mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp_map_lookup_kind_t lookup_kind) {
mp_map_elem_t *elem = mp_map_lookup(self, key, lookup_kind);
mp_obj_t value;
@ -286,23 +315,18 @@ static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
if (next != NULL) {
switch (self->kind) {
case MP_DICT_VIEW_ITEMS:
{
mp_obj_t items[] = {next->key, next->value};
return mp_obj_new_tuple(2, items);
}
case MP_DICT_VIEW_KEYS:
{
return next->key;
}
case MP_DICT_VIEW_VALUES:
{
return next->value;
}
default:
{
assert(0); /* can't happen */
}
case MP_DICT_VIEW_ITEMS:
{
mp_obj_t items[] = {next->key, next->value};
return mp_obj_new_tuple(2, items);
}
case MP_DICT_VIEW_KEYS:
return next->key;
case MP_DICT_VIEW_VALUES:
return next->value;
default:
assert(0); /* can't happen */
return mp_const_none;
}
} else {
return mp_const_stop_iteration;
@ -326,7 +350,6 @@ static mp_obj_t dict_view_getiter(mp_obj_t view_in) {
return o;
}
static void dict_view_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
mp_obj_dict_view_t *self = self_in;
@ -370,7 +393,6 @@ mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
return o;
}
static mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
mp_obj_dict_t *self = self_in;
@ -392,67 +414,13 @@ static mp_obj_t dict_values(mp_obj_t self_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
/******************************************************************************/
/* dict metaclass */
static mp_obj_t dict_fromkeys(int n_args, const mp_obj_t *args) {
assert(2 <= n_args && n_args <= 3);
mp_obj_t iter = rt_getiter(args[1]);
mp_obj_t len = mp_obj_len_maybe(iter);
mp_obj_t value = mp_const_none;
mp_obj_t next = NULL;
mp_obj_dict_t *self = NULL;
if (n_args > 2) {
value = args[2];
}
if (len == NULL) {
/* object's type doesn't have a __len__ slot */
self = mp_obj_new_dict(0);
} else {
self = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
}
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
}
return self;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_obj, 2, 3, dict_fromkeys);
static const mp_method_t dict_class_methods[] = {
{ "fromkeys", &dict_fromkeys_obj },
{ NULL, NULL }, // end-of-list sentinel
};
/* this should be unnecessary when inheritance works */
static void dict_class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "<class 'dict'>");
}
/* this should be unnecessary when inheritance works */
static mp_obj_t dict_class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
return rt_build_map(0);
}
static const mp_obj_type_t dict_class = {
{ &mp_const_type },
"dict_class",
.print = dict_class_print,
.methods = dict_class_methods,
.call_n = dict_class_call_n,
};
/******************************************************************************/
/* dict constructors & etc */
/* dict constructors & public C API */
static const mp_method_t dict_type_methods[] = {
{ "clear", &dict_clear_obj },
{ "copy", &dict_copy_obj },
{ "fromkeys", &dict_fromkeys_obj },
{ "get", &dict_get_obj },
{ "items", &dict_items_obj },
{ "keys", &dict_keys_obj },
@ -465,7 +433,7 @@ static const mp_method_t dict_type_methods[] = {
};
const mp_obj_type_t dict_type = {
{ &dict_class },
{ &mp_const_type },
"dict",
.print = dict_print,
.make_new = dict_make_new,

View File

@ -11,8 +11,16 @@
typedef struct _mp_obj_int_t {
mp_obj_base_t base;
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
mp_longint_impl_t val;
#endif
} mp_obj_int_t;
void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in);
mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in);
// This dispatcher function is expected to be independent of the implementation
// of long int
static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
switch (n_args) {
case 0:
@ -20,7 +28,7 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
case 1:
// TODO allow string as arg and parse it
return MP_OBJ_NEW_SMALL_INT(mp_obj_get_int(args[0]));
return mp_obj_new_int(mp_obj_get_int(args[0]));
//case 2:
// TODO, parse with given base
@ -33,9 +41,41 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
const mp_obj_type_t int_type = {
{ &mp_const_type },
"int",
.print = int_print,
.make_new = int_make_new,
.binary_op = int_binary_op,
};
mp_obj_t mp_obj_new_int(machine_int_t value) {
return MP_OBJ_NEW_SMALL_INT(value);
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
// This is called only for non-SMALL_INT
void int_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
}
// This is called only for non-SMALL_INT
mp_obj_t int_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
assert(0);
}
// This is called only with strings whose value doesn't fit in SMALL_INT
mp_obj_t mp_obj_new_int_from_long_str(const char *s) {
assert(0);
}
mp_obj_t mp_obj_new_int_from_uint(machine_uint_t value) {
// SMALL_INT accepts only signed numbers, of one bit less size
// then word size, which totals 2 bits less for unsigned numbers.
if ((value & (WORD_MSBIT_HIGH | (WORD_MSBIT_HIGH >> 1))) == 0) {
return MP_OBJ_NEW_SMALL_INT(value);
}
// TODO: Raise exception
assert(0);
}
mp_obj_t mp_obj_new_int(machine_int_t value) {
if (MP_OBJ_FITS_SMALL_INT(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
}
// TODO: Raise exception
assert(0);
}
#endif

View File

@ -21,6 +21,7 @@ typedef struct _mp_obj_list_t {
static mp_obj_t mp_obj_new_list_iterator(mp_obj_list_t *list, int cur);
static mp_obj_list_t *list_new(uint n);
static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in);
/******************************************************************************/
/* list */
@ -61,6 +62,61 @@ static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args
return NULL;
}
// Don't pass RT_COMPARE_OP_NOT_EQUAL here
static bool list_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
if (!MP_OBJ_IS_TYPE(another_in, &list_type)) {
return false;
}
mp_obj_list_t *self = self_in;
mp_obj_list_t *another = another_in;
if (op == RT_COMPARE_OP_EQUAL && self->len != another->len) {
return false;
}
// Let's deal only with > & >=
if (op == RT_COMPARE_OP_LESS || op == RT_COMPARE_OP_LESS_EQUAL) {
mp_obj_t t = self;
self = another;
another = t;
if (op == RT_COMPARE_OP_LESS) {
op = RT_COMPARE_OP_MORE;
} else {
op = RT_COMPARE_OP_MORE_EQUAL;
}
}
int len = self->len < another->len ? self->len : another->len;
bool eq_status = true; // empty lists are equal
bool rel_status;
for (int i = 0; i < len; i++) {
eq_status = mp_obj_equal(self->items[i], another->items[i]);
if (op == RT_COMPARE_OP_EQUAL && !eq_status) {
return false;
}
rel_status = (rt_binary_op(op, self->items[i], another->items[i]) == mp_const_true);
if (!eq_status && !rel_status) {
return false;
}
}
// If we had tie in the last element...
if (eq_status) {
// ... and we have lists of different lengths...
if (self->len != another->len) {
if (self->len < another->len) {
// ... then longer list length wins (we deal only with >)
return false;
}
} else if (op == RT_COMPARE_OP_MORE) {
// Otherwise, if we have strict relation, equality means failure
return false;
}
}
return true;
}
static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_list_t *o = lhs;
switch (op) {
@ -81,6 +137,14 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
memcpy(s->items + o->len, p->items, sizeof(mp_obj_t) * p->len);
return s;
}
case RT_BINARY_OP_INPLACE_ADD:
{
if (!MP_OBJ_IS_TYPE(rhs, &list_type)) {
return NULL;
}
list_extend(lhs, rhs);
return o;
}
case RT_BINARY_OP_MULTIPLY:
{
if (!MP_OBJ_IS_SMALL_INT(rhs)) {
@ -96,6 +160,15 @@ static mp_obj_t list_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
}
return s;
}
case RT_COMPARE_OP_EQUAL:
case RT_COMPARE_OP_LESS:
case RT_COMPARE_OP_LESS_EQUAL:
case RT_COMPARE_OP_MORE:
case RT_COMPARE_OP_MORE_EQUAL:
return MP_BOOL(list_cmp_helper(op, lhs, rhs));
case RT_COMPARE_OP_NOT_EQUAL:
return MP_BOOL(!list_cmp_helper(RT_COMPARE_OP_EQUAL, lhs, rhs));
default:
// op not supported
return NULL;
@ -117,6 +190,23 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
return mp_const_none; // return None, as per CPython
}
static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
assert(MP_OBJ_IS_TYPE(self_in, &list_type));
assert(MP_OBJ_IS_TYPE(arg_in, &list_type));
mp_obj_list_t *self = self_in;
mp_obj_list_t *arg = arg_in;
if (self->len + arg->len > self->alloc) {
// TODO: use alloc policy for "4"
self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + arg->len + 4);
self->alloc = self->len + arg->len + 4;
}
memcpy(self->items + self->len, arg->items, sizeof(mp_obj_t) * arg->len);
self->len += arg->len;
return mp_const_none; // return None, as per CPython
}
static mp_obj_t list_pop(int n_args, const mp_obj_t *args) {
assert(1 <= n_args && n_args <= 2);
assert(MP_OBJ_IS_TYPE(args[0], &list_type));
@ -281,6 +371,7 @@ static mp_obj_t list_reverse(mp_obj_t self_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append);
static MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend);
static MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, list_clear);
static MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy);
static MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count);
@ -296,6 +387,7 @@ static const mp_method_t list_type_methods[] = {
{ "clear", &list_clear_obj },
{ "copy", &list_copy_obj },
{ "count", &list_count_obj },
{ "extend", &list_extend_obj },
{ "index", &list_index_obj },
{ "insert", &list_insert_obj },
{ "pop", &list_pop_obj },

View File

@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
@ -16,8 +17,20 @@ typedef struct _mp_obj_set_t {
mp_set_t set;
} mp_obj_set_t;
typedef struct _mp_obj_set_it_t {
mp_obj_base_t base;
mp_obj_set_t *set;
machine_uint_t cur;
} mp_obj_set_it_t;
static mp_obj_t set_it_iternext(mp_obj_t self_in);
void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
mp_obj_set_t *self = self_in;
if (self->set.used == 0) {
print(env, "set()");
return;
}
bool first = true;
print(env, "{");
for (int i = 0; i < self->set.alloc; i++) {
@ -73,12 +86,383 @@ static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
}
}
const mp_obj_type_t set_it_type = {
{ &mp_const_type },
"set_iterator",
.iternext = set_it_iternext,
};
static mp_obj_t set_it_iternext(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_it_type));
mp_obj_set_it_t *self = self_in;
machine_uint_t max = self->set->set.alloc;
mp_obj_t *table = self->set->set.table;
for (machine_uint_t i = self->cur; i < max; i++) {
if (table[i] != NULL) {
self->cur = i + 1;
return table[i];
}
}
return mp_const_stop_iteration;
}
static mp_obj_t set_getiter(mp_obj_t set_in) {
mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t);
o->base.type = &set_it_type;
o->set = (mp_obj_set_t *)set_in;
o->cur = 0;
return o;
}
/******************************************************************************/
/* set methods */
static mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add);
static mp_obj_t set_clear(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_set_clear(&self->set);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear);
static mp_obj_t set_copy(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_obj_set_t *other = m_new_obj(mp_obj_set_t);
other->base.type = &set_type;
mp_set_init(&other->set, self->set.alloc - 1);
other->set.used = self->set.used;
memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t));
return other;
}
static MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy);
static mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard);
static mp_obj_t set_diff_int(int n_args, const mp_obj_t *args, bool update) {
assert(n_args > 0);
assert(MP_OBJ_IS_TYPE(args[0], &set_type));
mp_obj_set_t *self;
if (update) {
self = args[0];
} else {
self = set_copy(args[0]);
}
for (int i = 1; i < n_args; i++) {
mp_obj_t other = args[i];
if (self == other) {
set_clear(self);
} else {
mp_obj_t iter = rt_getiter(other);
mp_obj_t next;
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
set_discard(self, next);
}
}
}
return self;
}
static mp_obj_t set_diff(int n_args, const mp_obj_t *args) {
return set_diff_int(n_args, args, false);
}
static MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff);
static mp_obj_t set_diff_update(int n_args, const mp_obj_t *args) {
set_diff_int(n_args, args, true);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update);
static mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
if (self_in == other) {
return update ? mp_const_none : set_copy(self_in);
}
mp_obj_set_t *self = self_in;
mp_obj_set_t *out = mp_obj_new_set(0, NULL);
mp_obj_t iter = rt_getiter(other);
mp_obj_t next;
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
set_add(out, next);
}
}
if (update) {
m_del(mp_obj_t, self->set.table, self->set.alloc);
self->set.alloc = out->set.alloc;
self->set.used = out->set.used;
self->set.table = out->set.table;
}
return update ? mp_const_none : out;
}
static mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) {
return set_intersect_int(self_in, other, false);
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect);
static mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) {
return set_intersect_int(self_in, other, true);
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update);
static mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_obj_t iter = rt_getiter(other);
mp_obj_t next;
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
return mp_const_false;
}
}
return mp_const_true;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint);
static mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) {
mp_obj_set_t *self;
bool cleanup_self = false;
if (MP_OBJ_IS_TYPE(self_in, &set_type)) {
self = self_in;
} else {
self = set_make_new(NULL, 1, &self_in);
cleanup_self = true;
}
mp_obj_set_t *other;
bool cleanup_other = false;
if (MP_OBJ_IS_TYPE(other_in, &set_type)) {
other = other_in;
} else {
other = set_make_new(NULL, 1, &other_in);
cleanup_other = true;
}
bool out = true;
if (proper && self->set.used == other->set.used) {
out = false;
} else {
mp_obj_t iter = set_getiter(self);
mp_obj_t next;
while ((next = set_it_iternext(iter)) != mp_const_stop_iteration) {
if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
out = false;
break;
}
}
}
if (cleanup_self) {
set_clear(self);
}
if (cleanup_other) {
set_clear(other);
}
return MP_BOOL(out);
}
static mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) {
return set_issubset_internal(self_in, other_in, false);
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset);
static mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) {
return set_issubset_internal(self_in, other_in, true);
}
static mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) {
return set_issubset_internal(other_in, self_in, false);
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset);
static mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) {
return set_issubset_internal(other_in, self_in, true);
}
static mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
if (!MP_OBJ_IS_TYPE(other_in, &set_type)) {
return mp_const_false;
}
mp_obj_set_t *other = other_in;
if (self->set.used != other->set.used) {
return mp_const_false;
}
return set_issubset(self_in, other_in);
}
static mp_obj_t set_pop(mp_obj_t self_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
if (self->set.used == 0) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "pop from an empty set"));
}
mp_obj_t obj = mp_set_lookup(&self->set, NULL,
MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_FIRST);
return obj;
}
static MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop);
static mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {
nlr_jump(mp_obj_new_exception(MP_QSTR_KeyError));
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
static mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_obj_t iter = rt_getiter(other_in);
mp_obj_t next;
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_REMOVE_IF_FOUND | MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update);
static mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
self_in = set_copy(self_in);
set_symmetric_difference_update(self_in, other_in);
return self_in;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
static void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) {
mp_obj_t iter = rt_getiter(other_in);
mp_obj_t next;
while ((next = rt_iternext(iter)) != mp_const_stop_iteration) {
mp_set_lookup(&self->set, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
}
static mp_obj_t set_update(int n_args, const mp_obj_t *args) {
assert(n_args > 0);
assert(MP_OBJ_IS_TYPE(args[0], &set_type));
for (int i = 1; i < n_args; i++) {
set_update_int(args[0], args[i]);
}
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update);
static mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = set_copy(self_in);
set_update_int(self, other_in);
return self;
}
static MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);
static mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_t args[] = {lhs, rhs};
switch (op) {
case RT_BINARY_OP_OR:
return set_union(lhs, rhs);
case RT_BINARY_OP_XOR:
return set_symmetric_difference(lhs, rhs);
case RT_BINARY_OP_AND:
return set_intersect(lhs, rhs);
case RT_BINARY_OP_SUBTRACT:
return set_diff(2, args);
case RT_BINARY_OP_INPLACE_OR:
return set_union(lhs, rhs);
case RT_BINARY_OP_INPLACE_XOR:
return set_symmetric_difference(lhs, rhs);
case RT_BINARY_OP_INPLACE_AND:
return set_intersect(lhs, rhs);
case RT_BINARY_OP_INPLACE_SUBTRACT:
return set_diff(2, args);
case RT_COMPARE_OP_LESS:
return set_issubset_proper(lhs, rhs);
case RT_COMPARE_OP_MORE:
return set_issuperset_proper(lhs, rhs);
case RT_COMPARE_OP_EQUAL:
return set_equal(lhs, rhs);
case RT_COMPARE_OP_LESS_EQUAL:
return set_issubset(lhs, rhs);
case RT_COMPARE_OP_MORE_EQUAL:
return set_issuperset(lhs, rhs);
case RT_COMPARE_OP_NOT_EQUAL:
return MP_BOOL(set_equal(lhs, rhs) == mp_const_false);
default:
// op not supported
return NULL;
}
}
/******************************************************************************/
/* set constructors & public C API */
static const mp_method_t set_type_methods[] = {
{ "add", &set_add_obj },
{ "clear", &set_clear_obj },
{ "copy", &set_copy_obj },
{ "discard", &set_discard_obj },
{ "difference", &set_diff_obj },
{ "difference_update", &set_diff_update_obj },
{ "intersection", &set_intersect_obj },
{ "intersection_update", &set_intersect_update_obj },
{ "isdisjoint", &set_isdisjoint_obj },
{ "issubset", &set_issubset_obj },
{ "issuperset", &set_issuperset_obj },
{ "pop", &set_pop_obj },
{ "remove", &set_remove_obj },
{ "symmetric_difference", &set_symmetric_difference_obj },
{ "symmetric_difference_update", &set_symmetric_difference_update_obj },
{ "union", &set_union_obj },
{ "update", &set_update_obj },
{ NULL, NULL }, // end-of-list sentinel
};
const mp_obj_type_t set_type = {
{ &mp_const_type },
"set",
.print = set_print,
.binary_op = set_binary_op,
.make_new = set_make_new,
.binary_op = set_binary_op,
.getiter = set_getiter,
.methods = set_type_methods,
};
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
@ -86,7 +470,7 @@ mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
o->base.type = &set_type;
mp_set_init(&o->set, n_args);
for (int i = 0; i < n_args; i++) {
mp_set_lookup(&o->set, items[i], true);
mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}
return o;
}
@ -94,5 +478,5 @@ mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
assert(MP_OBJ_IS_TYPE(self_in, &set_type));
mp_obj_set_t *self = self_in;
mp_set_lookup(&self->set, item, true);
mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
}

View File

@ -165,6 +165,43 @@ static bool chr_in_str(const char* const str, const size_t str_len, const char c
return false;
}
static mp_obj_t str_find(int n_args, const mp_obj_t *args) {
assert(2 <= n_args && n_args <= 4);
assert(MP_OBJ_IS_TYPE(args[0], &str_type));
if (!MP_OBJ_IS_TYPE(args[1], &str_type)) {
nlr_jump(mp_obj_new_exception_msg_1_arg(
MP_QSTR_TypeError,
"Can't convert '%s' object to str implicitly",
mp_obj_get_type_str(args[1])));
}
const char* haystack = qstr_str(((mp_obj_str_t*)args[0])->qstr);
const char* needle = qstr_str(((mp_obj_str_t*)args[1])->qstr);
ssize_t haystack_len = strlen(haystack);
ssize_t needle_len = strlen(needle);
size_t start = 0;
size_t end = haystack_len;
/* TODO use a non-exception-throwing mp_get_index */
if (n_args >= 3 && args[2] != mp_const_none) {
start = mp_get_index(&str_type, haystack_len, args[2]);
}
if (n_args >= 4 && args[3] != mp_const_none) {
end = mp_get_index(&str_type, haystack_len, args[3]);
}
char *p = strstr(haystack + start, needle);
ssize_t pos = -1;
if (p) {
pos = p - haystack;
if (pos + needle_len > end) {
pos = -1;
}
}
return MP_OBJ_NEW_SMALL_INT(pos);
}
mp_obj_t str_strip(int n_args, const mp_obj_t *args) {
assert(1 <= n_args && n_args <= 2);
assert(MP_OBJ_IS_TYPE(args[0], &str_type));
@ -248,11 +285,13 @@ mp_obj_t str_format(int n_args, const mp_obj_t *args) {
return mp_obj_new_str(qstr_from_str_take(vstr->buf, vstr->alloc));
}
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find);
static MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join);
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip);
static MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format);
static const mp_method_t str_type_methods[] = {
{ "find", &str_find_obj },
{ "join", &str_join_obj },
{ "strip", &str_strip_obj },
{ "format", &str_format_obj },

View File

@ -27,15 +27,13 @@ static mp_obj_t mp_obj_new_class(mp_obj_t class) {
return o;
}
static mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, mp_map_lookup_kind_t lookup_kind) {
static mp_map_elem_t *mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr, mp_map_lookup_kind_t lookup_kind) {
for (;;) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type));
mp_obj_type_t *self = self_in;
if (self->locals_dict == NULL) {
if (type->locals_dict == NULL) {
return NULL;
}
assert(MP_OBJ_IS_TYPE(self->locals_dict, &dict_type)); // Micro Python restriction, for now
mp_map_t *locals_map = ((void*)self->locals_dict + sizeof(mp_obj_base_t)); // XXX hack to get map object from dict object
assert(MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)); // Micro Python restriction, for now
mp_map_t *locals_map = ((void*)type->locals_dict + sizeof(mp_obj_base_t)); // XXX hack to get map object from dict object
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), lookup_kind);
if (elem != NULL) {
return elem;
@ -44,25 +42,27 @@ static mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, mp_map_lo
// attribute not found, keep searching base classes
// for a const struct, this entry might be NULL
if (self->bases_tuple == MP_OBJ_NULL) {
if (type->bases_tuple == MP_OBJ_NULL) {
return NULL;
}
uint len;
mp_obj_t *items;
mp_obj_tuple_get(self->bases_tuple, &len, &items);
mp_obj_tuple_get(type->bases_tuple, &len, &items);
if (len == 0) {
return NULL;
}
for (uint i = 0; i < len - 1; i++) {
elem = mp_obj_class_lookup(items[i], attr, lookup_kind);
assert(MP_OBJ_IS_TYPE(items[i], &mp_const_type));
elem = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr, lookup_kind);
if (elem != NULL) {
return elem;
}
}
// search last base (simple tail recursion elimination)
self_in = items[len - 1];
assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_const_type));
type = (mp_obj_type_t*)items[len - 1];
}
}
@ -73,11 +73,12 @@ static void class_print(void (*print)(void *env, const char *fmt, ...), void *en
// args are reverse in the array
static mp_obj_t class_make_new(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type));
mp_obj_type_t *self = self_in;
mp_obj_t o = mp_obj_new_class(self_in);
// look for __init__ function
mp_map_elem_t *init_fn = mp_obj_class_lookup(self_in, MP_QSTR___init__, MP_MAP_LOOKUP);
mp_map_elem_t *init_fn = mp_obj_class_lookup(self, MP_QSTR___init__, MP_MAP_LOOKUP);
if (init_fn != NULL) {
// call __init__ function
@ -114,7 +115,7 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
dest[1] = elem->value;
return;
}
elem = mp_obj_class_lookup((mp_obj_t)self->base.type, attr, MP_MAP_LOOKUP);
elem = mp_obj_class_lookup(self->base.type, attr, MP_MAP_LOOKUP);
if (elem != NULL) {
if (mp_obj_is_callable(elem->value)) {
// class member is callable so build a bound method
@ -132,7 +133,7 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
static bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
// logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
mp_obj_class_t *self = self_in;
mp_map_elem_t *elem = mp_obj_class_lookup((mp_obj_t)self->base.type, attr, MP_MAP_LOOKUP);
mp_map_elem_t *elem = mp_obj_class_lookup(self->base.type, attr, MP_MAP_LOOKUP);
if (elem != NULL) {
elem->value = value;
} else {
@ -188,17 +189,47 @@ static mp_obj_t type_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args)
// for fail, do nothing; for attr, dest[1] = value; for method, dest[0] = self, dest[1] = method
static void type_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_map_elem_t *elem = mp_obj_class_lookup(self_in, attr, MP_MAP_LOOKUP);
assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type));
mp_obj_type_t *self = self_in;
mp_map_elem_t *elem = mp_obj_class_lookup(self, attr, MP_MAP_LOOKUP);
if (elem != NULL) {
dest[1] = elem->value;
return;
}
// generic method lookup
// this is a lookup in the class itself (ie not the classes type or instance)
const mp_method_t *meth = self->methods;
if (meth != NULL) {
for (; meth->name != NULL; meth++) {
if (strcmp(meth->name, qstr_str(attr)) == 0) {
// 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(meth->fun, &mp_type_staticmethod)) {
// return just the function
dest[1] = ((mp_obj_staticmethod_t*)meth->fun)->fun;
} else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) {
// return a bound method, with self being this class
dest[1] = ((mp_obj_classmethod_t*)meth->fun)->fun;
dest[0] = 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[1] = (mp_obj_t)meth->fun;
}
return;
}
}
}
}
static bool type_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type));
mp_obj_type_t *self = self_in;
// TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
mp_map_elem_t *elem = mp_obj_class_lookup(self_in, attr, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
mp_map_elem_t *elem = mp_obj_class_lookup(self, attr, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
if (elem != NULL) {
elem->value = value;
return true;
@ -284,3 +315,16 @@ static mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
/******************************************************************************/
// staticmethod and classmethod types (probably should go in a different file)
const mp_obj_type_t mp_type_staticmethod = {
{ &mp_const_type },
"staticmethod",
};
const mp_obj_type_t mp_type_classmethod = {
{ &mp_const_type },
"classmethod",
};

View File

@ -88,6 +88,7 @@ typedef struct _parser_t {
uint rule_stack_top;
rule_stack_t *rule_stack;
uint result_stack_alloc;
uint result_stack_top;
mp_parse_node_t *result_stack;
} parser_t;
@ -121,7 +122,7 @@ mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
int num_parse_nodes_allocated = 0;
mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) {
mp_parse_node_struct_t *pn = m_malloc(sizeof(mp_parse_node_struct_t) + num_args * sizeof(mp_parse_node_t));
mp_parse_node_struct_t *pn = m_new_obj_var(mp_parse_node_struct_t, mp_parse_node_t, num_args);
pn->source = 0; // TODO
pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8);
num_parse_nodes_allocated += 1;
@ -180,6 +181,10 @@ static mp_parse_node_t peek_result(parser_t *parser, int pos) {
}
static void push_result_node(parser_t *parser, mp_parse_node_t pn) {
if (parser->result_stack_top >= parser->result_stack_alloc) {
parser->result_stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc * 2);
parser->result_stack_alloc *= 2;
}
parser->result_stack[parser->result_stack_top++] = pn;
}
@ -191,7 +196,7 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
} else if (tok->kind == MP_TOKEN_NUMBER) {
bool dec = false;
bool small_int = true;
int int_val = 0;
machine_int_t int_val = 0;
int len = tok->len;
const char *str = tok->str;
int base = 10;
@ -211,7 +216,9 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
i = 2;
}
}
bool overflow = false;
for (; i < len; i++) {
machine_int_t old_val = int_val;
if (unichar_isdigit(str[i]) && str[i] - '0' < base) {
int_val = base * int_val + str[i] - '0';
} else if (base == 16 && 'a' <= str[i] && str[i] <= 'f') {
@ -225,10 +232,17 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
small_int = false;
break;
}
if (int_val < old_val) {
// If new value became less than previous, it's overflow
overflow = true;
} else if ((old_val ^ int_val) & WORD_MSBIT_HIGH) {
// If signed number changed sign - it's overflow
overflow = true;
}
}
if (dec) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_DECIMAL, qstr_from_strn_copy(str, len));
} else if (small_int && MP_FIT_SMALL_INT(int_val)) {
} else if (small_int && !overflow && MP_FIT_SMALL_INT(int_val)) {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, int_val);
} else {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_INTEGER, qstr_from_strn_copy(str, len));
@ -252,14 +266,20 @@ static void push_result_rule(parser_t *parser, const rule_t *rule, int num_args)
}
mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
parser_t *parser = m_new(parser_t, 1);
// allocate memory for the parser and its stacks
parser_t *parser = m_new_obj(parser_t);
parser->rule_stack_alloc = 64;
parser->rule_stack_top = 0;
parser->rule_stack = m_new(rule_stack_t, parser->rule_stack_alloc);
parser->result_stack = m_new(mp_parse_node_t, 1000);
parser->result_stack_alloc = 64;
parser->result_stack_top = 0;
parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc);
// work out the top-level rule to use, and push it on the stack
int top_level_rule;
switch (input_kind) {
case MP_PARSE_SINGLE_INPUT: top_level_rule = RULE_single_input; break;
@ -268,6 +288,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
}
push_rule(parser, rules[top_level_rule], 0);
// parse!
uint n, i;
bool backtrack = false;
const rule_t *rule;
@ -558,12 +580,25 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
//printf("--------------\n");
//result_stack_show(parser);
assert(parser->result_stack_top == 1);
//printf("maximum depth: %d\n", parser->rule_stack_alloc);
//printf("rule stack alloc: %d\n", parser->rule_stack_alloc);
//printf("result stack alloc: %d\n", parser->result_stack_alloc);
//printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated);
return parser->result_stack[0];
// get the root parse node that we created
assert(parser->result_stack_top == 1);
mp_parse_node_t result = parser->result_stack[0];
finished:
// free the memory that we don't need anymore
m_del(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc);
m_del(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc);
m_del_obj(parser_t, parser);
// return the result
return result;
syntax_error:
// TODO these should raise a proper exception
if (mp_lexer_is_kind(lex, MP_TOKEN_INDENT)) {
mp_lexer_show_error_pythonic(lex, "IndentationError: unexpected indent");
} else if (mp_lexer_is_kind(lex, MP_TOKEN_DEDENT_MISMATCH)) {
@ -575,5 +610,6 @@ syntax_error:
#endif
mp_token_show(mp_lexer_cur(lex));
}
return MP_PARSE_NODE_NULL;
result = MP_PARSE_NODE_NULL;
goto finished;
}

View File

@ -90,6 +90,7 @@ void rt_init(void) {
mp_map_add_qstr(&map_builtins, MP_QSTR_SyntaxError, mp_obj_new_exception(MP_QSTR_SyntaxError));
mp_map_add_qstr(&map_builtins, MP_QSTR_ValueError, mp_obj_new_exception(MP_QSTR_ValueError));
mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError));
mp_map_add_qstr(&map_builtins, MP_QSTR_AssertionError, mp_obj_new_exception(MP_QSTR_AssertionError));
// built-in objects
mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis);
@ -267,10 +268,6 @@ void rt_assign_inline_asm_code(int unique_code_id, void *fun, uint len, int n_ar
#endif
}
static bool fit_small_int(mp_small_int_t o) {
return true;
}
int rt_is_true(mp_obj_t arg) {
DEBUG_OP_printf("is true %p\n", arg);
if (MP_OBJ_IS_SMALL_INT(arg)) {
@ -435,13 +432,10 @@ mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
case RT_UNARY_OP_INVERT: val = ~val; break;
default: assert(0); val = 0;
}
if (fit_small_int(val)) {
if (MP_OBJ_FITS_SMALL_INT(val)) {
return MP_OBJ_NEW_SMALL_INT(val);
} else {
// TODO make a bignum
assert(0);
return mp_const_none;
}
return mp_obj_new_int(val);
} else { // will be an object (small ints are caught in previous if)
mp_obj_base_t *o = arg;
if (o->type->unary_op != NULL) {
@ -550,9 +544,11 @@ mp_obj_t rt_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
default: assert(0);
}
if (fit_small_int(lhs_val)) {
// TODO: We just should make mp_obj_new_int() inline and use that
if (MP_OBJ_FITS_SMALL_INT(lhs_val)) {
return MP_OBJ_NEW_SMALL_INT(lhs_val);
}
return mp_obj_new_int(lhs_val);
} else if (MP_OBJ_IS_TYPE(rhs, &float_type)) {
return mp_obj_float_binary_op(op, lhs_val, rhs);
} else if (MP_OBJ_IS_TYPE(rhs, &complex_type)) {
@ -809,12 +805,25 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
dest[0] = base;
} else {
// generic method lookup
// this is a lookup in the object (ie not class or type)
const mp_method_t *meth = type->methods;
if (meth != NULL) {
for (; meth->name != NULL; meth++) {
if (strcmp(meth->name, qstr_str(attr)) == 0) {
dest[1] = (mp_obj_t)meth->fun;
dest[0] = base;
// 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(meth->fun, &mp_type_staticmethod)) {
// return just the function
dest[1] = ((mp_obj_staticmethod_t*)meth->fun)->fun;
} else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) {
// return a bound method, with self being the type of this object
dest[1] = ((mp_obj_classmethod_t*)meth->fun)->fun;
dest[0] = mp_obj_get_type(base);
} else {
// return a bound method, with self being this object
dest[1] = (mp_obj_t)meth->fun;
dest[0] = base;
}
break;
}
}

View File

@ -105,6 +105,14 @@ SRC_STM = \
# usb_hcd.c \
# usb_hcd_int.c \
# usb_otg.c \
# usbh_core.c \
# usbh_hcs.c \
# usbh_stdreq.c \
# usbh_ioreq.c \
# usbh_usr.c \
# usbh_hid_core.c \
# usbh_hid_mouse.c \
# usbh_hid_keybd.c \
SRC_CC3K = \
cc3000_common.c \

View File

@ -117,6 +117,17 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) {
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*
// Configure ID pin (only in host mode)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_OTG_FS);
*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE);
}
@ -137,6 +148,84 @@ void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) {
NVIC_Init(&NVIC_InitStructure);
}
/**
* @brief BSP_Drive_VBUS
* Drives the Vbus signal through IO
* @param state : VBUS states
* @retval None
*/
void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev, uint8_t state) {
//printf("DriveVBUS %p %u\n", pdev, state);
/*
On-chip 5 V VBUS generation is not supported. For this reason, a charge pump
or, if 5 V are available on the application board, a basic power switch, must
be added externally to drive the 5 V VBUS line. The external charge pump can
be driven by any GPIO output. When the application decides to power on VBUS
using the chosen GPIO, it must also set the port power bit in the host port
control and status register (PPWR bit in OTG_FS_HPRT).
Bit 12 PPWR: Port power
The application uses this field to control power to this port, and the core
clears this bit on an overcurrent condition.
*/
#if 0 // not implemented
#ifndef USE_USB_OTG_HS
if (0 == state) {
/* DISABLE is needed on output of the Power Switch */
GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
} else {
/*ENABLE the Power Switch by driving the Enable LOW */
GPIO_ResetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
}
#endif
#endif
}
/**
* @brief USB_OTG_BSP_ConfigVBUS
* Configures the IO for the Vbus and OverCurrent
* @param None
* @retval None
*/
void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev) {
//printf("ConfigVBUS %p\n", pdev);
#if 0 // not implemented
#ifdef USE_USB_OTG_FS
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef USE_STM3210C_EVAL
RCC_APB2PeriphClockCmd(HOST_POWERSW_PORT_RCC, ENABLE);
/* Configure Power Switch Vbus Pin */
GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(HOST_POWERSW_PORT, &GPIO_InitStructure);
#else
#ifdef USE_USB_OTG_FS
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOH , ENABLE);
GPIO_InitStructure.GPIO_Pin = HOST_POWERSW_VBUS;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(HOST_POWERSW_PORT,&GPIO_InitStructure);
#endif
#endif
/* By Default, DISABLE is needed on output of the Power Switch */
GPIO_SetBits(HOST_POWERSW_PORT, HOST_POWERSW_VBUS);
USB_OTG_BSP_mDelay(200); /* Delay is need for stabilising the Vbus Low
in Reset Condition, when Vbus=1 and Reset-button is pressed by user */
#endif
#endif
}
/**
* @brief USB_OTG_BSP_uDelay
* This function provides delay time in micro sec

View File

@ -181,10 +181,65 @@
/****************** USB OTG MISC CONFIGURATION ********************************/
#define VBUS_SENSING_ENABLED
/* BEGIN host specific stuff */
/*******************************************************************************
* FIFO Size Configuration in Host mode
*
* (i) Receive data FIFO size = (Largest Packet Size / 4) + 1 or
* 2x (Largest Packet Size / 4) + 1, If a
* high-bandwidth channel or multiple isochronous
* channels are enabled
*
* (ii) For the host nonperiodic Transmit FIFO is the largest maximum packet size
* for all supported nonperiodic OUT channels. Typically, a space
* corresponding to two Largest Packet Size is recommended.
*
* (iii) The minimum amount of RAM required for Host periodic Transmit FIFO is
* the largest maximum packet size for all supported periodic OUT channels.
* If there is at least one High Bandwidth Isochronous OUT endpoint,
* then the space must be at least two times the maximum packet size for
* that channel.
*******************************************************************************/
/****************** USB OTG HS CONFIGURATION (for host) ***********************/
#ifdef USB_OTG_HS_CORE
#define RX_FIFO_HS_SIZE 512
#define TXH_NP_HS_FIFOSIZ 256
#define TXH_P_HS_FIFOSIZ 256
// #define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT
// #define USB_OTG_HS_SOF_OUTPUT_ENABLED
// #define USB_OTG_INTERNAL_VBUS_ENABLED
#define USB_OTG_EXTERNAL_VBUS_ENABLED
#ifdef USE_ULPI_PHY
#define USB_OTG_ULPI_PHY_ENABLED
#endif
#ifdef USE_EMBEDDED_PHY
#define USB_OTG_EMBEDDED_PHY_ENABLED
#endif
#define USB_OTG_HS_INTERNAL_DMA_ENABLED
// #define USB_OTG_HS_DEDICATED_EP1_ENABLED
#endif
/****************** USB OTG FS CONFIGURATION (for host) ***********************/
#ifdef USB_OTG_FS_CORE
//#define RX_FIFO_FS_SIZE 128 // already defined for device (and it's the same)
#define TXH_NP_FS_FIFOSIZ 96
#define TXH_P_FS_FIFOSIZ 96
// #define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
// #define USB_OTG_FS_SOF_OUTPUT_ENABLED
#endif
/* END host specific stuff */
/****************** USB OTG MODE CONFIGURATION ********************************/
//#define USE_HOST_MODE
//#define USE_HOST_MODE // set in Makefile
#define USE_DEVICE_MODE
//#define USE_OTG_MODE
//#define USE_OTG_MODE // set in Makefile
#ifndef USB_OTG_FS_CORE
#ifndef USB_OTG_HS_CORE

View File

@ -617,7 +617,7 @@ USB_OTG_STS USB_OTG_CoreInitHost(USB_OTG_CORE_HANDLE *pdev)
USB_OTG_HCFG_TypeDef hcfg;
#ifdef USE_OTG_MODE
USB_OTG_OTGCTL_TypeDef gotgctl;
USB_OTG_GOTGCTL_TypeDef gotgctl;
#endif
uint32_t i = 0;

View File

@ -307,7 +307,9 @@ char *strdup(const char *str) {
static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
void stdout_tx_str(const char *str) {
//usart_tx_str(str); // disabled because usart is a Python object and we now need specify which USART port
if (pyb_usart_global_debug != PYB_USART_NONE) {
usart_tx_str(pyb_usart_global_debug, str);
}
usb_vcp_send_str(str);
}
@ -322,10 +324,10 @@ int readline(vstr_t *line, const char *prompt) {
if (usb_vcp_rx_any() != 0) {
c = usb_vcp_rx_get();
break;
} /*else if (usart_rx_any()) { // disabled because usart is a Python object and we now need specify which USART port
c = usart_rx_char();
} else if (pyb_usart_global_debug != PYB_USART_NONE && usart_rx_any(pyb_usart_global_debug)) {
c = usart_rx_char(pyb_usart_global_debug);
break;
}*/
}
sys_tick_delay_ms(1);
if (storage_needs_flush()) {
storage_flush();
@ -775,7 +777,9 @@ int main(void) {
switch_init();
storage_init();
//usart_init(); disabled while wi-fi is enabled; also disabled because now usart is a proper Python object
// uncomment these 2 lines if you want REPL on USART_6 (or another usart) as well as on USB VCP
//pyb_usart_global_debug = PYB_USART_6;
//usart_init(pyb_usart_global_debug, 115200);
int first_soft_reset = true;
@ -937,6 +941,9 @@ soft_reset:
// USB
usb_init();
// USB host; not working!
//pyb_usbh_init();
// MMA
if (first_soft_reset) {
// init and reset address to zero

View File

@ -206,6 +206,21 @@ int pfenv_printf(const pfenv_t *pfenv, const char *fmt, va_list args) {
case 'P': // ?
chrs += pfenv_print_int(pfenv, va_arg(args, int), 0, 16, 'A', flags, width);
break;
case 'g':
{
// This is a very hacky approach to printing floats. Micropython
// uses %g when using print, and I just wanted to see somthing
// usable. I expect that this will be replaced with something
// more appropriate.
char dot = '.';
double d = va_arg(args, double);
int left = (int)d;
int right = (int)((d - (double)(int)d) * 1000000.0);
chrs += pfenv_print_int(pfenv, left, 1, 10, 'a', flags, width);
chrs += pfenv_print_strn(pfenv, &dot, 1, flags, width);
chrs += pfenv_print_int(pfenv, right, 0, 10, 'a', PF_FLAG_ZERO_PAD, 6);
break;
}
default:
pfenv->print_strn(pfenv->data, fmt, 1);
chrs += 1;
@ -220,12 +235,10 @@ void stdout_print_strn(void *data, const char *str, unsigned int len) {
// send stdout to USART, USB CDC VCP, and LCD if nothing else
bool any = false;
// TODO should have a setting for which USART port to send to
if (usart_is_enabled()) {
usart_tx_strn_cooked(str, len);
if (pyb_usart_global_debug != PYB_USART_NONE) {
usart_tx_strn_cooked(pyb_usart_global_debug, str, len);
any = true;
}
if (usb_vcp_is_enabled()) {
usb_vcp_send_strn_cooked(str, len);
any = true;

View File

@ -31,6 +31,7 @@
#include "stm32fxxx_it.h"
#include "stm32f4xx_exti.h"
#include "usb_core.h"
//#include "usb_hcd_int.h" // for usb host mode only
//#include "usbd_core.h"
//#include "usbd_cdc_core.h"
@ -197,7 +198,8 @@ void OTG_HS_IRQHandler(void)
void OTG_FS_IRQHandler(void)
#endif
{
USBD_OTG_ISR_Handler (&USB_OTG_dev);
USBD_OTG_ISR_Handler (&USB_OTG_dev); // device mode
//USBH_OTG_ISR_Handler (&USB_OTG_dev); // host mode FIXME
}
#ifdef USB_OTG_HS_DEDICATED_EP1_ENABLED

View File

@ -8,20 +8,14 @@
#include "obj.h"
#include "usart.h"
static bool is_enabled;
typedef enum {
PYB_USART_1 = 1,
PYB_USART_2 = 2,
PYB_USART_3 = 3,
PYB_USART_6 = 4,
PYB_USART_MAX = 4,
} pyb_usart_t;
pyb_usart_t pyb_usart_global_debug = PYB_USART_NONE;
static USART_TypeDef *usart_get_base(pyb_usart_t usart_id) {
USART_TypeDef *USARTx=NULL;
switch (usart_id) {
case PYB_USART_NONE:
break;
case PYB_USART_1:
USARTx = USART1;
break;
@ -52,6 +46,9 @@ void usart_init(pyb_usart_t usart_id, uint32_t baudrate) {
void (*RCC_APBxPeriphClockCmd)(uint32_t, FunctionalState)=NULL;
switch (usart_id) {
case PYB_USART_NONE:
return;
case PYB_USART_1:
USARTx = USART1;
@ -128,16 +125,13 @@ void usart_init(pyb_usart_t usart_id, uint32_t baudrate) {
USART_Cmd(USARTx, ENABLE);
}
bool usart_is_enabled(void) {
return is_enabled;
}
bool usart_rx_any(void) {
return USART_GetFlagStatus(USART6, USART_FLAG_RXNE) == SET;
bool usart_rx_any(pyb_usart_t usart_id) {
USART_TypeDef *USARTx = usart_get_base(usart_id);
return USART_GetFlagStatus(USARTx, USART_FLAG_RXNE) == SET;
}
int usart_rx_char(pyb_usart_t usart_id) {
USART_TypeDef *USARTx= usart_get_base(usart_id);
USART_TypeDef *USARTx = usart_get_base(usart_id);
return USART_ReceiveData(USARTx);
}
@ -176,8 +170,8 @@ typedef struct _pyb_usart_obj_t {
} pyb_usart_obj_t;
static mp_obj_t usart_obj_status(mp_obj_t self_in) {
// TODO make it check the correct USART port!
if (usart_rx_any()) {
pyb_usart_obj_t *self = self_in;
if (usart_rx_any(self->usart_id)) {
return mp_const_true;
} else {
return mp_const_false;

View File

@ -1 +1,18 @@
typedef enum {
PYB_USART_NONE = 0,
PYB_USART_1 = 1,
PYB_USART_2 = 2,
PYB_USART_3 = 3,
PYB_USART_6 = 4,
PYB_USART_MAX = 4,
} pyb_usart_t;
extern pyb_usart_t pyb_usart_global_debug;
void usart_init(pyb_usart_t usart_id, uint32_t baudrate);
bool usart_rx_any(pyb_usart_t usart_id);
int usart_rx_char(pyb_usart_t usart_id);
void usart_tx_str(pyb_usart_t usart_id, const char *str);
void usart_tx_strn_cooked(pyb_usart_t usart_id, const char *str, int len);
mp_obj_t pyb_Usart(mp_obj_t usart_id, mp_obj_t baudrate);

View File

@ -80,7 +80,7 @@ void usb_vcp_send_strn(const char *str, int len) {
}
}
#include "lib/usbd_conf.h"
#include "usbd_conf.h"
/* These are external variables imported from CDC core to be used for IN
transfer management. */
@ -105,3 +105,30 @@ void usb_vcp_send_strn_cooked(const char *str, int len) {
void usb_hid_send_report(uint8_t *buf) {
USBD_HID_SendReport(&USB_OTG_dev, buf, 4);
}
/******************************************************************************/
// code for experimental USB OTG support
#ifdef USE_HOST_MODE
#include "lib-otg/usbh_core.h"
#include "lib-otg/usbh_usr.h"
#include "lib-otg/usbh_hid_core.h"
__ALIGN_BEGIN USBH_HOST USB_Host __ALIGN_END ;
static int host_is_enabled = 0;
void pyb_usbh_init(void) {
if (!host_is_enabled) {
// only init USBH once in the device's power-lifetime
/* Init Host Library */
USBH_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USB_Host, &HID_cb, &USR_Callbacks);
}
host_is_enabled = 1;
}
void pyb_usbh_process(void) {
USBH_Process(&USB_OTG_dev, &USB_Host);
}
#endif // USE_HOST_MODE

View File

@ -6,3 +6,6 @@ void usb_vcp_send_str(const char* str);
void usb_vcp_send_strn(const char* str, int len);
void usb_vcp_send_strn_cooked(const char *str, int len);
void usb_hid_send_report(uint8_t *buf); // 4 bytes for mouse: ?, x, y, ?
void pyb_usbh_init(void);
void pyb_usbh_process(void);

View File

@ -33,7 +33,8 @@ SRC_C = \
lcd.c \
led.c \
lexerfatfs.c \
usart.c \
lexermemzip.c \
memzip.c \
usb.c \
STM_SRC_C = \
@ -60,9 +61,9 @@ OBJ = $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(STM_SRC_C:.c=.o) $(STM_SRC_S:.s=.o
#LIB += -ltermcap
all2: $(BUILD) hex
hex: $(BUILD)/flash.hex
hex: $(BUILD)/micropython-mz.hex
post_compile: $(BUILD)/flash.hex
post_compile: $(BUILD)/micropython-mz.hex
$(ECHO) "Preparing $@ for upload"
$(Q)$(TOOLS_PATH)/teensy_post_compile -file="$(basename $(<F))" -path="$(<D)" -tools="$(TOOLS_PATH)"
@ -72,11 +73,19 @@ reboot:
upload: post_compile reboot
$(BUILD)/flash.elf: $(OBJ)
$(BUILD)/micropython.elf: $(OBJ)
$(ECHO) "LINK $<"
$(Q)$(CC) $(LDFLAGS) -o "$@" -Wl,-Map,$(@:.elf=.map) $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
ifeq ($(MEMZIP_DIR),)
MEMZIP_DIR = memzip_files
endif
$(BUILD)/micropython-mz.hex: $(BUILD)/micropython.hex $(shell find ${MEMZIP_DIR} -type f)
@$(ECHO) "Creating $@"
$(Q)./add-memzip.sh $< $@ ${MEMZIP_DIR}
$(BUILD)/%.hex: $(BUILD)/%.elf
$(ECHO) "HEX $<"
$(Q)$(OBJCOPY) -O ihex -R .eeprom "$<" "$@"

27
teensy/add-memzip.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash
if [ "$#" != 3 ]; then
echo "Usage: add-memzip.sh input.hex output.hex file-directory"
exit 1
fi
#set -x
input_hex=$1
output_hex=$2
memzip_src_dir=$3
input_bin=${input_hex}.bin
output_bin=${output_hex}.bin
zip_file=${output_hex}.zip
zip_base=$(basename ${zip_file})
zip_dir=$(dirname ${zip_file})
abs_zip_dir=$(realpath ${zip_dir})
rm -f ${zip_file}
(cd ${memzip_src_dir}; zip -0 -r -D ${abs_zip_dir}/${zip_base} .)
objcopy -I ihex -O binary ${input_hex} ${input_bin}
cat ${input_bin} ${zip_file} > ${output_bin}
objcopy -I binary -O ihex ${output_bin} ${output_hex}
echo "Added ${memzip_src_dir} to ${input_hex} creating ${output_hex}"

18
teensy/lexermemzip.c Normal file
View File

@ -0,0 +1,18 @@
#include <stdint.h>
#include <stdlib.h>
#include "misc.h"
#include "lexer.h"
#include "memzip.h"
mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename)
{
void *data;
size_t len;
if (memzip_locate(filename, &data, &len) != MZ_OK) {
return NULL;
}
return mp_lexer_new_from_str_len(filename, (const char *)data, (uint)len, 0);
}

2
teensy/lexermemzip.h Normal file
View File

@ -0,0 +1,2 @@
mp_lexer_t *mp_lexer_new_from_memzip_file(const char *filename);

View File

@ -8,6 +8,7 @@
#include "mpconfig.h"
#include "mpqstr.h"
#include "lexer.h"
#include "lexermemzip.h"
#include "parse.h"
#include "obj.h"
#include "compile.h"
@ -22,52 +23,17 @@
extern uint32_t _heap_start;
#ifdef USE_READLINE
#include <readline/readline.h>
#include <readline/history.h>
#endif
bool do_file(const char *filename);
#if 0
static char *str_join(const char *s1, int sep_char, const char *s2) {
int l1 = strlen(s1);
int l2 = strlen(s2);
char *s = m_new(char, l1 + l2 + 2);
memcpy(s, s1, l1);
if (sep_char != 0) {
s[l1] = sep_char;
l1 += 1;
void flash_error(int n) {
for (int i = 0; i < n; i++) {
led_state(PYB_LED_BUILTIN, 1);
delay(250);
led_state(PYB_LED_BUILTIN, 0);
delay(250);
}
memcpy(s + l1, s2, l2);
s[l1 + l2] = 0;
return s;
}
static char *prompt(char *p) {
#ifdef USE_READLINE
char *line = readline(p);
if (line) {
add_history(line);
}
#else
static char buf[256];
fputs(p, stdout);
char *s = fgets(buf, sizeof(buf), stdin);
if (!s) {
return NULL;
}
int l = strlen(buf);
if (buf[l - 1] == '\n') {
buf[l - 1] = 0;
} else {
l++;
}
char *line = m_new(char, l);
memcpy(line, buf, l);
#endif
return line;
}
#endif
static const char *help_text =
"Welcome to Micro Python!\n\n"
"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
@ -215,6 +181,19 @@ mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
}
#endif
static qstr pyb_config_source_dir = 0;
static qstr pyb_config_main = 0;
mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
pyb_config_source_dir = mp_obj_get_qstr(source_dir);
return mp_const_none;
}
mp_obj_t pyb_main(mp_obj_t main) {
pyb_config_main = mp_obj_get_qstr(main);
return mp_const_none;
}
mp_obj_t pyb_delay(mp_obj_t count) {
delay(mp_obj_get_int(count));
return mp_const_none;
@ -225,6 +204,12 @@ mp_obj_t pyb_led(mp_obj_t state) {
return state;
}
mp_obj_t pyb_run(mp_obj_t filename_obj) {
const char *filename = qstr_str(mp_obj_get_qstr(filename_obj));
do_file(filename);
return mp_const_none;
}
char *strdup(const char *str) {
uint32_t len = strlen(str);
char *s2 = m_new(char, len + 1);
@ -316,6 +301,39 @@ int readline(vstr_t *line, const char *prompt) {
}
}
bool do_file(const char *filename) {
mp_lexer_t *lex = mp_lexer_new_from_memzip_file(filename);
if (lex == NULL) {
printf("could not open file '%s' for reading\n", filename);
return false;
}
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
return false;
}
mp_obj_t module_fun = mp_compile(pn, false);
if (module_fun == mp_const_none) {
return false;
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
rt_call_function_0(module_fun);
nlr_pop();
return true;
} else {
// uncaught exception
mp_obj_print((mp_obj_t)nlr.ret_val);
printf("\n");
return false;
}
}
void do_repl(void) {
stdout_tx_str("Micro Python for Teensy 3.1\r\n");
stdout_tx_str("Type \"help()\" for more information.\r\n");
@ -397,24 +415,53 @@ soft_reset:
rt_init();
#if 1
printf("About to add functions()\n");
// add some functions to the python namespace
{
rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help));
mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb"));
rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info));
rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir));
rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main));
rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc));
rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led));
rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj);
rt_store_name(qstr_from_str_static("pyb"), m);
rt_store_name(qstr_from_str_static("run"), rt_make_function_1(pyb_run));
}
#endif
if (!do_file("/boot.py")) {
printf("Unable to open '/boot.py'\n");
flash_error(4);
}
// Turn bootup LED off
led_state(PYB_LED_BUILTIN, 0);
// run main script
{
vstr_t *vstr = vstr_new();
vstr_add_str(vstr, "/");
if (pyb_config_source_dir == 0) {
vstr_add_str(vstr, "src");
} else {
vstr_add_str(vstr, qstr_str(pyb_config_source_dir));
}
vstr_add_char(vstr, '/');
if (pyb_config_main == 0) {
vstr_add_str(vstr, "main.py");
} else {
vstr_add_str(vstr, qstr_str(pyb_config_main));
}
if (!do_file(vstr_str(vstr))) {
printf("Unable to open '%s'\n", vstr_str(vstr));
flash_error(3);
}
vstr_free(vstr);
}
do_repl();
printf("PYB: soft reboot\n");

37
teensy/memzip.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "memzip.h"
extern uint8_t _staticfs[];
MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len)
{
const MEMZIP_FILE_HDR *file_hdr = (const MEMZIP_FILE_HDR *)_staticfs;
uint8_t *mem_data;
/* Zip file filenames don't have a leading /, so we strip it off */
if (*filename == '/') {
filename++;
}
while (file_hdr->signature == MEMZIP_FILE_HEADER_SIGNATURE) {
const char *file_hdr_filename = (const char *)&file_hdr[1];
mem_data = (uint8_t *)file_hdr_filename;
mem_data += file_hdr->filename_len;
mem_data += file_hdr->extra_len;
if (!strncmp(file_hdr_filename, filename, file_hdr->filename_len)) {
/* We found a match */
if (file_hdr->compression_method != 0) {
return MZ_FILE_COMPRESSED;
}
*data = mem_data;
*len = file_hdr->uncompressed_size;
return MZ_OK;
}
mem_data += file_hdr->uncompressed_size;
file_hdr = (const MEMZIP_FILE_HDR *)mem_data;
}
return MZ_NO_FILE;
}

73
teensy/memzip.h Normal file
View File

@ -0,0 +1,73 @@
#pragma pack(push, 1)
#define MEMZIP_FILE_HEADER_SIGNATURE 0x04034b50
typedef struct
{
uint32_t signature;
uint16_t version;
uint16_t flags;
uint16_t compression_method;
uint16_t last_mod_time;
uint16_t last_mod_date;
uint32_t crc32;
uint32_t compressed_size;
uint32_t uncompressed_size;
uint16_t filename_len;
uint16_t extra_len;
/* char filename[filename_len] */
/* uint8_t extra[extra_len] */
} MEMZIP_FILE_HDR;
#define MEMZIP_CENTRAL_DIRECTORY_SIGNATURE 0x02014b50
typedef struct
{
uint32_t signature;
uint16_t version_made_by;
uint16_t version_read_with;
uint16_t flags;
uint16_t compression_method;
uint16_t last_mod_time;
uint16_t last_mod_date;
uint32_t crc32;
uint32_t compressed_size;
uint32_t uncompressed_size;
uint16_t filename_len;
uint16_t extra_len;
uint16_t disk_num;
uint16_t internal_file_attributes;
uint32_t external_file_attributes;
uint32_t file_header_offset;
/* char filename[filename_len] */
/* uint8_t extra[extra_len] */
} MEMZIP_CENTRAL_DIRECTORY_HDR;
#define MEMZIP_END_OF_CENTRAL_DIRECTORY_SIGNATURE 0x06054b50
typedef struct
{
uint32_t signature;
uint16_t disk_num;
uint16_t central_directory_disk;
uint16_t num_central_directories_this_disk;
uint16_t total_central_directories;
uint32_t central_directory_size;
uint32_t central_directory_offset;
uint16_t comment_len;
/* char comment[comment_len] */
} MEMZIP_END_OF_CENTRAL_DIRECTORY;
#pragma pack(pop)
typedef enum {
MZ_OK = 0, /* (0) Succeeded */
MZ_NO_FILE, /* (1) Could not find the file. */
MZ_FILE_COMPRESSED, /* (2) File is compressed (expecting uncompressed) */
} MEMZIP_RESULT;
MEMZIP_RESULT memzip_locate(const char *filename, void **data, size_t *len);

View File

@ -0,0 +1 @@
print("Executing boot.py")

View File

@ -0,0 +1,11 @@
print("Executing main.py")
x=pyb.led(1)
pyb.delay(100)
x=pyb.led(0)
pyb.delay(100)
x=pyb.led(1)
pyb.delay(100)
x=pyb.led(0)

View File

@ -0,0 +1 @@
print("Executing /src/test.py")

View File

@ -0,0 +1 @@
print("Executing /test.py")

View File

@ -126,6 +126,12 @@ SECTIONS
_edata = .;
} > RAM
/*
* _staticfs is the place in flash where the static filesystem which
* is concatenated to the .hex file will wind up.
*/
_staticfs = LOADADDR(.data) + SIZEOF(.data);
.noinit (NOLOAD) : {
*(.noinit*)
} > RAM

View File

@ -0,0 +1,26 @@
# This test small int range for 32-bit machine
a = 0x3fffff
print(a)
a *= 0x10
print(a)
a *= 0x10
print(a)
a += 0xff
print(a)
# This would overflow
#a += 1
a = -0x3fffff
print(a)
a *= 0x10
print(a)
a *= 0x10
print(a)
a -= 0xff
print(a)
# This still doesn't overflow
a -= 1
print(a)
# This would overflow
#a -= 1

View File

@ -10,3 +10,9 @@ print(x)
f = x.append
f(4)
print(x)
x.extend([100, 200])
print(x)
x += [2, 1]
print(x)

View File

@ -0,0 +1,50 @@
print([] == [])
print([] > [])
print([] < [])
print([] == [1])
print([1] == [])
print([] > [1])
print([1] > [])
print([] < [1])
print([1] < [])
print([] >= [1])
print([1] >= [])
print([] <= [1])
print([1] <= [])
print([1] == [1])
print([1] != [1])
print([1] == [2])
print([1] == [1, 0])
print([1] > [1])
print([1] > [2])
print([2] > [1])
print([1, 0] > [1])
print([1, -1] > [1])
print([1] > [1, 0])
print([1] > [1, -1])
print([1] < [1])
print([2] < [1])
print([1] < [2])
print([1] < [1, 0])
print([1] < [1, -1])
print([1, 0] < [1])
print([1, -1] < [1])
print([1] >= [1])
print([1] >= [2])
print([2] >= [1])
print([1, 0] >= [1])
print([1, -1] >= [1])
print([1] >= [1, 0])
print([1] >= [1, -1])
print([1] <= [1])
print([2] <= [1])
print([1] <= [2])
print([1] <= [1, 0])
print([1] <= [1, -1])
print([1, 0] <= [1])
print([1, -1] <= [1])

View File

@ -0,0 +1,5 @@
s = {1, 2, 3, 4}
print(s.add(5))
l = list(s)
l.sort()
print(l)

View File

@ -0,0 +1,30 @@
def r(s):
l = list(s)
l.sort()
return l
sets = [set(), {1}, {1, 2}, {1, 2, 3}, {2, 3}, {2, 3, 5}, {5}, {7}]
for s in sets:
for t in sets:
print(s, '|', t, '=', r(s | t))
print(s, '^', t, '=', r(s ^ t))
print(s, '&', t, '=', r(s & t))
print(s, '-', t, '=', r(s - t))
u = s.copy()
u |= t
print(s, "|=", t, '-->', r(u))
u = s.copy()
u ^= t
print(s, "^=", t, '-->', r(u))
u = s.copy()
u &= t
print(s, "&=", t, "-->", r(u))
u = s.copy()
u -= t
print(s, "-=", t, "-->", r(u))
print(s, '==', t, '=', s == t)
print(s, '!=', t, '=', s != t)
print(s, '>', t, '=', s > t)
print(s, '>=', t, '=', s >= t)
print(s, '<', t, '=', s < t)
print(s, '<=', t, '=', s <= t)

View File

@ -0,0 +1,3 @@
s = {1, 2, 3, 4}
print(s.clear())
print(list(s))

View File

@ -0,0 +1,8 @@
s = {1, 2, 3, 4}
t = s.copy()
s.add(5)
t.add(7)
for i in s, t:
l = list(i)
l.sort()
print(l)

View File

@ -0,0 +1,21 @@
def report(s):
l = list(s)
l.sort()
print(l)
l = [1, 2, 3, 4]
s = set(l)
outs = [s.difference(),
s.difference({1}),
s.difference({1}, [1, 2]),
s.difference({1}, {1, 2}, {2, 3})]
for out in outs:
report(out)
s = set(l)
print(s.difference_update())
report(s)
print(s.difference_update({1}))
report(s)
print(s.difference_update({1}, [2]))
report(s)

View File

@ -0,0 +1,3 @@
s = {1, 2}
print(s.discard(1))
print(list(s))

View File

@ -0,0 +1,12 @@
def report(s):
l = list(s)
l.sort()
print(l)
s = {1, 2, 3, 4}
report(s)
report(s.intersection({1, 3}))
report(s.intersection([3, 4]))
print(s.intersection_update([1]))
report(s)

View File

@ -0,0 +1,6 @@
s = {1, 2, 3, 4}
print(s.isdisjoint({1}))
print(s.isdisjoint([2]))
print(s.isdisjoint([]))
print(s.isdisjoint({7,8,9,10}))
print(s.isdisjoint([7,8,9,1]))

View File

@ -0,0 +1,5 @@
sets = [set(), {1}, {1, 2, 3}, {3, 4, 5}, {5, 6, 7}]
for i in sets:
for j in sets:
print(i.issubset(j))
print(i.issuperset(j))

View File

@ -0,0 +1,5 @@
s = {1, 2, 3, 4}
l = list(s)
l.sort()
print(l)

View File

@ -0,0 +1,9 @@
s = {1}
print(s.pop())
try:
print(s.pop(), "!!!")
except KeyError:
pass
else:
print("Failed to raise KeyError")

View File

@ -0,0 +1,9 @@
s = {1}
print(s.remove(1))
print(list(s))
try:
print(s.remove(1), "!!!")
except KeyError:
pass
else:
print("failed to raise KeyError")

View File

@ -0,0 +1,7 @@
print({1,2}.symmetric_difference({2,3}))
print({1,2}.symmetric_difference([2,3]))
s = {1,2}
print(s.symmetric_difference_update({2,3}))
l = list(s)
l.sort()
print(l)

View File

@ -0,0 +1 @@
print({1}.union({2}))

View File

@ -0,0 +1,12 @@
def report(s):
l = list(s)
l.sort()
print(l)
s = {1}
s.update()
report(s)
s.update([2])
report(s)
s.update([1,3], [2,2,4])
report(s)

View File

@ -0,0 +1,11 @@
print("hello world".find("ll"))
print("hello world".find("ll", None))
print("hello world".find("ll", 1))
print("hello world".find("ll", 1, None))
print("hello world".find("ll", None, None))
print("hello world".find("ll", 1, -1))
print("hello world".find("ll", 1, 1))
print("hello world".find("ll", 1, 2))
print("hello world".find("ll", 1, 3))
print("hello world".find("ll", 1, 4))
print("hello world".find("ll", 1, 5))