✨ improve error info of out-of-range
This commit is contained in:
parent
a298aa3a63
commit
54317a39a7
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>(
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Reference in New Issue