diff --git a/README.md b/README.md index 2e4a5a5..e62ca96 100644 --- a/README.md +++ b/README.md @@ -633,7 +633,7 @@ var fib(var* args,usize size,gc* ngc){ // ok, you must know that vm_num now is not managed by gc // if want to return a gc object, use ngc->alloc(type) // usage of gc is the same as adding a native function - return {vm_num,fibonaci(num.tonum())}; + return var::num(fibonaci(num.tonum())); } // then put function name and address into this table diff --git a/doc/README_zh.md b/doc/README_zh.md index a8863b7..582e089 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -606,7 +606,7 @@ var fib(var* args,usize size,gc* ngc){ return nas_err("extern_fib","\"num\" must be number"); // vm_num作为普通的数字类型,不是内存管理的对象,所以无需申请 // 如果需要返回内存管理的对象,请使用ngc->alloc(type) - return {vm_num,fibonaci(num.tonum())}; + return var::num(fibonaci(num.tonum())); } // 然后将函数名字和函数地址放到一个表里,一定要记住表尾是{nullptr,nullptr} diff --git a/module/fib.cpp b/module/fib.cpp index f55d7f8..43f26fa 100644 --- a/module/fib.cpp +++ b/module/fib.cpp @@ -13,7 +13,7 @@ var fib(var* args,usize size,gc* ngc) { return nas_err("fib","lack arguments"); } var num=args[0]; - return {vm_num,fibonaci(num.tonum())}; + return var::num(fibonaci(num.tonum())); } var quick_fib(var* args,usize size,gc* ngc) { @@ -22,7 +22,7 @@ var quick_fib(var* args,usize size,gc* ngc) { } double num=args[0].tonum(); if (num<2) { - return {vm_num,num}; + return var::num(num); } double a=1,b=1,res=0; for(double i=1;ialloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()+v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()+v1[1].num()}); + res.vec().elems.push_back(var::num(v0[0].num()+v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()+v1[1].num())); return res; } @@ -37,8 +37,8 @@ var nas_vec2_sub(var* args,usize size,gc* ngc) { if (v0.size()!=2 || v1.size()!=2) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()-v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()-v1[1].num()}); + res.vec().elems.push_back(var::num(v0[0].num()-v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()-v1[1].num())); return res; } @@ -50,8 +50,8 @@ var nas_vec2_mult(var* args,usize size,gc* ngc) { if (v0.size()!=2 || v1.size()!=2) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()*v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()*v1[1].num()}); + res.vec().elems.push_back(var::num(v0[0].num()*v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()*v1[1].num())); return res; } @@ -63,8 +63,8 @@ var nas_vec2_div(var* args,usize size,gc* ngc) { if (v0.size()!=2 || v1.size()!=2) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()/v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()/v1[1].num()}); + res.vec().elems.push_back(var::num(v0[0].num()/v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()/v1[1].num())); return res; } @@ -75,8 +75,8 @@ var nas_vec2_neg(var* args,usize size,gc* ngc) { if (v0.size()!=2) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,-v0[0].num()}); - res.vec().elems.push_back({vm_num,-v0[1].num()}); + res.vec().elems.push_back(var::num(-v0[0].num())); + res.vec().elems.push_back(var::num(-v0[1].num())); return res; } @@ -90,8 +90,8 @@ var nas_vec2_norm(var* args,usize size,gc* ngc) { auto y=v0[1].num(); auto t=std::sqrt(x*x+y*y); var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,x/t}); - res.vec().elems.push_back({vm_num,y/t}); + res.vec().elems.push_back(var::num(x/t)); + res.vec().elems.push_back(var::num(y/t)); return res; } @@ -103,7 +103,7 @@ var nas_vec2_len(var* args,usize size,gc* ngc) { return nil; auto x=v0[0].num(); auto y=v0[1].num(); - return {vm_num,std::sqrt(x*x+y*y)}; + return var::num(std::sqrt(x*x+y*y)); } var nas_vec2_dot(var* args,usize size,gc* ngc) { @@ -113,7 +113,7 @@ var nas_vec2_dot(var* args,usize size,gc* ngc) { auto& v1=args[1].vec().elems; if (v0.size()!=2 || v1.size()!=2) return nil; - return {vm_num,v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()}; + return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()); } var nas_vec3_add(var* args,usize size,gc* ngc) { @@ -124,9 +124,9 @@ var nas_vec3_add(var* args,usize size,gc* ngc) { if (v0.size()!=3 || v1.size()!=3) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()+v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()+v1[1].num()}); - res.vec().elems.push_back({vm_num,v0[2].num()+v1[2].num()}); + res.vec().elems.push_back(var::num(v0[0].num()+v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()+v1[1].num())); + res.vec().elems.push_back(var::num(v0[2].num()+v1[2].num())); return res; } @@ -138,9 +138,9 @@ var nas_vec3_sub(var* args,usize size,gc* ngc) { if (v0.size()!=3 || v1.size()!=3) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()-v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()-v1[1].num()}); - res.vec().elems.push_back({vm_num,v0[2].num()-v1[2].num()}); + res.vec().elems.push_back(var::num(v0[0].num()-v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()-v1[1].num())); + res.vec().elems.push_back(var::num(v0[2].num()-v1[2].num())); return res; } @@ -152,9 +152,9 @@ var nas_vec3_mult(var* args,usize size,gc* ngc) { if (v0.size()!=3 || v1.size()!=3) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()*v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()*v1[1].num()}); - res.vec().elems.push_back({vm_num,v0[2].num()*v1[2].num()}); + res.vec().elems.push_back(var::num(v0[0].num()*v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()*v1[1].num())); + res.vec().elems.push_back(var::num(v0[2].num()*v1[2].num())); return res; } @@ -166,9 +166,9 @@ var nas_vec3_div(var* args,usize size,gc* ngc) { if (v0.size()!=3 || v1.size()!=3) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()/v1[0].num()}); - res.vec().elems.push_back({vm_num,v0[1].num()/v1[1].num()}); - res.vec().elems.push_back({vm_num,v0[2].num()/v1[2].num()}); + res.vec().elems.push_back(var::num(v0[0].num()/v1[0].num())); + res.vec().elems.push_back(var::num(v0[1].num()/v1[1].num())); + res.vec().elems.push_back(var::num(v0[2].num()/v1[2].num())); return res; } @@ -179,9 +179,9 @@ var nas_vec3_neg(var* args,usize size,gc* ngc) { if (v0.size()!=3) return nil; var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,-v0[0].num()}); - res.vec().elems.push_back({vm_num,-v0[1].num()}); - res.vec().elems.push_back({vm_num,-v0[2].num()}); + res.vec().elems.push_back(var::num(-v0[0].num())); + res.vec().elems.push_back(var::num(-v0[1].num())); + res.vec().elems.push_back(var::num(-v0[2].num())); return res; } @@ -196,9 +196,9 @@ var nas_vec3_norm(var* args,usize size,gc* ngc) { auto z=v0[2].num(); auto t=std::sqrt(x*x+y*y+z*z); var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,x/t}); - res.vec().elems.push_back({vm_num,y/t}); - res.vec().elems.push_back({vm_num,z/t}); + res.vec().elems.push_back(var::num(x/t)); + res.vec().elems.push_back(var::num(y/t)); + res.vec().elems.push_back(var::num(z/t)); return res; } @@ -211,7 +211,7 @@ var nas_vec3_len(var* args,usize size,gc* ngc) { auto x=v0[0].num(); auto y=v0[1].num(); auto z=v0[2].num(); - return {vm_num,std::sqrt(x*x+y*y+z*z)}; + return var::num(std::sqrt(x*x+y*y+z*z)); } var nas_rotate_x(var* args,usize size,gc* ngc) { @@ -222,9 +222,9 @@ var nas_rotate_x(var* args,usize size,gc* ngc) { return nil; auto angle=args[1].num(); var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()}); - res.vec().elems.push_back({vm_num,v0[2].num()*std::sin(angle)+v0[1].num()*std::cos(angle)}); - res.vec().elems.push_back({vm_num,v0[2].num()*std::cos(angle)-v0[1].num()*std::sin(angle)}); + res.vec().elems.push_back(var::num(v0[0].num())); + res.vec().elems.push_back(var::num(v0[2].num()*std::sin(angle)+v0[1].num()*std::cos(angle))); + res.vec().elems.push_back(var::num(v0[2].num()*std::cos(angle)-v0[1].num()*std::sin(angle))); return res; } @@ -236,9 +236,9 @@ var nas_rotate_y(var* args,usize size,gc* ngc) { return nil; auto angle=args[1].num(); var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()*std::cos(angle)-v0[2].num()*std::sin(angle)}); - res.vec().elems.push_back({vm_num,v0[1].num()}); - res.vec().elems.push_back({vm_num,v0[0].num()*std::sin(angle)+v0[2].num()*std::cos(angle)}); + res.vec().elems.push_back(var::num(v0[0].num()*std::cos(angle)-v0[2].num()*std::sin(angle))); + res.vec().elems.push_back(var::num(v0[1].num())); + res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[2].num()*std::cos(angle))); return res; } @@ -250,9 +250,9 @@ var nas_rotate_z(var* args,usize size,gc* ngc) { return nil; auto angle=args[1].num(); var res=ngc->alloc(vm_vec); - res.vec().elems.push_back({vm_num,v0[0].num()*std::cos(angle)-v0[1].num()*std::sin(angle)}); - res.vec().elems.push_back({vm_num,v0[0].num()*std::sin(angle)+v0[1].num()*std::cos(angle)}); - res.vec().elems.push_back({vm_num,v0[2].num()}); + res.vec().elems.push_back(var::num(v0[0].num()*std::cos(angle)-v0[1].num()*std::sin(angle))); + res.vec().elems.push_back(var::num(v0[0].num()*std::sin(angle)+v0[1].num()*std::cos(angle))); + res.vec().elems.push_back(var::num(v0[2].num())); return res; } @@ -263,7 +263,7 @@ var nas_vec3_dot(var* args,usize size,gc* ngc) { auto& v1=args[1].vec().elems; if (v0.size()!=3 || v1.size()!=3) return nil; - return {vm_num,v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()+v0[2].num()*v1[2].num()}; + return var::num(v0[0].num()*v1[0].num()+v0[1].num()*v1[1].num()+v0[2].num()*v1[2].num()); } mod_func func_tbl[]={ diff --git a/module/nasocket.cpp b/module/nasocket.cpp index 6abd935..fc13837 100644 --- a/module/nasocket.cpp +++ b/module/nasocket.cpp @@ -29,16 +29,16 @@ var nas_socket(var* args,usize size,gc* ngc) { if (args[0].type!=vm_num || args[1].type!=vm_num || args[2].type!=vm_num) return nas_err("socket","\"af\", \"type\", \"protocol\" should be number"); int sd=socket(args[0].num(),args[1].num(),args[2].num()); - return {vm_num,(double)sd}; + return var::num((double)sd); } var nas_closesocket(var* args,usize size,gc* ngc) { if (args[0].type!=vm_num) return nas_err("closesocket","\"\" should be number"); #ifdef _WIN32 - return {vm_num,(double)closesocket(args[0].num())}; + return var::num((double)closesocket(args[0].num())); #else - return {vm_num,(double)close(args[0].num())}; + return var::num((double)close(args[0].num())); #endif } @@ -47,7 +47,7 @@ var nas_shutdown(var* args,usize size,gc* ngc) { return nas_err("shutdown","\"sd\" must be a number"); if (args[1].type!=vm_num) return nas_err("shutdown","\"how\" must be a number"); - return {vm_num,(double)shutdown(args[0].num(),args[1].num())}; + return var::num((double)shutdown(args[0].num(),args[1].num())); } var nas_bind(var* args,usize size,gc* ngc) { @@ -62,7 +62,7 @@ var nas_bind(var* args,usize size,gc* ngc) { server.sin_family=AF_INET; server.sin_addr.s_addr=inet_addr(args[1].str().c_str()); server.sin_port=htons(args[2].num()); - return {vm_num,(double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))}; + return var::num((double)bind(args[0].num(),(sockaddr*)&server,sizeof(server))); } var nas_listen(var* args,usize size,gc* ngc) { @@ -70,7 +70,7 @@ var nas_listen(var* args,usize size,gc* ngc) { return nas_err("listen","\"sd\" must be a number"); if (args[1].type!=vm_num) return nas_err("listen","\"backlog\" must be a number"); - return{vm_num,(double)listen(args[0].num(),args[1].num())}; + return var::num((double)listen(args[0].num(),args[1].num())); } var nas_connect(var* args,usize size,gc* ngc) { @@ -86,7 +86,7 @@ var nas_connect(var* args,usize size,gc* ngc) { addr.sin_port=htons(args[2].num()); hostent* entry=gethostbyname(args[1].str().c_str()); memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); - return {vm_num,(double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))}; + return var::num((double)connect(args[0].num(),(sockaddr*)&addr,sizeof(sockaddr_in))); } var nas_accept(var* args,usize size,gc* ngc) { @@ -101,7 +101,7 @@ var nas_accept(var* args,usize size,gc* ngc) { #endif var res=ngc->temp=ngc->alloc(vm_hash); auto& hash=res.hash().elems; - hash["sd"]={vm_num,(double)client_sd}; + hash["sd"]=var::num((double)client_sd); hash["ip"]=ngc->newstr(inet_ntoa(client.sin_addr)); ngc->temp=nil; return res; @@ -114,7 +114,7 @@ var nas_send(var* args,usize size,gc* ngc) { return nas_err("send","\"buff\" must be a string"); if (args[2].type!=vm_num) return nas_err("send","\"flags\" muse be a number"); - return {vm_num,(double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())}; + return var::num((double)send(args[0].num(),args[1].str().c_str(),args[1].str().length(),args[2].num())); } var nas_sendto(var* args,usize size,gc* ngc) { @@ -134,7 +134,7 @@ var nas_sendto(var* args,usize size,gc* ngc) { addr.sin_port=htons(args[2].num()); hostent* entry=gethostbyname(args[1].str().c_str()); memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); - return {vm_num,(double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))}; + return var::num((double)sendto(args[0].num(),args[3].str().c_str(),args[3].str().length(),args[4].num(),(sockaddr*)&addr,sizeof(sockaddr_in))); } var nas_recv(var* args,usize size,gc* ngc) { @@ -149,7 +149,7 @@ var nas_recv(var* args,usize size,gc* ngc) { var res=ngc->temp=ngc->alloc(vm_hash); auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()]; - hash["size"]={vm_num,(double)recv(args[0].num(),buf,args[1].num(),args[2].num())}; + hash["size"]=var::num((double)recv(args[0].num(),buf,args[1].num(),args[2].num())); hash["str"]=ngc->newstr(buf); delete[] buf; ngc->temp=nil; @@ -171,9 +171,9 @@ var nas_recvfrom(var* args,usize size,gc* ngc) { auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()+1]; #ifdef _WIN32 - hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen)}; + hash["size"]=var::num((double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen)); #else - hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)}; + hash["size"]=var::num((double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)); #endif buf[(int)hash["size"].num()]=0; hash["str"]=ngc->newstr(buf); diff --git a/nasal_builtin.h b/nasal_builtin.h index 8a3339a..8ee38cd 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -86,9 +86,9 @@ var builtin_setsize(var* local,gc& ngc) { var builtin_system(var* local,gc& ngc) { var str=local[1]; if (str.type!=vm_str) { - return {vm_num,(f64)-1}; + return var::num(-1); } - return {vm_num,(f64)system(str.str().c_str())}; + return var::num((f64)system(str.str().c_str())); } var builtin_input(var* local,gc& ngc) { @@ -180,7 +180,7 @@ var builtin_rand(var* local,gc& ngc) { for(u32 i=0;i<5;++i) { num=(num+rand())*(1.0/(RAND_MAX+1.0)); } - return {vm_num,num}; + return var::num(num); } var builtin_id(var* local,gc& ngc) { @@ -198,12 +198,12 @@ var builtin_int(var* local,gc& ngc) { if (val.type!=vm_num && val.type!=vm_str) { return nil; } - return {vm_num,f64((i32)val.tonum())}; + return var::num(f64((i32)val.tonum())); } var builtin_floor(var* local,gc& ngc) { var val=local[1]; - return {vm_num,std::floor(val.num())}; + return var::num(std::floor(val.num())); } var builtin_num(var* local,gc& ngc) { @@ -218,7 +218,7 @@ var builtin_num(var* local,gc& ngc) { if (std::isnan(res)) { return nil; } - return {vm_num,res}; + return var::num(res); } var builtin_pop(var* local,gc& ngc) { @@ -248,100 +248,100 @@ var builtin_size(var* local,gc& ngc) { case vm_vec: num=val.vec().size(); break; case vm_hash: num=val.hash().size(); break; } - return {vm_num,num}; + return var::num(num); } var builtin_i32xor(var* local,gc& ngc) { - return {vm_num,(f64)(i32(local[1].num())^i32(local[2].num()))}; + return var::num((f64)(i32(local[1].num())^i32(local[2].num()))); } var builtin_i32and(var* local,gc& ngc) { - return {vm_num,(f64)(i32(local[1].num())&i32(local[2].num()))}; + return var::num((f64)(i32(local[1].num())&i32(local[2].num()))); } var builtin_i32or(var* local,gc& ngc) { - return {vm_num,(f64)(i32(local[1].num())|i32(local[2].num()))}; + return var::num((f64)(i32(local[1].num())|i32(local[2].num()))); } var builtin_i32nand(var* local,gc& ngc) { - return {vm_num,(f64)(~(i32(local[1].num())&i32(local[2].num())))}; + return var::num((f64)(~(i32(local[1].num())&i32(local[2].num())))); } var builtin_i32not(var* local,gc& ngc) { - return {vm_num,(f64)(~i32(local[1].num()))}; + return var::num((f64)(~i32(local[1].num()))); } var builtin_u32xor(var* local,gc& ngc) { - return {vm_num,(f64)(u32(local[1].num())^u32(local[2].num()))}; + return var::num((f64)(u32(local[1].num())^u32(local[2].num()))); } var builtin_u32and(var* local,gc& ngc) { - return {vm_num,(f64)(u32(local[1].num())&u32(local[2].num()))}; + return var::num((f64)(u32(local[1].num())&u32(local[2].num()))); } var builtin_u32or(var* local,gc& ngc) { - return {vm_num,(f64)(u32(local[1].num())|u32(local[2].num()))}; + return var::num((f64)(u32(local[1].num())|u32(local[2].num()))); } var builtin_u32nand(var* local,gc& ngc) { - return {vm_num,(f64)(u32)(~(u32(local[1].num())&u32(local[2].num())))}; + return var::num((f64)(u32)(~(u32(local[1].num())&u32(local[2].num())))); } var builtin_u32not(var* local,gc& ngc) { - return {vm_num,(f64)(u32)(~u32(local[1].num()))}; + return var::num((f64)(u32)(~u32(local[1].num()))); } var builtin_pow(var* local,gc& ngc) { var x=local[1]; var y=local[2]; if (x.type!=vm_num || y.type!=vm_num) { - return {vm_num,std::nan("")}; + return var::num(std::nan("")); } - return {vm_num,std::pow(x.num(),y.num())}; + return var::num(std::pow(x.num(),y.num())); } var builtin_sin(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?sin(val.num()):std::nan("")}; + return var::num(val.type==vm_num?sin(val.num()):std::nan("")); } var builtin_cos(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?cos(val.num()):std::nan("")}; + return var::num(val.type==vm_num?cos(val.num()):std::nan("")); } var builtin_tan(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?tan(val.num()):std::nan("")}; + return var::num(val.type==vm_num?tan(val.num()):std::nan("")); } var builtin_exp(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?exp(val.num()):std::nan("")}; + return var::num(val.type==vm_num?exp(val.num()):std::nan("")); } var builtin_lg(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?log(val.num())/log(10.0):std::nan("")}; + return var::num(val.type==vm_num?log(val.num())/log(10.0):std::nan("")); } var builtin_ln(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?log(val.num()):std::nan("")}; + return var::num(val.type==vm_num?log(val.num()):std::nan("")); } var builtin_sqrt(var* local,gc& ngc) { var val=local[1]; - return {vm_num,val.type==vm_num?sqrt(val.num()):std::nan("")}; + return var::num(val.type==vm_num?sqrt(val.num()):std::nan("")); } var builtin_atan2(var* local,gc& ngc) { var x=local[1]; var y=local[2]; if (x.type!=vm_num || y.type!=vm_num) { - return {vm_num,std::nan("")}; + return var::num(std::nan("")); } - return {vm_num,atan2(y.num(),x.num())}; + return var::num(atan2(y.num(),x.num())); } var builtin_isnan(var* local,gc& ngc) { @@ -355,7 +355,7 @@ var builtin_time(var* local,gc& ngc) { return nas_err("time","\"begin\" must be number"); } time_t begin=(time_t)val.num(); - return {vm_num,(f64)time(&begin)}; + return var::num((f64)time(&begin)); } var builtin_contains(var* local,gc& ngc) { @@ -406,9 +406,9 @@ var builtin_find(var* local,gc& ngc) { var haystack=local[2]; usize pos=haystack.tostr().find(needle.tostr()); if (pos==string::npos) { - return {vm_num,(f64)-1}; + return var::num((f64)-1); } - return {vm_num,(f64)pos}; + return var::num((f64)pos); } var builtin_type(var* local,gc& ngc) { @@ -450,7 +450,7 @@ var builtin_substr(var* local,gc& ngc) { var builtin_streq(var* local,gc& ngc) { var a=local[1]; var b=local[2]; - return {vm_num,f64((a.type!=vm_str || b.type!=vm_str)?0:(a.str()==b.str()))}; + return var::num(f64((a.type!=vm_str || b.type!=vm_str)?0:(a.str()==b.str()))); } var builtin_left(var* local,gc& ngc) { @@ -494,7 +494,7 @@ var builtin_cmp(var* local,gc& ngc) { if (a.type!=vm_str || b.type!=vm_str) { return nas_err("cmp","\"a\" and \"b\" must be string"); } - return {vm_num,(f64)strcmp(a.str().c_str(),b.str().c_str())}; + return var::num((f64)strcmp(a.str().c_str(),b.str().c_str())); } var builtin_chr(var* local,gc& ngc) { @@ -600,7 +600,7 @@ var builtin_read(var* local,gc& ngc) { buf.str()=buff; buf.val.gcobj->unmut=true; delete []buff; - return {vm_num,res}; + return var::num(res); } var builtin_write(var* local,gc& ngc) { @@ -612,7 +612,7 @@ var builtin_write(var* local,gc& ngc) { if (str.type!=vm_str) { return nas_err("write","\"str\" must be string"); } - return {vm_num,(f64)fwrite(str.str().c_str(),1,str.str().length(),(FILE*)fd.obj().ptr)}; + return var::num((f64)fwrite(str.str().c_str(),1,str.str().length(),(FILE*)fd.obj().ptr)); } var builtin_seek(var* local,gc& ngc) { @@ -622,7 +622,7 @@ var builtin_seek(var* local,gc& ngc) { if (!fd.objchk(nas_obj::file)) { return nas_err("seek","not a valid filehandle"); } - return {vm_num,(f64)fseek((FILE*)fd.obj().ptr,pos.num(),whence.num())}; + return var::num((f64)fseek((FILE*)fd.obj().ptr,pos.num(),whence.num())); } var builtin_tell(var* local,gc& ngc) { @@ -630,7 +630,7 @@ var builtin_tell(var* local,gc& ngc) { if (!fd.objchk(nas_obj::file)) { return nas_err("tell","not a valid filehandle"); } - return {vm_num,(f64)ftell((FILE*)fd.obj().ptr)}; + return var::num((f64)ftell((FILE*)fd.obj().ptr)); } var builtin_readln(var* local,gc& ngc) { @@ -666,17 +666,17 @@ var builtin_stat(var* local,gc& ngc) { } var ret=ngc.alloc(vm_vec); ret.vec().elems={ - {vm_num,(f64)buf.st_dev}, - {vm_num,(f64)buf.st_ino}, - {vm_num,(f64)buf.st_mode}, - {vm_num,(f64)buf.st_nlink}, - {vm_num,(f64)buf.st_uid}, - {vm_num,(f64)buf.st_gid}, - {vm_num,(f64)buf.st_rdev}, - {vm_num,(f64)buf.st_size}, - {vm_num,(f64)buf.st_atime}, - {vm_num,(f64)buf.st_mtime}, - {vm_num,(f64)buf.st_ctime} + var::num((f64)buf.st_dev), + var::num((f64)buf.st_ino), + var::num((f64)buf.st_mode), + var::num((f64)buf.st_nlink), + var::num((f64)buf.st_uid), + var::num((f64)buf.st_gid), + var::num((f64)buf.st_rdev), + var::num((f64)buf.st_size), + var::num((f64)buf.st_atime), + var::num((f64)buf.st_mtime), + var::num((f64)buf.st_ctime) }; return ret; } @@ -686,7 +686,7 @@ var builtin_eof(var* local,gc& ngc) { if (!fd.objchk(nas_obj::file)) { return nas_err("readln","not a valid filehandle"); } - return {vm_num,(f64)feof((FILE*)fd.obj().ptr)}; + return var::num((f64)feof((FILE*)fd.obj().ptr)); } var builtin_fld(var* local,gc& ngc) { @@ -714,7 +714,7 @@ var builtin_fld(var* local,gc& ngc) { res|=1<<(bit+len-i-1); } } - return {vm_num,(f64)res}; + return var::num((f64)res); } var builtin_sfld(var* local,gc& ngc) { @@ -746,7 +746,7 @@ var builtin_sfld(var* local,gc& ngc) { if (res&(1<<(len-1))) { res|=~((1< (std::chrono::high_resolution_clock::now().time_since_epoch()) .count(); - return {vm_num,res}; + return var::num(res); } var builtin_sysargv(var* local,gc& ngc) { diff --git a/nasal_gc.h b/nasal_gc.h index 43bfd68..8a7f16d 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -39,6 +39,7 @@ enum vm_type:u8 { vm_obj, vm_co }; + const u32 gc_tsize=vm_co-vm_str+1; struct nas_vec; // vector @@ -59,27 +60,27 @@ struct var { nas_val* gcobj; } val; - // vm_none/vm_nil - var(const u8 t=vm_none):type(t) {} - // vm_ret - var(const u8 t,const u32 n):type(t) {val.ret=n;} - // vm_cnt - var(const u8 t,const i64 n):type(t) {val.cnt=n;} - // vm_num - var(const u8 t,const f64 n):type(t) {val.num=n;} - // nas_val - var(const u8 t,nas_val* n):type(t) {val.gcobj=n;} - // vm_addr - var(const u8 t,var* n):type(t) {val.addr=n;} - // copy - var(const var& nr):type(nr.type),val(nr.val) {} + var() = default; + var(const var&) = default; bool operator==(const var& nr) const {return type==nr.type && val.gcobj==nr.val.gcobj;} bool operator!=(const var& nr) const {return type!=nr.type || val.gcobj!=nr.val.gcobj;} + // number and string can be translated to each other - f64 tonum(); + f64 tonum(); string tostr(); friend std::ostream& operator<<(std::ostream&,var&); - bool objchk(u32); + bool objchk(u32); + + // create new var object + static var none(); + static var nil(); + static var ret(u32); + static var cnt(i64); + static var num(f64); + static var gcobj(nas_val*); + static var addr(var*); + + // get content var* addr(); u32 ret (); i64& cnt (); @@ -95,21 +96,25 @@ struct var { struct nas_vec { std::vector elems; + + // mark if this is printed, avoid stackoverflow bool printed; nas_vec():printed(false) {} usize size() const {return elems.size();} - var get_val(const i32); + var get_val(const i32); var* get_mem(const i32); }; struct nas_hash { std::unordered_map elems; + + // mark if this is printed, avoid stackoverflow bool printed; nas_hash():printed(false) {} usize size() const {return elems.size();} - var get_val(const string&); + var get_val(const string&); var* get_mem(const string&); }; @@ -127,13 +132,16 @@ struct nas_func { }; struct nas_upval { + // if on stack, use these three variables bool onstk; - u32 size; + u32 size; var* stk; + + // if not on stack, use this std::vector elems; nas_upval() {onstk=true;stk=nullptr;size=0;} - var& operator[](usize n) {return onstk?stk[n]:elems[n];} + var& operator[](usize n) {return onstk? stk[n]:elems[n];} void clear() {onstk=true;elems.clear();size=0;} }; @@ -194,6 +202,8 @@ struct nas_co { running, dead }; + + // calculation stack var stack[STACK_DEPTH]; u32 pc; @@ -205,29 +215,30 @@ struct nas_co { var upvalr; u32 status; - nas_co() { - clear(); - } + nas_co() {clear();} void clear() { for(u32 i=0;i=size) { - return {vm_none}; + return var::none(); } return elems[n>=0?n:n+size]; } @@ -279,7 +290,7 @@ var nas_hash::get_val(const string& key) { if (elems.count(key)) { return elems.at(key); } else if (elems.count("parents")) { - var ret(vm_none); + var ret=var::none(); var val=elems["parents"]; if (val.type==vm_vec) { for(auto& i:val.vec().elems) { @@ -292,7 +303,7 @@ var nas_hash::get_val(const string& key) { } } } - return {vm_none}; + return var::none(); } var* nas_hash::get_mem(const string& key) { @@ -338,7 +349,7 @@ void nas_func::clear() { } nas_val::nas_val(u8 val_type) { - mark=GC_COLLECTED; + mark=status::collected; type=val_type; unmut=0; switch(val_type) { @@ -378,7 +389,7 @@ void nas_val::clear() { } f64 var::tonum() { - return type!=vm_str?val.num:str2num(str().c_str()); + return type!=vm_str? val.num:str2num(str().c_str()); } string var::tostr() { @@ -412,6 +423,54 @@ bool var::objchk(u32 objtype) { return type==vm_obj && obj().type==objtype && obj().ptr; } +var var::none() { + var t; + t.type=vm_none; + return t; +} + +var var::nil() { + var t; + t.type=vm_nil; + t.val.num=0; + return t; +} + +var var::ret(u32 pc) { + var t; + t.type=vm_ret; + t.val.ret=pc; + return t; +} + +var var::cnt(i64 n) { + var t; + t.type=vm_cnt; + t.val.cnt=n; + return t; +} + +var var::num(f64 n) { + var t; + t.type=vm_num; + t.val.num=n; + return t; +} + +var var::gcobj(nas_val* p) { + var t; + t.type=p->type; // use nas_val::type directly + t.val.gcobj=p; + return t; +} + +var var::addr(var* p) { + var t; + t.type=vm_addr; + t.val.addr=p; + return t; +} + var* var::addr () {return val.addr; } u32 var::ret () {return val.ret; } i64& var::cnt () {return val.cnt; } @@ -424,9 +483,9 @@ nas_upval& var::upval() {return *val.gcobj->ptr.upval;} nas_obj& var::obj () {return *val.gcobj->ptr.obj; } nas_co& var::co () {return *val.gcobj->ptr.co; } -const var zero={vm_num,(f64)0}; -const var one ={vm_num,(f64)1}; -const var nil ={vm_nil,(f64)0}; +const var zero=var::num(0); +const var one =var::num(1); +const var nil =var::nil(); struct gc { /* main context */ @@ -461,6 +520,7 @@ struct gc { std::vector memory; // gc memory std::vector unused[gc_tsize]; // gc free list + // heap increase size u32 incr[gc_tsize]={ 128, // vm_str 128, // vm_vec @@ -488,10 +548,10 @@ struct gc { void init(const std::vector&,const std::vector&); void clear(); void info(); - var alloc(const u8); - var newstr(char); - var newstr(const char*); - var newstr(const string&); + var alloc(const u8); + var newstr(char); + var newstr(const char*); + var newstr(const string&); void ctxchg(nas_co&); void ctxreserve(); }; @@ -509,7 +569,9 @@ void gc::mark() { bfs.push_back(funcr); bfs.push_back(upvalr); bfs.push_back(temp); - if (cort) { // scan main process stack + + // if coroutine is running, scan main process stack from mctx + if (cort) { for(var* i=mctx.stack;i<=mctx.top;++i) { bfs.push_back(*i); } @@ -523,7 +585,7 @@ void gc::mark() { if (tmp.type<=vm_num || tmp.val.gcobj->mark) { continue; } - tmp.val.gcobj->mark=GC_FOUND; + tmp.val.gcobj->mark=nas_val::status::found; switch(tmp.type) { case vm_vec: for(auto& i:tmp.vec().elems) { @@ -561,12 +623,12 @@ void gc::mark() { void gc::sweep() { for(auto i:memory) { - if (i->mark==GC_UNCOLLECTED) { + if (i->mark==nas_val::status::uncollected) { i->clear(); unused[i->type-vm_str].push_back(i); - i->mark=GC_COLLECTED; - } else if (i->mark==GC_FOUND) { - i->mark=GC_UNCOLLECTED; + i->mark=nas_val::status::collected; + } else if (i->mark==nas_val::status::found) { + i->mark=nas_val::status::uncollected; } } } @@ -586,25 +648,30 @@ void gc::extend(u8 type) { } void gc::init(const std::vector& s,const std::vector& argv) { - // initiaize function register + // initialize function register funcr=nil; worktime=0; + // initialize counters for(u8 i=0;iunmut=1; strs[i].str()=s[i]; } + // record arguments env_argv.resize(argv.size()); for(usize i=0;iunmut=1; env_argv[i].str()=argv[i]; } @@ -646,10 +713,10 @@ void gc::info() { std::clog<<" | "<mark=GC_UNCOLLECTED; + var ret=var::gcobj(unused[index].back()); + ret.val.gcobj->mark=nas_val::status::uncollected; unused[index].pop_back(); return ret; } @@ -691,6 +758,7 @@ var gc::newstr(const string& buff) { } void gc::ctxchg(nas_co& ctx) { + // store running state to main context mctx.pc=pc; mctx.top=top; mctx.localr=localr; @@ -700,6 +768,7 @@ void gc::ctxchg(nas_co& ctx) { mctx.canary=canary; mctx.stack=stack; + // restore coroutine context state pc=ctx.pc; top=ctx.top; localr=ctx.localr; @@ -710,12 +779,15 @@ void gc::ctxchg(nas_co& ctx) { stack=ctx.stack; cort=&ctx; + // set coroutine state to running cort->status=nas_co::running; } void gc::ctxreserve() { // pc=0 means this coroutine is finished cort->status=pc? nas_co::suspended:nas_co::dead; + + // store running state to coroutine cort->pc=pc; cort->localr=localr; cort->memr=memr; @@ -724,6 +796,7 @@ void gc::ctxreserve() { cort->canary=canary; cort->top=top; + // restore main context state pc=mctx.pc; localr=mctx.localr; memr=mctx.memr; @@ -738,7 +811,7 @@ void gc::ctxreserve() { // use to print error log and return error value var nas_err(const string& err_f,const string& info) { std::cerr<<"[vm] "<size has 1 place reserved for "me" func.keys[imm[pc]]=func.psize; - func.local[func.psize++]={vm_none}; + func.local[func.psize++]=var::none(); } void vm::o_deft() { @@ -444,7 +444,7 @@ void vm::o_unot() { case vm_str:{ const f64 num=str2num(val.str().c_str()); if (std::isnan(num)) { - top[0]={vm_num,(f64)val.str().empty()}; + top[0]=var::num((f64)val.str().empty()); } else { top[0]=num?zero:one; } @@ -457,11 +457,11 @@ void vm::o_unot() { } void vm::o_usub() { - top[0]={vm_num,-top[0].tonum()}; + top[0]=var::num(-top[0].tonum()); } #define op_calc(type)\ - top[-1]={vm_num,top[-1].tonum() type top[0].tonum()};\ + top[-1]=var::num(top[-1].tonum() type top[0].tonum());\ --top; void vm::o_add() {op_calc(+);} @@ -474,7 +474,7 @@ void vm::o_lnk() { } #define op_calc_const(type)\ - top[0]={vm_num,top[0].tonum() type cnum[imm[pc]]}; + top[0]=var::num(top[0].tonum() type cnum[imm[pc]]); void vm::o_addc() {op_calc_const(+);} void vm::o_subc() {op_calc_const(-);} @@ -485,7 +485,7 @@ void vm::o_lnkc() { } #define op_calc_eq(type)\ - top[-1]=memr[0]={vm_num,memr[0].tonum() type top[-1].tonum()};\ + top[-1]=memr[0]=var::num(memr[0].tonum() type top[-1].tonum());\ memr=nullptr;\ top-=imm[pc]+1; @@ -500,7 +500,7 @@ void vm::o_lnkeq() { } #define op_calc_eq_const(type)\ - top[0]=memr[0]={vm_num,memr[0].tonum() type cnum[imm[pc]&0x7fffffff]};\ + top[0]=memr[0]=var::num(memr[0].tonum() type cnum[imm[pc]&0x7fffffff]);\ memr=nullptr;\ top-=(imm[pc]>>31); @@ -601,7 +601,7 @@ void vm::o_cnt() { die("must use vector in forindex/foreach"); return; } - (++top)[0]={vm_cnt,(i64)-1}; + (++top)[0]=var::cnt(-1); } void vm::o_findex() { @@ -609,7 +609,7 @@ void vm::o_findex() { pc=imm[pc]-1; return; } - top[1]={vm_num,(f64)top[0].cnt()}; + top[1]=var::num(top[0].cnt()); ++top; } @@ -666,7 +666,7 @@ void vm::o_callv() { die("out of range:"+std::to_string(val.tonum())); return; } - top[0]={vm_num,f64((u8)str[num>=0? num:num+len])}; + top[0]=var::num(f64((u8)str[num>=0? num:num+len])); } else { die("must call a vector/hash/string"); return; @@ -753,8 +753,8 @@ void vm::o_callfv() { } top[0]=upvalr; - (++top)[0]={vm_addr,localr}; - (++top)[0]={vm_ret,pc}; + (++top)[0]=var::addr(localr); + (++top)[0]=var::ret(pc); pc=func.entry-1; localr=local; upvalr=nil; @@ -797,8 +797,8 @@ void vm::o_callfh() { } top[0]=upvalr; - (++top)[0]={vm_addr,localr}; - (++top)[0]={vm_ret,pc}; // rewrite top with vm_ret + (++top)[0]=var::addr(localr); + (++top)[0]=var::ret(pc); // rewrite top with vm_ret pc=func.entry-1; localr=local; upvalr=nil; @@ -806,12 +806,18 @@ void vm::o_callfh() { void vm::o_callb() { // reserve place for builtin function return, - // in fact this code is changed because of coroutine + // this code is written for coroutine (++top)[0]=nil; - // this ++top should not be used like: (++top)[0] here - // because if running a builtin function about coroutine + + // if running a builtin function about coroutine // (top) will be set to another context.top, instead of main_context.top - top[0]=(*builtin[imm[pc]].func)(localr,ngc); + var tmp=(*builtin[imm[pc]].func)(localr,ngc); + + // so we use tmp variable to store this return value + // and set it to top[0] later + top[0]=tmp; + + // if get none, this means errors occurred when calling this native function if (top[0].type==vm_none) { die("native function error"); return;