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.
pull/195/head
Damien George 2014-01-18 23:24:36 +00:00
rodzic aefe79880f
commit 08335004cf
24 zmienionych plików z 355 dodań i 198 usunięć

Wyświetl plik

@ -1,2 +1,2 @@
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);

Wyświetl plik

@ -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

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -1 +1 @@
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);

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}
void* emit_bc_get_code(emit_t* emit) {
return emit->code_base;
}
// 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) {
// 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_offset += num_bytes_to_write;
emit->code_info_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->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;
}
}
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_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;
}
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->byte_code_offset += num_bytes_to_write;
return emit->dummy_data;
} else {
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_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);
emit_write_byte_1(emit, MP_BC_ROT_THREE);
emit_write_byte_code_byte(emit, MP_BC_ROT_THREE);
}
static void emit_bc_jump(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_signed_label(emit, MP_BC_JUMP, label);
emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP, label);
}
static void emit_bc_pop_jump_if_true(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_TRUE, label);
}
static void emit_bc_pop_jump_if_false(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
emit_write_byte_code_byte_signed_label(emit, MP_BC_POP_JUMP_IF_FALSE, label);
}
static void emit_bc_jump_if_true_or_pop(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_TRUE_OR_POP, label);
}
static void emit_bc_jump_if_false_or_pop(emit_t *emit, int label) {
emit_pre(emit, -1);
emit_write_byte_1_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
emit_write_byte_code_byte_signed_label(emit, MP_BC_JUMP_IF_FALSE_OR_POP, label);
}
static void emit_bc_setup_loop(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_LOOP, label);
}
static void emit_bc_break_loop(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_unsigned_label(emit, MP_BC_BREAK_LOOP, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_BREAK_LOOP, label);
}
static void emit_bc_continue_loop(emit_t *emit, int label) {
emit_pre(emit, 0);
emit_write_byte_1_unsigned_label(emit, MP_BC_CONTINUE_LOOP, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_CONTINUE_LOOP, label);
}
static void emit_bc_setup_with(emit_t *emit, int label) {
emit_pre(emit, 7);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_WITH, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_WITH, label);
}
static void emit_bc_with_cleanup(emit_t *emit) {
emit_pre(emit, -7);
emit_write_byte_1(emit, MP_BC_WITH_CLEANUP);
emit_write_byte_code_byte(emit, MP_BC_WITH_CLEANUP);
}
static void emit_bc_setup_except(emit_t *emit, int label) {
emit_pre(emit, 6);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_EXCEPT, label);
}
static void emit_bc_setup_finally(emit_t *emit, int label) {
emit_pre(emit, 6);
emit_write_byte_1_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_SETUP_FINALLY, label);
}
static void emit_bc_end_finally(emit_t *emit) {
emit_pre(emit, -1);
emit_write_byte_1(emit, MP_BC_END_FINALLY);
emit_write_byte_code_byte(emit, MP_BC_END_FINALLY);
}
static void emit_bc_get_iter(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, MP_BC_GET_ITER);
emit_write_byte_code_byte(emit, MP_BC_GET_ITER);
}
static void emit_bc_for_iter(emit_t *emit, int label) {
emit_pre(emit, 1);
emit_write_byte_1_unsigned_label(emit, MP_BC_FOR_ITER, label);
emit_write_byte_code_byte_unsigned_label(emit, MP_BC_FOR_ITER, label);
}
static void emit_bc_for_iter_end(emit_t *emit) {
@ -513,99 +573,99 @@ static void emit_bc_for_iter_end(emit_t *emit) {
static void emit_bc_pop_block(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, MP_BC_POP_BLOCK);
emit_write_byte_code_byte(emit, MP_BC_POP_BLOCK);
}
static void emit_bc_pop_except(emit_t *emit) {
emit_pre(emit, 0);
emit_write_byte_1(emit, MP_BC_POP_EXCEPT);
emit_write_byte_code_byte(emit, MP_BC_POP_EXCEPT);
}
static void emit_bc_unary_op(emit_t *emit, rt_unary_op_t op) {
emit_pre(emit, 0);
emit_write_byte_1_byte(emit, MP_BC_UNARY_OP, op);
emit_write_byte_code_byte_byte(emit, MP_BC_UNARY_OP, op);
}
static void emit_bc_binary_op(emit_t *emit, rt_binary_op_t op) {
emit_pre(emit, -1);
emit_write_byte_1_byte(emit, MP_BC_BINARY_OP, op);
emit_write_byte_code_byte_byte(emit, MP_BC_BINARY_OP, op);
}
static void emit_bc_build_tuple(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_TUPLE, n_args);
emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_TUPLE, n_args);
}
static void emit_bc_build_list(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_LIST, n_args);
emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_LIST, n_args);
}
static void emit_bc_list_append(emit_t *emit, int list_stack_index) {
assert(list_stack_index >= 0);
emit_pre(emit, -1);
emit_write_byte_1_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
emit_write_byte_code_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index);
}
static void emit_bc_build_map(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, MP_BC_BUILD_MAP, n_args);
emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_MAP, n_args);
}
static void emit_bc_store_map(emit_t *emit) {
emit_pre(emit, -2);
emit_write_byte_1(emit, MP_BC_STORE_MAP);
emit_write_byte_code_byte(emit, MP_BC_STORE_MAP);
}
static void emit_bc_map_add(emit_t *emit, int map_stack_index) {
assert(map_stack_index >= 0);
emit_pre(emit, -2);
emit_write_byte_1_uint(emit, MP_BC_MAP_ADD, map_stack_index);
emit_write_byte_code_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index);
}
static void emit_bc_build_set(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_SET, n_args);
emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SET, n_args);
}
static void emit_bc_set_add(emit_t *emit, int set_stack_index) {
assert(set_stack_index >= 0);
emit_pre(emit, -1);
emit_write_byte_1_uint(emit, MP_BC_SET_ADD, set_stack_index);
emit_write_byte_code_byte_uint(emit, MP_BC_SET_ADD, set_stack_index);
}
static void emit_bc_build_slice(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, 1 - n_args);
emit_write_byte_1_uint(emit, MP_BC_BUILD_SLICE, n_args);
emit_write_byte_code_byte_uint(emit, MP_BC_BUILD_SLICE, n_args);
}
static void emit_bc_unpack_sequence(emit_t *emit, int n_args) {
assert(n_args >= 0);
emit_pre(emit, -1 + n_args);
emit_write_byte_1_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args);
}
static void emit_bc_unpack_ex(emit_t *emit, int n_left, int n_right) {
assert(n_left >=0 && n_right >= 0);
emit_pre(emit, -1 + n_left + n_right + 1);
emit_write_byte_1_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
emit_write_byte_code_byte_uint(emit, MP_BC_UNPACK_EX, n_left | (n_right << 8));
}
static void emit_bc_make_function(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
assert(n_default_params == 0 && n_dict_params == 0);
emit_pre(emit, 1);
emit_write_byte_1_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_FUNCTION, scope->unique_code_id);
}
static void emit_bc_make_closure(emit_t *emit, scope_t *scope, int n_dict_params, int n_default_params) {
assert(n_default_params == 0 && n_dict_params == 0);
emit_pre(emit, 0);
emit_write_byte_1_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
emit_write_byte_code_byte_uint(emit, MP_BC_MAKE_CLOSURE, scope->unique_code_id);
}
static void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
@ -631,7 +691,7 @@ static void emit_bc_call_function(emit_t *emit, int n_positional, int n_keyword,
op = MP_BC_CALL_FUNCTION;
}
}
emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
}
static void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, bool have_star_arg, bool have_dbl_star_arg) {
@ -657,19 +717,19 @@ static void emit_bc_call_method(emit_t *emit, int n_positional, int n_keyword, b
op = MP_BC_CALL_METHOD;
}
}
emit_write_byte_1_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
emit_write_byte_code_byte_uint(emit, op, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints
}
static void emit_bc_return_value(emit_t *emit) {
emit_pre(emit, -1);
emit->last_emit_was_return_value = true;
emit_write_byte_1(emit, MP_BC_RETURN_VALUE);
emit_write_byte_code_byte(emit, MP_BC_RETURN_VALUE);
}
static void emit_bc_raise_varargs(emit_t *emit, int n_args) {
assert(0 <= n_args && n_args <= 2);
emit_pre(emit, -n_args);
emit_write_byte_1_byte(emit, MP_BC_RAISE_VARARGS, n_args);
emit_write_byte_code_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
}
static void emit_bc_yield_value(emit_t *emit) {
@ -677,7 +737,7 @@ static void emit_bc_yield_value(emit_t *emit) {
if (emit->pass == PASS_2) {
emit->scope->flags |= SCOPE_FLAG_GENERATOR;
}
emit_write_byte_1(emit, MP_BC_YIELD_VALUE);
emit_write_byte_code_byte(emit, MP_BC_YIELD_VALUE);
}
static void emit_bc_yield_from(emit_t *emit) {
@ -685,7 +745,7 @@ static void emit_bc_yield_from(emit_t *emit) {
if (emit->pass == PASS_2) {
emit->scope->flags |= SCOPE_FLAG_GENERATOR;
}
emit_write_byte_1(emit, MP_BC_YIELD_FROM);
emit_write_byte_code_byte(emit, MP_BC_YIELD_FROM);
}
const emit_method_table_t emit_bc_method_table = {
@ -695,6 +755,7 @@ const emit_method_table_t emit_bc_method_table = {
emit_bc_last_emit_was_return_value,
emit_bc_get_stack_size,
emit_bc_set_stack_size,
emit_bc_set_source_line,
emit_bc_load_id,
emit_bc_store_id,

Wyświetl plik

@ -68,6 +68,9 @@ static void emit_cpy_set_stack_size(emit_t *emit, int size) {
emit->stack_size = size;
}
static void emit_cpy_set_source_line(emit_t *emit, int source_line) {
}
static void emit_cpy_load_id(emit_t *emit, qstr qstr) {
emit_common_load_id(emit, &emit_cpython_method_table, emit->scope, qstr);
}
@ -798,6 +801,7 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_last_emit_was_return_value,
emit_cpy_get_stack_size,
emit_cpy_set_stack_size,
emit_cpy_set_source_line,
emit_cpy_load_id,
emit_cpy_store_id,

Wyświetl plik

@ -281,6 +281,9 @@ static void emit_native_set_stack_size(emit_t *emit, int size) {
emit->stack_size = size;
}
static void emit_native_set_source_line(emit_t *emit, int source_line) {
}
static void adjust_stack(emit_t *emit, int stack_size_delta) {
emit->stack_size += stack_size_delta;
assert(emit->stack_size >= 0);
@ -1228,6 +1231,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_last_emit_was_return_value,
emit_native_get_stack_size,
emit_native_set_stack_size,
emit_native_set_source_line,
emit_native_load_id,
emit_native_store_id,

Wyświetl plik

@ -103,6 +103,7 @@ const emit_method_table_t emit_pass1_method_table = {
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
emit_pass1_load_id,
emit_pass1_store_id,

Wyświetl plik

@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "misc.h"
@ -14,7 +15,7 @@
// don't know if that's intentional or not, but we don't allow it
struct _mp_lexer_t {
const char *name; // name of source
qstr source_name; // name of source
void *stream_data; // data for stream
mp_lexer_stream_next_char_t stream_next_char; // stream callback to get next char
mp_lexer_stream_close_t stream_close; // stream callback to free
@ -49,7 +50,7 @@ bool str_strn_equal(const char *str, const char *strn, int len) {
}
void mp_token_show(const mp_token_t *tok) {
printf("(%s:%d:%d) kind:%d str:%p len:%d", tok->src_name, tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
printf("(%d:%d) kind:%d str:%p len:%d", tok->src_line, tok->src_column, tok->kind, tok->str, tok->len);
if (tok->str != NULL && tok->len > 0) {
const char *i = tok->str;
const char *j = i + tok->len;
@ -292,7 +293,6 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
next_char(lex);
if (!is_physical_newline(lex)) {
// SyntaxError: unexpected character after line continuation character
tok->src_name = lex->name;
tok->src_line = lex->line;
tok->src_column = lex->column;
tok->kind = MP_TOKEN_BAD_LINE_CONTINUATION;
@ -309,7 +309,6 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
}
// set token source information
tok->src_name = lex->name;
tok->src_line = lex->line;
tok->src_column = lex->column;
@ -594,7 +593,7 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_stream_next_char_t stream_next_char, mp_lexer_stream_close_t stream_close) {
mp_lexer_t *lex = m_new(mp_lexer_t, 1);
lex->name = src_name; // TODO do we need to strdup this?
lex->source_name = qstr_from_strn_copy(src_name, strlen(src_name));
lex->stream_data = stream_data;
lex->stream_next_char = stream_next_char;
lex->stream_close = stream_close;
@ -642,6 +641,10 @@ void mp_lexer_free(mp_lexer_t *lex) {
}
}
qstr mp_lexer_source_name(mp_lexer_t *lex) {
return lex->source_name;
}
void mp_lexer_to_next(mp_lexer_t *lex) {
mp_lexer_next_token_into(lex, &lex->tok_cur, false);
}
@ -677,11 +680,11 @@ bool mp_lexer_opt_str(mp_lexer_t *lex, const char *str) {
*/
bool mp_lexer_show_error_pythonic_prefix(mp_lexer_t *lex) {
printf(" File \"%s\", line %d column %d\n", lex->tok_cur.src_name, lex->tok_cur.src_line, lex->tok_cur.src_column);
printf(" File \"%s\", line %d column %d\n", qstr_str(lex->source_name), lex->tok_cur.src_line, lex->tok_cur.src_column);
return false;
}
bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg) {
printf(" File \"%s\", line %d column %d\n%s\n", lex->tok_cur.src_name, lex->tok_cur.src_line, lex->tok_cur.src_column, msg);
printf(" File \"%s\", line %d column %d\n%s\n", qstr_str(lex->source_name), lex->tok_cur.src_line, lex->tok_cur.src_column, msg);
return false;
}

Wyświetl plik

@ -105,7 +105,6 @@ typedef enum _mp_token_kind_t {
} mp_token_kind_t;
typedef struct _mp_token_t {
const char *src_name; // name of source
uint src_line; // source line
uint src_column; // source column
@ -129,6 +128,7 @@ mp_lexer_t *mp_lexer_new(const char *src_name, void *stream_data, mp_lexer_strea
mp_lexer_t *mp_lexer_new_from_str_len(const char *src_name, const char *str, uint len, uint free_len);
void mp_lexer_free(mp_lexer_t *lex);
qstr mp_lexer_source_name(mp_lexer_t *lex);
void mp_lexer_to_next(mp_lexer_t *lex);
const mp_token_t *mp_lexer_cur(const mp_lexer_t *lex);
bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind);

Wyświetl plik

@ -273,6 +273,8 @@ machine_int_t mp_obj_int_get_checked(mp_obj_t self_in);
// exception
extern const mp_obj_type_t exception_type;
qstr mp_obj_exception_get_type(mp_obj_t self_in);
void mp_obj_exception_set_source_info(mp_obj_t self_in, qstr file, machine_uint_t line);
void mp_obj_exception_get_source_info(mp_obj_t self_in, qstr *file, machine_uint_t *line);
// str
extern const mp_obj_type_t str_type;

Wyświetl plik

@ -17,6 +17,8 @@
// have args tuple (or otherwise have it as NULL).
typedef struct mp_obj_exception_t {
mp_obj_base_t base;
qstr source_file;
machine_uint_t source_line;
qstr id;
qstr msg;
mp_obj_tuple_t args;
@ -87,6 +89,8 @@ mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
// make exception object
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
o->base.type = &exception_type;
o->source_file = 0;
o->source_line = 0;
o->id = id;
o->args.len = 0;
if (fmt == NULL) {
@ -109,3 +113,23 @@ qstr mp_obj_exception_get_type(mp_obj_t self_in) {
mp_obj_exception_t *self = self_in;
return self->id;
}
void mp_obj_exception_set_source_info(mp_obj_t self_in, qstr file, machine_uint_t line) {
assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
mp_obj_exception_t *self = self_in;
// TODO make a list of file/line pairs for the traceback
// for now, just keep the first one
if (file != 0 && self->source_file == 0) {
self->source_file = file;
}
if (line != 0 && self->source_line == 0) {
self->source_line = line;
}
}
void mp_obj_exception_get_source_info(mp_obj_t self_in, qstr *file, machine_uint_t *line) {
assert(MP_OBJ_IS_TYPE(self_in, &exception_type));
mp_obj_exception_t *self = self_in;
*file = self->source_file;
*line = self->source_line;
}

Wyświetl plik

@ -58,6 +58,7 @@ mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun) {
typedef struct _mp_obj_gen_instance_t {
mp_obj_base_t base;
const byte *code_info;
const byte *ip;
mp_obj_t *sp;
uint n_state;
@ -74,7 +75,7 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
mp_obj_gen_instance_t *self = self_in;
bool yield = mp_execute_byte_code_2(&self->ip, &self->state[self->n_state - 1], &self->sp);
bool yield = mp_execute_byte_code_2(self->code_info, &self->ip, &self->state[self->n_state - 1], &self->sp);
if (yield) {
return *self->sp;
} else {
@ -98,6 +99,7 @@ const mp_obj_type_t gen_instance_type = {
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, mp_obj_t, n_state);
o->base.type = &gen_instance_type;
o->code_info = bytecode;
o->ip = bytecode;
o->sp = &o->state[0] - 1; // sp points to top of stack, which starts off 1 below the state
o->n_state = n_state;
@ -111,6 +113,10 @@ mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args,
// prelude for making cells (closed over variables)
// for now we just make sure there are no cells variables
// need to work out how to implement closed over variables in generators
// get code info size
machine_uint_t code_info_size = bytecode[0] | (bytecode[1] << 8) | (bytecode[2] << 16) | (bytecode[3] << 24);
o->ip += code_info_size;
assert(o->ip[0] == 0);
o->ip += 1;

Wyświetl plik

@ -80,7 +80,8 @@ static const rule_t *rules[] = {
};
typedef struct _rule_stack_t {
byte rule_id;
unsigned int src_line : 24;
unsigned int rule_id : 8;
int32_t arg_i; // what should be the size and signedness?
} rule_stack_t;
@ -92,45 +93,54 @@ typedef struct _parser_t {
uint result_stack_alloc;
uint result_stack_top;
mp_parse_node_t *result_stack;
mp_lexer_t *lexer;
} parser_t;
static void push_rule(parser_t *parser, const rule_t *rule, int arg_i) {
static void push_rule(parser_t *parser, int src_line, const rule_t *rule, int arg_i) {
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
parser->rule_stack = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc * 2);
parser->rule_stack_alloc *= 2;
}
parser->rule_stack[parser->rule_stack_top].rule_id = rule->rule_id;
parser->rule_stack[parser->rule_stack_top].arg_i = arg_i;
parser->rule_stack_top += 1;
rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
rs->src_line = src_line;
rs->rule_id = rule->rule_id;
rs->arg_i = arg_i;
}
static void push_rule_from_arg(parser_t *parser, uint arg) {
assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE);
uint rule_id = arg & RULE_ARG_ARG_MASK;
assert(rule_id < RULE_maximum_number_of);
push_rule(parser, rules[rule_id], 0);
push_rule(parser, mp_lexer_cur(parser->lexer)->src_line, rules[rule_id], 0);
}
static void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i) {
static void pop_rule(parser_t *parser, const rule_t **rule, uint *arg_i, uint *src_line) {
parser->rule_stack_top -= 1;
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
*src_line = parser->rule_stack[parser->rule_stack_top].src_line;
}
mp_parse_node_t mp_parse_node_new_leaf(machine_int_t kind, machine_int_t arg) {
return (mp_parse_node_t)(kind | (arg << 4));
}
int num_parse_nodes_allocated = 0;
mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) {
//int num_parse_nodes_allocated = 0;
mp_parse_node_struct_t *parse_node_new_struct(int src_line, int rule_id, int num_args) {
mp_parse_node_struct_t *pn = m_new_obj_var(mp_parse_node_struct_t, mp_parse_node_t, num_args);
pn->source = 0; // TODO
pn->source_line = src_line;
pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8);
num_parse_nodes_allocated += 1;
//num_parse_nodes_allocated += 1;
return pn;
}
void mp_parse_node_show(mp_parse_node_t pn, int indent) {
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
printf("[% 4d] ", (int)((mp_parse_node_struct_t*)pn)->source_line);
} else {
printf(" ");
}
for (int i = 0; i < indent; i++) {
printf(" ");
}
@ -258,8 +268,8 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
push_result_node(parser, pn);
}
static void push_result_rule(parser_t *parser, const rule_t *rule, int num_args) {
mp_parse_node_struct_t *pn = parse_node_new_struct(rule->rule_id, num_args);
static void push_result_rule(parser_t *parser, int src_line, const rule_t *rule, int num_args) {
mp_parse_node_struct_t *pn = parse_node_new_struct(src_line, rule->rule_id, num_args);
for (int i = num_args; i > 0; i--) {
pn->nodes[i - 1] = pop_result(parser);
}
@ -280,6 +290,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
parser->result_stack_top = 0;
parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc);
parser->lexer = lex;
// work out the top-level rule to use, and push it on the stack
int top_level_rule;
switch (input_kind) {
@ -287,13 +299,14 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
default: top_level_rule = RULE_file_input;
}
push_rule(parser, rules[top_level_rule], 0);
push_rule(parser, mp_lexer_cur(lex)->src_line, rules[top_level_rule], 0);
// parse!
uint n, i;
uint n, i; // state for the current rule
uint rule_src_line; // source line for the first token matched by the current rule
bool backtrack = false;
const rule_t *rule;
const rule_t *rule = NULL;
mp_token_kind_t tok_kind;
bool emit_rule;
bool had_trailing_sep;
@ -304,7 +317,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
break;
}
pop_rule(parser, &rule, &i);
pop_rule(parser, &rule, &i, &rule_src_line);
n = rule->act & RULE_ACT_ARG_MASK;
/*
@ -333,8 +346,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
break;
case RULE_ARG_RULE:
push_rule(parser, rule, i + 1);
push_rule_from_arg(parser, rule->arg[i]);
push_rule(parser, rule_src_line, rule, i + 1); // save this or-rule
push_rule_from_arg(parser, rule->arg[i]); // push child of or-rule
goto next_rule;
default:
assert(0);
@ -398,14 +411,9 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
break;
case RULE_ARG_RULE:
//if (i + 1 < n) {
push_rule(parser, rule, i + 1);
//}
push_rule_from_arg(parser, rule->arg[i]);
goto next_rule;
case RULE_ARG_OPT_RULE:
push_rule(parser, rule, i + 1);
push_rule_from_arg(parser, rule->arg[i]);
push_rule(parser, rule_src_line, rule, i + 1); // save this and-rule
push_rule_from_arg(parser, rule->arg[i]); // push child of and-rule
goto next_rule;
default:
assert(0);
@ -462,9 +470,9 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
//printf("done and %s n=%d i=%d notnil=%d\n", rule->rule_name, n, i, num_not_nil);
if (emit_rule) {
push_result_rule(parser, rule, i);
push_result_rule(parser, rule_src_line, rule, i);
} else if (num_not_nil == 0) {
push_result_rule(parser, rule, i); // needed for, eg, atom_paren, testlist_comp_3b
push_result_rule(parser, rule_src_line, rule, i); // needed for, eg, atom_paren, testlist_comp_3b
//result_stack_show(parser);
//assert(0);
} else if (num_not_nil == 1) {
@ -478,7 +486,7 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
push_result_node(parser, pn);
} else {
push_result_rule(parser, rule, i);
push_result_rule(parser, rule_src_line, rule, i);
}
break;
@ -538,8 +546,8 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
}
break;
case RULE_ARG_RULE:
push_rule(parser, rule, i + 1);
push_rule_from_arg(parser, arg);
push_rule(parser, rule_src_line, rule, i + 1); // save this list-rule
push_rule_from_arg(parser, arg); // push child of list-rule
goto next_rule;
default:
assert(0);
@ -559,13 +567,13 @@ mp_parse_node_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, qstr
// list matched single item
if (had_trailing_sep) {
// if there was a trailing separator, make a list of a single item
push_result_rule(parser, rule, i);
push_result_rule(parser, rule_src_line, rule, i);
} else {
// just leave single item on stack (ie don't wrap in a list)
}
} else {
//printf("done list %s %d %d\n", rule->rule_name, n, i);
push_result_rule(parser, rule, i);
push_result_rule(parser, rule_src_line, rule, i);
}
break;

Wyświetl plik

@ -28,7 +28,7 @@ struct _mp_lexer_t;
typedef machine_uint_t mp_parse_node_t; // must be pointer size
typedef struct _mp_parse_node_struct_t {
uint32_t source; // file identifier, and line number
uint32_t source_line; // line number in source file
uint32_t kind_num_nodes; // parse node kind, and number of nodes
mp_parse_node_t nodes[]; // nodes
} mp_parse_node_struct_t;

Wyświetl plik

@ -18,6 +18,10 @@
void mp_show_byte_code(const byte *ip, int len) {
const byte *ip_start = ip;
// get code info size
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
ip += code_info_size;
// decode prelude
{
uint n_local = *ip++;

28
py/vm.c
Wyświetl plik

@ -38,8 +38,13 @@ mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_arg
assert(i < 8);
state[n_state - 1 - i] = args[i];
}
const byte *ip = code;
// get code info size
machine_uint_t code_info_size = ip[0] | (ip[1] << 8) | (ip[2] << 16) | (ip[3] << 24);
ip += code_info_size;
// execute prelude to make any cells (closed over variables)
{
for (uint n_local = *ip++; n_local > 0; n_local--) {
@ -53,7 +58,7 @@ mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_arg
}
// execute the byte code
if (mp_execute_byte_code_2(&ip, &state[n_state - 1], &sp)) {
if (mp_execute_byte_code_2(code, &ip, &state[n_state - 1], &sp)) {
// it shouldn't yield
assert(0);
}
@ -65,7 +70,7 @@ mp_obj_t mp_execute_byte_code(const byte *code, const mp_obj_t *args, uint n_arg
// fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc)
// sp points to bottom of stack which grows up
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) {
// careful: be sure to declare volatile any variables read in the exception handler (written is ok, I think)
const byte *ip = *ip_in_out;
@ -79,12 +84,14 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
volatile machine_uint_t currently_in_except_block = 0; // 0 or 1, to detect nested exceptions
machine_uint_t exc_stack[8]; // on the exception stack we store (ip, sp | X) for each block, X = previous value of currently_in_except_block
machine_uint_t *volatile exc_sp = &exc_stack[0] - 1; // stack grows up, exc_sp points to top of stack
const byte *volatile save_ip = ip; // this is so we can access ip in the exception handler without making ip volatile (which means the compiler can't keep it in a register in the main loop)
// outer exception handling loop
for (;;) {
if (nlr_push(&nlr) == 0) {
// loop to execute byte code
for (;;) {
save_ip = ip;
int op = *ip++;
switch (op) {
case MP_BC_LOAD_CONST_FALSE:
@ -518,6 +525,23 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
} else {
// exception occurred
// set file and line number that the exception occurred at
if (MP_OBJ_IS_TYPE(nlr.ret_val, &exception_type)) {
machine_uint_t code_info_size = code_info[0] | (code_info[1] << 8) | (code_info[2] << 16) | (code_info[3] << 24);
qstr = code_info[4] | (code_info[5] << 8) | (code_info[6] << 16) | (code_info[7] << 24);
machine_uint_t source_line = 1;
machine_uint_t bc = save_ip - code_info - code_info_size;
//printf("find %lu %d %d\n", bc, code_info[8], code_info[9]);
for (const byte* ci = code_info + 8; bc > ci[0]; ci += 2) {
bc -= ci[0];
source_line += ci[1];
if (ci[0] == 0 && ci[1] == 0) {
break;
}
}
mp_obj_exception_set_source_info(nlr.ret_val, qstr, source_line);
}
while (currently_in_except_block) {
// nested exception

Wyświetl plik

@ -421,6 +421,7 @@ void do_repl(void) {
qstr parse_exc_id;
const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_exc_id, &parse_exc_msg);
qstr source_name = mp_lexer_source_name(lex);
if (pn == MP_PARSE_NODE_NULL) {
// parse error
@ -430,7 +431,7 @@ void do_repl(void) {
} else {
// parse okay
mp_lexer_free(lex);
mp_obj_t module_fun = mp_compile(pn, true);
mp_obj_t module_fun = mp_compile(pn, source_name, true);
if (module_fun != mp_const_none) {
nlr_buf_t nlr;
uint32_t start = sys_tick_counter;
@ -465,6 +466,7 @@ bool do_file(const char *filename) {
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);
if (pn == MP_PARSE_NODE_NULL) {
// parse error
@ -476,7 +478,7 @@ bool do_file(const char *filename) {
mp_lexer_free(lex);
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) {
return false;
}
@ -1095,7 +1097,7 @@ soft_reset:
printf("pars;al=%u\n", m_get_total_bytes_allocated());
sys_tick_delay_ms(1000);
//parse_node_show(pn, 0);
mp_obj_t module_fun = mp_compile(pn, false);
mp_obj_t module_fun = mp_compile(pn, 0, false);
printf("comp;al=%u\n", m_get_total_bytes_allocated());
sys_tick_delay_ms(1000);

Wyświetl plik

@ -310,13 +310,14 @@ bool do_file(const char *filename) {
}
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
qstr source_name = mp_lexer_source_name(lex);
mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) {
return false;
}
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) {
return false;
}

Wyświetl plik

@ -48,7 +48,7 @@ void do_file(const char *file) {
//printf("----------------\n");
// compile
mp_obj_t module_fun = mp_compile(pn, false);
mp_obj_t module_fun = mp_compile(pn, 0, false);
//printf("----------------\n");

Wyświetl plik

@ -49,13 +49,14 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
return;
}
qstr source_name = mp_lexer_source_name(lex);
mp_lexer_free(lex);
//printf("----------------\n");
//parse_node_show(pn, 0);
//mp_parse_node_show(pn, 0);
//printf("----------------\n");
mp_obj_t module_fun = mp_compile(pn, is_repl);
mp_obj_t module_fun = mp_compile(pn, source_name, is_repl);
if (module_fun == mp_const_none) {
// compile error
@ -69,7 +70,14 @@ static void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind
nlr_pop();
} else {
// uncaught exception
mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
mp_obj_t exc = (mp_obj_t)nlr.ret_val;
if (MP_OBJ_IS_TYPE(exc, &exception_type)) {
qstr file;
machine_uint_t line;
mp_obj_exception_get_source_info(exc, &file, &line);
printf("File \"%s\", line %d\n", qstr_str(file), (int)line);
}
mp_obj_print(exc, PRINT_REPR);
printf("\n");
}
}

Wyświetl plik

@ -13,6 +13,7 @@
#define MICROPY_ENABLE_LEXER_UNIX (1)
#define MICROPY_ENABLE_FLOAT (1)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
#define MICROPY_SHOW_BC (0)
// type definitions for the specific machine