✨ add detail error info in callh
This commit is contained in:
parent
1580b31122
commit
a298aa3a63
|
@ -20,14 +20,14 @@ var fib(var* args, usize size, gc* ngc) {
|
||||||
return nas_err("fib", "lack arguments");
|
return nas_err("fib", "lack arguments");
|
||||||
}
|
}
|
||||||
var num = args[0];
|
var num = args[0];
|
||||||
return var::num(fibonaci(num.tonum()));
|
return var::num(fibonaci(num.to_num()));
|
||||||
}
|
}
|
||||||
|
|
||||||
var quick_fib(var* args, usize size, gc* ngc) {
|
var quick_fib(var* args, usize size, gc* ngc) {
|
||||||
if (!size) {
|
if (!size) {
|
||||||
return nas_err("quick_fib","lack arguments");
|
return nas_err("quick_fib","lack arguments");
|
||||||
}
|
}
|
||||||
double num = args[0].tonum();
|
double num = args[0].to_num();
|
||||||
if (num<2) {
|
if (num<2) {
|
||||||
return var::num(num);
|
return var::num(num);
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ var builtin_int(var* local, gc& ngc) {
|
||||||
if (val.type!=vm_num && val.type!=vm_str) {
|
if (val.type!=vm_num && val.type!=vm_str) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return var::num(static_cast<f64>(static_cast<i32>(val.tonum())));
|
return var::num(static_cast<f64>(static_cast<i32>(val.to_num())));
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_floor(var* local, gc& ngc) {
|
var builtin_floor(var* local, gc& ngc) {
|
||||||
|
@ -161,7 +161,7 @@ var builtin_num(var* local, gc& ngc) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
f64 res = val.tonum();
|
f64 res = val.to_num();
|
||||||
if (std::isnan(res)) {
|
if (std::isnan(res)) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ var builtin_pop(var* local, gc& ngc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_str(var* local, gc& ngc) {
|
var builtin_str(var* local, gc& ngc) {
|
||||||
return ngc.newstr(local[1].tostr());
|
return ngc.newstr(local[1].to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_size(var* local, gc& ngc) {
|
var builtin_size(var* local, gc& ngc) {
|
||||||
|
@ -254,13 +254,13 @@ var builtin_keys(var* local, gc& ngc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_die(var* local, gc& ngc) {
|
var builtin_die(var* local, gc& ngc) {
|
||||||
return nas_err("error", local[1].tostr());
|
return nas_err("error", local[1].to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
var builtin_find(var* local, gc& ngc) {
|
var builtin_find(var* local, gc& ngc) {
|
||||||
var needle = local[1];
|
var needle = local[1];
|
||||||
var haystack = local[2];
|
var haystack = local[2];
|
||||||
usize pos = haystack.tostr().find(needle.tostr());
|
usize pos = haystack.to_str().find(needle.to_str());
|
||||||
if (pos==std::string::npos) {
|
if (pos==std::string::npos) {
|
||||||
return var::num(-1.0);
|
return var::num(-1.0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,11 +232,11 @@ void nas_val::clear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 var::tonum() {
|
f64 var::to_num() {
|
||||||
return type!=vm_str? val.num:str2num(str().c_str());
|
return type!=vm_str? val.num:str2num(str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string var::tostr() {
|
std::string var::to_str() {
|
||||||
if (type==vm_str) {
|
if (type==vm_str) {
|
||||||
return str();
|
return str();
|
||||||
} else if (type==vm_num) {
|
} else if (type==vm_num) {
|
||||||
|
|
|
@ -70,8 +70,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// number and string can be translated to each other
|
// number and string can be translated to each other
|
||||||
f64 tonum();
|
f64 to_num();
|
||||||
std::string tostr();
|
std::string to_str();
|
||||||
bool objchk(const std::string&);
|
bool objchk(const std::string&);
|
||||||
|
|
||||||
// create new var object
|
// create new var object
|
||||||
|
|
|
@ -340,6 +340,39 @@ std::string vm::report_special_call_lack_arguments(
|
||||||
return result + out.str();
|
return result + out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string vm::report_key_not_found(
|
||||||
|
const std::string& not_found, const nas_hash& hash) const {
|
||||||
|
auto result = "member \"" + not_found + "\" doesn't exist in hash {";
|
||||||
|
for(const auto& i : hash.elems) {
|
||||||
|
result += i.first + ", ";
|
||||||
|
}
|
||||||
|
if (hash.elems.size()) {
|
||||||
|
result = result.substr(0, result.length()-2);
|
||||||
|
}
|
||||||
|
result += "}";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string vm::type_name_string(const var& value) const {
|
||||||
|
switch(value.type) {
|
||||||
|
case vm_none: return "none";
|
||||||
|
case vm_cnt: return "counter";
|
||||||
|
case vm_addr: return "address";
|
||||||
|
case vm_ret: return "program counter";
|
||||||
|
case vm_nil: return "nil";
|
||||||
|
case vm_num: return "number";
|
||||||
|
case vm_str: return "string";
|
||||||
|
case vm_vec: return "vector";
|
||||||
|
case vm_hash: return "hash";
|
||||||
|
case vm_func: return "function";
|
||||||
|
case vm_upval: return "upvalue";
|
||||||
|
case vm_obj: return "ghost type";
|
||||||
|
case vm_co: return "coroutine";
|
||||||
|
case vm_map: return "namespace";
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
void vm::die(const std::string& str) {
|
void vm::die(const std::string& str) {
|
||||||
std::cerr << "[vm] error: " << str << "\n";
|
std::cerr << "[vm] error: " << str << "\n";
|
||||||
function_call_trace();
|
function_call_trace();
|
||||||
|
|
106
src/nasal_vm.h
106
src/nasal_vm.h
|
@ -71,6 +71,8 @@ protected:
|
||||||
void all_state_detail();
|
void all_state_detail();
|
||||||
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 type_name_string(const var&) const;
|
||||||
void die(const std::string&);
|
void die(const std::string&);
|
||||||
|
|
||||||
/* vm calculation functions*/
|
/* vm calculation functions*/
|
||||||
|
@ -315,7 +317,7 @@ inline void vm::o_lnot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_usub() {
|
inline void vm::o_usub() {
|
||||||
ctx.top[0] = var::num(-ctx.top[0].tonum());
|
ctx.top[0] = var::num(-ctx.top[0].to_num());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_bnot() {
|
inline void vm::o_bnot() {
|
||||||
|
@ -324,30 +326,30 @@ inline void vm::o_bnot() {
|
||||||
|
|
||||||
inline void vm::o_btor() {
|
inline void vm::o_btor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<i32>(ctx.top[-1].tonum())|
|
static_cast<i32>(ctx.top[-1].to_num())|
|
||||||
static_cast<i32>(ctx.top[0].tonum())
|
static_cast<i32>(ctx.top[0].to_num())
|
||||||
);
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btxor() {
|
inline void vm::o_btxor() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<i32>(ctx.top[-1].tonum())^
|
static_cast<i32>(ctx.top[-1].to_num())^
|
||||||
static_cast<i32>(ctx.top[0].tonum())
|
static_cast<i32>(ctx.top[0].to_num())
|
||||||
);
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void vm::o_btand() {
|
inline void vm::o_btand() {
|
||||||
ctx.top[-1] = var::num(
|
ctx.top[-1] = var::num(
|
||||||
static_cast<i32>(ctx.top[-1].tonum())&
|
static_cast<i32>(ctx.top[-1].to_num())&
|
||||||
static_cast<i32>(ctx.top[0].tonum())
|
static_cast<i32>(ctx.top[0].to_num())
|
||||||
);
|
);
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define op_calc(type)\
|
#define op_calc(type)\
|
||||||
ctx.top[-1] = var::num(ctx.top[-1].tonum() type ctx.top[0].tonum());\
|
ctx.top[-1] = var::num(ctx.top[-1].to_num() type ctx.top[0].to_num());\
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
|
||||||
inline void vm::o_add() {op_calc(+);}
|
inline void vm::o_add() {op_calc(+);}
|
||||||
|
@ -370,19 +372,19 @@ inline void vm::o_lnk() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// concat strings
|
// concat strings
|
||||||
ctx.top[-1] = ngc.newstr(ctx.top[-1].tostr()+ctx.top[0].tostr());
|
ctx.top[-1] = ngc.newstr(ctx.top[-1].to_str()+ctx.top[0].to_str());
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define op_calc_const(type)\
|
#define op_calc_const(type)\
|
||||||
ctx.top[0] = var::num(ctx.top[0].tonum() type const_number[imm[ctx.pc]]);
|
ctx.top[0] = var::num(ctx.top[0].to_num() type const_number[imm[ctx.pc]]);
|
||||||
|
|
||||||
inline void vm::o_addc() {op_calc_const(+);}
|
inline void vm::o_addc() {op_calc_const(+);}
|
||||||
inline void vm::o_subc() {op_calc_const(-);}
|
inline void vm::o_subc() {op_calc_const(-);}
|
||||||
inline void vm::o_mulc() {op_calc_const(*);}
|
inline void vm::o_mulc() {op_calc_const(*);}
|
||||||
inline void vm::o_divc() {op_calc_const(/);}
|
inline void vm::o_divc() {op_calc_const(/);}
|
||||||
inline void vm::o_lnkc() {
|
inline void vm::o_lnkc() {
|
||||||
ctx.top[0] = ngc.newstr(ctx.top[0].tostr()+const_string[imm[ctx.pc]]);
|
ctx.top[0] = ngc.newstr(ctx.top[0].to_str()+const_string[imm[ctx.pc]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// top[0] stores the value of memr[0], to avoid being garbage-collected
|
// top[0] stores the value of memr[0], to avoid being garbage-collected
|
||||||
|
@ -391,7 +393,9 @@ inline void vm::o_lnkc() {
|
||||||
// like this: func{a+=c;}(); the result of 'a+c' will no be used later, imm[pc] = 1
|
// like this: func{a+=c;}(); the result of 'a+c' will no be used later, imm[pc] = 1
|
||||||
// but if b+=a+=c; the result of 'a+c' will be used later, imm[pc] = 0
|
// but if b+=a+=c; the result of 'a+c' will be used later, imm[pc] = 0
|
||||||
#define op_calc_eq(type)\
|
#define op_calc_eq(type)\
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(ctx.memr[0].tonum() type ctx.top[-1].tonum());\
|
ctx.top[-1] = ctx.memr[0] = var::num(\
|
||||||
|
ctx.memr[0].to_num() type ctx.top[-1].to_num()\
|
||||||
|
);\
|
||||||
ctx.memr = nullptr;\
|
ctx.memr = nullptr;\
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
|
|
||||||
|
@ -401,7 +405,7 @@ inline void vm::o_muleq() {op_calc_eq(*);}
|
||||||
inline void vm::o_diveq() {op_calc_eq(/);}
|
inline void vm::o_diveq() {op_calc_eq(/);}
|
||||||
inline void vm::o_lnkeq() {
|
inline void vm::o_lnkeq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = ngc.newstr(
|
ctx.top[-1] = ctx.memr[0] = ngc.newstr(
|
||||||
ctx.memr[0].tostr()+ctx.top[-1].tostr()
|
ctx.memr[0].to_str()+ctx.top[-1].to_str()
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
|
@ -409,8 +413,8 @@ inline void vm::o_lnkeq() {
|
||||||
|
|
||||||
inline void vm::o_bandeq() {
|
inline void vm::o_bandeq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
static_cast<i32>(ctx.memr[0].tonum())&
|
static_cast<i32>(ctx.memr[0].to_num())&
|
||||||
static_cast<i32>(ctx.top[-1].tonum())
|
static_cast<i32>(ctx.top[-1].to_num())
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
|
@ -418,8 +422,8 @@ inline void vm::o_bandeq() {
|
||||||
|
|
||||||
inline void vm::o_boreq() {
|
inline void vm::o_boreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
static_cast<i32>(ctx.memr[0].tonum())|
|
static_cast<i32>(ctx.memr[0].to_num())|
|
||||||
static_cast<i32>(ctx.top[-1].tonum())
|
static_cast<i32>(ctx.top[-1].to_num())
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
|
@ -427,8 +431,8 @@ inline void vm::o_boreq() {
|
||||||
|
|
||||||
inline void vm::o_bxoreq() {
|
inline void vm::o_bxoreq() {
|
||||||
ctx.top[-1] = ctx.memr[0] = var::num(
|
ctx.top[-1] = ctx.memr[0] = var::num(
|
||||||
static_cast<i32>(ctx.memr[0].tonum())^
|
static_cast<i32>(ctx.memr[0].to_num())^
|
||||||
static_cast<i32>(ctx.top[-1].tonum())
|
static_cast<i32>(ctx.top[-1].to_num())
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
ctx.top -= imm[ctx.pc]+1;
|
ctx.top -= imm[ctx.pc]+1;
|
||||||
|
@ -441,7 +445,7 @@ inline void vm::o_bxoreq() {
|
||||||
// but if b+=a+=1; the result of 'a+1' will be used later, imm[pc]>>31=0
|
// but if b+=a+=1; the result of 'a+1' will be used later, imm[pc]>>31=0
|
||||||
#define op_calc_eq_const(type)\
|
#define op_calc_eq_const(type)\
|
||||||
ctx.top[0] = ctx.memr[0] = var::num(\
|
ctx.top[0] = ctx.memr[0] = var::num(\
|
||||||
ctx.memr[0].tonum() type const_number[imm[ctx.pc]]\
|
ctx.memr[0].to_num() type const_number[imm[ctx.pc]]\
|
||||||
);\
|
);\
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
|
|
||||||
|
@ -451,14 +455,14 @@ inline void vm::o_muleqc() {op_calc_eq_const(*);}
|
||||||
inline void vm::o_diveqc() {op_calc_eq_const(/);}
|
inline void vm::o_diveqc() {op_calc_eq_const(/);}
|
||||||
inline void vm::o_lnkeqc() {
|
inline void vm::o_lnkeqc() {
|
||||||
ctx.top[0] = ctx.memr[0] = ngc.newstr(
|
ctx.top[0] = ctx.memr[0] = ngc.newstr(
|
||||||
ctx.memr[0].tostr()+const_string[imm[ctx.pc]]
|
ctx.memr[0].to_str()+const_string[imm[ctx.pc]]
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define op_calc_eq_const_and_pop(type)\
|
#define op_calc_eq_const_and_pop(type)\
|
||||||
ctx.top[0] = ctx.memr[0] = var::num(\
|
ctx.top[0] = ctx.memr[0] = var::num(\
|
||||||
ctx.memr[0].tonum() type const_number[imm[ctx.pc]]\
|
ctx.memr[0].to_num() type const_number[imm[ctx.pc]]\
|
||||||
);\
|
);\
|
||||||
ctx.memr = nullptr;\
|
ctx.memr = nullptr;\
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
@ -469,7 +473,7 @@ inline void vm::o_mulecp() {op_calc_eq_const_and_pop(*);}
|
||||||
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
|
inline void vm::o_divecp() {op_calc_eq_const_and_pop(/);}
|
||||||
inline void vm::o_lnkecp() {
|
inline void vm::o_lnkecp() {
|
||||||
ctx.top[0] = ctx.memr[0] = ngc.newstr(
|
ctx.top[0] = ctx.memr[0] = ngc.newstr(
|
||||||
ctx.memr[0].tostr()+const_string[imm[ctx.pc]]
|
ctx.memr[0].to_str()+const_string[imm[ctx.pc]]
|
||||||
);
|
);
|
||||||
ctx.memr = nullptr;
|
ctx.memr = nullptr;
|
||||||
--ctx.top;
|
--ctx.top;
|
||||||
|
@ -495,7 +499,7 @@ inline void vm::o_eq() {
|
||||||
ctx.top[0] = (val1.str()==val2.str())? one:zero;
|
ctx.top[0] = (val1.str()==val2.str())? one:zero;
|
||||||
} else if ((val1.type==vm_num || val2.type==vm_num)
|
} else if ((val1.type==vm_num || val2.type==vm_num)
|
||||||
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
||||||
ctx.top[0] = (val1.tonum()==val2.tonum())? one:zero;
|
ctx.top[0] = (val1.to_num()==val2.to_num())? one:zero;
|
||||||
} else {
|
} else {
|
||||||
ctx.top[0] = (val1==val2)? one:zero;
|
ctx.top[0] = (val1==val2)? one:zero;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +514,7 @@ inline void vm::o_neq() {
|
||||||
ctx.top[0] = (val1.str()!=val2.str())? one:zero;
|
ctx.top[0] = (val1.str()!=val2.str())? one:zero;
|
||||||
} else if ((val1.type==vm_num || val2.type==vm_num)
|
} else if ((val1.type==vm_num || val2.type==vm_num)
|
||||||
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
&& val1.type!=vm_nil && val2.type!=vm_nil) {
|
||||||
ctx.top[0] = (val1.tonum()!=val2.tonum())? one:zero;
|
ctx.top[0] = (val1.to_num()!=val2.to_num())? one:zero;
|
||||||
} else {
|
} else {
|
||||||
ctx.top[0] = (val1!=val2)? one:zero;
|
ctx.top[0] = (val1!=val2)? one:zero;
|
||||||
}
|
}
|
||||||
|
@ -518,7 +522,7 @@ inline void vm::o_neq() {
|
||||||
|
|
||||||
#define op_cmp(type)\
|
#define op_cmp(type)\
|
||||||
--ctx.top;\
|
--ctx.top;\
|
||||||
ctx.top[0] = (ctx.top[0].tonum() type ctx.top[1].tonum())? one:zero;
|
ctx.top[0] = (ctx.top[0].to_num() type ctx.top[1].to_num())? one:zero;
|
||||||
|
|
||||||
inline void vm::o_less() {op_cmp(<);}
|
inline void vm::o_less() {op_cmp(<);}
|
||||||
inline void vm::o_leq() {op_cmp(<=);}
|
inline void vm::o_leq() {op_cmp(<=);}
|
||||||
|
@ -526,7 +530,7 @@ inline void vm::o_grt() {op_cmp(>);}
|
||||||
inline void vm::o_geq() {op_cmp(>=);}
|
inline void vm::o_geq() {op_cmp(>=);}
|
||||||
|
|
||||||
#define op_cmp_const(type)\
|
#define op_cmp_const(type)\
|
||||||
ctx.top[0] = (ctx.top[0].tonum() type const_number[imm[ctx.pc]])? one:zero;
|
ctx.top[0] = (ctx.top[0].to_num() type const_number[imm[ctx.pc]])? one:zero;
|
||||||
|
|
||||||
inline void vm::o_lessc() {op_cmp_const(<);}
|
inline void vm::o_lessc() {op_cmp_const(<);}
|
||||||
inline void vm::o_leqc() {op_cmp_const(<=);}
|
inline void vm::o_leqc() {op_cmp_const(<=);}
|
||||||
|
@ -559,7 +563,9 @@ inline void vm::o_jf() {
|
||||||
|
|
||||||
inline void vm::o_cnt() {
|
inline void vm::o_cnt() {
|
||||||
if (ctx.top[0].type!=vm_vec) {
|
if (ctx.top[0].type!=vm_vec) {
|
||||||
die("must use vector in forindex/foreach");
|
die("must use vector in forindex/foreach but get "+
|
||||||
|
type_name_string(ctx.top[0])
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(++ctx.top)[0] = var::cnt(-1);
|
(++ctx.top)[0] = var::cnt(-1);
|
||||||
|
@ -603,14 +609,14 @@ inline void vm::o_callv() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
var vec = (--ctx.top)[0];
|
var vec = (--ctx.top)[0];
|
||||||
if (vec.type==vm_vec) {
|
if (vec.type==vm_vec) {
|
||||||
ctx.top[0] = vec.vec().get_val(val.tonum());
|
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.tonum()));
|
die("out of range:"+std::to_string(val.to_num()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (vec.type==vm_hash) {
|
} else if (vec.type==vm_hash) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
die("must use string as the key");
|
die("must use string as the key but get "+type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0] = vec.hash().get_val(val.str());
|
ctx.top[0] = vec.hash().get_val(val.str());
|
||||||
|
@ -622,10 +628,10 @@ inline void vm::o_callv() {
|
||||||
}
|
}
|
||||||
} else if (vec.type==vm_str) {
|
} else if (vec.type==vm_str) {
|
||||||
const auto& str = vec.str();
|
const auto& str = vec.str();
|
||||||
i32 num = val.tonum();
|
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.tonum()));
|
die("out of range:"+std::to_string(val.to_num()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0] = var::num(
|
ctx.top[0] = var::num(
|
||||||
|
@ -633,7 +639,7 @@ inline void vm::o_callv() {
|
||||||
);
|
);
|
||||||
} else if (vec.type==vm_map) {
|
} else if (vec.type==vm_map) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
die("must use string as the key");
|
die("must use string as the key but get "+type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0] = vec.map().get_val(val.str());
|
ctx.top[0] = vec.map().get_val(val.str());
|
||||||
|
@ -642,7 +648,7 @@ inline void vm::o_callv() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
die("must call a vector/hash/string");
|
die("must call a vector/hash/string but get "+type_name_string(vec));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -650,7 +656,7 @@ inline void vm::o_callv() {
|
||||||
inline void vm::o_callvi() {
|
inline void vm::o_callvi() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
if (val.type!=vm_vec) {
|
if (val.type!=vm_vec) {
|
||||||
die("must use a vector");
|
die("must use a vector but get "+type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// cannot use operator[],because this may cause overflow
|
// cannot use operator[],because this may cause overflow
|
||||||
|
@ -664,7 +670,7 @@ inline void vm::o_callvi() {
|
||||||
inline void vm::o_callh() {
|
inline void vm::o_callh() {
|
||||||
var val = ctx.top[0];
|
var val = ctx.top[0];
|
||||||
if (val.type!=vm_hash && val.type!=vm_map) {
|
if (val.type!=vm_hash && val.type!=vm_map) {
|
||||||
die("must call a hash");
|
die("must call a hash but get "+type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& str = const_string[imm[ctx.pc]];
|
const auto& str = const_string[imm[ctx.pc]];
|
||||||
|
@ -675,7 +681,7 @@ inline void vm::o_callh() {
|
||||||
}
|
}
|
||||||
if (ctx.top[0].type==vm_none) {
|
if (ctx.top[0].type==vm_none) {
|
||||||
val.type==vm_hash?
|
val.type==vm_hash?
|
||||||
die("member \"" + str + "\" does not exist"):
|
die(report_key_not_found(str, val.hash())):
|
||||||
die("cannot find symbol \"" + str + "\"");
|
die("cannot find symbol \"" + str + "\"");
|
||||||
return;
|
return;
|
||||||
} else if (ctx.top[0].type==vm_func) {
|
} else if (ctx.top[0].type==vm_func) {
|
||||||
|
@ -687,7 +693,7 @@ inline void vm::o_callfv() {
|
||||||
const u32 argc = imm[ctx.pc]; // arguments counter
|
const u32 argc = imm[ctx.pc]; // arguments counter
|
||||||
var* local = ctx.top-argc+1; // arguments begin address
|
var* local = ctx.top-argc+1; // arguments begin address
|
||||||
if (local[-1].type!=vm_func) {
|
if (local[-1].type!=vm_func) {
|
||||||
die("must call a function");
|
die("must call a function but get "+type_name_string(local[-1]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& func = local[-1].func();
|
const auto& func = local[-1].func();
|
||||||
|
@ -756,7 +762,7 @@ inline void vm::o_callfv() {
|
||||||
inline void vm::o_callfh() {
|
inline void vm::o_callfh() {
|
||||||
const auto& hash = ctx.top[0].hash().elems;
|
const auto& hash = ctx.top[0].hash().elems;
|
||||||
if (ctx.top[-1].type!=vm_func) {
|
if (ctx.top[-1].type!=vm_func) {
|
||||||
die("must call a function");
|
die("must call a function but get "+type_name_string(ctx.top[-1]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& func = ctx.top[-1].func();
|
const auto& func = ctx.top[-1].func();
|
||||||
|
@ -833,7 +839,7 @@ inline void vm::o_slcbeg() {
|
||||||
// +--------------+
|
// +--------------+
|
||||||
(++ctx.top)[0] = ngc.alloc(vm_vec);
|
(++ctx.top)[0] = ngc.alloc(vm_vec);
|
||||||
if (ctx.top[-1].type!=vm_vec) {
|
if (ctx.top[-1].type!=vm_vec) {
|
||||||
die("must slice a vector");
|
die("must slice a vector but get "+type_name_string(ctx.top[-1]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -845,9 +851,9 @@ inline void vm::o_slcend() {
|
||||||
|
|
||||||
inline void vm::o_slc() {
|
inline void vm::o_slc() {
|
||||||
var val = (ctx.top--)[0];
|
var val = (ctx.top--)[0];
|
||||||
var res = ctx.top[-1].vec().get_val(val.tonum());
|
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.tonum()) + " out of range");
|
die("index " + std::to_string(val.to_num()) + " out of range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.top[0].vec().elems.push_back(res);
|
ctx.top[0].vec().elems.push_back(res);
|
||||||
|
@ -860,8 +866,8 @@ inline void vm::o_slc2() {
|
||||||
auto& aim = ctx.top[0].vec().elems;
|
auto& aim = ctx.top[0].vec().elems;
|
||||||
|
|
||||||
u8 type1 = val1.type,type2=val2.type;
|
u8 type1 = val1.type,type2=val2.type;
|
||||||
i32 num1 = val1.tonum();
|
i32 num1 = val1.to_num();
|
||||||
i32 num2 = val2.tonum();
|
i32 num2 = val2.to_num();
|
||||||
i32 size = ref.size();
|
i32 size = ref.size();
|
||||||
if (type1==vm_nil && type2==vm_nil) {
|
if (type1==vm_nil && type2==vm_nil) {
|
||||||
num1 = 0;
|
num1 = 0;
|
||||||
|
@ -912,14 +918,14 @@ inline void vm::o_mcallv() {
|
||||||
var val = ctx.top[0]; // index
|
var val = ctx.top[0]; // index
|
||||||
var vec = (--ctx.top)[0]; // mcall vector, reserved on stack to avoid gc
|
var vec = (--ctx.top)[0]; // mcall vector, reserved on stack to avoid gc
|
||||||
if (vec.type==vm_vec) {
|
if (vec.type==vm_vec) {
|
||||||
ctx.memr = vec.vec().get_mem(val.tonum());
|
ctx.memr = vec.vec().get_mem(val.to_num());
|
||||||
if (!ctx.memr) {
|
if (!ctx.memr) {
|
||||||
die("index "+std::to_string(val.tonum())+" out of range");
|
die("index "+std::to_string(val.to_num())+" out of range");
|
||||||
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
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
die("key must be string");
|
die("must use string as the key but get "+type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref = vec.hash();
|
auto& ref = vec.hash();
|
||||||
|
@ -931,7 +937,7 @@ inline void vm::o_mcallv() {
|
||||||
}
|
}
|
||||||
} else if (vec.type==vm_map) {
|
} else if (vec.type==vm_map) {
|
||||||
if (val.type!=vm_str) {
|
if (val.type!=vm_str) {
|
||||||
die("key must be string");
|
die("must use string as the key but get "+type_name_string(val));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& ref = vec.map();
|
auto& ref = vec.map();
|
||||||
|
@ -949,7 +955,7 @@ inline void vm::o_mcallv() {
|
||||||
inline void vm::o_mcallh() {
|
inline void vm::o_mcallh() {
|
||||||
var hash = ctx.top[0]; // mcall hash, reserved on stack to avoid gc
|
var hash = ctx.top[0]; // mcall hash, reserved on stack to avoid gc
|
||||||
if (hash.type!=vm_hash && hash.type!=vm_map) {
|
if (hash.type!=vm_hash && hash.type!=vm_map) {
|
||||||
die("must call a hash");
|
die("must call a hash/namespace but get "+type_name_string(hash));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& str = const_string[imm[ctx.pc]];
|
const auto& str = const_string[imm[ctx.pc]];
|
||||||
|
|
Loading…
Reference in New Issue