From e0ed8f827835946f33aa602247e34466fc304ac1 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Thu, 28 Apr 2022 12:31:30 +0300 Subject: [PATCH] eval: make the interpreter backtrace more efficient and informative. --- vlib/v/ast/ast.v | 2 + vlib/v/builder/interpreterbuilder/ibuilder.v | 2 +- vlib/v/eval/eval.v | 50 ++++++++++++++------ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index bce6e6d7f4..72a067d18f 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -520,6 +520,7 @@ pub: attrs []Attr ctdefine_idx int = -1 // the index in fn.attrs of `[if xyz]`, when such attribute exists pub mut: + idx int // index in an external container; can be used to refer to the function in a more efficient way, just by its integer index params []Param stmts []Stmt defer_stmts []DeferStmt @@ -707,6 +708,7 @@ pub: is_generated bool // true for `[generated] module xyz` files; turn off notices is_translated bool // true for `[translated] module xyz` files; turn off some checks pub mut: + idx int // index in an external container; can be used to refer to the file in a more efficient way, just by its integer index path string // absolute path of the source file - '/projects/v/file.v' path_base string // file name - 'file.v' (useful for tracing) scope &Scope diff --git a/vlib/v/builder/interpreterbuilder/ibuilder.v b/vlib/v/builder/interpreterbuilder/ibuilder.v index 06994d3ebe..452349d6cc 100644 --- a/vlib/v/builder/interpreterbuilder/ibuilder.v +++ b/vlib/v/builder/interpreterbuilder/ibuilder.v @@ -19,6 +19,6 @@ pub fn interpret_v(mut b builder.Builder) { util.timing_start('INTERPRET') mut e := eval.new_eval(b.table, b.pref) - e.eval(b.parsed_files) + e.eval(mut b.parsed_files) util.timing_measure('INTERPRET') } diff --git a/vlib/v/eval/eval.v b/vlib/v/eval/eval.v index f932c50e9c..2e27e88268 100644 --- a/vlib/v/eval/eval.v +++ b/vlib/v/eval/eval.v @@ -30,28 +30,37 @@ pub mut: return_values []Object cur_mod string cur_file string - back_trace []string + // + trace_file_paths []string + trace_function_names []string + back_trace []EvalTrace } -pub fn (mut e Eval) eval(files []&ast.File) { - e.register_symbols(files) +pub struct EvalTrace { + fn_idx int + file_idx int + line int +} + +pub fn (mut e Eval) eval(mut files []&ast.File) { + e.register_symbols(mut files) // println(files.map(it.path_base)) e.run_func(e.mods['main']['main'] or { ast.EmptyStmt{} } as ast.FnDecl) } // first arg is reciever (if method) pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) { - e.back_trace << func.name + e.back_trace << EvalTrace{func.idx, func.source_file.idx, func.pos.line_nr} old_mod := e.cur_mod - e.cur_mod = func.mod - old_file := e.cur_file + e.cur_mod = func.mod e.cur_file = func.file defer { e.cur_mod = old_mod e.cur_file = old_file e.back_trace.pop() } + // mut args := _args.clone() if func.params.len != args.len && !func.is_variadic { e.error('mismatched parameter length for $func.name: got `$args.len`, expected `$func.params.len`') @@ -90,7 +99,7 @@ pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) { } if func.is_method { print(e.back_trace) - println(func.receiver.typ - 65536) + println(func.receiver.typ.set_nr_muls(0)) e.local_vars[func.receiver.name] = Var{ val: args[0] scope_idx: e.scope_idx @@ -104,13 +113,19 @@ pub fn (mut e Eval) run_func(func ast.FnDecl, _args ...Object) { } } -pub fn (mut e Eval) register_symbols(files []&ast.File) { - for file in files { +pub fn (mut e Eval) register_symbols(mut files []&ast.File) { + for mut file in files { + file.idx = e.trace_file_paths.len + e.trace_file_paths << file.path // eprintln('registering file: $file.path_base') mod := file.mod.name - e.register_symbol_stmts(file.stmts[1..], mod, file.path) - - // eprintln('registered file: $file.path_base') + for mut stmt in file.stmts { + if mut stmt is ast.FnDecl { + stmt.idx = e.trace_function_names.len + e.trace_function_names << stmt.name + } + } + e.register_symbol_stmts(file.stmts, mod, file.path) } for mod, const_files in e.future_register_consts { e.cur_mod = mod @@ -133,14 +148,16 @@ pub fn (mut e Eval) register_symbols(files []&ast.File) { } pub fn (mut e Eval) register_symbol_stmts(stmts []ast.Stmt, mod string, file string) { - for stmt in stmts { // first is just module declaration, so ignore + for stmt in stmts { e.register_symbol(stmt, mod, file) } } pub fn (mut e Eval) register_symbol(stmt ast.Stmt, mod string, file string) { match stmt { - ast.Module {} + ast.Module { + // ignore module declarations for now + } ast.FnDecl { // this mess because c error x := ast.Stmt(stmt) @@ -205,5 +222,10 @@ pub fn (mut e Eval) register_symbol(stmt ast.Stmt, mod string, file string) { } fn (e Eval) error(msg string) { + eprintln('> V interpeter backtrace:') + for idx, t in e.back_trace { + eprintln(' ${e.trace_file_paths[t.file_idx]}:${t.line + 1}:${e.trace_function_names[t.fn_idx]}') + // eprintln('${e.trace_file_paths[t.file_idx]}:${t.line + 1}:$t.fn_idx') + } util.verror('interpreter', msg) }