Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
b7ffdcc1
Commit
b7ffdcc1
authored
Apr 08, 2014
by
Damien George
Browse files
py: Improve compiler syntax errors; catch more errors.
parent
2137bc71
Changes
1
Hide whitespace changes
Inline
Side-by-side
py/compile.c
View file @
b7ffdcc1
...
...
@@ -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 call
s
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
implement
ed
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
{
...
...
@@ -2090,10 +2100,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 +2278,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 +2438,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 dictiona
ry
"
);
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 s
et
"
);
return
;
}
}
...
...
@@ -2557,7 +2564,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 +2573,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 +2585,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 +2601,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 +2665,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 +2751,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 +3056,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
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment