eval: make the interpreter backtrace more efficient and informative.

Delyan Angelov 2022-04-28 12:31:30 +03:00 committed by Jef Roosens
parent 31bee98607
commit 705e260180
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
3 changed files with 39 additions and 15 deletions

View File

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

View File

@ -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')
}

View File

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