From 54317a39a7c6797b009246a451d3f8b91b2c6f7c Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 18 Oct 2023 00:29:53 +0800 Subject: [PATCH] :sparkles: improve error info of out-of-range --- module/fib.cpp | 4 ++-- src/dylib_lib.cpp | 6 +++--- src/io_lib.cpp | 14 +++++++------- src/nasal_type.cpp | 2 +- src/nasal_type.h | 2 +- src/nasal_vm.cpp | 11 +++++++++++ src/nasal_vm.h | 21 +++++++++++++-------- src/unix_lib.cpp | 4 ++-- 8 files changed, 40 insertions(+), 24 deletions(-) diff --git a/module/fib.cpp b/module/fib.cpp index 9116540..1bb9046 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -59,7 +59,7 @@ var create_new_ghost(var* args, usize size, gc* ngc) { var set_new_ghost(var* args, usize size, gc* ngc) { var res = args[0]; - if (!res.objchk(ghost_for_test)) { + if (!res.object_check(ghost_for_test)) { std::cout << "set_new_ghost: not ghost for test type.\n"; return nil; } @@ -71,7 +71,7 @@ var set_new_ghost(var* args, usize size, gc* ngc) { var print_new_ghost(var* args, usize size, gc* ngc) { var res = args[0]; - if (!res.objchk(ghost_for_test)) { + if (!res.object_check(ghost_for_test)) { std::cout << "print_new_ghost: not ghost for test type.\n"; return nil; } diff --git a/src/dylib_lib.cpp b/src/dylib_lib.cpp index daae5aa..0c424df 100644 --- a/src/dylib_lib.cpp +++ b/src/dylib_lib.cpp @@ -69,7 +69,7 @@ var builtin_dlopen(var* local, gc& ngc) { var builtin_dlclose(var* local, gc& ngc) { var libptr = local[1]; - if (!libptr.objchk(dylib_type_name)) { + if (!libptr.object_check(dylib_type_name)) { return nas_err("dlclose", "\"lib\" is not a valid dynamic lib"); } libptr.obj().clear(); @@ -79,7 +79,7 @@ var builtin_dlclose(var* local, gc& ngc) { var builtin_dlcallv(var* local, gc& ngc) { var fp = local[1]; var args = local[2]; - if (!fp.objchk(func_addr_type_name)) { + if (!fp.object_check(func_addr_type_name)) { return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); } auto& vec = args.vec().elems; @@ -92,7 +92,7 @@ var builtin_dlcallv(var* local, gc& ngc) { var builtin_dlcall(var* local, gc& ngc) { var fp = local[1]; - if (!fp.objchk(func_addr_type_name)) { + if (!fp.object_check(func_addr_type_name)) { return nas_err("dlcall", "\"ptr\" is not a valid function pointer"); } diff --git a/src/io_lib.cpp b/src/io_lib.cpp index 63c5dee..089647c 100644 --- a/src/io_lib.cpp +++ b/src/io_lib.cpp @@ -65,7 +65,7 @@ var builtin_open(var* local, gc& ngc) { var builtin_close(var* local, gc& ngc) { var fd = local[1]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("close", "not a valid filehandle"); } fd.obj().clear(); @@ -76,7 +76,7 @@ var builtin_read(var* local, gc& ngc) { var fd = local[1]; var buf = local[2]; var len = local[3]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("read", "not a valid filehandle"); } if (buf.type!=vm_str || buf.val.gcobj->unmutable) { @@ -102,7 +102,7 @@ var builtin_read(var* local, gc& ngc) { var builtin_write(var* local, gc& ngc) { var fd = local[1]; var str = local[2]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("write", "not a valid filehandle"); } if (str.type!=vm_str) { @@ -120,7 +120,7 @@ var builtin_seek(var* local, gc& ngc) { var fd = local[1]; var pos = local[2]; var whence = local[3]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("seek", "not a valid filehandle"); } return var::num(static_cast(fseek( @@ -132,7 +132,7 @@ var builtin_seek(var* local, gc& ngc) { var builtin_tell(var* local, gc& ngc) { var fd = local[1]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("tell", "not a valid filehandle"); } return var::num(static_cast( @@ -142,7 +142,7 @@ var builtin_tell(var* local, gc& ngc) { var builtin_readln(var* local, gc& ngc) { var fd = local[1]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("readln", "not a valid filehandle"); } var str = ngc.alloc(vm_str); @@ -190,7 +190,7 @@ var builtin_stat(var* local, gc& ngc) { var builtin_eof(var* local, gc& ngc) { var fd = local[1]; - if (!fd.objchk(file_type_name)) { + if (!fd.object_check(file_type_name)) { return nas_err("readln", "not a valid filehandle"); } return var::num(static_cast( diff --git a/src/nasal_type.cpp b/src/nasal_type.cpp index ab11624..f3fe65e 100644 --- a/src/nasal_type.cpp +++ b/src/nasal_type.cpp @@ -264,7 +264,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) { return out; } -bool var::objchk(const std::string& name) { +bool var::object_check(const std::string& name) { return type==vm_obj && obj().type_name==name && obj().pointer; } diff --git a/src/nasal_type.h b/src/nasal_type.h index 1cee06f..b4cefdd 100644 --- a/src/nasal_type.h +++ b/src/nasal_type.h @@ -72,7 +72,7 @@ public: // number and string can be translated to each other f64 to_num(); std::string to_str(); - bool objchk(const std::string&); + bool object_check(const std::string&); // create new var object static var none(); diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp index b1c1d63..bc943ca 100644 --- a/src/nasal_vm.cpp +++ b/src/nasal_vm.cpp @@ -353,6 +353,17 @@ std::string vm::report_key_not_found( return result; } +std::string vm::report_out_of_range(f64 index, usize real_size) const { + auto result = "index out of range: " + std::to_string(index); + result += " but max size is " + std::to_string(real_size); + if (!real_size) { + return result; + } + result += ", index range is -" + std::to_string(real_size); + result += "~" + std::to_string(real_size-1); + return result; +} + std::string vm::type_name_string(const var& value) const { switch(value.type) { case vm_none: return "none"; diff --git a/src/nasal_vm.h b/src/nasal_vm.h index 366bcf5..8b20630 100644 --- a/src/nasal_vm.h +++ b/src/nasal_vm.h @@ -72,6 +72,7 @@ protected: std::string report_lack_arguments(u32, const nas_func&) const; std::string report_special_call_lack_arguments(var*, const nas_func&) const; std::string report_key_not_found(const std::string&, const nas_hash&) const; + std::string report_out_of_range(f64, usize) const; std::string type_name_string(const var&) const; void die(const std::string&); @@ -312,7 +313,9 @@ inline void vm::o_lnot() { ctx.top[0] = num? zero:one; } } break; - default: die("incorrect value type"); return; + default: + die("cannot do not-operation on "+type_name_string(val)); + return; } } @@ -611,7 +614,7 @@ inline void vm::o_callv() { if (vec.type==vm_vec) { ctx.top[0] = vec.vec().get_val(val.to_num()); if (ctx.top[0].type==vm_none) { - die("out of range:"+std::to_string(val.to_num())); + die(report_out_of_range(val.to_num(), vec.vec().size())); return; } } else if (vec.type==vm_hash) { @@ -621,7 +624,7 @@ inline void vm::o_callv() { } ctx.top[0] = vec.hash().get_val(val.str()); if (ctx.top[0].type==vm_none) { - die("cannot find member \""+val.str()+"\""); + die(report_key_not_found(val.str(), vec.hash())); return; } else if (ctx.top[0].type==vm_func) { ctx.top[0].func().local[0] = val; // 'me' @@ -631,7 +634,7 @@ inline void vm::o_callv() { i32 num = val.to_num(); i32 len = str.length(); if (num<-len || num>=len) { - die("out of range:"+std::to_string(val.to_num())); + die(report_out_of_range(num, str.size())); return; } ctx.top[0] = var::num( @@ -662,7 +665,7 @@ inline void vm::o_callvi() { // cannot use operator[],because this may cause overflow (++ctx.top)[0] = val.vec().get_val(imm[ctx.pc]); if (ctx.top[0].type==vm_none) { - die("out of range:"+std::to_string(imm[ctx.pc])); + die(report_out_of_range(imm[ctx.pc], val.vec().size())); return; } } @@ -853,7 +856,7 @@ inline void vm::o_slc() { var val = (ctx.top--)[0]; var res = ctx.top[-1].vec().get_val(val.to_num()); if (res.type==vm_none) { - die("index " + std::to_string(val.to_num()) + " out of range"); + die(report_out_of_range(val.to_num(), ctx.top[-1].vec().size())); return; } ctx.top[0].vec().elems.push_back(res); @@ -880,7 +883,9 @@ inline void vm::o_slc2() { if (num1<-size || num1>=size || num2<-size || num2>=size) { die("index " + std::to_string(num1) + ":" + - std::to_string(num2) + " out of range"); + std::to_string(num2) + " out of range, real size is " + + std::to_string(size) + ); return; } else if (num1<=num2) { for(i32 i = num1; i<=num2; ++i) { @@ -920,7 +925,7 @@ inline void vm::o_mcallv() { if (vec.type==vm_vec) { ctx.memr = vec.vec().get_mem(val.to_num()); if (!ctx.memr) { - die("index "+std::to_string(val.to_num())+" out of range"); + die(report_out_of_range(val.to_num(), vec.vec().size())); return; } } else if (vec.type==vm_hash) { // do mcallh but use the mcallv way diff --git a/src/unix_lib.cpp b/src/unix_lib.cpp index 865384f..dbd64d9 100644 --- a/src/unix_lib.cpp +++ b/src/unix_lib.cpp @@ -79,7 +79,7 @@ var builtin_opendir(var* local, gc& ngc) { var builtin_readdir(var* local, gc& ngc) { var handle = local[1]; - if (!handle.objchk(dir_type_name)) { + if (!handle.object_check(dir_type_name)) { return nas_err("readdir", "not a valid dir handle"); } #ifdef _MSC_VER @@ -96,7 +96,7 @@ var builtin_readdir(var* local, gc& ngc) { var builtin_closedir(var* local, gc& ngc) { var handle = local[1]; - if (!handle.objchk(dir_type_name)) { + if (!handle.object_check(dir_type_name)) { return nas_err("closedir", "not a valid dir handle"); } handle.obj().clear();