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); 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) { ...@@ -28,6 +28,7 @@ static mp_obj_t mp_builtin_eval(mp_obj_t o_in) {
qstr parse_exc_id; qstr parse_exc_id;
const char *parse_exc_msg; const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_EVAL_INPUT, &parse_exc_id, &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); mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) { if (pn == MP_PARSE_NODE_NULL) {
...@@ -36,7 +37,7 @@ static mp_obj_t mp_builtin_eval(mp_obj_t o_in) { ...@@ -36,7 +37,7 @@ static mp_obj_t mp_builtin_eval(mp_obj_t o_in) {
} }
// compile the string // 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) { if (module_fun == mp_const_none) {
// TODO handle compile error correctly // TODO handle compile error correctly
......
...@@ -51,6 +51,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { ...@@ -51,6 +51,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
qstr parse_exc_id; qstr parse_exc_id;
const char *parse_exc_msg; const char *parse_exc_msg;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &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); mp_lexer_free(lex);
if (pn == MP_PARSE_NODE_NULL) { if (pn == MP_PARSE_NODE_NULL) {
...@@ -61,7 +62,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) { ...@@ -61,7 +62,7 @@ mp_obj_t mp_builtin___import__(int n_args, mp_obj_t *args) {
} }
// compile the imported script // 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) { if (module_fun == mp_const_none) {
// TODO handle compile error correctly // TODO handle compile error correctly
......
...@@ -2505,6 +2505,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) { ...@@ -2505,6 +2505,7 @@ void compile_node(compiler_t *comp, mp_parse_node_t pn) {
} }
} else { } else {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; 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)]; compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)];
if (f == NULL) { if (f == NULL) {
printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns)); 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) { ...@@ -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); compiler_t *comp = m_new(compiler_t, 1);
comp->is_repl = is_repl; comp->is_repl = is_repl;
...@@ -3131,7 +3132,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) { ...@@ -3131,7 +3132,7 @@ mp_obj_t mp_compile(mp_parse_node_t pn, bool is_repl) {
default: default:
if (emit_bc == NULL) { 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 = emit_bc;
comp->emit_method_table = &emit_bc_method_table; 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 { ...@@ -23,6 +23,7 @@ typedef struct _emit_method_table_t {
bool (*last_emit_was_return_value)(emit_t *emit); bool (*last_emit_was_return_value)(emit_t *emit);
int (*get_stack_size)(emit_t *emit); int (*get_stack_size)(emit_t *emit);
void (*set_stack_size)(emit_t *emit, int size); 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 (*load_id)(emit_t *emit, qstr qstr);
void (*store_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; ...@@ -119,7 +120,7 @@ extern const emit_method_table_t emit_native_thumb_method_table;
emit_t *emit_pass1_new(qstr qstr___class__); emit_t *emit_pass1_new(qstr qstr___class__);
void emit_pass1_free(emit_t *emit); void emit_pass1_free(emit_t *emit);
emit_t *emit_cpython_new(uint max_num_labels); 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_x64_new(uint max_num_labels);
emit_t *emit_native_thumb_new(uint max_num_labels); emit_t *emit_native_thumb_new(uint max_num_labels);
......
This diff is collapsed.
...@@ -68,6 +68,9 @@ static void emit_cpy_set_stack_size(emit_t *emit, int size) { ...@@ -68,6 +68,9 @@ static void emit_cpy_set_stack_size(emit_t *emit, int size) {
emit->stack_size = 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) { static void emit_cpy_load_id(emit_t *emit, qstr qstr) {
emit_common_load_id(emit, &emit_cpython_method_table, emit->scope, 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 = { ...@@ -798,6 +801,7 @@ const emit_method_table_t emit_cpython_method_table = {
emit_cpy_last_emit_was_return_value, emit_cpy_last_emit_was_return_value,
emit_cpy_get_stack_size, emit_cpy_get_stack_size,
emit_cpy_set_stack_size, emit_cpy_set_stack_size,
emit_cpy_set_source_line,
emit_cpy_load_id, emit_cpy_load_id,
emit_cpy_store_id, emit_cpy_store_id,
......
...@@ -281,6 +281,9 @@ static void emit_native_set_stack_size(emit_t *emit, int size) { ...@@ -281,6 +281,9 @@ static void emit_native_set_stack_size(emit_t *emit, int size) {
emit->stack_size = 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) { static void adjust_stack(emit_t *emit, int stack_size_delta) {
emit->stack_size += stack_size_delta; emit->stack_size += stack_size_delta;
assert(emit->stack_size >= 0); assert(emit->stack_size >= 0);
...@@ -1228,6 +1231,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = { ...@@ -1228,6 +1231,7 @@ const emit_method_table_t EXPORT_FUN(method_table) = {
emit_native_last_emit_was_return_value, emit_native_last_emit_was_return_value,
emit_native_get_stack_size, emit_native_get_stack_size,
emit_native_set_stack_size, emit_native_set_stack_size,
emit_native_set_source_line,
emit_native_load_id, emit_native_load_id,
emit_native_store_id, emit_native_store_id,
......
...@@ -103,6 +103,7 @@ const emit_method_table_t emit_pass1_method_table = { ...@@ -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,
(void*)emit_pass1_dummy, (void*)emit_pass1_dummy,
(void*)emit_pass1_dummy,
emit_pass1_load_id, emit_pass1_load_id,
emit_pass1_store_id, emit_pass1_store_id,
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include "misc.h" #include "misc.h"
...@@ -14,7 +15,7 @@ ...@@ -14,7 +15,7 @@
// don't know if that's intentional or not, but we don't allow it // don't know if that's intentional or not, but we don't allow it
struct _mp_lexer_t { struct _mp_lexer_t {
const char *name; // name of source qstr source_name; // name of source
void *stream_data; // data for stream void *stream_data; // data for stream
mp_lexer_stream_next_char_t stream_next_char; // stream callback to get next char 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 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) { ...@@ -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) { 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) { if (tok->str != NULL && tok->len > 0) {
const char *i = tok->str; const char *i = tok->str;
const char *j = i + tok->len; 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 ...@@ -292,7 +293,6 @@ static void mp_lexer_next_token_into(mp_lexer_t *lex, mp_token_t *tok, bool firs
next_char(lex); next_char(lex);
if (!is_physical_newline(lex)) { if (!is_physical_newline(lex)) {
// SyntaxError: unexpected character after line continuation character // SyntaxError: unexpected character after line continuation character
tok->src_name = lex->name;
tok->src_line = lex->line; tok->src_line = lex->line;
tok->src_column = lex->column; tok->src_column = lex->column;
tok->kind = MP_TOKEN_BAD_LINE_CONTINUATION; 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 ...@@ -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 // set token source information
tok->src_name = lex->name;
tok->src_line = lex->line; tok->src_line = lex->line;
tok->src_column = lex->column; 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 ...@@ -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 *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); 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_data = stream_data;
lex->stream_next_char = stream_next_char; lex->stream_next_char = stream_next_char;
lex->stream_close = stream_close; lex->stream_close = stream_close;
...@@ -642,6 +641,10 @@ void mp_lexer_free(mp_lexer_t *lex) { ...@@ -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) { void mp_lexer_to_next(mp_lexer_t *lex) {
mp_lexer_next_token_into(lex, &lex->tok_cur, false); 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) { ...@@ -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) { 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; return false;
} }
bool mp_lexer_show_error_pythonic(mp_lexer_t *lex, const char *msg) { 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; return false;
} }
...@@ -105,7 +105,6 @@ typedef enum _mp_token_kind_t { ...@@ -105,7 +105,6 @@ typedef enum _mp_token_kind_t {
} mp_token_kind_t; } mp_token_kind_t;
typedef struct _mp_token_t { typedef struct _mp_token_t {
const char *src_name; // name of source
uint src_line; // source line uint src_line; // source line
uint src_column; // source column 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 ...@@ -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); 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); 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); void mp_lexer_to_next(mp_lexer_t *lex);
const mp_token_t *mp_lexer_cur(const 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); bool mp_lexer_is_kind(mp_lexer_t *lex, mp_token_kind_t kind);
......
...@@ -273,6 +273,8 @@ machine_int_t mp_obj_int_get_checked(mp_obj_t self_in); ...@@ -273,6 +273,8 @@ machine_int_t mp_obj_int_get_checked(mp_obj_t self_in);
// exception // exception
extern const mp_obj_type_t exception_type; extern const mp_obj_type_t exception_type;
qstr mp_obj_exception_get_type(mp_obj_t self_in); 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 // str
extern const mp_obj_type_t str_type; extern const mp_obj_type_t str_type;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
// have args tuple (or otherwise have it as NULL). // have args tuple (or otherwise have it as NULL).
typedef struct mp_obj_exception_t { typedef struct mp_obj_exception_t {
mp_obj_base_t base; mp_obj_base_t base;
qstr source_file;
machine_uint_t source_line;
qstr id; qstr id;
qstr msg; qstr msg;
mp_obj_tuple_t args; mp_obj_tuple_t args;
...@@ -87,6 +89,8 @@ mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) { ...@@ -87,6 +89,8 @@ mp_obj_t mp_obj_new_exception_msg_varg(qstr id, const char *fmt, ...) {
// make exception object // make exception object
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0); mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, 0);
o->base.type = &exception_type; o->base.type = &exception_type;
o->source_file = 0;
o->source_line = 0;
o->id = id; o->id = id;
o->args.len = 0; o->args.len = 0;
if (fmt == NULL) { if (fmt == NULL) {
...@@ -109,3 +113,23 @@ qstr mp_obj_exception_get_type(mp_obj_t self_in) { ...@@ -109,3 +113,23 @@ qstr mp_obj_exception_get_type(mp_obj_t self_in) {
mp_obj_exception_t *self = self_in; mp_obj_exception_t *self = self_in;
return self->id; 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;
}
...@@ -58,6 +58,7 @@ mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun) { ...@@ -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 { typedef struct _mp_obj_gen_instance_t {
mp_obj_base_t base; mp_obj_base_t base;
const byte *code_info;
const byte *ip; const byte *ip;
mp_obj_t *sp; mp_obj_t *sp;
uint n_state; uint n_state;
...@@ -74,7 +75,7 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) { ...@@ -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_t gen_instance_iternext(mp_obj_t self_in) {
mp_obj_gen_instance_t *self = 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) { if (yield) {
return *self->sp; return *self->sp;
} else { } else {
...@@ -98,6 +99,7 @@ const mp_obj_type_t gen_instance_type = { ...@@ -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_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); 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->base.type = &gen_instance_type;
o->code_info = bytecode;
o->ip = bytecode; o->ip = bytecode;
o->sp = &o->state[0] - 1; // sp points to top of stack, which starts off 1 below the state o->sp = &o->state[0] - 1; // sp points to top of stack, which starts off 1 below the state
o->n_state = n_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, ...@@ -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) // prelude for making cells (closed over variables)
// for now we just make sure there are no cells variables // for now we just make sure there are no cells variables
// need to work out how to implement closed over variables in generators // 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); assert(o->ip[0] == 0);
o->ip += 1; o->ip += 1;
......
...@@ -80,7 +80,8 @@ static const rule_t *rules[] = { ...@@ -80,7 +80,8 @@ static const rule_t *rules[] = {
}; };
typedef struct _rule_stack_t { 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? int32_t arg_i; // what should be the size and signedness?
} rule_stack_t; } rule_stack_t;
...@@ -92,45 +93,54 @@ typedef struct _parser_t { ...@@ -92,45 +93,54 @@ typedef struct _parser_t {
uint result_stack_alloc; uint result_stack_alloc;
uint result_stack_top; uint result_stack_top;
mp_parse_node_t *result_stack; mp_parse_node_t *result_stack;
mp_lexer_t *lexer;
} parser_t; } 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) { 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 = 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_alloc *= 2;
} }
parser->rule_stack[parser->rule_stack_top].rule_id = rule->rule_id; rule_stack_t *rs = &parser->rule_stack[parser->rule_stack_top++];
parser->rule_stack[parser->rule_stack_top].arg_i = arg_i; rs->src_line = src_line;
parser->rule_stack_top += 1; rs->rule_id = rule->rule_id;
rs->arg_i = arg_i;
} }
static void push_rule_from_arg(parser_t *parser, uint arg) { 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); 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; uint rule_id = arg & RULE_ARG_ARG_MASK;
assert(rule_id < RULE_maximum_number_of); 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; parser->rule_stack_top -= 1;
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id]; *rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i; *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) { 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)); return (mp_parse_node_t)(kind | (arg << 4));
} }
int num_parse_nodes_allocated = 0; //int num_parse_nodes_allocated = 0;
mp_parse_node_struct_t *parse_node_new_struct(int rule_id, int num_args) { 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); 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); pn->kind_num_nodes = (rule_id & 0xff) | (num_args << 8);
num_parse_nodes_allocated += 1; //num_parse_nodes_allocated += 1;
return pn; return pn;
} }
void mp_parse_node_show(mp_parse_node_t pn, int indent) { 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++) { for (int i = 0; i < indent; i++) {
printf(" "); printf(" ");
} }
...@@ -258,8 +268,8 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) { ...@@ -258,8 +268,8 @@ static void push_result_token(parser_t *parser, const mp_lexer_t *lex) {
push_result_node(parser, pn); push_result_node(parser, pn);
} }
static void push_result_rule(parser_t *parser, const rule_t *rule, int 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(rule->rule_id, 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--) { for (int i = num_args; i > 0; i--) {
pn->nodes[i - 1] = pop_result(parser); 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 ...@@ -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_top = 0;
parser->result_stack = m_new(mp_parse_node_t, parser->result_stack_alloc); 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 // work out the top-level rule to use, and push it on the stack
int top_level_rule; int top_level_rule;
switch (input_kind) { 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 ...@@ -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; case MP_PARSE_EVAL_INPUT: top_level_rule = RULE_eval_input; break;
default: top_level_rule = RULE_file_input; default: top_level_rule = RULE_file_input;
} }
push_rule(parser, rules[top_level_rule], 0); push_rule(parser, mp_lexer_cur