Skip to content

Commit b7ffdcc

Browse files
committed
py: Improve compiler syntax errors; catch more errors.
1 parent 2137bc7 commit b7ffdcc

1 file changed

Lines changed: 61 additions & 54 deletions

File tree

py/compile.c

Lines changed: 61 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,13 @@ typedef struct _compiler_t {
6969
const emit_inline_asm_method_table_t *emit_inline_asm_method_table; // current emit method table for inline asm
7070
} compiler_t;
7171

72-
STATIC void compile_syntax_error(compiler_t *comp, const char *msg) {
72+
STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, const char *msg) {
7373
// TODO store the error message to a variable in compiler_t instead of printing it
74+
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
75+
printf(" File \"%s\", line " UINT_FMT "\n", qstr_str(comp->source_file), (machine_uint_t)((mp_parse_node_struct_t*)pn)->source_line);
76+
} else {
77+
printf(" File \"%s\"\n", qstr_str(comp->source_file));
78+
}
7479
printf("SyntaxError: %s\n", msg);
7580
comp->had_error = true;
7681
}
@@ -351,7 +356,7 @@ STATIC void cpython_c_tuple_emit_const(compiler_t *comp, mp_parse_node_t pn, vst
351356
case MP_TOKEN_KW_FALSE: vstr_printf(vstr, "False"); break;
352357
case MP_TOKEN_KW_NONE: vstr_printf(vstr, "None"); break;
353358
case MP_TOKEN_KW_TRUE: vstr_printf(vstr, "True"); break;
354-
default: assert(0);
359+
default: assert(0); // shouldn't happen
355360
}
356361
break;
357362
default: assert(0);
@@ -588,8 +593,7 @@ void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t
588593
pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
589594
}
590595
if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
591-
compile_syntax_error(comp, "can't assign to function call");
592-
return;
596+
goto cannot_assign;
593597
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
594598
if (assign_kind == ASSIGN_AUG_STORE) {
595599
EMIT(rot_three);
@@ -615,18 +619,20 @@ void c_assign_power(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t
615619
EMIT_ARG(store_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
616620
}
617621
} else {
618-
// shouldn't happen
619-
assert(0);
622+
goto cannot_assign;
620623
}
621624
} else {
622-
// shouldn't happen
623-
assert(0);
625+
goto cannot_assign;
624626
}
625627

626628
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
627-
// SyntaxError, cannot assign
628-
assert(0);
629+
goto cannot_assign;
629630
}
631+
632+
return;
633+
634+
cannot_assign:
635+
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
630636
}
631637

632638
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) {
638644
EMIT_ARG(unpack_ex, i, n - i - 1);
639645
have_star_index = i;
640646
} else {
641-
compile_syntax_error(comp, "two starred expressions in assignment");
647+
compile_syntax_error(comp, nodes[i], "two starred expressions in assignment");
642648
return;
643649
}
644650
}
@@ -673,7 +679,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
673679
break;
674680
}
675681
} else {
676-
compile_syntax_error(comp, "can't assign to literal");
682+
compile_syntax_error(comp, pn, "can't assign to literal");
677683
return;
678684
}
679685
} else {
@@ -697,7 +703,7 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
697703
// lhs is something in parenthesis
698704
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
699705
// empty tuple
700-
compile_syntax_error(comp, "can't assign to ()");
706+
compile_syntax_error(comp, pn, "can't assign to ()");
701707
return;
702708
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp)) {
703709
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) {
727733
break;
728734

729735
default:
730-
printf("unknown assign, %u\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
731-
assert(0);
736+
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
737+
return;
732738
}
733739
return;
734740

@@ -750,8 +756,9 @@ void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) {
750756
c_assign(comp, pns2->nodes[i], ASSIGN_STORE);
751757
}
752758
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
753-
// TODO not implemented
754-
assert(0);
759+
// TODO can we ever get here? can it be compiled?
760+
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't assign to expression");
761+
return;
755762
} else {
756763
// sequence with 2 items
757764
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) {
766773
return;
767774

768775
bad_aug:
769-
compile_syntax_error(comp, "illegal expression for augmented assignment");
776+
compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
770777
}
771778

772779
// stuff for lambda and comprehensions and generators
@@ -841,6 +848,7 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
841848
pn_equal = pns->nodes[2];
842849

843850
} else {
851+
// XXX what to do here?
844852
assert(0);
845853
return;
846854
}
@@ -850,7 +858,7 @@ void compile_funcdef_param(compiler_t *comp, mp_parse_node_t pn) {
850858

851859
// check for non-default parameters given after default parameters (allowed by parser, but not syntactically valid)
852860
if (!comp->have_bare_star && comp->param_pass_num_default_params != 0) {
853-
compile_syntax_error(comp, "non-default argument follows default argument");
861+
compile_syntax_error(comp, pn, "non-default argument follows default argument");
854862
return;
855863
}
856864

@@ -988,7 +996,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
988996
}
989997

990998
if (name_len != 2) {
991-
compile_syntax_error(comp, "invalid micropython decorator");
999+
compile_syntax_error(comp, name_nodes[0], "invalid micropython decorator");
9921000
return true;
9931001
}
9941002

@@ -1006,7 +1014,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, int name_len, mp_parse_
10061014
*emit_options = MP_EMIT_OPT_ASM_THUMB;
10071015
#endif
10081016
} else {
1009-
compile_syntax_error(comp, "invalid micropython decorator");
1017+
compile_syntax_error(comp, name_nodes[1], "invalid micropython decorator");
10101018
}
10111019

10121020
return true;
@@ -1100,26 +1108,23 @@ void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
11001108
pns1 = (mp_parse_node_struct_t*)pns1->nodes[n - 1];
11011109
}
11021110
if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_paren) {
1103-
// SyntaxError: can't delete a function call
1104-
assert(0);
1111+
// can't delete function calls
1112+
goto cannot_delete;
11051113
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_bracket) {
11061114
compile_node(comp, pns1->nodes[0]);
11071115
EMIT(delete_subscr);
11081116
} else if (MP_PARSE_NODE_STRUCT_KIND(pns1) == PN_trailer_period) {
11091117
assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0]));
11101118
EMIT_ARG(delete_attr, MP_PARSE_NODE_LEAF_ARG(pns1->nodes[0]));
11111119
} else {
1112-
// shouldn't happen
1113-
assert(0);
1120+
goto cannot_delete;
11141121
}
11151122
} else {
1116-
// shouldn't happen
1117-
assert(0);
1123+
goto cannot_delete;
11181124
}
11191125

11201126
if (!MP_PARSE_NODE_IS_NULL(pns->nodes[2])) {
1121-
// SyntaxError, cannot delete
1122-
assert(0);
1127+
goto cannot_delete;
11231128
}
11241129
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_paren)) {
11251130
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) {
11421147
}
11431148
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_comp_for) {
11441149
// TODO not implemented; can't del comprehension?
1145-
assert(0);
1150+
goto cannot_delete;
11461151
} else {
11471152
// sequence with 2 items
11481153
goto sequence_with_2_items;
@@ -1158,9 +1163,14 @@ void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) {
11581163
c_del_stmt(comp, pn);
11591164
}
11601165
} else {
1161-
// not implemented
1162-
assert(0);
1166+
// TODO is there anything else to implement?
1167+
goto cannot_delete;
11631168
}
1169+
1170+
return;
1171+
1172+
cannot_delete:
1173+
compile_syntax_error(comp, (mp_parse_node_t)pn, "can't delete expression");
11641174
}
11651175

11661176
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) {
11691179

11701180
void compile_break_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
11711181
if (comp->break_label == 0) {
1172-
compile_syntax_error(comp, "'break' outside loop");
1182+
compile_syntax_error(comp, (mp_parse_node_t)pns, "'break' outside loop");
11731183
}
11741184
EMIT_ARG(break_loop, comp->break_label, comp->cur_except_level - comp->break_continue_except_level);
11751185
}
11761186

11771187
void compile_continue_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
11781188
if (comp->continue_label == 0) {
1179-
compile_syntax_error(comp, "'continue' outside loop");
1189+
compile_syntax_error(comp, (mp_parse_node_t)pns, "'continue' outside loop");
11801190
}
11811191
EMIT_ARG(continue_loop, comp->continue_label, comp->cur_except_level - comp->break_continue_except_level);
11821192
}
11831193

11841194
void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
11851195
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
1186-
compile_syntax_error(comp, "'return' outside function");
1196+
compile_syntax_error(comp, (mp_parse_node_t)pns, "'return' outside function");
11871197
return;
11881198
}
11891199
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) {
12801290
} else {
12811291
// TODO not implemented
12821292
// This covers relative imports starting with dot(s) like "from .foo import"
1283-
compile_syntax_error(comp, "Relative imports not implemented");
1284-
assert(0);
1293+
compile_syntax_error(comp, pn, "Relative imports not implemented");
1294+
return;
12851295
}
12861296
} else {
12871297
// TODO not implemented
12881298
// This covers relative imports with dots only like "from .. import"
1289-
compile_syntax_error(comp, "Relative imports not implemented");
1290-
assert(0);
1299+
compile_syntax_error(comp, pn, "Relative imports not implemented");
1300+
return;
12911301
}
12921302
}
12931303

@@ -1699,7 +1709,7 @@ void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except,
16991709
if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
17001710
// this is a catch all exception handler
17011711
if (i + 1 != n_except) {
1702-
compile_syntax_error(comp, "default 'except:' must be last");
1712+
compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last");
17031713
return;
17041714
}
17051715
} else {
@@ -2090,10 +2100,7 @@ void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) {
20902100
}
20912101

20922102
void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
2093-
// TODO
2094-
assert(0);
2095-
compile_node(comp, pns->nodes[0]);
2096-
//EMIT_ARG(unary_op, "UNARY_STAR");
2103+
compile_syntax_error(comp, (mp_parse_node_t)pns, "can use starred expression only as assignment target");
20972104
}
20982105

20992106
void compile_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
@@ -2271,7 +2278,7 @@ void compile_atom_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
22712278
if (i == 0) {
22722279
string_kind = pn_kind;
22732280
} else if (pn_kind != string_kind) {
2274-
compile_syntax_error(comp, "cannot mix bytes and nonbytes literals");
2281+
compile_syntax_error(comp, (mp_parse_node_t)pns, "cannot mix bytes and nonbytes literals");
22752282
return;
22762283
}
22772284
n_bytes += qstr_len(MP_PARSE_NODE_LEAF_ARG(pns->nodes[i]));
@@ -2431,13 +2438,13 @@ void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
24312438
compile_node(comp, pn);
24322439
if (is_dict) {
24332440
if (!is_key_value) {
2434-
compile_syntax_error(comp, "?expecting key:value for dictiona");
2441+
compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
24352442
return;
24362443
}
24372444
EMIT(store_map);
24382445
} else {
24392446
if (is_key_value) {
2440-
compile_syntax_error(comp, "?expecting just a value for s");
2447+
compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
24412448
return;
24422449
}
24432450
}
@@ -2557,7 +2564,7 @@ void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) {
25572564

25582565
void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
25592566
if (comp->have_star_arg) {
2560-
compile_syntax_error(comp, "?can't have multiple *x");
2567+
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't have multiple *x");
25612568
return;
25622569
}
25632570
comp->have_star_arg = true;
@@ -2566,7 +2573,7 @@ void compile_arglist_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
25662573

25672574
void compile_arglist_dbl_star(compiler_t *comp, mp_parse_node_struct_t *pns) {
25682575
if (comp->have_dbl_star_arg) {
2569-
compile_syntax_error(comp, "?can't have multiple **x");
2576+
compile_syntax_error(comp, (mp_parse_node_t)pns, "can't have multiple **x");
25702577
return;
25712578
}
25722579
comp->have_dbl_star_arg = true;
@@ -2578,7 +2585,7 @@ void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
25782585
mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t*)pns->nodes[1];
25792586
if (MP_PARSE_NODE_STRUCT_KIND(pns2) == PN_argument_3) {
25802587
if (!MP_PARSE_NODE_IS_ID(pns->nodes[0])) {
2581-
compile_syntax_error(comp, "?lhs of keyword argument must be an id");
2588+
compile_syntax_error(comp, (mp_parse_node_t)pns, "left-hand-side of keyword argument must be an id");
25822589
return;
25832590
}
25842591
EMIT_ARG(load_const_id, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]));
@@ -2594,7 +2601,7 @@ void compile_argument(compiler_t *comp, mp_parse_node_struct_t *pns) {
25942601

25952602
void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) {
25962603
if (comp->scope_cur->kind != SCOPE_FUNCTION) {
2597-
compile_syntax_error(comp, "'yield' outside function");
2604+
compile_syntax_error(comp, (mp_parse_node_t)pns, "'yield' outside function");
25982605
return;
25992606
}
26002607
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
@@ -2658,7 +2665,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
26582665
#if MICROPY_DEBUG_PRINTERS
26592666
mp_parse_node_print(pn, 0);
26602667
#endif
2661-
assert(0);
2668+
compile_syntax_error(comp, pn, "internal compiler error");
26622669
} else {
26632670
f(comp, pns);
26642671
}
@@ -2744,7 +2751,7 @@ void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_ki
27442751
bool added;
27452752
id_info_t *id_info = scope_find_or_add_id(comp->scope_cur, param_name, &added);
27462753
if (!added) {
2747-
compile_syntax_error(comp, "?same name used for parameter");
2754+
compile_syntax_error(comp, pn, "same name used for parameter");
27482755
return;
27492756
}
27502757
id_info->param = true;
@@ -3049,7 +3056,7 @@ void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass
30493056
// emit instructions
30503057
if (strcmp(qstr_str(op), "label") == 0) {
30513058
if (!(n_args == 1 && MP_PARSE_NODE_IS_ID(pn_arg[0]))) {
3052-
compile_syntax_error(comp, "inline assembler 'label' requires 1 argument");
3059+
compile_syntax_error(comp, nodes[i], "inline assembler 'label' requires 1 argument");
30533060
return;
30543061
}
30553062
int lab = comp_next_label(comp);

0 commit comments

Comments
 (0)