eval: make the interpreter backtrace more efficient and informative.
parent
f72297c331
commit
e0ed8f8278
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue