improve error info of out-of-range

This commit is contained in:
ValKmjolnir 2023-10-18 00:29:53 +08:00
parent a298aa3a63
commit 54317a39a7
8 changed files with 40 additions and 24 deletions

View File

@ -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 set_new_ghost(var* args, usize size, gc* ngc) {
var res = args[0]; 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"; std::cout << "set_new_ghost: not ghost for test type.\n";
return nil; 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 print_new_ghost(var* args, usize size, gc* ngc) {
var res = args[0]; 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"; std::cout << "print_new_ghost: not ghost for test type.\n";
return nil; return nil;
} }

View File

@ -69,7 +69,7 @@ var builtin_dlopen(var* local, gc& ngc) {
var builtin_dlclose(var* local, gc& ngc) { var builtin_dlclose(var* local, gc& ngc) {
var libptr = local[1]; 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"); return nas_err("dlclose", "\"lib\" is not a valid dynamic lib");
} }
libptr.obj().clear(); libptr.obj().clear();
@ -79,7 +79,7 @@ var builtin_dlclose(var* local, gc& ngc) {
var builtin_dlcallv(var* local, gc& ngc) { var builtin_dlcallv(var* local, gc& ngc) {
var fp = local[1]; var fp = local[1];
var args = local[2]; 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"); return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
} }
auto& vec = args.vec().elems; auto& vec = args.vec().elems;
@ -92,7 +92,7 @@ var builtin_dlcallv(var* local, gc& ngc) {
var builtin_dlcall(var* local, gc& ngc) { var builtin_dlcall(var* local, gc& ngc) {
var fp = local[1]; 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"); return nas_err("dlcall", "\"ptr\" is not a valid function pointer");
} }

View File

@ -65,7 +65,7 @@ var builtin_open(var* local, gc& ngc) {
var builtin_close(var* local, gc& ngc) { var builtin_close(var* local, gc& ngc) {
var fd = local[1]; 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"); return nas_err("close", "not a valid filehandle");
} }
fd.obj().clear(); fd.obj().clear();
@ -76,7 +76,7 @@ var builtin_read(var* local, gc& ngc) {
var fd = local[1]; var fd = local[1];
var buf = local[2]; var buf = local[2];
var len = local[3]; 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"); return nas_err("read", "not a valid filehandle");
} }
if (buf.type!=vm_str || buf.val.gcobj->unmutable) { 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 builtin_write(var* local, gc& ngc) {
var fd = local[1]; var fd = local[1];
var str = local[2]; 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"); return nas_err("write", "not a valid filehandle");
} }
if (str.type!=vm_str) { if (str.type!=vm_str) {
@ -120,7 +120,7 @@ var builtin_seek(var* local, gc& ngc) {
var fd = local[1]; var fd = local[1];
var pos = local[2]; var pos = local[2];
var whence = local[3]; 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 nas_err("seek", "not a valid filehandle");
} }
return var::num(static_cast<f64>(fseek( return var::num(static_cast<f64>(fseek(
@ -132,7 +132,7 @@ var builtin_seek(var* local, gc& ngc) {
var builtin_tell(var* local, gc& ngc) { var builtin_tell(var* local, gc& ngc) {
var fd = local[1]; 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 nas_err("tell", "not a valid filehandle");
} }
return var::num(static_cast<f64>( return var::num(static_cast<f64>(
@ -142,7 +142,7 @@ var builtin_tell(var* local, gc& ngc) {
var builtin_readln(var* local, gc& ngc) { var builtin_readln(var* local, gc& ngc) {
var fd = local[1]; 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 nas_err("readln", "not a valid filehandle");
} }
var str = ngc.alloc(vm_str); 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 builtin_eof(var* local, gc& ngc) {
var fd = local[1]; 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 nas_err("readln", "not a valid filehandle");
} }
return var::num(static_cast<f64>( return var::num(static_cast<f64>(

View File

@ -264,7 +264,7 @@ std::ostream& operator<<(std::ostream& out, var& ref) {
return out; 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; return type==vm_obj && obj().type_name==name && obj().pointer;
} }

View File

@ -72,7 +72,7 @@ public:
// number and string can be translated to each other // number and string can be translated to each other
f64 to_num(); f64 to_num();
std::string to_str(); std::string to_str();
bool objchk(const std::string&); bool object_check(const std::string&);
// create new var object // create new var object
static var none(); static var none();

View File

@ -353,6 +353,17 @@ std::string vm::report_key_not_found(
return result; 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 { std::string vm::type_name_string(const var& value) const {
switch(value.type) { switch(value.type) {
case vm_none: return "none"; case vm_none: return "none";

View File

@ -72,6 +72,7 @@ protected:
std::string report_lack_arguments(u32, const nas_func&) const; 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_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_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; std::string type_name_string(const var&) const;
void die(const std::string&); void die(const std::string&);
@ -312,7 +313,9 @@ inline void vm::o_lnot() {
ctx.top[0] = num? zero:one; ctx.top[0] = num? zero:one;
} }
} break; } 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) { if (vec.type==vm_vec) {
ctx.top[0] = vec.vec().get_val(val.to_num()); ctx.top[0] = vec.vec().get_val(val.to_num());
if (ctx.top[0].type==vm_none) { 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; return;
} }
} else if (vec.type==vm_hash) { } else if (vec.type==vm_hash) {
@ -621,7 +624,7 @@ inline void vm::o_callv() {
} }
ctx.top[0] = vec.hash().get_val(val.str()); ctx.top[0] = vec.hash().get_val(val.str());
if (ctx.top[0].type==vm_none) { if (ctx.top[0].type==vm_none) {
die("cannot find member \""+val.str()+"\""); die(report_key_not_found(val.str(), vec.hash()));
return; return;
} else if (ctx.top[0].type==vm_func) { } else if (ctx.top[0].type==vm_func) {
ctx.top[0].func().local[0] = val; // 'me' ctx.top[0].func().local[0] = val; // 'me'
@ -631,7 +634,7 @@ inline void vm::o_callv() {
i32 num = val.to_num(); i32 num = val.to_num();
i32 len = str.length(); i32 len = str.length();
if (num<-len || num>=len) { if (num<-len || num>=len) {
die("out of range:"+std::to_string(val.to_num())); die(report_out_of_range(num, str.size()));
return; return;
} }
ctx.top[0] = var::num( ctx.top[0] = var::num(
@ -662,7 +665,7 @@ inline void vm::o_callvi() {
// cannot use operator[],because this may cause overflow // cannot use operator[],because this may cause overflow
(++ctx.top)[0] = val.vec().get_val(imm[ctx.pc]); (++ctx.top)[0] = val.vec().get_val(imm[ctx.pc]);
if (ctx.top[0].type==vm_none) { 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; return;
} }
} }
@ -853,7 +856,7 @@ inline void vm::o_slc() {
var val = (ctx.top--)[0]; var val = (ctx.top--)[0];
var res = ctx.top[-1].vec().get_val(val.to_num()); var res = ctx.top[-1].vec().get_val(val.to_num());
if (res.type==vm_none) { 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; return;
} }
ctx.top[0].vec().elems.push_back(res); 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) { if (num1<-size || num1>=size || num2<-size || num2>=size) {
die("index " + std::to_string(num1) + ":" + 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; return;
} else if (num1<=num2) { } else if (num1<=num2) {
for(i32 i = num1; i<=num2; ++i) { for(i32 i = num1; i<=num2; ++i) {
@ -920,7 +925,7 @@ inline void vm::o_mcallv() {
if (vec.type==vm_vec) { if (vec.type==vm_vec) {
ctx.memr = vec.vec().get_mem(val.to_num()); ctx.memr = vec.vec().get_mem(val.to_num());
if (!ctx.memr) { 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; return;
} }
} else if (vec.type==vm_hash) { // do mcallh but use the mcallv way } else if (vec.type==vm_hash) { // do mcallh but use the mcallv way

View File

@ -79,7 +79,7 @@ var builtin_opendir(var* local, gc& ngc) {
var builtin_readdir(var* local, gc& ngc) { var builtin_readdir(var* local, gc& ngc) {
var handle = local[1]; 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"); return nas_err("readdir", "not a valid dir handle");
} }
#ifdef _MSC_VER #ifdef _MSC_VER
@ -96,7 +96,7 @@ var builtin_readdir(var* local, gc& ngc) {
var builtin_closedir(var* local, gc& ngc) { var builtin_closedir(var* local, gc& ngc) {
var handle = local[1]; 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"); return nas_err("closedir", "not a valid dir handle");
} }
handle.obj().clear(); handle.obj().clear();