@@ -27,6 +27,10 @@ typedef enum {
2727
2828#define EMIT (fun , arg ...) (comp->emit_method_table->fun(comp->emit, ##arg))
2929
30+ #define EMIT_OPT_NONE (0)
31+ #define EMIT_OPT_BYTE_CODE (1)
32+ #define EMIT_OPT_NATIVE_PYTHON (2)
33+
3034typedef struct _compiler_t {
3135 qstr qstr___class__ ;
3236 qstr qstr___locals__ ;
@@ -35,6 +39,8 @@ typedef struct _compiler_t {
3539 qstr qstr___qualname__ ;
3640 qstr qstr___doc__ ;
3741 qstr qstr_assertion_error ;
42+ qstr qstr_micropython ;
43+ qstr qstr_native ;
3844
3945 pass_kind_t pass ;
4046
@@ -56,8 +62,8 @@ typedef struct _compiler_t {
5662 scope_t * scope_head ;
5763 scope_t * scope_cur ;
5864
59- emit_t * emit ;
60- const emit_method_table_t * emit_method_table ;
65+ emit_t * emit ; // current emitter
66+ const emit_method_table_t * emit_method_table ; // current emit method table
6167} compiler_t ;
6268
6369py_parse_node_t fold_constants (py_parse_node_t pn ) {
@@ -165,8 +171,8 @@ static int comp_next_label(compiler_t *comp) {
165171 return comp -> next_label ++ ;
166172}
167173
168- static scope_t * scope_new_and_link (compiler_t * comp , scope_kind_t kind , py_parse_node_t pn ) {
169- scope_t * scope = scope_new (kind , pn , rt_get_new_unique_code_id ());
174+ static scope_t * scope_new_and_link (compiler_t * comp , scope_kind_t kind , py_parse_node_t pn , uint emit_options ) {
175+ scope_t * scope = scope_new (kind , pn , rt_get_new_unique_code_id (), emit_options );
170176 scope -> parent = comp -> scope_cur ;
171177 scope -> next = NULL ;
172178 if (comp -> scope_head == NULL ) {
@@ -661,10 +667,10 @@ void compile_funcdef_param(compiler_t *comp, py_parse_node_t pn) {
661667
662668// leaves function object on stack
663669// returns function name
664- qstr compile_funcdef_helper (compiler_t * comp , py_parse_node_struct_t * pns ) {
670+ qstr compile_funcdef_helper (compiler_t * comp , py_parse_node_struct_t * pns , uint emit_options ) {
665671 if (comp -> pass == PASS_1 ) {
666672 // create a new scope for this function
667- scope_t * s = scope_new_and_link (comp , SCOPE_FUNCTION , (py_parse_node_t )pns );
673+ scope_t * s = scope_new_and_link (comp , SCOPE_FUNCTION , (py_parse_node_t )pns , emit_options );
668674 // store the function scope so the compiling function can use it at each pass
669675 pns -> nodes [4 ] = (py_parse_node_t )s ;
670676 }
@@ -705,10 +711,10 @@ qstr compile_funcdef_helper(compiler_t *comp, py_parse_node_struct_t *pns) {
705711
706712// leaves class object on stack
707713// returns class name
708- qstr compile_classdef_helper (compiler_t * comp , py_parse_node_struct_t * pns ) {
714+ qstr compile_classdef_helper (compiler_t * comp , py_parse_node_struct_t * pns , uint emit_options ) {
709715 if (comp -> pass == PASS_1 ) {
710716 // create a new scope for this class
711- scope_t * s = scope_new_and_link (comp , SCOPE_CLASS , (py_parse_node_t )pns );
717+ scope_t * s = scope_new_and_link (comp , SCOPE_CLASS , (py_parse_node_t )pns , emit_options );
712718 // store the class scope so the compiling function can use it at each pass
713719 pns -> nodes [3 ] = (py_parse_node_t )s ;
714720 }
@@ -739,41 +745,82 @@ qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns) {
739745 return cscope -> simple_name ;
740746}
741747
748+ // returns true if it was a built-in decorator (even if the built-in had an error)
749+ static bool compile_built_in_decorator (compiler_t * comp , int name_len , py_parse_node_t * name_nodes , uint * emit_options ) {
750+ if (PY_PARSE_NODE_LEAF_ARG (name_nodes [0 ]) != comp -> qstr_micropython ) {
751+ return false;
752+ }
753+
754+ if (name_len != 2 ) {
755+ printf ("SyntaxError: invalid micropython decorator\n" );
756+ return true;
757+ }
758+
759+ qstr attr = PY_PARSE_NODE_LEAF_ARG (name_nodes [1 ]);
760+ if (attr == comp -> qstr_native ) {
761+ * emit_options = EMIT_OPT_NATIVE_PYTHON ;
762+ } else {
763+ printf ("SyntaxError: invalid micropython decorator\n" );
764+ }
765+
766+ return true;
767+ }
768+
742769void compile_decorated (compiler_t * comp , py_parse_node_struct_t * pns ) {
743770 // get the list of decorators
744771 py_parse_node_t * nodes ;
745772 int n = list_get (& pns -> nodes [0 ], PN_decorators , & nodes );
746773
747- // load each decorator
774+ // inherit emit options for this function/class definition
775+ uint emit_options = comp -> scope_cur -> emit_options ;
776+
777+ // compile each decorator
778+ int num_built_in_decorators = 0 ;
748779 for (int i = 0 ; i < n ; i ++ ) {
749780 assert (PY_PARSE_NODE_IS_STRUCT_KIND (nodes [i ], PN_decorator )); // should be
750781 py_parse_node_struct_t * pns_decorator = (py_parse_node_struct_t * )nodes [i ];
751- py_parse_node_t * nodes2 ;
752- int n2 = list_get (& pns_decorator -> nodes [0 ], PN_dotted_name , & nodes2 );
753- compile_node (comp , nodes2 [0 ]);
754- for (int i = 1 ; i < n2 ; i ++ ) {
755- EMIT (load_attr , PY_PARSE_NODE_LEAF_ARG (nodes2 [i ]));
756- }
757- if (!PY_PARSE_NODE_IS_NULL (pns_decorator -> nodes [1 ])) {
758- // first call the function with these arguments
759- compile_node (comp , pns_decorator -> nodes [1 ]);
782+
783+ // nodes[0] contains the decorator function, which is a dotted name
784+ py_parse_node_t * name_nodes ;
785+ int name_len = list_get (& pns_decorator -> nodes [0 ], PN_dotted_name , & name_nodes );
786+
787+ // check for built-in decorators
788+ if (compile_built_in_decorator (comp , name_len , name_nodes , & emit_options )) {
789+ // this was a built-in
790+ num_built_in_decorators += 1 ;
791+
792+ } else {
793+ // not a built-in, compile normally
794+
795+ // compile the decorator function
796+ compile_node (comp , name_nodes [0 ]);
797+ for (int i = 1 ; i < name_len ; i ++ ) {
798+ assert (PY_PARSE_NODE_IS_ID (name_nodes [i ])); // should be
799+ EMIT (load_attr , PY_PARSE_NODE_LEAF_ARG (name_nodes [i ]));
800+ }
801+
802+ // nodes[1] contains arguments to the decorator function, if any
803+ if (!PY_PARSE_NODE_IS_NULL (pns_decorator -> nodes [1 ])) {
804+ // call the decorator function with the arguments in nodes[1]
805+ compile_node (comp , pns_decorator -> nodes [1 ]);
806+ }
760807 }
761808 }
762809
763810 // compile the body (funcdef or classdef) and get its name
764811 py_parse_node_struct_t * pns_body = (py_parse_node_struct_t * )pns -> nodes [1 ];
765812 qstr body_name = 0 ;
766813 if (PY_PARSE_NODE_STRUCT_KIND (pns_body ) == PN_funcdef ) {
767- body_name = compile_funcdef_helper (comp , pns_body );
814+ body_name = compile_funcdef_helper (comp , pns_body , emit_options );
768815 } else if (PY_PARSE_NODE_STRUCT_KIND (pns_body ) == PN_classdef ) {
769- body_name = compile_classdef_helper (comp , pns_body );
816+ body_name = compile_classdef_helper (comp , pns_body , emit_options );
770817 } else {
771818 // shouldn't happen
772819 assert (0 );
773820 }
774821
775822 // call each decorator
776- for (int i = 0 ; i < n ; i ++ ) {
823+ for (int i = 0 ; i < n - num_built_in_decorators ; i ++ ) {
777824 EMIT (call_function , 1 , 0 , false, false);
778825 }
779826
@@ -782,7 +829,7 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) {
782829}
783830
784831void compile_funcdef (compiler_t * comp , py_parse_node_struct_t * pns ) {
785- qstr fname = compile_funcdef_helper (comp , pns );
832+ qstr fname = compile_funcdef_helper (comp , pns , comp -> scope_cur -> emit_options );
786833 // store function object into function name
787834 EMIT (store_id , fname );
788835}
@@ -1514,7 +1561,7 @@ void compile_lambdef(compiler_t *comp, py_parse_node_struct_t *pns) {
15141561
15151562 if (comp -> pass == PASS_1 ) {
15161563 // create a new scope for this lambda
1517- scope_t * s = scope_new_and_link (comp , SCOPE_LAMBDA , (py_parse_node_t )pns );
1564+ scope_t * s = scope_new_and_link (comp , SCOPE_LAMBDA , (py_parse_node_t )pns , comp -> scope_cur -> emit_options );
15181565 // store the lambda scope so the compiling function (this one) can use it at each pass
15191566 pns -> nodes [2 ] = (py_parse_node_t )s ;
15201567 }
@@ -1780,7 +1827,7 @@ void compile_comprehension(compiler_t *comp, py_parse_node_struct_t *pns, scope_
17801827
17811828 if (comp -> pass == PASS_1 ) {
17821829 // create a new scope for this comprehension
1783- scope_t * s = scope_new_and_link (comp , kind , (py_parse_node_t )pns );
1830+ scope_t * s = scope_new_and_link (comp , kind , (py_parse_node_t )pns , comp -> scope_cur -> emit_options );
17841831 // store the comprehension scope so the compiling function (this one) can use it at each pass
17851832 pns_comp_for -> nodes [3 ] = (py_parse_node_t )s ;
17861833 }
@@ -2048,7 +2095,7 @@ void compile_dictorsetmaker_item(compiler_t *comp, py_parse_node_struct_t *pns)
20482095}
20492096
20502097void compile_classdef (compiler_t * comp , py_parse_node_struct_t * pns ) {
2051- qstr cname = compile_classdef_helper (comp , pns );
2098+ qstr cname = compile_classdef_helper (comp , pns , comp -> scope_cur -> emit_options );
20522099 // store class object into class name
20532100 EMIT (store_id , cname );
20542101}
@@ -2332,6 +2379,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
23322379 assert (PY_PARSE_NODE_STRUCT_KIND (pns ) == PN_funcdef );
23332380
23342381 // work out number of parameters, keywords and default parameters, and add them to the id_info array
2382+ // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
23352383 if (comp -> pass == PASS_1 ) {
23362384 comp -> have_bare_star = false;
23372385 apply_to_single_or_list (comp , pns -> nodes [1 ], PN_typedargslist , compile_scope_func_param );
@@ -2351,6 +2399,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
23512399 assert (PY_PARSE_NODE_STRUCT_NUM_NODES (pns ) == 3 );
23522400
23532401 // work out number of parameters, keywords and default parameters, and add them to the id_info array
2402+ // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc)
23542403 if (comp -> pass == PASS_1 ) {
23552404 comp -> have_bare_star = false;
23562405 apply_to_single_or_list (comp , pns -> nodes [0 ], PN_varargslist , compile_scope_lambda_param );
@@ -2367,7 +2416,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
23672416 assert (PY_PARSE_NODE_IS_STRUCT_KIND (pns -> nodes [1 ], PN_comp_for ));
23682417 py_parse_node_struct_t * pns_comp_for = (py_parse_node_struct_t * )pns -> nodes [1 ];
23692418
2370- qstr qstr_arg = qstr_from_strn_copy (".0" , 2 );
2419+ qstr qstr_arg = qstr_from_str_static (".0" );
23712420 if (comp -> pass == PASS_1 ) {
23722421 bool added ;
23732422 id_info_t * id_info = scope_find_or_add_id (comp -> scope_cur , qstr_arg , & added );
@@ -2493,13 +2542,15 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
24932542void py_compile (py_parse_node_t pn ) {
24942543 compiler_t * comp = m_new (compiler_t , 1 );
24952544
2496- comp -> qstr___class__ = qstr_from_strn_copy ("__class__" , 9 );
2497- comp -> qstr___locals__ = qstr_from_strn_copy ("__locals__" , 10 );
2498- comp -> qstr___name__ = qstr_from_strn_copy ("__name__" , 8 );
2499- comp -> qstr___module__ = qstr_from_strn_copy ("__module__" , 10 );
2500- comp -> qstr___qualname__ = qstr_from_strn_copy ("__qualname__" , 12 );
2501- comp -> qstr___doc__ = qstr_from_strn_copy ("__doc__" , 7 );
2502- comp -> qstr_assertion_error = qstr_from_strn_copy ("AssertionError" , 14 );
2545+ comp -> qstr___class__ = qstr_from_str_static ("__class__" );
2546+ comp -> qstr___locals__ = qstr_from_str_static ("__locals__" );
2547+ comp -> qstr___name__ = qstr_from_str_static ("__name__" );
2548+ comp -> qstr___module__ = qstr_from_str_static ("__module__" );
2549+ comp -> qstr___qualname__ = qstr_from_str_static ("__qualname__" );
2550+ comp -> qstr___doc__ = qstr_from_str_static ("__doc__" );
2551+ comp -> qstr_assertion_error = qstr_from_str_static ("AssertionError" );
2552+ comp -> qstr_micropython = qstr_from_str_static ("micropython" );
2553+ comp -> qstr_native = qstr_from_str_static ("native" );
25032554
25042555 comp -> max_num_labels = 0 ;
25052556 comp -> break_label = 0 ;
@@ -2508,10 +2559,11 @@ void py_compile(py_parse_node_t pn) {
25082559 comp -> scope_head = NULL ;
25092560 comp -> scope_cur = NULL ;
25102561
2511- emit_pass1_new (& comp -> emit , & comp -> emit_method_table , comp -> qstr___class__ );
2562+ comp -> emit = emit_pass1_new (comp -> qstr___class__ );
2563+ comp -> emit_method_table = & emit_pass1_method_table ;
25122564
25132565 pn = fold_constants (pn );
2514- scope_new_and_link (comp , SCOPE_MODULE , pn );
2566+ scope_new_and_link (comp , SCOPE_MODULE , pn , EMIT_OPT_NONE );
25152567
25162568 for (scope_t * s = comp -> scope_head ; s != NULL ; s = s -> next ) {
25172569 compile_scope (comp , s , PASS_1 );
@@ -2521,11 +2573,29 @@ void py_compile(py_parse_node_t pn) {
25212573 compile_scope_compute_things (comp , s );
25222574 }
25232575
2524- emit_cpython_new (& comp -> emit , & comp -> emit_method_table , comp -> max_num_labels );
2525- //emit_bc_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels);
2526- //emit_x64_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels);
2576+ emit_pass1_free (comp -> emit );
2577+
2578+ emit_t * emit_bc = NULL ;
2579+ emit_t * emit_x64 = NULL ;
25272580
25282581 for (scope_t * s = comp -> scope_head ; s != NULL ; s = s -> next ) {
2582+ switch (s -> emit_options ) {
2583+ case EMIT_OPT_NATIVE_PYTHON :
2584+ if (emit_x64 == NULL ) {
2585+ emit_x64 = emit_x64_new (comp -> max_num_labels );
2586+ }
2587+ comp -> emit = emit_x64 ;
2588+ comp -> emit_method_table = & emit_x64_method_table ;
2589+ break ;
2590+
2591+ default :
2592+ if (emit_bc == NULL ) {
2593+ emit_bc = emit_bc_new (comp -> max_num_labels );
2594+ }
2595+ comp -> emit = emit_bc ;
2596+ comp -> emit_method_table = & emit_bc_method_table ;
2597+ break ;
2598+ }
25292599 compile_scope (comp , s , PASS_2 );
25302600 compile_scope (comp , s , PASS_3 );
25312601 }
0 commit comments