diff --git a/makefile b/makefile index 5b1c9b4..6c5845a 100644 --- a/makefile +++ b/makefile @@ -31,7 +31,6 @@ test:nasal @ ./nasal -o -e test/ascii-art.nas @ ./nasal -o -c test/auto_crash.nas @ ./nasal -o -a -c test/bf.nas - @ ./nasal -o -a -c test/bfcolored.nas @ ./nasal -o -a -c test/bfconvertor.nas @ ./nasal -o -e -d test/bfs.nas @ ./nasal -o -t test/bigloop.nas diff --git a/nasal_builtin.h b/nasal_builtin.h index 7677432..a0adae7 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -1047,21 +1047,21 @@ nas_ref builtin_cocreate(nas_ref* local,nasal_gc& gc) if(gc.cort) return nas_err("coroutine::create","cannot create another coroutine in a coroutine"); nas_ref co=gc.alloc(vm_co); - nas_co& coroutine=co.co(); - coroutine.pc=func.func().entry-1; + nas_co& cort=co.co(); + cort.pc=func.func().entry-1; - coroutine.top[0]=nil; - coroutine.localr=coroutine.top+1; - coroutine.top=coroutine.localr+func.func().lsize; - coroutine.localr[0]=func.func().local[0]; - coroutine.top[0]=nil; // old upvalr - coroutine.top++; - coroutine.top[0]={vm_addr,(nas_ref*)nullptr}; // old localr - coroutine.top++; - coroutine.top[0]={vm_ret,(u32)0}; // old pc, set to zero to make op_ret recognizing this as coroutine function + cort.top[0]=nil; + cort.localr=cort.top+1; + cort.top=cort.localr+func.func().lsize; + cort.localr[0]=func.func().local[0]; + cort.top[0]=nil; // old upvalr + cort.top++; + cort.top[0]={vm_addr,(nas_ref*)nullptr}; // old localr + cort.top++; + cort.top[0]={vm_ret,(u32)0}; // old pc, set to zero to make op_ret recognizing this as coroutine function - coroutine.funcr=func; // make sure the coroutine function can use correct upvalues - coroutine.status=nas_co::suspended; + cort.funcr=func; // make sure the coroutine function can use correct upvalues + cort.status=nas_co::suspended; return co; } diff --git a/nasal_gc.h b/nasal_gc.h index 44d131b..6f709e9 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -32,20 +32,20 @@ const u32 ini[gc_tsize]= 128, // vm_str 128, // vm_vec 32, // vm_hash - 512, // vm_func - 512, // vm_upval + 128, // vm_func + 0, // vm_upval 0, // vm_obj 0 // vm_co }; const u32 incr[gc_tsize]= { 256, // vm_str - 512, // vm_vec - 512, // vm_hash - 512, // vm_func + 256, // vm_vec + 256, // vm_hash + 128, // vm_func 128, // vm_upval 128, // vm_obj - 16 // vm_co + 32 // vm_co }; struct nas_vec; // vector diff --git a/nasal_vm.h b/nasal_vm.h index 57fe49d..a69105a 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -45,7 +45,8 @@ protected: void lstate(); void ustate(); void detail(); - [[noreturn]] void die(const string&); + void die(const string&); +#define vm_error(info) {die(info);return;} /* vm calculation functions*/ bool condition(nas_ref); /* vm operands */ @@ -306,8 +307,6 @@ void nasal_vm::detail() lstate(); ustate(); } - -[[noreturn]] void nasal_vm::die(const string& str) { std::cout<<"[vm] error: "<=len) - die("index out of range:"+std::to_string(val.tonum())); + vm_error("index out of range:"+std::to_string(val.tonum())); top[0]={vm_num,f64((u8)str[num>=0? num:num+len])}; } else - die("must call a vector/hash/string"); + vm_error("must call a vector/hash/string"); } inline void nasal_vm::o_callvi() { nas_ref val=top[0]; if(val.type!=vm_vec) - die("must use a vector"); - + vm_error("must use a vector"); // cannot use operator[],because this may cause overflow (++top)[0]=val.vec().get_val(imm[pc]); if(top[0].type==vm_none) - die("index out of range:"+std::to_string(imm[pc])); + vm_error("index out of range:"+std::to_string(imm[pc])); } inline void nasal_vm::o_callh() { nas_ref val=top[0]; if(val.type!=vm_hash) - die("must call a hash"); - + vm_error("must call a hash"); top[0]=val.hash().get_val(str_table[imm[pc]]); if(top[0].type==vm_none) - die("member \""+str_table[imm[pc]]+"\" does not exist"); - + vm_error("member \""+str_table[imm[pc]]+"\" does not exist"); if(top[0].type==vm_func) top[0].func().local[0]=val;// 'me' } @@ -679,19 +681,18 @@ inline void nasal_vm::o_callfv() u32 argc=imm[pc]; // arguments counter nas_ref* local=top-argc+1; // arguments begin address if(local[-1].type!=vm_func) - die("must call a function"); - + vm_error("must call a function"); auto& func=local[-1].func(); nas_ref tmp=local[-1]; local[-1]=funcr; funcr=tmp; // top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr) if(top-argc+func.lsize+3>=canary) - die("stack overflow"); + vm_error("stack overflow"); // parameter size is func->psize-1, 1 is reserved for "me" u32 psize=func.psize-1; if(argc=canary) - die("stack overflow"); + vm_error("stack overflow"); if(func.dpara>=0) - die("special call cannot use dynamic argument"); + vm_error("special call cannot use dynamic argument"); nas_ref* local=top; top+=func.lsize; @@ -749,7 +749,7 @@ inline void nasal_vm::o_callfh() if(hash.count(key)) local[i.second]=hash[key]; else if(local[i.second].type==vm_none) - die("lack argument(s): \""+key+"\""); + vm_error("lack argument(s): \""+key+"\""); } top[0]=upvalr; @@ -769,7 +769,7 @@ inline void nasal_vm::o_callb() // (top) will be set to another context.top, instead of main_context.top top[0]=(*builtin[imm[pc]].func)(localr,gc); if(top[0].type==vm_none) - die("native function error"); + vm_error("native function error"); } inline void nasal_vm::o_slcbeg() { @@ -780,7 +780,7 @@ inline void nasal_vm::o_slcbeg() // +--------------+ (++top)[0]=gc.alloc(vm_vec); if(top[-1].type!=vm_vec) - die("must slice a vector"); + vm_error("must slice a vector"); } inline void nasal_vm::o_slcend() { @@ -792,7 +792,7 @@ inline void nasal_vm::o_slc() nas_ref val=(top--)[0]; nas_ref res=top[-1].vec().get_val(val.tonum()); if(res.type==vm_none) - die("index out of range:"+std::to_string(val.tonum())); + vm_error("index out of range:"+std::to_string(val.tonum())); top[0].vec().elems.push_back(res); } inline void nasal_vm::o_slc2() @@ -816,15 +816,12 @@ inline void nasal_vm::o_slc2() else if(type1!=vm_nil && type2==vm_nil) num2=num1<0? -1:size-1; - if(num1>num2) - die("begin index must be less than or equal to end index"); - else if(num1<-size || num1>=size) - die("begin index out of range: "+std::to_string(num1)); - else if(num2<-size || num2>=size) - die("end index out of range: "+std::to_string(num2)); - else + if(num1<-size || num1>=size || num2<-size || num2>=size){ + vm_error("index "+std::to_string(num1)+":"+std::to_string(num2)+" out of range."); + }else if(num1<=num2){ for(i32 i=num1;i<=num2;++i) aim.push_back(i>=0?ref[i]:ref[i+size]); + } } inline void nasal_vm::o_mcallg() { @@ -855,12 +852,11 @@ inline void nasal_vm::o_mcallv() { memr=vec.vec().get_mem(val.tonum()); if(!memr) - die("index out of range:"+std::to_string(val.tonum())); - } - else if(vec.type==vm_hash) // do mcallh but use the mcallv way + vm_error("index out of range:"+std::to_string(val.tonum())); + }else if(vec.type==vm_hash) // do mcallh but use the mcallv way { if(val.type!=vm_str) - die("must use string as the key"); + vm_error("must use string as the key"); nas_hash& ref=vec.hash(); string& str=val.str(); memr=ref.get_mem(str); @@ -869,15 +865,14 @@ inline void nasal_vm::o_mcallv() ref.elems[str]=nil; memr=ref.get_mem(str); } - } - else - die("cannot get memory space in this type"); + }else + vm_error("cannot get memory space in this type"); } inline void nasal_vm::o_mcallh() { nas_ref hash=top[0]; // mcall hash, reserved on stack to avoid gc if(hash.type!=vm_hash) - die("must call a hash"); + vm_error("must call a hash"); nas_hash& ref=hash.hash(); const string& str=str_table[imm[pc]]; memr=ref.get_mem(str); @@ -1021,14 +1016,12 @@ void nasal_vm::run( while(code[pc]){ (this->*code[pc])(); if(top>=canary) - break; + die("stack overflow"); ++pc; } #endif vmexit: - if(top>=canary) - die("stack overflow"); if(detail) gc.info(); gc.clear(); @@ -1041,7 +1034,7 @@ vmexit: op();\ if(top