diff --git a/py/compile.c b/py/compile.c index 2d2f800d42..f0d3934fd7 100644 --- a/py/compile.c +++ b/py/compile.c @@ -27,6 +27,10 @@ typedef enum { #define EMIT(fun, arg...) (comp->emit_method_table->fun(comp->emit, ##arg)) +#define EMIT_OPT_NONE (0) +#define EMIT_OPT_BYTE_CODE (1) +#define EMIT_OPT_NATIVE_PYTHON (2) + typedef struct _compiler_t { qstr qstr___class__; qstr qstr___locals__; @@ -35,6 +39,8 @@ typedef struct _compiler_t { qstr qstr___qualname__; qstr qstr___doc__; qstr qstr_assertion_error; + qstr qstr_micropython; + qstr qstr_native; pass_kind_t pass; @@ -56,8 +62,8 @@ typedef struct _compiler_t { scope_t *scope_head; scope_t *scope_cur; - emit_t *emit; - const emit_method_table_t *emit_method_table; + emit_t *emit; // current emitter + const emit_method_table_t *emit_method_table; // current emit method table } compiler_t; py_parse_node_t fold_constants(py_parse_node_t pn) { @@ -165,8 +171,8 @@ static int comp_next_label(compiler_t *comp) { return comp->next_label++; } -static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn) { - scope_t *scope = scope_new(kind, pn, rt_get_new_unique_code_id()); +static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, py_parse_node_t pn, uint emit_options) { + scope_t *scope = scope_new(kind, pn, rt_get_new_unique_code_id(), emit_options); scope->parent = comp->scope_cur; scope->next = NULL; if (comp->scope_head == NULL) { @@ -661,10 +667,10 @@ void compile_funcdef_param(compiler_t *comp, py_parse_node_t pn) { // leaves function object on stack // returns function name -qstr compile_funcdef_helper(compiler_t *comp, py_parse_node_struct_t *pns) { +qstr compile_funcdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == PASS_1) { // create a new scope for this function - scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (py_parse_node_t)pns); + scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (py_parse_node_t)pns, emit_options); // store the function scope so the compiling function can use it at each pass pns->nodes[4] = (py_parse_node_t)s; } @@ -705,10 +711,10 @@ qstr compile_funcdef_helper(compiler_t *comp, py_parse_node_struct_t *pns) { // leaves class object on stack // returns class name -qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns) { +qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == PASS_1) { // create a new scope for this class - scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (py_parse_node_t)pns); + scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (py_parse_node_t)pns, emit_options); // store the class scope so the compiling function can use it at each pass pns->nodes[3] = (py_parse_node_t)s; } @@ -739,24 +745,65 @@ qstr compile_classdef_helper(compiler_t *comp, py_parse_node_struct_t *pns) { return cscope->simple_name; } +// returns true if it was a built-in decorator (even if the built-in had an error) +static bool compile_built_in_decorator(compiler_t *comp, int name_len, py_parse_node_t *name_nodes, uint *emit_options) { + if (PY_PARSE_NODE_LEAF_ARG(name_nodes[0]) != comp->qstr_micropython) { + return false; + } + + if (name_len != 2) { + printf("SyntaxError: invalid micropython decorator\n"); + return true; + } + + qstr attr = PY_PARSE_NODE_LEAF_ARG(name_nodes[1]); + if (attr == comp->qstr_native) { + *emit_options = EMIT_OPT_NATIVE_PYTHON; + } else { + printf("SyntaxError: invalid micropython decorator\n"); + } + + return true; +} + void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { // get the list of decorators py_parse_node_t *nodes; int n = list_get(&pns->nodes[0], PN_decorators, &nodes); - // load each decorator + // inherit emit options for this function/class definition + uint emit_options = comp->scope_cur->emit_options; + + // compile each decorator + int num_built_in_decorators = 0; for (int i = 0; i < n; i++) { assert(PY_PARSE_NODE_IS_STRUCT_KIND(nodes[i], PN_decorator)); // should be py_parse_node_struct_t *pns_decorator = (py_parse_node_struct_t*)nodes[i]; - py_parse_node_t *nodes2; - int n2 = list_get(&pns_decorator->nodes[0], PN_dotted_name, &nodes2); - compile_node(comp, nodes2[0]); - for (int i = 1; i < n2; i++) { - EMIT(load_attr, PY_PARSE_NODE_LEAF_ARG(nodes2[i])); - } - if (!PY_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) { - // first call the function with these arguments - compile_node(comp, pns_decorator->nodes[1]); + + // nodes[0] contains the decorator function, which is a dotted name + py_parse_node_t *name_nodes; + int name_len = list_get(&pns_decorator->nodes[0], PN_dotted_name, &name_nodes); + + // check for built-in decorators + if (compile_built_in_decorator(comp, name_len, name_nodes, &emit_options)) { + // this was a built-in + num_built_in_decorators += 1; + + } else { + // not a built-in, compile normally + + // compile the decorator function + compile_node(comp, name_nodes[0]); + for (int i = 1; i < name_len; i++) { + assert(PY_PARSE_NODE_IS_ID(name_nodes[i])); // should be + EMIT(load_attr, PY_PARSE_NODE_LEAF_ARG(name_nodes[i])); + } + + // nodes[1] contains arguments to the decorator function, if any + if (!PY_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) { + // call the decorator function with the arguments in nodes[1] + compile_node(comp, pns_decorator->nodes[1]); + } } } @@ -764,16 +811,16 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { py_parse_node_struct_t *pns_body = (py_parse_node_struct_t*)pns->nodes[1]; qstr body_name = 0; if (PY_PARSE_NODE_STRUCT_KIND(pns_body) == PN_funcdef) { - body_name = compile_funcdef_helper(comp, pns_body); + body_name = compile_funcdef_helper(comp, pns_body, emit_options); } else if (PY_PARSE_NODE_STRUCT_KIND(pns_body) == PN_classdef) { - body_name = compile_classdef_helper(comp, pns_body); + body_name = compile_classdef_helper(comp, pns_body, emit_options); } else { // shouldn't happen assert(0); } // call each decorator - for (int i = 0; i < n; i++) { + for (int i = 0; i < n - num_built_in_decorators; i++) { EMIT(call_function, 1, 0, false, false); } @@ -782,7 +829,7 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) { } void compile_funcdef(compiler_t *comp, py_parse_node_struct_t *pns) { - qstr fname = compile_funcdef_helper(comp, pns); + qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options); // store function object into function name EMIT(store_id, fname); } @@ -1514,7 +1561,7 @@ void compile_lambdef(compiler_t *comp, py_parse_node_struct_t *pns) { if (comp->pass == PASS_1) { // create a new scope for this lambda - scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (py_parse_node_t)pns); + scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (py_parse_node_t)pns, comp->scope_cur->emit_options); // store the lambda scope so the compiling function (this one) can use it at each pass pns->nodes[2] = (py_parse_node_t)s; } @@ -1780,7 +1827,7 @@ void compile_comprehension(compiler_t *comp, py_parse_node_struct_t *pns, scope_ if (comp->pass == PASS_1) { // create a new scope for this comprehension - scope_t *s = scope_new_and_link(comp, kind, (py_parse_node_t)pns); + scope_t *s = scope_new_and_link(comp, kind, (py_parse_node_t)pns, comp->scope_cur->emit_options); // store the comprehension scope so the compiling function (this one) can use it at each pass pns_comp_for->nodes[3] = (py_parse_node_t)s; } @@ -2048,7 +2095,7 @@ void compile_dictorsetmaker_item(compiler_t *comp, py_parse_node_struct_t *pns) } void compile_classdef(compiler_t *comp, py_parse_node_struct_t *pns) { - qstr cname = compile_classdef_helper(comp, pns); + qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options); // store class object into class name EMIT(store_id, cname); } @@ -2332,6 +2379,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { assert(PY_PARSE_NODE_STRUCT_KIND(pns) == PN_funcdef); // work out number of parameters, keywords and default parameters, and add them to the id_info array + // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) if (comp->pass == PASS_1) { comp->have_bare_star = false; 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) { assert(PY_PARSE_NODE_STRUCT_NUM_NODES(pns) == 3); // work out number of parameters, keywords and default parameters, and add them to the id_info array + // must be done before compiling the body so that arguments are numbered first (for LOAD_FAST etc) if (comp->pass == PASS_1) { comp->have_bare_star = false; 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) { assert(PY_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); py_parse_node_struct_t *pns_comp_for = (py_parse_node_struct_t*)pns->nodes[1]; - qstr qstr_arg = qstr_from_strn_copy(".0", 2); + qstr qstr_arg = qstr_from_str_static(".0"); if (comp->pass == PASS_1) { bool added; 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) { void py_compile(py_parse_node_t pn) { compiler_t *comp = m_new(compiler_t, 1); - comp->qstr___class__ = qstr_from_strn_copy("__class__", 9); - comp->qstr___locals__ = qstr_from_strn_copy("__locals__", 10); - comp->qstr___name__ = qstr_from_strn_copy("__name__", 8); - comp->qstr___module__ = qstr_from_strn_copy("__module__", 10); - comp->qstr___qualname__ = qstr_from_strn_copy("__qualname__", 12); - comp->qstr___doc__ = qstr_from_strn_copy("__doc__", 7); - comp->qstr_assertion_error = qstr_from_strn_copy("AssertionError", 14); + comp->qstr___class__ = qstr_from_str_static("__class__"); + comp->qstr___locals__ = qstr_from_str_static("__locals__"); + comp->qstr___name__ = qstr_from_str_static("__name__"); + comp->qstr___module__ = qstr_from_str_static("__module__"); + comp->qstr___qualname__ = qstr_from_str_static("__qualname__"); + comp->qstr___doc__ = qstr_from_str_static("__doc__"); + comp->qstr_assertion_error = qstr_from_str_static("AssertionError"); + comp->qstr_micropython = qstr_from_str_static("micropython"); + comp->qstr_native = qstr_from_str_static("native"); comp->max_num_labels = 0; comp->break_label = 0; @@ -2508,10 +2559,11 @@ void py_compile(py_parse_node_t pn) { comp->scope_head = NULL; comp->scope_cur = NULL; - emit_pass1_new(&comp->emit, &comp->emit_method_table, comp->qstr___class__); + comp->emit = emit_pass1_new(comp->qstr___class__); + comp->emit_method_table = &emit_pass1_method_table; pn = fold_constants(pn); - scope_new_and_link(comp, SCOPE_MODULE, pn); + scope_new_and_link(comp, SCOPE_MODULE, pn, EMIT_OPT_NONE); for (scope_t *s = comp->scope_head; s != NULL; s = s->next) { compile_scope(comp, s, PASS_1); @@ -2521,11 +2573,29 @@ void py_compile(py_parse_node_t pn) { compile_scope_compute_things(comp, s); } - emit_cpython_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels); - //emit_bc_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels); - //emit_x64_new(&comp->emit, &comp->emit_method_table, comp->max_num_labels); + emit_pass1_free(comp->emit); + + emit_t *emit_bc = NULL; + emit_t *emit_x64 = NULL; for (scope_t *s = comp->scope_head; s != NULL; s = s->next) { + switch (s->emit_options) { + case EMIT_OPT_NATIVE_PYTHON: + if (emit_x64 == NULL) { + emit_x64 = emit_x64_new(comp->max_num_labels); + } + comp->emit = emit_x64; + comp->emit_method_table = &emit_x64_method_table; + break; + + default: + if (emit_bc == NULL) { + emit_bc = emit_bc_new(comp->max_num_labels); + } + comp->emit = emit_bc; + comp->emit_method_table = &emit_bc_method_table; + break; + } compile_scope(comp, s, PASS_2); compile_scope(comp, s, PASS_3); } diff --git a/py/emit.h b/py/emit.h index c27b231db5..288141303b 100644 --- a/py/emit.h +++ b/py/emit.h @@ -116,8 +116,15 @@ void emit_common_load_id(emit_t *emit, const emit_method_table_t *emit_method_ta void emit_common_store_id(emit_t *emit, const emit_method_table_t *emit_method_table, scope_t *scope, qstr qstr); void emit_common_delete_id(emit_t *emit, const emit_method_table_t *emit_method_table, scope_t *scope, qstr qstr); -void emit_pass1_new(emit_t **emit, const emit_method_table_t **emit_method_table, qstr qstr___class__); -void emit_cpython_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels); -void emit_bc_new(emit_t **emit, const emit_method_table_t **emit_method_table, uint max_num_labels); -void emit_x64_new(emit_t **emit, const emit_method_table_t **emit_method_table, uint max_num_labels); -void emit_thumb_new(emit_t **emit, const emit_method_table_t **emit_method_table, uint max_num_labels); +extern const emit_method_table_t emit_pass1_method_table; +extern const emit_method_table_t emit_cpython_method_table; +extern const emit_method_table_t emit_bc_method_table; +extern const emit_method_table_t emit_x64_method_table; +extern const emit_method_table_t emit_thumb_method_table; + +emit_t *emit_pass1_new(qstr qstr___class__); +void emit_pass1_free(emit_t *emit); +emit_t *emit_cpython_new(uint max_num_labels); +emit_t *emit_bc_new(uint max_num_labels); +emit_t *emit_x64_new(uint max_num_labels); +emit_t *emit_thumb_new(uint max_num_labels); diff --git a/py/emitbc.c b/py/emitbc.c index 4cfd88ed4f..5c566ccb8c 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -32,8 +32,15 @@ struct _emit_t { byte dummy_data[8]; }; -// forward declaration -static const emit_method_table_t emit_bc_method_table; +emit_t *emit_bc_new(uint max_num_labels) { + emit_t *emit = m_new(emit_t, 1); + emit->max_num_labels = max_num_labels; + emit->label_offsets = m_new(uint, emit->max_num_labels); + emit->code_offset = 0; + emit->code_size = 0; + emit->code_base = NULL; + return emit; +} uint emit_bc_get_code_size(emit_t* emit) { return emit->code_size; @@ -672,7 +679,7 @@ static void emit_bc_yield_from(emit_t *emit) { emit_write_byte_1(emit, PYBC_YIELD_FROM); } -static const emit_method_table_t emit_bc_method_table = { +const emit_method_table_t emit_bc_method_table = { emit_bc_set_native_types, emit_bc_start_pass, emit_bc_end_pass, @@ -767,15 +774,3 @@ static const emit_method_table_t emit_bc_method_table = { emit_bc_yield_value, emit_bc_yield_from, }; - -void emit_bc_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) { - emit_t *emit = m_new(emit_t, 1); - emit->max_num_labels = max_num_labels; - emit->label_offsets = m_new(uint, emit->max_num_labels); - emit->code_offset = 0; - emit->code_size = 0; - emit->code_base = NULL; - - *emit_out = emit; - *emit_method_table_out = &emit_bc_method_table; -} diff --git a/py/emitcpy.c b/py/emitcpy.c index 0a3149fcd5..db5c118673 100644 --- a/py/emitcpy.c +++ b/py/emitcpy.c @@ -29,10 +29,16 @@ struct _emit_t { int *label_offsets; }; -// forward declarations -static const emit_method_table_t emit_cpy_method_table; +// forward declaration static void emit_cpy_load_const_verbatim_quoted_str(emit_t *emit, qstr qstr, bool bytes); +emit_t *emit_cpython_new(uint max_num_labels) { + emit_t *emit = m_new(emit_t, 1); + emit->max_num_labels = max_num_labels; + emit->label_offsets = m_new(int, max_num_labels); + return emit; +} + static void emit_cpy_set_native_types(emit_t *emit, bool do_native_types) { } @@ -68,15 +74,15 @@ static void emit_cpy_set_stack_size(emit_t *emit, int size) { } static void emit_cpy_load_id(emit_t *emit, qstr qstr) { - emit_common_load_id(emit, &emit_cpy_method_table, emit->scope, qstr); + emit_common_load_id(emit, &emit_cpython_method_table, emit->scope, qstr); } static void emit_cpy_store_id(emit_t *emit, qstr qstr) { - emit_common_store_id(emit, &emit_cpy_method_table, emit->scope, qstr); + emit_common_store_id(emit, &emit_cpython_method_table, emit->scope, qstr); } static void emit_cpy_delete_id(emit_t *emit, qstr qstr) { - emit_common_delete_id(emit, &emit_cpy_method_table, emit->scope, qstr); + emit_common_delete_id(emit, &emit_cpython_method_table, emit->scope, qstr); } static void emit_pre(emit_t *emit, int stack_size_delta, int byte_code_size) { @@ -260,6 +266,13 @@ static void emit_cpy_load_const_verbatim_end(emit_t *emit) { } } +static void emit_cpy_load_fast(emit_t *emit, qstr qstr, int local_num) { + emit_pre(emit, 1, 3); + if (emit->pass == PASS_3) { + printf("LOAD_FAST %d %s\n", local_num, qstr_str(qstr)); + } +} + static void emit_cpy_load_name(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); if (emit->pass == PASS_3) { @@ -274,13 +287,6 @@ static void emit_cpy_load_global(emit_t *emit, qstr qstr) { } } -static void emit_cpy_load_fast(emit_t *emit, qstr qstr, int local_num) { - emit_pre(emit, 1, 3); - if (emit->pass == PASS_3) { - printf("LOAD_FAST %s\n", qstr_str(qstr)); - } -} - static void emit_cpy_load_deref(emit_t *emit, qstr qstr) { emit_pre(emit, 1, 3); if (emit->pass == PASS_3) { @@ -313,6 +319,13 @@ static void emit_cpy_load_build_class(emit_t *emit) { } } +static void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) { + emit_pre(emit, -1, 3); + if (emit->pass == PASS_3) { + printf("STORE_FAST %d %s\n", local_num, qstr_str(qstr)); + } +} + static void emit_cpy_store_name(emit_t *emit, qstr qstr) { emit_pre(emit, -1, 3); if (emit->pass == PASS_3) { @@ -327,13 +340,6 @@ static void emit_cpy_store_global(emit_t *emit, qstr qstr) { } } -static void emit_cpy_store_fast(emit_t *emit, qstr qstr, int local_num) { - emit_pre(emit, -1, 3); - if (emit->pass == PASS_3) { - printf("STORE_FAST %s\n", qstr_str(qstr)); - } -} - static void emit_cpy_store_deref(emit_t *emit, qstr qstr) { emit_pre(emit, -1, 3); if (emit->pass == PASS_3) { @@ -362,6 +368,13 @@ static void emit_cpy_store_subscr(emit_t *emit) { } } +static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) { + emit_pre(emit, 0, 3); + if (emit->pass == PASS_3) { + printf("DELETE_FAST %d %s\n", local_num, qstr_str(qstr)); + } +} + static void emit_cpy_delete_name(emit_t *emit, qstr qstr) { emit_pre(emit, 0, 3); if (emit->pass == PASS_3) { @@ -376,13 +389,6 @@ static void emit_cpy_delete_global(emit_t *emit, qstr qstr) { } } -static void emit_cpy_delete_fast(emit_t *emit, qstr qstr, int local_num) { - emit_pre(emit, 0, 3); - if (emit->pass == PASS_3) { - printf("DELETE_FAST %s\n", qstr_str(qstr)); - } -} - static void emit_cpy_delete_deref(emit_t *emit, qstr qstr) { emit_pre(emit, 0, 3); if (emit->pass == PASS_3) { @@ -825,7 +831,7 @@ static void emit_cpy_yield_from(emit_t *emit) { } } -static const emit_method_table_t emit_cpy_method_table = { +const emit_method_table_t emit_cpython_method_table = { emit_cpy_set_native_types, emit_cpy_start_pass, emit_cpy_end_pass, @@ -921,13 +927,4 @@ static const emit_method_table_t emit_cpy_method_table = { emit_cpy_yield_from, }; -void emit_cpython_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) { - emit_t *emit = m_new(emit_t, 1); - emit->max_num_labels = max_num_labels; - emit->label_offsets = m_new(int, max_num_labels); - - *emit_out = emit; - *emit_method_table_out = &emit_cpy_method_table; -} - #endif // EMIT_ENABLE_CPY diff --git a/py/emitx64.c b/py/emitx64.c index cde98fe457..8ed617f2b0 100644 --- a/py/emitx64.c +++ b/py/emitx64.c @@ -53,8 +53,12 @@ struct _emit_t { bool do_native_types; }; -// forward declaration -static const emit_method_table_t emit_x64_method_table; +emit_t *emit_x64_new(uint max_num_labels) { + emit_t *emit = m_new(emit_t, 1); + emit->as = asm_x64_new(max_num_labels); + emit->do_native_types = false; + return emit; +} static void emit_x64_set_native_types(emit_t *emit, bool do_native_types) { emit->do_native_types = do_native_types; @@ -678,7 +682,7 @@ static void emit_x64_yield_from(emit_t *emit) { assert(0); } -static const emit_method_table_t emit_x64_method_table = { +const emit_method_table_t emit_x64_method_table = { emit_x64_set_native_types, emit_x64_start_pass, emit_x64_end_pass, @@ -774,13 +778,4 @@ static const emit_method_table_t emit_x64_method_table = { emit_x64_yield_from, }; -void emit_x64_new(emit_t **emit_out, const emit_method_table_t **emit_method_table_out, uint max_num_labels) { - emit_t *emit = m_new(emit_t, 1); - emit->as = asm_x64_new(max_num_labels); - emit->do_native_types = false; - - *emit_out = emit; - *emit_method_table_out = &emit_x64_method_table; -} - #endif // EMIT_ENABLE_X64 diff --git a/py/main.c b/py/main.c index d765bc24f1..7b17c38a85 100644 --- a/py/main.c +++ b/py/main.c @@ -40,7 +40,7 @@ int main(int argc, char **argv) { py_lexer_free(lex); - if (0) { + if (1) { // execute it py_obj_t module_fun = rt_make_function_from_id(1); if (module_fun != py_const_none) { diff --git a/py/runtime.c b/py/runtime.c index 21f3c8c50a..26ecdc14fe 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -9,8 +9,8 @@ #include "runtime.h" #include "vm.h" -#define DEBUG_printf(args...) (void)0 -//#define DEBUG_printf(args...) printf(args) +//#define DEBUG_printf(args...) (void)0 +#define DEBUG_printf(args...) printf(args) #define DEBUG_OP_printf(args...) (void)0 //#define DEBUG_OP_printf(args...) printf(args) @@ -423,6 +423,12 @@ const char *py_obj_get_type_str(py_obj_t o_in) { case O_FLOAT: return "float"; #endif + case O_FUN_0: + case O_FUN_1: + case O_FUN_2: + case O_FUN_N: + case O_FUN_BC: + return "function"; case O_LIST: return "list"; case O_SET: @@ -714,12 +720,12 @@ py_obj_t rt_call_function_0(py_obj_t fun) { py_obj_t rt_call_function_1(py_obj_t fun, py_obj_t arg) { if (IS_O(fun, O_FUN_1)) { py_obj_base_t *o = fun; - DEBUG_OP_printf("calling native %p...\n", o->u_fun.fun); + DEBUG_OP_printf("calling native %p with 1 arg\n", o->u_fun.fun); return ((py_fun_1_t)o->u_fun.fun)(arg); } else if (IS_O(fun, O_FUN_BC)) { py_obj_base_t *o = fun; assert(o->u_fun_bc.n_args == 1); - DEBUG_OP_printf("calling byte code %p...\n", o->u_fun_bc.code); + DEBUG_OP_printf("calling byte code %p with 1 arg\n", o->u_fun_bc.code); return py_execute_byte_code(o->u_fun_bc.code, o->u_fun_bc.len, &arg, 1); } else if (IS_O(fun, O_BOUND_METH)) { py_obj_base_t *o = fun; diff --git a/py/scope.c b/py/scope.c index 57a7e6875d..640d4f742b 100644 --- a/py/scope.c +++ b/py/scope.c @@ -8,7 +8,7 @@ #include "parse.h" #include "scope.h" -scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id) { +scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, uint emit_options) { scope_t *scope = m_new(scope_t, 1); scope->kind = kind; scope->parent = NULL; @@ -53,6 +53,7 @@ scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id) { */ scope->num_locals = 0; scope->unique_code_id = unique_code_id; + scope->emit_options = emit_options; return scope; } @@ -80,17 +81,23 @@ id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added) { */ } - { - // sort insert into id_info array, so we are equivalent to CPython (no other reason to do it) - scope->id_info_len += 1; - for (int i = scope->id_info_len - 1;; i--) { - if (i == 0 || strcmp(qstr_str(scope->id_info[i - 1].qstr), qstr_str(qstr)) < 0) { - id_info = &scope->id_info[i]; - break; - } else { - scope->id_info[i] = scope->id_info[i - 1]; + if (0) { + // sort insert into id_info array, so we are equivalent to CPython (no other reason to do it) + // actually, seems that this is not what CPython does... + scope->id_info_len += 1; + for (int i = scope->id_info_len - 1;; i--) { + if (i == 0 || strcmp(qstr_str(scope->id_info[i - 1].qstr), qstr_str(qstr)) < 0) { + id_info = &scope->id_info[i]; + break; + } else { + scope->id_info[i] = scope->id_info[i - 1]; + } } - } + } else { + // just add new id to end of array of all ids; this seems to match CPython + // important thing is that function arguments are first, but that is + // handled by the compiler because it adds arguments before compiling the body + id_info = &scope->id_info[scope->id_info_len++]; } id_info->param = false; diff --git a/py/scope.h b/py/scope.h index f9ad748d97..1b626c8ec1 100644 --- a/py/scope.h +++ b/py/scope.h @@ -47,9 +47,10 @@ typedef struct _scope_t { int num_locals; int stack_size; uint unique_code_id; + uint emit_options; } scope_t; -scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id); +scope_t *scope_new(scope_kind_t kind, py_parse_node_t pn, uint unique_code_id, uint emit_options); id_info_t *scope_find_or_add_id(scope_t *scope, qstr qstr, bool *added); id_info_t *scope_find(scope_t *scope, qstr qstr); id_info_t *scope_find_global(scope_t *scope, qstr qstr);