Implement built-in decorators to select emit type.
This commit is contained in:
parent
4b03e77d4a
commit
6cdd3af601
146
py/compile.c
146
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);
|
||||
}
|
||||
|
17
py/emit.h
17
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);
|
||||
|
25
py/emitbc.c
25
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;
|
||||
}
|
||||
|
69
py/emitcpy.c
69
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
|
||||
|
19
py/emitx64.c
19
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
|
||||
|
@ -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) {
|
||||
|
14
py/runtime.c
14
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;
|
||||
|
29
py/scope.c
29
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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user