Commit 08335004 authored by Damien George's avatar Damien George
Browse files

Add source file name and line number to error messages.

Byte code has a map from byte-code offset to source-code line number,
used to give better error messages.
parent aefe7988
mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_args, uint n_state);
bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out);
bool mp_execute_byte_code_2(const byte *code_info, const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **sp_in_out);
......@@ -28,6 +28,7 @@ static mp_obj_t mp_builtin_eval(mp_obj_t o_in) {
qstr parse_exc_id;
const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_EVAL_INPUT, &parse_exc_id, &parse_exc_msg);
qstr source_name = mp_lexer_source_name(lex);
mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
......@@ -36,7 +37,7 @@ static mp_obj_t mp_builtin_eval(mp_obj_t o_in) {
}
// compile the string
mp_obj_t module_fun = mp_compile(pn, false);
mp_obj_t module_fun = mp_compile(pn, source_name, false);
if (module_fun == mp_const_none) {
// TODO handle compile error correctly
......
......@@ -51,6 +51,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
qstr parse_exc_id;
const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg);
qstr source_name = mp_lexer_source_name(lex);
mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
......@@ -61,7 +62,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
}
// compile the imported script
mp_obj_t module_fun = mp_compile(pn, false);
mp_obj_t module_fun = mp_compile(pn, source_name, false);
if (module_fun == mp_const_none) {
// TODO handle compile error correctly
......
......@@ -2505,6 +2505,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
}
} else {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
EMIT(set_line_number, pns->source_line);
compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
if (f == NULL) {
printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns));
......@@ -3024,7 +3025,7 @@ void compile_scope_compute_things(compiler_t *comp, scope_t *scope) {
}
}
mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl) {
compiler_t *comp = m_new(compiler_t, 1);
comp->is_repl = is_repl;
......@@ -3131,7 +3132,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
default:
if (emit_bc == NULL) {
emit_bc = emit_bc_new(max_num_labels);
emit_bc = emit_bc_new(source_file, max_num_labels);
}
comp->emit = emit_bc;
comp->emit_method_table = &emit_bc_method_table;
......
mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl);
mp_obj_t mp_compile(mp_parse_node_t pn, qstr source_file, bool is_repl);
......@@ -23,6 +23,7 @@ typedef struct _emit_method_table_t {
bool (*last_emit_was_return_value)(emit_t *emit);
int (*get_stack_size)(emit_t *emit);
void (*set_stack_size)(emit_t *emit, int size);
void (*set_line_number)(emit_t *emit, int line);
void (*load_id)(emit_t *emit, qstr qstr);
void (*store_id)(emit_t *emit, qstr qstr);
......@@ -119,7 +120,7 @@ extern const emit_method_table_t emit_native_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_bc_new(qstr source_file, uint max_num_labels);
emit_t *emit_native_x64_new(uint max_num_labels);
emit_t *emit_native_thumb_new(uint max_num_labels);
......
......@@ -21,79 +21,104 @@ struct _emit_t {
scope_t *scope;
qstr source_file;
uint last_source_line_offset;
uint last_source_line;
uint max_num_labels;
uint *label_offsets;
uint code_offset;
uint code_size;
byte *code_base;
uint code_info_offset;
uint code_info_size;
uint byte_code_offset;
uint byte_code_size;
byte *code_base; // stores both byte code and code info
byte dummy_data[8];
};
emit_t *emit_bc_new(uint max_num_labels) {
emit_t *emit = m_new(emit_t, 1);
emit_t *emit_bc_new(qstr source_file, uint max_num_labels) {
emit_t *emit = m_new0(emit_t, 1);
emit->source_file = source_file;
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;
// all functions must go through this one to emit code info
static byte* emit_get_cur_to_write_code_info(emit_t* emit, int num_bytes_to_write) {
//printf("emit %d\n", num_bytes_to_write);
if (emit->pass < PASS_3) {
emit->code_info_offset += num_bytes_to_write;
return emit->dummy_data;
} else {
assert(emit->code_info_offset + num_bytes_to_write <= emit->code_info_size);
byte *c = emit->code_base + emit->code_info_offset;
emit->code_info_offset += num_bytes_to_write;
return c;
}
}
void* emit_bc_get_code(emit_t* emit) {
return emit->code_base;
static void emit_write_code_info_qstr(emit_t* emit, qstr qstr) {
byte* c = emit_get_cur_to_write_code_info(emit, 4);
// TODO variable length encoding for qstr
c[0] = qstr & 0xff;
c[1] = (qstr >> 8) & 0xff;
c[2] = (qstr >> 16) & 0xff;
c[3] = (qstr >> 24) & 0xff;
}
// all functions must go through this one to emit bytes
static byte* emit_get_cur_to_write_bytes(emit_t* emit, int num_bytes_to_write) {
static void emit_write_code_info_byte_byte(emit_t* emit, byte b1, uint b2) {
byte* c = emit_get_cur_to_write_code_info(emit, 2);
c[0] = b1;
c[1] = b2;
}
// all functions must go through this one to emit byte code
static byte* emit_get_cur_to_write_byte_code(emit_t* emit, int num_bytes_to_write) {
//printf("emit %d\n", num_bytes_to_write);
if (emit->pass < PASS_3) {
emit->code_offset += num_bytes_to_write;
emit->byte_code_offset += num_bytes_to_write;
return emit->dummy_data;
} else {
assert(emit->code_offset + num_bytes_to_write <= emit->code_size);
byte *c = emit->code_base + emit->code_offset;
emit->code_offset += num_bytes_to_write;
assert(emit->byte_code_offset + num_bytes_to_write <= emit->byte_code_size);
byte *c = emit->code_base + emit->code_info_size + emit->byte_code_offset;
emit->byte_code_offset += num_bytes_to_write;
return c;
}
}
static void emit_write_byte_1(emit_t* emit, byte b1) {
byte* c = emit_get_cur_to_write_bytes(emit, 1);
static void emit_write_byte_code_byte(emit_t* emit, byte b1) {
byte* c = emit_get_cur_to_write_byte_code(emit, 1);
c[0] = b1;
}
static void emit_write_byte_1_byte(emit_t* emit, byte b1, uint b2) {
static void emit_write_byte_code_byte_byte(emit_t* emit, byte b1, uint b2) {
assert((b2 & (~0xff)) == 0);
byte* c = emit_get_cur_to_write_bytes(emit, 2);
byte* c = emit_get_cur_to_write_byte_code(emit, 2);
c[0] = b1;
c[1] = b2;
}
// integers (for small ints) are stored as 24 bits, in excess
static void emit_write_byte_1_int(emit_t* emit, byte b1, int num) {
static void emit_write_byte_code_byte_int(emit_t* emit, byte b1, int num) {
num += 0x800000;
assert(0 <= num && num <= 0xffffff);
byte* c = emit_get_cur_to_write_bytes(emit, 4);
byte* c = emit_get_cur_to_write_byte_code(emit, 4);
c[0] = b1;
c[1] = num;
c[2] = num >> 8;
c[3] = num >> 16;
}
static void emit_write_byte_1_uint(emit_t* emit, byte b1, uint num) {
static void emit_write_byte_code_byte_uint(emit_t* emit, byte b1, uint num) {
if (num <= 127) { // fits in 0x7f
// fit argument in single byte
byte* c = emit_get_cur_to_write_bytes(emit, 2);
byte* c = emit_get_cur_to_write_byte_code(emit, 2);
c[0] = b1;
c[1] = num;
} else if (num <= 16383) { // fits in 0x3fff
// fit argument in two bytes
byte* c = emit_get_cur_to_write_bytes(emit, 3);
byte* c = emit_get_cur_to_write_byte_code(emit, 3);
c[0] = b1;
c[1] = (num >> 8) | 0x80;
c[2] = num;
......@@ -103,36 +128,36 @@ static void emit_write_byte_1_uint(emit_t* emit, byte b1, uint num) {
}
}
static void emit_write_byte_1_qstr(emit_t* emit, byte b1, qstr qstr) {
emit_write_byte_1_uint(emit, b1, qstr);
static void emit_write_byte_code_byte_qstr(emit_t* emit, byte b1, qstr qstr) {
emit_write_byte_code_byte_uint(emit, b1, qstr);
}
// unsigned labels are relative to ip following this instruction, stored as 16 bits
static void emit_write_byte_1_unsigned_label(emit_t* emit, byte b1, int label) {
uint code_offset;
static void emit_write_byte_code_byte_unsigned_label(emit_t* emit, byte b1, int label) {
uint byte_code_offset;
if (emit->pass < PASS_3) {
code_offset = 0;
byte_code_offset = 0;
} else {
code_offset = emit->label_offsets[label] - emit->code_offset - 3;
byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3;
}
byte* c = emit_get_cur_to_write_bytes(emit, 3);
byte* c = emit_get_cur_to_write_byte_code(emit, 3);
c[0] = b1;
c[1] = code_offset;
c[2] = code_offset >> 8;
c[1] = byte_code_offset;
c[2] = byte_code_offset >> 8;
}
// signed labels are relative to ip following this instruction, stored as 16 bits, in excess
static void emit_write_byte_1_signed_label(emit_t* emit, byte b1, int label) {
int code_offset;
static void emit_write_byte_code_byte_signed_label(emit_t* emit, byte b1, int label) {
int byte_code_offset;
if (emit->pass < PASS_3) {
code_offset = 0;
byte_code_offset = 0;
} else {
code_offset = emit->label_offsets[label] - emit->code_offset - 3 + 0x8000;
byte_code_offset = emit->label_offsets[label] - emit->byte_code_offset - 3 + 0x8000;
}
byte* c = emit_get_cur_to_write_bytes(emit, 3);
byte* c = emit_get_cur_to_write_byte_code(emit, 3);
c[0] = b1;
c[1] = code_offset;
c[2] = code_offset >> 8;
c[1] = byte_code_offset;
c[2] = byte_code_offset >> 8;
}
static void emit_bc_set_native_types(emit_t *emit, bool do_native_types) {
......@@ -143,10 +168,26 @@ static void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
emit->stack_size = 0;
emit->last_emit_was_return_value = false;
emit->scope = scope;
emit->last_source_line_offset = 0;
emit->last_source_line = 1;
if (pass == PASS_2) {
memset(emit->label_offsets, -1, emit->max_num_labels * sizeof(uint));
}
emit->code_offset = 0;
emit->byte_code_offset = 0;
emit->code_info_offset = 0;
// write code info size (don't know size at this stage in PASS_2 so need to use maximum space (4 bytes) to write it)
{
byte* c = emit_get_cur_to_write_code_info(emit, 4);
machine_uint_t s = emit->code_info_size;
c[0] = s & 0xff;
c[1] = (s >> 8) & 0xff;
c[2] = (s >> 16) & 0xff;
c[3] = (s >> 24) & 0xff;
}
// code info
emit_write_code_info_qstr(emit, emit->source_file);
// prelude for initialising closed over variables
int num_cell = 0;
......@@ -157,11 +198,11 @@ static void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
}
}
assert(num_cell <= 255);
emit_write_byte_1(emit, num_cell); // write number of locals that are cells
emit_write_byte_code_byte(emit, num_cell); // write number of locals that are cells
for (int i = 0; i < scope->id_info_len; i++) {
id_info_t *id = &scope->id_info[i];
if (id->kind == ID_INFO_KIND_CELL) {
emit_write_byte_1(emit, id->local_num); // write the local which should be converted to a cell
emit_write_byte_code_byte(emit, id->local_num); // write the local which should be converted to a cell
}
}
}
......@@ -172,13 +213,16 @@ static void emit_bc_end_pass(emit_t *emit) {
printf("ERROR: stack size not back to zero; got %d\n", emit->stack_size);
}
emit_write_code_info_byte_byte(emit, 0, 0); // end of line number info
if (emit->pass == PASS_2) {
// calculate size of code in bytes
emit->code_size = emit->code_offset;
emit->code_base = m_new(byte, emit->code_size);
emit->code_info_size = emit->code_info_offset;
emit->byte_code_size = emit->byte_code_offset;
emit->code_base = m_new(byte, emit->code_info_size + emit->byte_code_size);
} else if (emit->pass == PASS_3) {
rt_assign_byte_code(emit->scope->unique_code_id, emit->code_base, emit->code_size, emit->scope->num_params, emit->scope->num_locals, emit->scope->stack_size, (emit->scope->flags & SCOPE_FLAG_GENERATOR) != 0);
rt_assign_byte_code(emit->scope->unique_code_id, emit->code_base, emit->code_info_size + emit->byte_code_size, emit->scope->num_params, emit->scope->num_locals, emit->scope->stack_size, (emit->scope->flags & SCOPE_FLAG_GENERATOR) != 0);
}
}
......@@ -194,6 +238,22 @@ static void emit_bc_set_stack_size(emit_t *emit, int size) {
emit->stack_size = size;
}
static void emit_bc_set_source_line(emit_t *emit, int source_line) {
if (source_line > emit->last_source_line) {
int bytes_to_skip = emit->byte_code_offset - emit->last_source_line_offset;
for (; bytes_to_skip > 255; bytes_to_skip -= 255) {
emit_write_code_info_byte_byte(emit, 255, 0);
}
int lines_to_skip = source_line - emit->last_source_line;
for (; lines_to_skip > 255; lines_to_skip -= 255) {
emit_write_code_info_byte_byte(emit, 0, 255);
}
emit_write_code_info_byte_byte(emit, bytes_to_skip, lines_to_skip);
emit->last_source_line_offset = emit->byte_code_offset;
emit->last_source_line = source_line;
}
}
static void emit_bc_load_id(emit_t *emit, qstr qstr) {
emit_common_load_id(emit, &emit_bc_method_table, emit->scope, qstr);
}
......@@ -220,66 +280,66 @@ static void emit_bc_label_assign(emit_t *emit, int l) {
if (emit->pass == PASS_2) {
// assign label offset
assert(emit->label_offsets[l] == -1);
emit->label_offsets[l] = emit->code_offset;
emit->label_offsets[l] = emit->byte_code_offset;
} else if (emit->pass == PASS_3) {
// ensure label offset has not changed from PASS_2 to PASS_3
//printf("l%d: (at %d vs %d)\n", l, emit->code_offset, emit->label_offsets[l]);
assert(emit->label_offsets[l] == emit->code_offset);
//printf("l%d: (at %d vs %d)\n", l, emit->byte_code_offset, emit->label_offsets[l]);
assert(emit->label_offsets[l] == emit->byte_code_offset);
}
}
static void emit_bc_import_name(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, MP_BC_IMPORT_NAME, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_NAME, qstr);
}
static void emit_bc_import_from(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, MP_BC_IMPORT_FROM, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_IMPORT_FROM, qstr);
}
static void emit_bc_import_star(emit_t *emit) {
emit_pre(emit, -1);
emit_write_byte_1(emit, MP_BC_IMPORT_STAR);
emit_write_byte_code_byte(emit, MP_BC_IMPORT_STAR);
}
static void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
emit_pre(emit, 1);
switch (tok) {
case MP_TOKEN_KW_FALSE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_FALSE); break;
case MP_TOKEN_KW_NONE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_NONE); break;
case MP_TOKEN_KW_TRUE: emit_write_byte_1(emit, MP_BC_LOAD_CONST_TRUE); break;
case MP_TOKEN_ELLIPSIS: emit_write_byte_1(emit, MP_BC_LOAD_CONST_ELLIPSIS); break;
case MP_TOKEN_KW_FALSE: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_FALSE); break;
case MP_TOKEN_KW_NONE: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_NONE); break;
case MP_TOKEN_KW_TRUE: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_TRUE); break;
case MP_TOKEN_ELLIPSIS: emit_write_byte_code_byte(emit, MP_BC_LOAD_CONST_ELLIPSIS); break;
default: assert(0);
}
}
static void emit_bc_load_const_small_int(emit_t *emit, int arg) {
emit_pre(emit, 1);
emit_write_byte_1_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
emit_write_byte_code_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
}
static void emit_bc_load_const_int(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_INT, qstr);
}
static void emit_bc_load_const_dec(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_DEC, qstr);
}
static void emit_bc_load_const_id(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_ID, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_ID, qstr);
}
static void emit_bc_load_const_str(emit_t *emit, qstr qstr, bool bytes) {
emit_pre(emit, 1);
if (bytes) {
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_BYTES, qstr);
} else {
emit_write_byte_1_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_CONST_STRING, qstr);
}
}
......@@ -292,16 +352,16 @@ static void emit_bc_load_fast(emit_t *emit, qstr qstr, int local_num) {
assert(local_num >= 0);
emit_pre(emit, 1);
switch (local_num) {
case 0: emit_write_byte_1(emit, MP_BC_LOAD_FAST_0); break;
case 1: emit_write_byte_1(emit, MP_BC_LOAD_FAST_1); break;
case 2: emit_write_byte_1(emit, MP_BC_LOAD_FAST_2); break;
default: emit_write_byte_1_uint(emit, MP_BC_LOAD_FAST_N, local_num); break;
case 0: emit_write_byte_code_byte(emit, MP_BC_LOAD_FAST_0); break;
case 1: emit_write_byte_code_byte(emit, MP_BC_LOAD_FAST_1); break;
case 2: emit_write_byte_code_byte(emit, MP_BC_LOAD_FAST_2); break;
default: emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num); break;
}
}
static void emit_bc_load_deref(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, MP_BC_LOAD_DEREF, local_num);
emit_write_byte_code_byte_uint(emit, MP_BC_LOAD_DEREF, local_num);
}
static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
......@@ -311,200 +371,200 @@ static void emit_bc_load_closure(emit_t *emit, qstr qstr, int local_num) {
static void emit_bc_load_name(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_NAME, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_NAME, qstr);
}
static void emit_bc_load_global(emit_t *emit, qstr qstr) {
emit_pre(emit, 1);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_GLOBAL, qstr);
}
static void emit_bc_load_attr(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_ATTR, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_ATTR, qstr);
}
static void emit_bc_load_method(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, MP_BC_LOAD_METHOD, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_LOAD_METHOD, qstr);
}
static void emit_bc_load_build_class(emit_t *emit) {
emit_pre(emit, 1);
emit_write_byte_1(emit, MP_BC_LOAD_BUILD_CLASS);
emit_write_byte_code_byte(emit, MP_BC_LOAD_BUILD_CLASS);
}
static void emit_bc_store_fast(emit_t *emit, qstr qstr, int local_num) {
assert(local_num >= 0);
emit_pre(emit, -1);
switch (local_num) {
case 0: emit_write_byte_1(emit, MP_BC_STORE_FAST_0); break;
case 1: emit_write_byte_1(emit, MP_BC_STORE_FAST_1); break;
case 2: emit_write_byte_1(emit, MP_BC_STORE_FAST_2); break;
default: emit_write_byte_1_uint(emit, MP_BC_STORE_FAST_N, local_num); break;
case 0: emit_write_byte_code_byte(emit, MP_BC_STORE_FAST_0); break;
case 1: emit_write_byte_code_byte(emit, MP_BC_STORE_FAST_1); break;
case 2: emit_write_byte_code_byte(emit, MP_BC_STORE_FAST_2); break;
default: emit_write_byte_code_byte_uint(emit, MP_BC_STORE_FAST_N, local_num); break;
}
}
static void emit_bc_store_deref(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, -1);
emit_write_byte_1_uint(emit, MP_BC_STORE_DEREF, local_num);
emit_write_byte_code_byte_uint(emit, MP_BC_STORE_DEREF, local_num);
}
static void emit_bc_store_name(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, MP_BC_STORE_NAME, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_NAME, qstr);
}
static void emit_bc_store_global(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_GLOBAL, qstr);
}
static void emit_bc_store_attr(emit_t *emit, qstr qstr) {
emit_pre(emit, -2);
emit_write_byte_1_qstr(emit, MP_BC_STORE_ATTR, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_STORE_ATTR, qstr);
}
static void emit_bc_store_subscr(emit_t *emit) {
emit_pre(emit, -3);
emit_write_byte_1(emit, MP_BC_STORE_SUBSCR);
emit_write_byte_code_byte(emit, MP_BC_STORE_SUBSCR);
}
static void emit_bc_store_locals(emit_t *emit) {
// not needed
emit_pre(emit, -1);
emit_write_byte_1(emit, MP_BC_POP_TOP);
emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
}
static void emit_bc_delete_fast(emit_t *emit, qstr qstr, int local_num) {
assert(local_num >= 0);
emit_pre(emit, 0);
emit_write_byte_1_uint(emit, MP_BC_DELETE_FAST_N, local_num);
emit_write_byte_code_byte_uint(emit, MP_BC_DELETE_FAST_N, local_num);
}
static void emit_bc_delete_deref(emit_t *emit, qstr qstr, int local_num) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_DEREF, local_num);
emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_DEREF, local_num);
}
static void emit_bc_delete_name(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_NAME, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_NAME, qstr);
}
static void emit_bc_delete_global(emit_t *emit, qstr qstr) {
emit_pre(emit, 0);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_GLOBAL, qstr);
}
static void emit_bc_delete_attr(emit_t *emit, qstr qstr) {
emit_pre(emit, -1);
emit_write_byte_1_qstr(emit, MP_BC_DELETE_ATTR, qstr);
emit_write_byte_code_byte_qstr(emit, MP_BC_DELETE_ATTR, qstr);
}
static void emit_bc_delete_subscr(emit_t *emit) {
emit_pre(emit, -2);
emit_write_byte_1(emit, MP_BC_DELETE_SUBSCR);
emit_write_byte_code_byte(emit, MP_BC_DELETE_SUBSCR);
}
static void emit_bc_dup_top(emit_t *emit) {
emit_pre(emit, 1);
emit_write_byte_1(emit, MP_BC_DUP_TOP);
emit_write_byte_code_byte(emit, MP_BC_DUP_TOP);
}
static void emit_bc_dup_top_two(emit_t *emit) {
emit_pre(emit, 2);
emit_write_byte_1(emit, MP_BC_DUP_TOP_TWO);
emit_write_byte_code_byte(emit, MP_BC_DUP_TOP_TWO);
}
static void emit_bc_pop_top(emit_t *emit) {
emit_pre(emit, -1);
emit_write_byte_1(emit, MP_BC_POP_TOP);
emit_write_byte_code_byte(emit, MP_BC_POP_TOP);
}
static void emit_bc_rot_two(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, MP_BC_ROT_TWO);
emit_write_byte_code_byte(emit, MP_BC_ROT_TWO);
}
static void emit_bc_rot_three(emit_t *emit) {
emit_pre(emit, 0);