1
1
/*
2
- * This file is part of the Micro Python project, http://micropython.org/
2
+ * This file is part of the MicroPython project, http://micropython.org/
3
3
*
4
4
* The MIT License (MIT)
5
5
*
6
- * Copyright (c) 2013-2015 Damien P. George
6
+ * Copyright (c) 2013-2016 Damien P. George
7
7
*
8
8
* Permission is hereby granted, free of charge, to any person obtaining a copy
9
9
* of this software and associated documentation files (the "Software"), to deal
33
33
#include "py/scope.h"
34
34
#include "py/emit.h"
35
35
#include "py/compile.h"
36
- #include "py/smallint.h"
37
36
#include "py/runtime.h"
38
- #include "py/builtin.h"
37
+
38
+ #if MICROPY_ENABLE_COMPILER
39
39
40
40
// TODO need to mangle __attr names
41
41
@@ -80,7 +80,7 @@ typedef struct _compiler_t {
80
80
81
81
// try to keep compiler clean from nlr
82
82
mp_obj_t compile_error ; // set to an exception object if there's an error
83
- mp_uint_t compile_error_line ; // set to best guess of line of error
83
+ size_t compile_error_line ; // set to best guess of line of error
84
84
85
85
uint next_label ;
86
86
@@ -94,7 +94,7 @@ typedef struct _compiler_t {
94
94
95
95
mp_uint_t * co_data ;
96
96
97
- mp_uint_t num_scopes ;
97
+ size_t num_scopes ;
98
98
scope_t * * scopes ;
99
99
scope_t * scope_cur ;
100
100
@@ -112,7 +112,7 @@ typedef struct _compiler_t {
112
112
STATIC void compile_error_set_line (compiler_t * comp , const byte * p ) {
113
113
// if the line of the error is unknown then try to update it from the parse data
114
114
if (comp -> compile_error_line == 0 && p != NULL && pt_is_any_rule (p )) {
115
- mp_uint_t rule_id , src_line ;
115
+ size_t rule_id , src_line ;
116
116
const byte * ptop ;
117
117
pt_rule_extract (p , & rule_id , & src_line , & ptop );
118
118
comp -> compile_error_line = src_line ;
@@ -147,7 +147,7 @@ STATIC void compile_decrease_except_level(compiler_t *comp) {
147
147
comp -> cur_except_level -= 1 ;
148
148
}
149
149
150
- STATIC void scope_new_and_link (compiler_t * comp , mp_uint_t scope_idx , scope_kind_t kind , const byte * p , uint emit_options ) {
150
+ STATIC void scope_new_and_link (compiler_t * comp , size_t scope_idx , scope_kind_t kind , const byte * p , uint emit_options ) {
151
151
scope_t * scope = scope_new (kind , p , comp -> source_file , emit_options );
152
152
scope -> parent = comp -> scope_cur ;
153
153
comp -> scopes [scope_idx ] = scope ;
@@ -284,14 +284,12 @@ STATIC const byte *c_if_cond(compiler_t *comp, const byte *p, bool jump_if, int
284
284
if (jump_if == false) {
285
285
EMIT_ARG (jump , label );
286
286
}
287
- } else if (pt_is_rule (pt_rule_first (p ), PN_testlist_comp )) {
287
+ } else {
288
+ assert (pt_is_rule (pt_rule_first (p ), PN_testlist_comp ));
288
289
// non-empty tuple, acts as true for the condition
289
290
if (jump_if == true) {
290
291
EMIT_ARG (jump , label );
291
292
}
292
- } else {
293
- // parenthesis around 1 item, is just that item
294
- c_if_cond (comp , pt_rule_first (p ), jump_if , label );
295
293
}
296
294
return pt_next (p );
297
295
}
@@ -416,7 +414,6 @@ STATIC void c_assign_tuple(compiler_t *comp, const byte *p_head, const byte *p_t
416
414
417
415
// assigns top of stack to pn
418
416
STATIC void c_assign (compiler_t * comp , const byte * p , assign_kind_t assign_kind ) {
419
- tail_recursion :
420
417
assert (!pt_is_null (p ));
421
418
if (pt_is_any_id (p )) {
422
419
qstr arg ;
@@ -459,16 +456,13 @@ STATIC void c_assign(compiler_t *comp, const byte *p, assign_kind_t assign_kind)
459
456
if (pt_is_null_with_top (p0 , ptop )) {
460
457
// empty tuple
461
458
goto cannot_assign ;
462
- } else if (pt_is_rule (p0 , PN_testlist_comp )) {
459
+ } else {
460
+ assert (pt_is_rule (p0 , PN_testlist_comp ));
463
461
if (assign_kind != ASSIGN_STORE ) {
464
462
goto bad_aug ;
465
463
}
466
464
p = p0 ;
467
465
goto testlist_comp ;
468
- } else {
469
- // parenthesis around 1 item, is just that item
470
- p = p0 ;
471
- goto tail_recursion ;
472
466
}
473
467
break ;
474
468
}
@@ -670,6 +664,13 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, const byte *p) {
670
<
10000
td data-grid-cell-id="diff-b269b1258984f6dd604742fabe070f5f6fbc7b654199efff569d545cd42ff230-670-664-1" data-selected="false" role="gridcell" style="background-color:var(--bgColor-default);text-align:center" tabindex="-1" valign="top" class="focusable-grid-cell diff-line-number position-relative diff-line-number-neutral left-side">664
}
671
665
672
666
STATIC void compile_funcdef_lambdef (compiler_t * comp , scope_t * scope , const byte * p , pn_kind_t pn_list_kind ) {
667
+ // When we call compile_funcdef_lambdef_param below it can compile an arbitrary
668
+ // expression for default arguments, which may contain a lambda. The lambda will
669
+ // call here in a nested way, so we must save and restore the relevant state.
670
+ bool orig_have_star = comp -> have_star ;
671
+ uint16_t orig_num_dict_params = comp -> num_dict_params ;
672
+ uint16_t orig_num_default_params = comp -> num_default_params ;
673
+
673
674
// compile default parameters
674
675
comp -> have_star = false;
675
676
comp -> num_dict_params = 0 ;
@@ -689,6 +690,11 @@ STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, const byte
689
690
690
691
// make the function
691
692
close_over_variables_etc (comp , scope , comp -> num_default_params , comp -> num_dict_params );
693
+
694
+ // restore state
695
+ comp -> have_star = orig_have_star ;
696
+ comp -> num_dict_params = orig_num_dict_params ;
697
+ comp -> num_default_params = orig_num_default_params ;
692
698
}
693
699
694
700
// leaves function object on stack
@@ -897,8 +903,11 @@ STATIC void c_del_stmt(compiler_t *comp, const byte *p) {
897
903
goto cannot_delete ;
898
904
}
899
905
} else if (pt_is_rule (p , PN_atom_paren )) {
900
- p = pt_rule_first (p );
901
- if (pt_is_rule (p , PN_testlist_comp )) {
906
+ if (pt_is_rule_empty (p )) {
907
+ goto cannot_delete ;
908
+ } else {
909
+ p = pt_rule_first (p );
910
+ assert (pt_is_rule (p , PN_testlist_comp ));
902
911
// TODO perhaps factorise testlist_comp code with other uses of PN_testlist_comp
903
912
// or, simplify the logic here my making the parser simplify everything to a list
904
913
const byte * p0 = pt_rule_first (p );
@@ -923,12 +932,9 @@ STATIC void c_del_stmt(compiler_t *comp, const byte *p) {
923
932
// sequence with 2 items
924
933
c_del_stmt (comp , p1 );
925
934
}
926
- } else {
927
- // tuple with 1 element
928
- c_del_stmt (comp , p );
929
935
}
930
936
} else {
931
- // TODO is there anything else to implement?
937
+ // some arbitrary statment that we can't delete (eg del 1)
932
938
goto cannot_delete ;
933
939
}
934
940
@@ -1062,7 +1068,7 @@ STATIC void do_import_name(compiler_t *comp, const byte *p, qstr *q_base) {
1062
1068
}
1063
1069
qstr qst ;
1064
1070
p2 = pt_extract_id (p2 , & qst );
1065
- mp_uint_t str_src_len ;
1071
+ size_t str_src_len ;
1066
1072
const byte * str_src = qstr_data (qst , & str_src_len );
1067
1073
memcpy (str_dest , str_src , str_src_len );
1068
1074
str_dest += str_src_len ;
@@ -1495,6 +1501,19 @@ STATIC void compile_for_stmt(compiler_t *comp, const byte *p, const byte *ptop)
1495
1501
}
1496
1502
}
1497
1503
}
1504
+ // arguments must be able to be compiled as standard expressions
1505
+ if (pt_is_any_rule (p_start )) {
1506
+ int k = pt_rule_extract_rule_id (p_start );
1507
+ if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument ) {
1508
+ goto optimise_fail ;
1509
+ }
1510
+ }
1511
+ if (pt_is_any_rule (p_end )) {
1512
+ int k = pt_rule_extract_rule_id (p_end );
1513
+ if (k == PN_arglist_star || k == PN_arglist_dbl_star || k == PN_argument ) {
1514
+ goto optimise_fail ;
1515
+ }
1516
+ }
1498
1517
// can optimise
1499
1518
const byte * p_body = p_it_top ;
1500
1519
const byte * p_else = pt_next (p_body );
@@ -2221,7 +2240,8 @@ STATIC void compile_atom_paren(compiler_t *comp, const byte *p, const byte *ptop
2221
2240
if (pt_is_null_with_top (p , ptop )) {
2222
2241
// an empty tuple
2223
2242
c_tuple (comp , NULL , NULL , NULL );
2224
- } else if (pt_is_rule (p , PN_testlist_comp )) {
2243
+ } else {
2244
+ assert (pt_is_rule (p , PN_testlist_comp ));
2225
2245
p = pt_rule_first (p );
2226
2246
const byte * p1 = pt_next (p );
2227
2247
if (pt_is_rule (p1 , PN_testlist_comp_3b ) || pt_is_rule (p1 , PN_testlist_comp_3c )) {
@@ -2234,9 +2254,6 @@ STATIC void compile_atom_paren(compiler_t *comp, const byte *p, const byte *ptop
2234
2254
// tuple with 2 items
2235
2255
c_tuple (comp , NULL , p , ptop );
2236
2256
}
2237
- } else {
2238
- // parenthesis around a single item, is just that item
2239
- compile_node (comp , p );
2240
2257
}
2241
2258
}
2242
2259
@@ -2499,7 +2516,7 @@ STATIC const byte *compile_node(compiler_t *comp, const byte *p) {
2499
2516
EMIT_ARG (load_const_obj , mp_const_none );
2500
2517
} else {
2501
2518
qstr qst = p [1 ] | (p [2 ] << 8 );
2502
- mp_uint_t len ;
2519
+ size_t len ;
2503
2520
const byte * data = qstr_data (qst , & len );
2504
2521
EMIT_ARG (load_const_obj , mp_obj_new_bytes (data , len ));
2505
2522
}
@@ -2510,13 +2527,13 @@ STATIC const byte *compile_node(compiler_t *comp, const byte *p) {
2510
2527
compile_load_id (comp , qst );
2511
2528
return p ;
2512
2529
} else if (* p == MP_PT_CONST_OBJECT ) {
2513
- mp_uint_t idx ;
2530
+ size_t idx ;
2514
2531
p = pt_extract_const_obj (p , & idx );
2515
2532
EMIT_ARG (load_const_obj , (mp_obj_t )comp -> co_data [idx ]);
2516
2533
return p ;
2517
2534
} else {
2518
2535
assert (* p >= MP_PT_RULE_BASE );
2519
- mp_uint_t rule_id , src_line ;
2536
+ size_t rule_id , src_line ;
2520
2537
const byte * ptop ;
2521
2538
p = pt_rule_extract (p , & rule_id , & src_line , & ptop );
2522
2539
EMIT_ARG (set_source_line , src_line );
@@ -2542,7 +2559,12 @@ STATIC const byte *compile_node(compiler_t *comp, const byte *p) {
2542
2559
2543
2560
STATIC void compile_scope_func_lambda_param (compiler_t * comp , const byte * p , pn_kind_t pn_name , pn_kind_t pn_star , pn_kind_t pn_dbl_star ) {
2544
2561
(void )pn_dbl_star ;
2545
- // TODO verify that *k and **k are last etc
2562
+ // check that **kw is last
2563
+ if ((comp -> scope_cur -> scope_flags & MP_SCOPE_FLAG_VARKEYWORDS ) != 0 ) {
2564
+ compile_syntax_error (comp , p , "invalid syntax" );
2565
+ return ;
2566
+ }
2567
+
2546
2568
qstr param_name = MP_QSTR_NULL ;
2547
2569
uint param_flag = ID_FLAG_IS_PARAM ;
2548
2570
if (pt_is_any_id (p )) {
@@ -2565,6 +2587,11 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, const byte *p, pn_
2565
2587
comp -> scope_cur -> num_pos_args += 1 ;
2566
2588
}
2567
2589
} else if (pt_is_rule (p , pn_star )) {
2590
+ if (comp -> have_star ) {
2591
+ // more than one star
2592
+ compile_syntax_error (comp , p , "invalid syntax" );
2593
+ return ;
2594
+ }
2568
2595
comp -> have_star = true;
2569
2596
param_flag = ID_FLAG_IS_PARAM | ID_FLAG_IS_STAR_PARAM ;
2570
2597
if (pt_is_rule_empty (p )) {
@@ -2655,9 +2682,16 @@ STATIC void compile_scope_func_annotations(compiler_t *comp, const byte *p) {
2655
2682
}
2656
2683
#endif // MICROPY_EMIT_NATIVE
2657
2684
2658
- STATIC void compile_scope_comp_iter (compiler_t * comp , const byte * p_iter , const byte * p_inner_expr , int l_top , int for_depth ) {
2685
+ STATIC void compile_scope_comp_iter (compiler_t * comp , const byte * p_comp_for , const byte * p_comp_for_top , const byte * p_inner_expr , int for_depth ) {
2686
+ uint l_top = comp_next_label (comp );
2687
+ uint l_end = comp_next_label (comp );
2688
+ EMIT_ARG (label_assign , l_top );
2689
+ EMIT_ARG (for_iter , l_end );
2690
+ c_assign (comp , p_comp_for , ASSIGN_STORE );
2691
+ const byte * p_iter = pt_next (pt_next (p_comp_for ));
2692
+
2659
2693
tail_recursion :
2660
- if (p_iter == NULL ) {
2694
+ if (p_iter == p_comp_for_top ) {
2661
2695
// no more nested if/for; compile inner expression
2662
2696
compile_node (comp , p_inner_expr );
2663
2697
if (comp -> scope_cur -> kind == SCOPE_LIST_COMP ) {
@@ -2674,31 +2708,23 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, const byte *p_iter, const
2674
2708
}
2675
2709
} else if (pt_is_rule (p_iter , PN_comp_if )) {
2676
2710
// if condition
2677
- const byte * ptop ;
2678
- const byte * p0 = pt_rule_extract_top (p_iter , & ptop );
2711
+ const byte * p0 = pt_rule_extract_top (p_iter , & p_comp_for_top );
2679
2712
p_iter = c_if_cond (comp , p0 , false, l_top );
2680
- if (p_iter == ptop ) {
2681
- p_iter = NULL ;
2682
- }
2683
2713
goto tail_recursion ;
2684
2714
} else {
2685
2715
assert (pt_is_rule (p_iter , PN_comp_for )); // should be
2686
2716
// for loop
2687
2717
const byte * ptop ;
2688
2718
const byte * p0 = pt_rule_extract_top (p_iter , & ptop );
2689
2719
p0 = pt_next (p0 ); // skip scope index
2690
- const byte * p2 = compile_node (comp , pt_next (p0 ));
2691
- uint l_end2 = comp_next_label (comp );
2692
- uint l_top2 = comp_next_label (comp );
2720
+ compile_node (comp , pt_next (p0 ));
2693
2721
EMIT (get_iter );
2694
- EMIT_ARG (label_assign , l_top2 );
2695
- EMIT_ARG (for_iter , l_end2 );
2696
- c_assign (comp , p0 , ASSIGN_STORE );
2697
- compile_scope_comp_iter (comp , p2 == ptop ? NULL : p2 , p_inner_expr , l_top2 , for_depth + 1 );
2698
- EMIT_ARG (jump , l_top2 );
2699
- EMIT_ARG (label_assign , l_end2 );
2700
- EMIT (for_iter_end );
2722
+ compile_scope_comp_iter (comp , p0 , ptop , p_inner_expr , for_depth + 1 );
2701
2723
}
2724
+
2725
+ EMIT_ARG (jump , l_top );
2726
+ EMIT_ARG (label_assign , l_end );
2727
+ EMIT (for_iter_end );
2702
2728
}
2703
2729
2704
2730
#if 0
@@ -2865,20 +2891,8 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
2865
2891
#endif
2866
2892
}
2867
2893
2868
- uint l_end = comp_next_label (comp );
2869
- uint l_top = comp_next_label (comp );
2870
2894
compile_load_id (comp , qstr_arg );
2871
- EMIT_ARG (label_assign , l_top );
2872
- EMIT_ARG (for_iter , l_end );
2873
- c_assign (comp , p_comp_for , ASSIGN_STORE );
2874
- const byte * p_comp_for_p2 = pt_next (pt_next (p_comp_for ));
2875
- if (p_comp_for_p2 == p_comp_for_top ) {
2876
- p_comp_for_p2 = NULL ;
2877
- }
2878
- compile_scope_comp_iter (comp , p_comp_for_p2 , p , l_top , 0 );
2879
- EMIT_ARG (jump , l_top );
2880
- EMIT_ARG (label_assign , l_end );
2881
- EMIT (for_iter_end );
2895
+ compile_scope_comp_iter (comp , p_comp_for , p_comp_for_top , p , 0 );
2882
2896
2883
2897
if (scope -> kind == SCOPE_GEN_EXPR ) {
2884
2898
EMIT_ARG (load_const_tok , MP_TOKEN_KW_NONE );
@@ -3063,7 +3077,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind
3063
3077
}
3064
3078
3065
3079
if (comp -> pass > MP_PASS_SCOPE ) {
3066
- EMIT_INLINE_ASM (end_pass );
3080
+ EMIT_INLINE_ASM_ARG (end_pass , 0 );
3067
3081
}
3068
3082
3069
3083
if (comp -> compile_error != MP_OBJ_NULL ) {
@@ -3154,7 +3168,10 @@ STATIC void scope_compute_things(scope_t *scope) {
3154
3168
}
3155
3169
}
3156
3170
3157
- mp_obj_t mp_compile (mp_parse_tree_t * parse_tree , qstr source_file , uint emit_opt , bool is_repl ) {
3171
+ #if !MICROPY_PERSISTENT_CODE_SAVE
3172
+ STATIC
3173
+ #endif
3174
+ mp_raw_code_t * mp_compile_to_raw_code (mp_parse_tree_t * parse_tree , qstr source_file , uint emit_opt , bool is_repl ) {
3158
3175
// put compiler state on the stack, it's relatively small
3159
3176
compiler_t comp_state = {0 };
3160
3177
compiler_t * comp = & comp_state ;
@@ -3351,7 +3368,14 @@ mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, uint emit_opt
3351
3368
if (comp -> compile_error != MP_OBJ_NULL ) {
3352
3369
nlr_raise (comp -> compile_error );
3353
3370
} else {
3354
- // return function that executes the outer module
3355
- return mp_make_function_from_raw_code (outer_raw_code , MP_OBJ_NULL , MP_OBJ_NULL );
3371
+ return outer_raw_code ;
3356
3372
}
3357
3373
}
3374
+
3375
+ mp_obj_t mp_compile (mp_parse_tree_t * parse_tree , qstr source_file , uint emit_opt , bool is_repl ) {
3376
+ mp_raw_code_t * rc = mp_compile_to_raw_code (parse_tree , source_file , emit_opt , is_repl );
3377
+ // return function that executes the outer module
3378
+ return mp_make_function_from_raw_code (rc , MP_OBJ_NULL , MP_OBJ_NULL );
3379
+ }
3380
+
3381
+ #endif // MICROPY_ENABLE_COMPILER
0 commit comments