summaryrefslogtreecommitdiffstatshomepage
path: root/py/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/compile.c')
-rw-r--r--py/compile.c116
1 files changed, 84 insertions, 32 deletions
diff --git a/py/compile.c b/py/compile.c
index 6a87236b9d..d1aec30958 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -73,6 +73,12 @@ 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) {
+ // TODO store the error message to a variable in compiler_t instead of printing it
+ printf("SyntaxError: %s\n", msg);
+ comp->had_error = true;
+}
+
mp_parse_node_t fold_constants(mp_parse_node_t pn) {
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@@ -574,7 +580,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) {
- printf("SyntaxError: can't assign to function call\n");
+ compile_syntax_error(comp, "can't assign to function call");
return;
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
if (assign_kind == ASSIGN_AUG_STORE) {
@@ -624,7 +630,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 {
- printf("SyntaxError: two starred expressions in assignment\n");
+ compile_syntax_error(comp, "two starred expressions in assignment");
return;
}
}
@@ -659,7 +665,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
break;
}
} else {
- printf("SyntaxError: can't assign to literal\n");
+ compile_syntax_error(comp, "can't assign to literal");
return;
}
} else {
@@ -683,7 +689,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
- printf("SyntaxError: can't assign to ()\n");
+ compile_syntax_error(comp, "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];
@@ -752,7 +758,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
return;
bad_aug:
- printf("SyntaxError: illegal expression for augmented assignment\n");
+ compile_syntax_error(comp, "illegal expression for augmented assignment");
}
// stuff for lambda and comprehensions and generators
@@ -792,30 +798,69 @@ void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_dict_
}
void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
- if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
+ if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
- if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
+ if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
+ // bare star
+ comp->have_bare_star = true;
+ }
+
+ } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)) {
+ // TODO do we need to do anything with this?
+
+ } else {
+ mp_parse_node_t pn_id;
+ mp_parse_node_t pn_colon;
+ mp_parse_node_t pn_equal;
+ if (MP_PARSE_NODE_IS_ID(pn)) {
+ // this parameter is just an id
+
+ pn_id = pn;
+ pn_colon = MP_PARSE_NODE_NULL;
+ pn_equal = MP_PARSE_NODE_NULL;
+
+ } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
+ // this parameter has a colon and/or equal specifier
+
+ mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
+ pn_id = pns->nodes[0];
+ pn_colon = pns->nodes[1];
+ pn_equal = pns->nodes[2];
+
+ } else {
+ assert(0);
+ return;
+ }
+
+ if (MP_PARSE_NODE_IS_NULL(pn_equal)) {
+ // this parameter does not have a default value
+
+ // 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");
+ return;
+ }
+
+ } else {
// this parameter has a default value
// in CPython, None (and True, False?) as default parameters are loaded with LOAD_NAME; don't understandy why
+
if (comp->have_bare_star) {
comp->param_pass_num_dict_params += 1;
if (comp->param_pass == 1) {
- EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
- compile_node(comp, pns->nodes[2]);
+ EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pn_id));
+ compile_node(comp, pn_equal);
}
} else {
comp->param_pass_num_default_params += 1;
if (comp->param_pass == 2) {
- compile_node(comp, pns->nodes[2]);
+ compile_node(comp, pn_equal);
}
}
}
- } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)) {
- mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
- if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
- // bare star
- comp->have_bare_star = true;
- }
+
+ // TODO pn_colon not implemented
+ (void)pn_colon;
}
}
@@ -836,13 +881,21 @@ qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint
int old_param_pass_num_default_params = comp->param_pass_num_default_params;
// compile default parameters
+
+ // pass 1 does any default parameters after bare star
comp->have_bare_star = false;
- comp->param_pass = 1; // pass 1 does any default parameters after bare star
+ comp->param_pass = 1;
comp->param_pass_num_dict_params = 0;
comp->param_pass_num_default_params = 0;
apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
+
+ if (comp->had_error) {
+ return MP_QSTR_NULL;
+ }
+
+ // pass 2 does any default parameters before bare star
comp->have_bare_star = false;
- comp->param_pass = 2; // pass 2 does any default parameters before bare star
+ comp->param_pass = 2;
comp->param_pass_num_dict_params = 0;
comp->param_pass_num_default_params = 0;
apply_to_single_or_list(comp, pns->nodes[1], PN_typedargslist, compile_funcdef_param);
@@ -899,7 +952,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
}
if (name_len != 2) {
- printf("SyntaxError: invalid micropython decorator\n");
+ compile_syntax_error(comp, "invalid micropython decorator");
return true;
}
@@ -917,7 +970,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
*emit_options = EMIT_OPT_ASM_THUMB;
#endif
} else {
- printf("SyntaxError: invalid micropython decorator '%s'\n", qstr_str(attr));
+ compile_syntax_error(comp, "invalid micropython decorator");
}
return true;
@@ -1094,8 +1147,7 @@ void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
- printf("SyntaxError: 'return' outside function\n");
- comp->had_error = true;
+ compile_syntax_error(comp, "'return' outside function");
return;
}
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -1593,7 +1645,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) {
- printf("SyntaxError: default 'except:' must be last\n");
+ compile_syntax_error(comp, "default 'except:' must be last");
return;
}
} else {
@@ -2163,7 +2215,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) {
- printf("SyntaxError: cannot mix bytes and nonbytes literals\n");
+ compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
return;
}
n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
@@ -2323,13 +2375,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) {
- printf("SyntaxError?: expecting key:value for dictionary");
+ compile_syntax_error(comp, "?expecting key:value for dictiona");
return;
}
EMIT(store_map);
} else {
if (is_key_value) {
- printf("SyntaxError?: expecting just a value for set");
+ compile_syntax_error(comp, "?expecting just a value for s");
return;
}
}
@@ -2449,7 +2501,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) {
- printf("SyntaxError?: can't have multiple *x\n");
+ compile_syntax_error(comp, "?can't have multiple *x");
return;
}
comp->have_star_arg = true;
@@ -2458,7 +2510,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) {
- printf("SyntaxError?: can't have multiple **x\n");
+ compile_syntax_error(comp, "?can't have multiple **x");
return;
}
comp->have_dbl_star_arg = true;
@@ -2470,7 +2522,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])) {
- printf("SyntaxError?: lhs of keyword argument must be an id\n");
+ compile_syntax_error(comp, "?lhs of keyword argument must be an id");
return;
}
EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
@@ -2486,7 +2538,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) {
- printf("SyntaxError: 'yield' outside function\n");
+ compile_syntax_error(comp, "'yield' outside function");
return;
}
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -2636,7 +2688,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) {
- printf("SyntaxError?: same name used for parameter; %s\n", qstr_str(param_name));
+ compile_syntax_error(comp, "?same name used for parameter");
return;
}
id_info->param = true;
@@ -2941,7 +2993,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]))) {
- printf("SyntaxError: inline assembler 'label' requires 1 argument\n");
+ compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
return;
}
int lab = comp_next_label(comp);