summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/asmthumb.c32
-rw-r--r--py/asmthumb.h7
-rw-r--r--py/compile.c127
-rw-r--r--py/emitinlinethumb.c163
-rw-r--r--py/obj.h1
-rw-r--r--py/objlist.c7
-rw-r--r--py/runtime.c64
-rw-r--r--py/runtime.h1
-rw-r--r--py/vm.c17
9 files changed, 277 insertions, 142 deletions
diff --git a/py/asmthumb.c b/py/asmthumb.c
index 3fcd28a91d..f37b1ff8fe 100644
--- a/py/asmthumb.c
+++ b/py/asmthumb.c
@@ -275,6 +275,12 @@ void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src) {
asm_thumb_write_op16(as, 0x4600 | op_lo);
}
+#define OP_ADD_REG_REG_REG(rlo_dest, rlo_src_a, rlo_src_b) (0x1800 | ((rlo_src_b) << 6) | ((rlo_src_a) << 3) | (rlo_dest))
+
+void asm_thumb_add_reg_reg_reg(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) {
+ asm_thumb_write_op16(as, OP_ADD_REG_REG_REG(rlo_dest, rlo_src_a, rlo_src_b));
+}
+
#define OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src) (0x1e00 | ((i3_src) << 6) | ((rlo_src) << 3) | (rlo_dest))
void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src) {
@@ -283,6 +289,12 @@ void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int
asm_thumb_write_op16(as, OP_SUBS_RLO_RLO_I3(rlo_dest, rlo_src, i3_src));
}
+#define OP_CMP_REG_REG(rlo_a, rlo_b) (0x4280 | ((rlo_b) << 3) | (rlo_a))
+
+void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b) {
+ asm_thumb_write_op16(as, OP_CMP_REG_REG(rlo_a, rlo_b));
+}
+
#define OP_CMP_RLO_I8(rlo, i8) (0x2800 | ((rlo) << 8) | (i8))
void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) {
@@ -290,6 +302,10 @@ void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8) {
asm_thumb_write_op16(as, OP_CMP_RLO_I8(rlo, i8));
}
+void asm_thumb_ite_ge(asm_thumb_t *as) {
+ asm_thumb_write_op16(as, 0xbfac);
+}
+
#define OP_B_N(byte_offset) (0xe000 | (((byte_offset) >> 1) & 0x07ff))
void asm_thumb_b_n(asm_thumb_t *as, int label) {
@@ -360,22 +376,6 @@ void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num)
asm_thumb_write_op16(as, OP_ADD_REG_SP_OFFSET(rlo_dest, word_offset));
}
-#define OP_ADD_REG_REG_REG(rlo_dest, rlo_src_a, rlo_src_b) (0x1800 | ((rlo_src_b) << 6) | ((rlo_src_a) << 3) | (rlo_dest))
-
-void asm_thumb_add_reg_reg_reg(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b) {
- asm_thumb_write_op16(as, OP_ADD_REG_REG_REG(rlo_dest, rlo_src_a, rlo_src_b));
-}
-
-#define OP_CMP_REG_REG(rlo_a, rlo_b) (0x4280 | ((rlo_b) << 3) | (rlo_a))
-
-void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b) {
- asm_thumb_write_op16(as, OP_CMP_REG_REG(rlo_a, rlo_b));
-}
-
-void asm_thumb_ite_ge(asm_thumb_t *as) {
- asm_thumb_write_op16(as, 0xbfac);
-}
-
// this could be wrong, because it should have a range of +/- 16MiB...
#define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff))
#define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff))
diff --git a/py/asmthumb.h b/py/asmthumb.h
index dcd9c2e3ad..60a86ea50b 100644
--- a/py/asmthumb.h
+++ b/py/asmthumb.h
@@ -62,8 +62,11 @@ void asm_thumb_movs_rlo_i8(asm_thumb_t *as, uint rlo_dest, int i8_src);
void asm_thumb_movw_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src);
void asm_thumb_movt_reg_i16(asm_thumb_t *as, uint reg_dest, int i16_src);
void asm_thumb_mov_reg_reg(asm_thumb_t *as, uint reg_dest, uint reg_src);
+void asm_thumb_add_reg_reg_reg(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b);
void asm_thumb_subs_rlo_rlo_i3(asm_thumb_t *as, uint rlo_dest, uint rlo_src, int i3_src);
+void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b);
void asm_thumb_cmp_rlo_i8(asm_thumb_t *as, uint rlo, int i8);
+void asm_thumb_ite_ge(asm_thumb_t *as);
void asm_thumb_b_n(asm_thumb_t *as, int label);
void asm_thumb_bcc_n(asm_thumb_t *as, int cond, int label);
@@ -73,10 +76,6 @@ void asm_thumb_mov_local_reg(asm_thumb_t *as, int local_num_dest, uint rlo_src);
void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience
void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience
-void asm_thumb_add_reg_reg_reg(asm_thumb_t *as, uint rlo_dest, uint rlo_src_a, uint rlo_src_b); // convenience ?
-void asm_thumb_cmp_reg_reg(asm_thumb_t *as, uint rlo_a, uint rlo_b); // convenience ?
-void asm_thumb_ite_ge(asm_thumb_t *as); // convenience ?
-
void asm_thumb_b_label(asm_thumb_t *as, int label); // convenience ?
void asm_thumb_bcc_label(asm_thumb_t *as, int cc, int label); // convenience: picks narrow or wide branch
void asm_thumb_bl_ind(asm_thumb_t *as, void *fun_ptr, uint fun_id, uint reg_temp); // convenience ?
diff --git a/py/compile.c b/py/compile.c
index f1870bf36e..95fe1d759f 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -69,8 +69,13 @@ typedef struct _compiler_t {
const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
} compiler_t;
-STATIC void compile_syntax_error(compiler_t *comp, const char *msg) {
+STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
// TODO store the error message to a variable in compiler_t instead of printing it
+ if (MP_PARSE_NODE_IS_STRUCT(pn)) {
+ printf(" File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (machine_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
+ } else {
+ printf(" File \"%s\"\n", qstr_str(comp->source_file));
+ }
printf("SyntaxError: %s\n", msg);
comp->had_error = true;
}
@@ -351,7 +356,7 @@ STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vst
case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
- default: assert(0);
+ default: assert(0); // shouldn't happen
}
break;
default: assert(0);
@@ -588,8 +593,7 @@ void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t
pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
}
if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
- compile_syntax_error(comp, "can't assign to function call");
- return;
+ goto cannot_assign;
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
if (assign_kind == ASSIGN_AUG_STORE) {
EMIT(rot_three);
@@ -615,18 +619,20 @@ void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t
EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
}
} else {
- // shouldn't happen
- assert(0);
+ goto cannot_assign;
}
} else {
- // shouldn't happen
- assert(0);
+ goto cannot_assign;
}
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
- // SyntaxError, cannot assign
- assert(0);
+ goto cannot_assign;
}
+
+ return;
+
+cannot_assign:
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
}
void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
@@ -638,7 +644,7 @@ void c_assign_tuple(compiler_t *comp, int n, mp_parse_node_t *nodes) {
EMIT_ARG(unpack_ex, i, n - i - 1);
have_star_index = i;
} else {
- compile_syntax_error(comp, "two starred expressions in assignment");
+ compile_syntax_error(comp, nodes[i], "two starred expressions in assignment");
return;
}
}
@@ -673,7 +679,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
break;
}
} else {
- compile_syntax_error(comp, "can't assign to literal");
+ compile_syntax_error(comp, pn, "can't assign to literal");
return;
}
} else {
@@ -697,7 +703,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
// lhs is something in parenthesis
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// empty tuple
- compile_syntax_error(comp, "can't assign to ()");
+ compile_syntax_error(comp, pn, "can't assign to ()");
return;
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
pns = (mp_parse_node_struct_t*)pns->nodes[0];
@@ -727,8 +733,8 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
break;
default:
- printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
- assert(0);
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
+ return;
}
return;
@@ -750,8 +756,9 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
}
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
- // TODO not implemented
- assert(0);
+ // TODO can we ever get here? can it be compiled?
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
+ return;
} else {
// sequence with 2 items
goto sequence_with_2_items;
@@ -766,7 +773,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
return;
bad_aug:
- compile_syntax_error(comp, "illegal expression for augmented assignment");
+ compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
}
// stuff for lambda and comprehensions and generators
@@ -841,6 +848,7 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
pn_equal = pns->nodes[2];
} else {
+ // XXX what to do here?
assert(0);
return;
}
@@ -850,7 +858,7 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
// check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
if (!comp->have_bare_star && comp->param_pass_num_default_params != 0) {
- compile_syntax_error(comp, "non-default argument follows default argument");
+ compile_syntax_error(comp, pn, "non-default argument follows default argument");
return;
}
@@ -988,7 +996,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
}
if (name_len != 2) {
- compile_syntax_error(comp, "invalid micropython decorator");
+ compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
return true;
}
@@ -1006,7 +1014,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
*emit_options = MP_EMIT_OPT_ASM_THUMB;
#endif
} else {
- compile_syntax_error(comp, "invalid micropython decorator");
+ compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
}
return true;
@@ -1100,8 +1108,8 @@ void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
}
if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
- // SyntaxError: can't delete a function call
- assert(0);
+ // can't delete function calls
+ goto cannot_delete;
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
compile_node(comp, pns1->nodes[0]);
EMIT(delete_subscr);
@@ -1109,17 +1117,14 @@ void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
} else {
- // shouldn't happen
- assert(0);
+ goto cannot_delete;
}
} else {
- // shouldn't happen
- assert(0);
+ goto cannot_delete;
}
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
- // SyntaxError, cannot delete
- assert(0);
+ goto cannot_delete;
}
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
pn = ((mp_parse_node_struct_t*)pn)->nodes[0];
@@ -1142,7 +1147,7 @@ void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
}
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
// TODO not implemented; can't del comprehension?
- assert(0);
+ goto cannot_delete;
} else {
// sequence with 2 items
goto sequence_with_2_items;
@@ -1158,9 +1163,14 @@ void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
c_del_stmt(comp, pn);
}
} else {
- // not implemented
- assert(0);
+ // TODO is there anything else to implement?
+ goto cannot_delete;
}
+
+ return;
+
+cannot_delete:
+ compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
}
void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
@@ -1169,21 +1179,21 @@ void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->break_label == 0) {
- compile_syntax_error(comp, "'break' outside loop");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
}
EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
}
void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->continue_label == 0) {
- compile_syntax_error(comp, "'continue' outside loop");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
}
EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
}
void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
- compile_syntax_error(comp, "'return' outside function");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
return;
}
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -1280,14 +1290,14 @@ void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q1, qstr *q2) {
} else {
// TODO not implemented
// This covers relative imports starting with dot(s) like "from .foo import"
- compile_syntax_error(comp, "Relative imports not implemented");
- assert(0);
+ compile_syntax_error(comp, pn, "Relative imports not implemented");
+ return;
}
} else {
// TODO not implemented
// This covers relative imports with dots only like "from .. import"
- compile_syntax_error(comp, "Relative imports not implemented");
- assert(0);
+ compile_syntax_error(comp, pn, "Relative imports not implemented");
+ return;
}
}
@@ -1699,7 +1709,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
// this is a catch all exception handler
if (i + 1 != n_except) {
- compile_syntax_error(comp, "default 'except:' must be last");
+ compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last");
return;
}
} else {
@@ -1923,6 +1933,11 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
// optimisation for a, b = c, d; to match CPython's optimisation
mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
+ if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
+ || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)) {
+ // can't optimise when it's a star expression on the lhs
+ goto no_optimisation;
+ }
compile_node(comp, pns10->nodes[0]); // rhs
compile_node(comp, pns10->nodes[1]); // rhs
EMIT(rot_two);
@@ -1935,6 +1950,12 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
// optimisation for a, b, c = d, e, f; to match CPython's optimisation
mp_parse_node_struct_t* pns10 = (mp_parse_node_struct_t*)pns1->nodes[0];
mp_parse_node_struct_t* pns0 = (mp_parse_node_struct_t*)pns->nodes[0];
+ if (MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[0], PN_star_expr)
+ || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[1], PN_star_expr)
+ || MP_PARSE_NODE_IS_STRUCT_KIND(pns0->nodes[2], PN_star_expr)) {
+ // can't optimise when it's a star expression on the lhs
+ goto no_optimisation;
+ }
compile_node(comp, pns10->nodes[0]); // rhs
compile_node(comp, pns10->nodes[1]); // rhs
compile_node(comp, pns10->nodes[2]); // rhs
@@ -1944,6 +1965,7 @@ void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
c_assign(comp, pns0->nodes[1], ASSIGN_STORE); // lhs store
c_assign(comp, pns0->nodes[2], ASSIGN_STORE); // lhs store
} else {
+ no_optimisation:
compile_node(comp, pns1->nodes[0]); // rhs
c_assign(comp, pns->nodes[0], ASSIGN_STORE); // lhs store
}
@@ -2090,10 +2112,7 @@ void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
- // TODO
- assert(0);
- compile_node(comp, pns->nodes[0]);
- //EMIT_ARG(unary_op, "UNARY_STAR");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "can use starred expression only as assignment target");
}
void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
@@ -2271,7 +2290,7 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (i == 0) {
string_kind = pn_kind;
} else if (pn_kind != string_kind) {
- compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals");
return;
}
n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
@@ -2431,13 +2450,13 @@ void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
compile_node(comp, pn);
if (is_dict) {
if (!is_key_value) {
- compile_syntax_error(comp, "?expecting key:value for dictiona");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
return;
}
EMIT(store_map);
} else {
if (is_key_value) {
- compile_syntax_error(comp, "?expecting just a value for s");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
return;
}
}
@@ -2557,7 +2576,7 @@ void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->have_star_arg) {
- compile_syntax_error(comp, "?can't have multiple *x");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "can't have multiple *x");
return;
}
comp->have_star_arg = true;
@@ -2566,7 +2585,7 @@ void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->have_dbl_star_arg) {
- compile_syntax_error(comp, "?can't have multiple **x");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "can't have multiple **x");
return;
}
comp->have_dbl_star_arg = true;
@@ -2578,7 +2597,7 @@ void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
- compile_syntax_error(comp, "?lhs of keyword argument must be an id");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "left-hand-side of keyword argument must be an id");
return;
}
EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
@@ -2594,7 +2613,7 @@ void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
- compile_syntax_error(comp, "'yield' outside function");
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
return;
}
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -2658,7 +2677,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
#if MICROPY_DEBUG_PRINTERS
mp_parse_node_print(pn, 0);
#endif
- assert(0);
+ compile_syntax_error(comp, pn, "internal compiler error");
} else {
f(comp, pns);
}
@@ -2744,7 +2763,7 @@ void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_ki
bool added;
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
if (!added) {
- compile_syntax_error(comp, "?same name used for parameter");
+ compile_syntax_error(comp, pn, "same name used for parameter");
return;
}
id_info->param = true;
@@ -3049,7 +3068,7 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
// emit instructions
if (strcmp(qstr_str(op), "label") == 0) {
if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
- compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
+ compile_syntax_error(comp, nodes[i], "inline assembler 'label' requires 1 argument");
return;
}
int lab = comp_next_label(comp);
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 9ea2cc24bc..c5136ab371 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -81,45 +81,36 @@ STATIC void emit_inline_thumb_label(emit_inline_asm_t *emit, int label_num, qstr
asm_thumb_label_assign(emit->as, label_num);
}
-STATIC bool check_n_arg(qstr op, int n_args, int wanted_n_args) {
- if (wanted_n_args == n_args) {
- return true;
- } else {
- printf("SyntaxError: '%s' expects %d arguments'\n", qstr_str(op), wanted_n_args);
- return false;
- }
-}
-
-STATIC uint get_arg_rlo(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) {
+STATIC uint get_arg_rlo(const char *op, mp_parse_node_t *pn_args, int wanted_arg_num) {
if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
- printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
+ printf("SyntaxError: '%s' expects a register in position %d\n", op, wanted_arg_num);
return 0;
}
qstr reg_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
const char *reg_str = qstr_str(reg_qstr);
if (!(strlen(reg_str) == 2 && reg_str[0] == 'r' && ('0' <= reg_str[1] && reg_str[1] <= '7'))) {
- printf("SyntaxError: '%s' expects a register in position %d\n", qstr_str(op), wanted_arg_num);
+ printf("SyntaxError: '%s' expects a register in position %d\n", op, wanted_arg_num);
return 0;
}
return reg_str[1] - '0';
}
-STATIC int get_arg_i(qstr op, mp_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
+STATIC int get_arg_i(const char *op, mp_parse_node_t *pn_args, int wanted_arg_num, int fit_mask) {
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_args[wanted_arg_num])) {
- printf("SyntaxError: '%s' expects an integer in position %d\n", qstr_str(op), wanted_arg_num);
+ printf("SyntaxError: '%s' expects an integer in position %d\n", op, wanted_arg_num);
return 0;
}
int i = MP_PARSE_NODE_LEAF_SMALL_INT(pn_args[wanted_arg_num]);
if ((i & (~fit_mask)) != 0) {
- printf("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n", qstr_str(op), i, fit_mask);
+ printf("SyntaxError: '%s' integer 0x%x does not fit in mask 0x%x\n", op, i, fit_mask);
return 0;
}
return i;
}
-STATIC int get_arg_label(emit_inline_asm_t *emit, qstr op, mp_parse_node_t *pn_args, int wanted_arg_num) {
+STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t *pn_args, int wanted_arg_num) {
if (!MP_PARSE_NODE_IS_ID(pn_args[wanted_arg_num])) {
- printf("SyntaxError: '%s' expects a label in position %d\n", qstr_str(op), wanted_arg_num);
+ printf("SyntaxError: '%s' expects a label in position %d\n", op, wanted_arg_num);
return 0;
}
qstr label_qstr = MP_PARSE_NODE_LEAF_ARG(pn_args[wanted_arg_num]);
@@ -135,6 +126,24 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, qstr op, mp_parse_node_t *pn_a
return 0;
}
+typedef struct _cc_name_t { byte cc; byte name[2]; } cc_name_t;
+STATIC const cc_name_t cc_name_table[] = {
+ {THUMB_CC_EQ, "eq"},
+ {THUMB_CC_NE, "ne"},
+ {THUMB_CC_CS, "cs"},
+ {THUMB_CC_CC, "cc"},
+ {THUMB_CC_MI, "mi"},
+ {THUMB_CC_PL, "pl"},
+ {THUMB_CC_VS, "vs"},
+ {THUMB_CC_VC, "vc"},
+ {THUMB_CC_HI, "hi"},
+ {THUMB_CC_LS, "ls"},
+ {THUMB_CC_GE, "ge"},
+ {THUMB_CC_LT, "lt"},
+ {THUMB_CC_GT, "gt"},
+ {THUMB_CC_LE, "le"},
+};
+
STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, mp_parse_node_t *pn_args) {
// TODO perhaps make two tables:
// one_args =
@@ -146,60 +155,86 @@ STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, int n_args, m
// three_args =
// "subs", RLO, RLO, I3, asm_thumb_subs_reg_reg_i3
- // 1 arg
- if (strcmp(qstr_str(op), "b") == 0) {
- if (!check_n_arg(op, n_args, 1)) {
- return;
- }
- int label_num = get_arg_label(emit, op, pn_args, 0);
- // TODO check that this succeeded, ie branch was within range
- asm_thumb_b_n(emit->as, label_num);
- } else if (strcmp(qstr_str(op), "bgt") == 0) {
- if (!check_n_arg(op, n_args, 1)) {
- return;
- }
- int label_num = get_arg_label(emit, op, pn_args, 0);
- // TODO check that this succeeded, ie branch was within range
- asm_thumb_bcc_n(emit->as, THUMB_CC_GT, label_num);
-
- // 2 args
- } else if (strcmp(qstr_str(op), "movs") == 0) {
- if (!check_n_arg(op, n_args, 2)) {
- return;
+ const char *op_str = qstr_str(op);
+ uint op_len = strlen(op_str);
+
+ if (n_args == 0) {
+ if (strcmp(op_str, "ite.ge") == 0) { // TODO correct name for this op?
+ asm_thumb_ite_ge(emit->as);
+ } else {
+ goto unknown_op;
}
- uint rlo_dest = get_arg_rlo(op, pn_args, 0);
- int i_src = get_arg_i(op, pn_args, 1, 0xff);
- asm_thumb_movs_rlo_i8(emit->as, rlo_dest, i_src);
- } else if (strcmp(qstr_str(op), "movw") == 0) {
- if (!check_n_arg(op, n_args, 2)) {
- return;
+
+ } else if (n_args == 1) {
+ if (strcmp(op_str, "b") == 0) {
+ int label_num = get_arg_label(emit, op_str, pn_args, 0);
+ // TODO check that this succeeded, ie branch was within range
+ asm_thumb_b_n(emit->as, label_num);
+ } else if (op_str[0] == 'b' && op_len == 3) {
+ uint cc = -1;
+ for (uint i = 0; i < (sizeof cc_name_table) / (sizeof cc_name_table[0]); i++) {
+ if (op_str[1] == cc_name_table[i].name[0] && op_str[2] == cc_name_table[i].name[1]) {
+ cc = cc_name_table[i].cc;
+ }
+ }
+ if (cc == -1) {
+ goto unknown_op;
+ }
+ int label_num = get_arg_label(emit, op_str, pn_args, 0);
+ // TODO check that this succeeded, ie branch was within range
+ asm_thumb_bcc_n(emit->as, cc, label_num);
+ } else {
+ goto unknown_op;
}
- uint rlo_dest = get_arg_rlo(op, pn_args, 0); // TODO can be reg lo or hi
- int i_src = get_arg_i(op, pn_args, 1, 0xffff);
- asm_thumb_movw_reg_i16(emit->as, rlo_dest, i_src);
- } else if (strcmp(qstr_str(op), "cmp") == 0) {
- if (!check_n_arg(op, n_args, 2)) {
- return;
+
+ } else if (n_args == 2) {
+ if (strcmp(op_str, "mov") == 0) {
+ uint rlo_dest = get_arg_rlo(op_str, pn_args, 0);
+ uint rlo_src = get_arg_rlo(op_str, pn_args, 1);
+ asm_thumb_mov_reg_reg(emit->as, rlo_dest, rlo_src);
+ } else if (strcmp(op_str, "movs") == 0) {
+ uint rlo_dest = get_arg_rlo(op_str, pn_args, 0);
+ int i_src = get_arg_i(op_str, pn_args, 1, 0xff);
+ asm_thumb_movs_rlo_i8(emit->as, rlo_dest, i_src);
+ } else if (strcmp(op_str, "movw") == 0) {
+ uint rlo_dest = get_arg_rlo(op_str, pn_args, 0); // TODO can be reg lo or hi
+ int i_src = get_arg_i(op_str, pn_args, 1, 0xffff);
+ asm_thumb_movw_reg_i16(emit->as, rlo_dest, i_src);
+ } else if (strcmp(op_str, "movt") == 0) {
+ uint rlo_dest = get_arg_rlo(op_str, pn_args, 0); // TODO can be reg lo or hi
+ int i_src = get_arg_i(op_str, pn_args, 1, 0xffff);
+ asm_thumb_movt_reg_i16(emit->as, rlo_dest, i_src);
+ } else if (strcmp(op_str, "cmp") == 0) {
+ uint rlo = get_arg_rlo(op_str, pn_args, 0);
+ int i8 = get_arg_i(op_str, pn_args, 1, 0xff);
+ asm_thumb_cmp_rlo_i8(emit->as, rlo, i8);
+ } else {
+ goto unknown_op;
}
- uint rlo = get_arg_rlo(op, pn_args, 0);
- int i8 = get_arg_i(op, pn_args, 1, 0xff);
- asm_thumb_cmp_rlo_i8(emit->as, rlo, i8);
-
- // 3 args
- } else if (strcmp(qstr_str(op), "subs") == 0) {
- if (!check_n_arg(op, n_args, 3)) {
- return;
+
+ } else if (n_args == 3) {
+ if (strcmp(op_str, "add") == 0) {
+ uint rlo_dest = get_arg_rlo(op_str, pn_args, 0);
+ uint rlo_src_a = get_arg_rlo(op_str, pn_args, 1);
+ uint rlo_src_b = get_arg_rlo(op_str, pn_args, 2);
+ asm_thumb_add_reg_reg_reg(emit->as, rlo_dest, rlo_src_a, rlo_src_b);
+ } else if (strcmp(op_str, "subs") == 0) {
+ uint rlo_dest = get_arg_rlo(op_str, pn_args, 0);
+ uint rlo_src = get_arg_rlo(op_str, pn_args, 1);
+ int i3_src = get_arg_i(op_str, pn_args, 2, 0x7);
+ asm_thumb_subs_rlo_rlo_i3(emit->as, rlo_dest, rlo_src, i3_src);
+ } else {
+ goto unknown_op;
}
- uint rlo_dest = get_arg_rlo(op, pn_args, 0);
- uint rlo_src = get_arg_rlo(op, pn_args, 1);
- int i3_src = get_arg_i(op, pn_args, 2, 0x7);
- asm_thumb_subs_rlo_rlo_i3(emit->as, rlo_dest, rlo_src, i3_src);
- // unknown op
} else {
- printf("SyntaxError: unsupported ARM Thumb instruction '%s'\n", qstr_str(op));
- return;
+ goto unknown_op;
}
+
+ return;
+
+unknown_op:
+ printf("SyntaxError: unsupported ARM Thumb instruction '%s' with %d arguments\n", op_str, n_args);
}
const emit_inline_asm_method_table_t emit_inline_thumb_method_table = {
diff --git a/py/obj.h b/py/obj.h
index fc99055b6e..77cf7838ee 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -440,6 +440,7 @@ mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m
// list
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
+void mp_obj_list_set_len(mp_obj_t self_in, uint len);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, mp_map_t *kwargs);
diff --git a/py/objlist.c b/py/objlist.c
index 620bf2944a..371d1cb26e 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -378,6 +378,13 @@ void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
*items = self->items;
}
+void mp_obj_list_set_len(mp_obj_t self_in, uint len) {
+ // trust that the caller knows what it's doing
+ // TODO realloc if len got much smaller than alloc
+ mp_obj_list_t *self = self_in;
+ self->len = len;
+}
+
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_list_t *self = self_in;
uint i = mp_get_index(self->base.type, self->len, index, false);
diff --git a/py/runtime.c b/py/runtime.c
index 44e0ded507..3d1ae72c2f 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -672,6 +672,70 @@ too_long:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
}
+// unpacked items are stored in reverse order into the array pointed to by items
+void mp_unpack_ex(mp_obj_t seq_in, uint num_in, mp_obj_t *items) {
+ uint num_left = num_in & 0xff;
+ uint num_right = (num_in >> 8) & 0xff;
+ DEBUG_OP_printf("unpack ex %d %d\n", num_left, num_right);
+ uint seq_len;
+ if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
+ mp_obj_t *seq_items;
+ if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
+ mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
+ } else {
+ if (num_left == 0 && num_right == 0) {
+ // *a, = b # sets a to b if b is a list
+ items[0] = seq_in;
+ return;
+ }
+ mp_obj_list_get(seq_in, &seq_len, &seq_items);
+ }
+ if (seq_len < num_left + num_right) {
+ goto too_short;
+ }
+ for (uint i = 0; i < num_right; i++) {
+ items[i] = seq_items[seq_len - 1 - i];
+ }
+ items[num_right] = mp_obj_new_list(seq_len - num_left - num_right, seq_items + num_left);
+ for (uint i = 0; i < num_left; i++) {
+ items[num_right + 1 + i] = seq_items[num_left - 1 - i];
+ }
+ } else {
+ // Generic iterable; this gets a bit messy: we unpack known left length to the
+ // items destination array, then the rest to a dynamically created list. Once the
+ // iterable is exhausted, we take from this list for the right part of the items.
+ // TODO Improve to waste less memory in the dynamically created list.
+ mp_obj_t iterable = mp_getiter(seq_in);
+ mp_obj_t item;
+ for (seq_len = 0; seq_len < num_left; seq_len++) {
+ item = mp_iternext(iterable);
+ if (item == MP_OBJ_NULL) {
+ goto too_short;
+ }
+ items[num_left + num_right + 1 - 1 - seq_len] = item;
+ }
+ mp_obj_t rest = mp_obj_new_list(0, NULL);
+ while ((item = mp_iternext(iterable)) != MP_OBJ_NULL) {
+ mp_obj_list_append(rest, item);
+ }
+ uint rest_len;
+ mp_obj_t *rest_items;
+ mp_obj_list_get(rest, &rest_len, &rest_items);
+ if (rest_len < num_right) {
+ goto too_short;
+ }
+ items[num_right] = rest;
+ for (uint i = 0; i < num_right; i++) {
+ items[num_right - 1 - i] = rest_items[rest_len - num_right + i];
+ }
+ mp_obj_list_set_len(rest, rest_len - num_right);
+ }
+ return;
+
+too_short:
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len));
+}
+
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
// use load_method
diff --git a/py/runtime.h b/py/runtime.h
index cc76186f4e..ab34be2da9 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -44,6 +44,7 @@ mp_obj_t mp_call_method_n_kw(uint n_args, uint n_kw, const mp_obj_t *args);
mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_t *args);
void mp_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
+void mp_unpack_ex(mp_obj_t seq, uint num, mp_obj_t *items);
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
diff --git a/py/vm.c b/py/vm.c
index 567e8bb675..869a9381ad 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -639,8 +639,10 @@ unwind_jump:
obj1 = TOP();
SET_TOP(mp_obj_new_slice(obj1, obj2, NULL));
} else {
- printf("3-argument slice is not supported\n");
- assert(0);
+ obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "3-argument slice is not supported");
+ nlr_pop();
+ fastn[0] = obj1;
+ return MP_VM_RETURN_EXCEPTION;
}
break;
#endif
@@ -651,6 +653,12 @@ unwind_jump:
sp += unum - 1;
break;
+ case MP_BC_UNPACK_EX:
+ DECODE_UINT;
+ mp_unpack_ex(sp[0], unum, sp);
+ sp += (unum & 0xff) + ((unum >> 8) & 0xff);
+ break;
+
case MP_BC_MAKE_FUNCTION:
DECODE_UINT;
PUSH(mp_make_function_from_id(unum, MP_OBJ_NULL, MP_OBJ_NULL));
@@ -833,9 +841,10 @@ yield:
default:
printf("code %p, byte code 0x%02x not implemented\n", ip, op);
- assert(0);
+ obj1 = mp_obj_new_exception_msg(&mp_type_NotImplementedError, "byte code not implemented");
nlr_pop();
- return MP_VM_RETURN_NORMAL;
+ fastn[0] = obj1;
+ return MP_VM_RETURN_EXCEPTION;
}
}