use new way of constructing var objects

This commit is contained in:
ValKmjolnir 2023-01-05 22:42:17 +08:00
parent 48611c50f7
commit 268a03864e
9 changed files with 281 additions and 202 deletions

View File

@ -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 // ok, you must know that vm_num now is not managed by gc
// if want to return a gc object, use ngc->alloc(type) // if want to return a gc object, use ngc->alloc(type)
// usage of gc is the same as adding a native function // 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 // then put function name and address into this table

View File

@ -606,7 +606,7 @@ var fib(var* args,usize size,gc* ngc){
return nas_err("extern_fib","\"num\" must be number"); return nas_err("extern_fib","\"num\" must be number");
// vm_num作为普通的数字类型不是内存管理的对象所以无需申请 // vm_num作为普通的数字类型不是内存管理的对象所以无需申请
// 如果需要返回内存管理的对象请使用ngc->alloc(type) // 如果需要返回内存管理的对象请使用ngc->alloc(type)
return {vm_num,fibonaci(num.tonum())}; return var::num(fibonaci(num.tonum()));
} }
// 然后将函数名字和函数地址放到一个表里,一定要记住表尾是{nullptr,nullptr} // 然后将函数名字和函数地址放到一个表里,一定要记住表尾是{nullptr,nullptr}

View File

@ -13,7 +13,7 @@ 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 {vm_num,fibonaci(num.tonum())}; return var::num(fibonaci(num.tonum()));
} }
var quick_fib(var* args,usize size,gc* ngc) { 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(); double num=args[0].tonum();
if (num<2) { if (num<2) {
return {vm_num,num}; return var::num(num);
} }
double a=1,b=1,res=0; double a=1,b=1,res=0;
for(double i=1;i<num;i+=1) { for(double i=1;i<num;i+=1) {
@ -30,7 +30,7 @@ var quick_fib(var* args,usize size,gc* ngc) {
a=b; a=b;
b=res; b=res;
} }
return {vm_num,res}; return var::num(res);
} }
mod_func func_tbl[]={ mod_func func_tbl[]={

View File

@ -73,14 +73,14 @@ public:
noecho_input this_window; noecho_input this_window;
var nas_getch(var* args,usize size,gc* ngc) { var nas_getch(var* args,usize size,gc* ngc) {
return {vm_num,(double)this_window.noecho_getch()}; return var::num((double)this_window.noecho_getch());
} }
var nas_kbhit(var* args,usize size,gc* ngc) { var nas_kbhit(var* args,usize size,gc* ngc) {
return {vm_num,(double)this_window.noecho_kbhit()}; return var::num((double)this_window.noecho_kbhit());
} }
var nas_noblock(var* args,usize size,gc* ngc) { var nas_noblock(var* args,usize size,gc* ngc) {
if (this_window.noecho_kbhit()) { if (this_window.noecho_kbhit()) {
return {vm_num,(double)this_window.noecho_getch()}; return var::num((double)this_window.noecho_getch());
} }
return nil; return nil;
} }

View File

@ -24,8 +24,8 @@ var nas_vec2_add(var* args,usize size,gc* ngc) {
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()+v1[0].num()}); res.vec().elems.push_back(var::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[1].num()+v1[1].num()));
return res; return res;
} }
@ -37,8 +37,8 @@ var nas_vec2_sub(var* args,usize size,gc* ngc) {
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()-v1[0].num()}); res.vec().elems.push_back(var::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[1].num()-v1[1].num()));
return res; return res;
} }
@ -50,8 +50,8 @@ var nas_vec2_mult(var* args,usize size,gc* ngc) {
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()*v1[0].num()}); res.vec().elems.push_back(var::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[1].num()*v1[1].num()));
return res; return res;
} }
@ -63,8 +63,8 @@ var nas_vec2_div(var* args,usize size,gc* ngc) {
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()/v1[0].num()}); res.vec().elems.push_back(var::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[1].num()/v1[1].num()));
return res; return res;
} }
@ -75,8 +75,8 @@ var nas_vec2_neg(var* args,usize size,gc* ngc) {
if (v0.size()!=2) if (v0.size()!=2)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,-v0[0].num()}); res.vec().elems.push_back(var::num(-v0[0].num()));
res.vec().elems.push_back({vm_num,-v0[1].num()}); res.vec().elems.push_back(var::num(-v0[1].num()));
return res; return res;
} }
@ -90,8 +90,8 @@ var nas_vec2_norm(var* args,usize size,gc* ngc) {
auto y=v0[1].num(); auto y=v0[1].num();
auto t=std::sqrt(x*x+y*y); auto t=std::sqrt(x*x+y*y);
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,x/t}); res.vec().elems.push_back(var::num(x/t));
res.vec().elems.push_back({vm_num,y/t}); res.vec().elems.push_back(var::num(y/t));
return res; return res;
} }
@ -103,7 +103,7 @@ var nas_vec2_len(var* args,usize size,gc* ngc) {
return nil; return nil;
auto x=v0[0].num(); auto x=v0[0].num();
auto y=v0[1].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) { 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; auto& v1=args[1].vec().elems;
if (v0.size()!=2 || v1.size()!=2) if (v0.size()!=2 || v1.size()!=2)
return nil; 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) { 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) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()+v1[0].num()}); res.vec().elems.push_back(var::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[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[2].num()+v1[2].num()));
return res; return res;
} }
@ -138,9 +138,9 @@ var nas_vec3_sub(var* args,usize size,gc* ngc) {
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()-v1[0].num()}); res.vec().elems.push_back(var::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[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[2].num()-v1[2].num()));
return res; return res;
} }
@ -152,9 +152,9 @@ var nas_vec3_mult(var* args,usize size,gc* ngc) {
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()*v1[0].num()}); res.vec().elems.push_back(var::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[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[2].num()*v1[2].num()));
return res; return res;
} }
@ -166,9 +166,9 @@ var nas_vec3_div(var* args,usize size,gc* ngc) {
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()/v1[0].num()}); res.vec().elems.push_back(var::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[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[2].num()/v1[2].num()));
return res; return res;
} }
@ -179,9 +179,9 @@ var nas_vec3_neg(var* args,usize size,gc* ngc) {
if (v0.size()!=3) if (v0.size()!=3)
return nil; return nil;
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,-v0[0].num()}); res.vec().elems.push_back(var::num(-v0[0].num()));
res.vec().elems.push_back({vm_num,-v0[1].num()}); res.vec().elems.push_back(var::num(-v0[1].num()));
res.vec().elems.push_back({vm_num,-v0[2].num()}); res.vec().elems.push_back(var::num(-v0[2].num()));
return res; return res;
} }
@ -196,9 +196,9 @@ var nas_vec3_norm(var* args,usize size,gc* ngc) {
auto z=v0[2].num(); auto z=v0[2].num();
auto t=std::sqrt(x*x+y*y+z*z); auto t=std::sqrt(x*x+y*y+z*z);
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,x/t}); res.vec().elems.push_back(var::num(x/t));
res.vec().elems.push_back({vm_num,y/t}); res.vec().elems.push_back(var::num(y/t));
res.vec().elems.push_back({vm_num,z/t}); res.vec().elems.push_back(var::num(z/t));
return res; return res;
} }
@ -211,7 +211,7 @@ var nas_vec3_len(var* args,usize size,gc* ngc) {
auto x=v0[0].num(); auto x=v0[0].num();
auto y=v0[1].num(); auto y=v0[1].num();
auto z=v0[2].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) { 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; return nil;
auto angle=args[1].num(); auto angle=args[1].num();
var res=ngc->alloc(vm_vec); var res=ngc->alloc(vm_vec);
res.vec().elems.push_back({vm_num,v0[0].num()}); res.vec().elems.push_back(var::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(var::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[2].num()*std::cos(angle)-v0[1].num()*std::sin(angle)));
return res; return res;
} }
@ -236,9 +236,9 @@ var nas_rotate_y(var* args,usize size,gc* ngc) {
return nil; return nil;
auto angle=args[1].num(); auto angle=args[1].num();
var res=ngc->alloc(vm_vec); 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(var::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(var::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::sin(angle)+v0[2].num()*std::cos(angle)));
return res; return res;
} }
@ -250,9 +250,9 @@ var nas_rotate_z(var* args,usize size,gc* ngc) {
return nil; return nil;
auto angle=args[1].num(); auto angle=args[1].num();
var res=ngc->alloc(vm_vec); 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(var::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(var::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[2].num()));
return res; return res;
} }
@ -263,7 +263,7 @@ var nas_vec3_dot(var* args,usize size,gc* ngc) {
auto& v1=args[1].vec().elems; auto& v1=args[1].vec().elems;
if (v0.size()!=3 || v1.size()!=3) if (v0.size()!=3 || v1.size()!=3)
return nil; 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[]={ mod_func func_tbl[]={

View File

@ -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) 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"); return nas_err("socket","\"af\", \"type\", \"protocol\" should be number");
int sd=socket(args[0].num(),args[1].num(),args[2].num()); 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) { var nas_closesocket(var* args,usize size,gc* ngc) {
if (args[0].type!=vm_num) if (args[0].type!=vm_num)
return nas_err("closesocket","\"\" should be number"); return nas_err("closesocket","\"\" should be number");
#ifdef _WIN32 #ifdef _WIN32
return {vm_num,(double)closesocket(args[0].num())}; return var::num((double)closesocket(args[0].num()));
#else #else
return {vm_num,(double)close(args[0].num())}; return var::num((double)close(args[0].num()));
#endif #endif
} }
@ -47,7 +47,7 @@ var nas_shutdown(var* args,usize size,gc* ngc) {
return nas_err("shutdown","\"sd\" must be a number"); return nas_err("shutdown","\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("shutdown","\"how\" must be a number"); 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) { 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_family=AF_INET;
server.sin_addr.s_addr=inet_addr(args[1].str().c_str()); server.sin_addr.s_addr=inet_addr(args[1].str().c_str());
server.sin_port=htons(args[2].num()); 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) { 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"); return nas_err("listen","\"sd\" must be a number");
if (args[1].type!=vm_num) if (args[1].type!=vm_num)
return nas_err("listen","\"backlog\" must be a number"); 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) { 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()); addr.sin_port=htons(args[2].num());
hostent* entry=gethostbyname(args[1].str().c_str()); hostent* entry=gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); 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) { var nas_accept(var* args,usize size,gc* ngc) {
@ -101,7 +101,7 @@ var nas_accept(var* args,usize size,gc* ngc) {
#endif #endif
var res=ngc->temp=ngc->alloc(vm_hash); var res=ngc->temp=ngc->alloc(vm_hash);
auto& hash=res.hash().elems; 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)); hash["ip"]=ngc->newstr(inet_ntoa(client.sin_addr));
ngc->temp=nil; ngc->temp=nil;
return res; return res;
@ -114,7 +114,7 @@ var nas_send(var* args,usize size,gc* ngc) {
return nas_err("send","\"buff\" must be a string"); return nas_err("send","\"buff\" must be a string");
if (args[2].type!=vm_num) if (args[2].type!=vm_num)
return nas_err("send","\"flags\" muse be a number"); 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) { 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()); addr.sin_port=htons(args[2].num());
hostent* entry=gethostbyname(args[1].str().c_str()); hostent* entry=gethostbyname(args[1].str().c_str());
memcpy(&addr.sin_addr,entry->h_addr,entry->h_length); 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) { 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); var res=ngc->temp=ngc->alloc(vm_hash);
auto& hash=res.hash().elems; auto& hash=res.hash().elems;
char* buf=new char[(int)args[1].num()]; 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); hash["str"]=ngc->newstr(buf);
delete[] buf; delete[] buf;
ngc->temp=nil; ngc->temp=nil;
@ -171,9 +171,9 @@ var nas_recvfrom(var* args,usize size,gc* ngc) {
auto& hash=res.hash().elems; auto& hash=res.hash().elems;
char* buf=new char[(int)args[1].num()+1]; char* buf=new char[(int)args[1].num()+1];
#ifdef _WIN32 #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 #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 #endif
buf[(int)hash["size"].num()]=0; buf[(int)hash["size"].num()]=0;
hash["str"]=ngc->newstr(buf); hash["str"]=ngc->newstr(buf);

View File

@ -86,9 +86,9 @@ var builtin_setsize(var* local,gc& ngc) {
var builtin_system(var* local,gc& ngc) { var builtin_system(var* local,gc& ngc) {
var str=local[1]; var str=local[1];
if (str.type!=vm_str) { 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) { 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) { for(u32 i=0;i<5;++i) {
num=(num+rand())*(1.0/(RAND_MAX+1.0)); num=(num+rand())*(1.0/(RAND_MAX+1.0));
} }
return {vm_num,num}; return var::num(num);
} }
var builtin_id(var* local,gc& ngc) { 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) { if (val.type!=vm_num && val.type!=vm_str) {
return nil; return nil;
} }
return {vm_num,f64((i32)val.tonum())}; return var::num(f64((i32)val.tonum()));
} }
var builtin_floor(var* local,gc& ngc) { var builtin_floor(var* local,gc& ngc) {
var val=local[1]; 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) { var builtin_num(var* local,gc& ngc) {
@ -218,7 +218,7 @@ var builtin_num(var* local,gc& ngc) {
if (std::isnan(res)) { if (std::isnan(res)) {
return nil; return nil;
} }
return {vm_num,res}; return var::num(res);
} }
var builtin_pop(var* local,gc& ngc) { 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_vec: num=val.vec().size(); break;
case vm_hash: num=val.hash().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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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) { 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 builtin_pow(var* local,gc& ngc) {
var x=local[1]; var x=local[1];
var y=local[2]; var y=local[2];
if (x.type!=vm_num || y.type!=vm_num) { 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 builtin_sin(var* local,gc& ngc) {
var val=local[1]; 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 builtin_cos(var* local,gc& ngc) {
var val=local[1]; 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 builtin_tan(var* local,gc& ngc) {
var val=local[1]; 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 builtin_exp(var* local,gc& ngc) {
var val=local[1]; 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 builtin_lg(var* local,gc& ngc) {
var val=local[1]; 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 builtin_ln(var* local,gc& ngc) {
var val=local[1]; 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 builtin_sqrt(var* local,gc& ngc) {
var val=local[1]; 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 builtin_atan2(var* local,gc& ngc) {
var x=local[1]; var x=local[1];
var y=local[2]; var y=local[2];
if (x.type!=vm_num || y.type!=vm_num) { 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) { 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"); return nas_err("time","\"begin\" must be number");
} }
time_t begin=(time_t)val.num(); 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) { var builtin_contains(var* local,gc& ngc) {
@ -406,9 +406,9 @@ var builtin_find(var* local,gc& ngc) {
var haystack=local[2]; var haystack=local[2];
usize pos=haystack.tostr().find(needle.tostr()); usize pos=haystack.tostr().find(needle.tostr());
if (pos==string::npos) { 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) { 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 builtin_streq(var* local,gc& ngc) {
var a=local[1]; var a=local[1];
var b=local[2]; 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) { 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) { if (a.type!=vm_str || b.type!=vm_str) {
return nas_err("cmp","\"a\" and \"b\" must be string"); 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) { var builtin_chr(var* local,gc& ngc) {
@ -600,7 +600,7 @@ var builtin_read(var* local,gc& ngc) {
buf.str()=buff; buf.str()=buff;
buf.val.gcobj->unmut=true; buf.val.gcobj->unmut=true;
delete []buff; delete []buff;
return {vm_num,res}; return var::num(res);
} }
var builtin_write(var* local,gc& ngc) { var builtin_write(var* local,gc& ngc) {
@ -612,7 +612,7 @@ var builtin_write(var* local,gc& ngc) {
if (str.type!=vm_str) { if (str.type!=vm_str) {
return nas_err("write","\"str\" must be string"); 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) { var builtin_seek(var* local,gc& ngc) {
@ -622,7 +622,7 @@ var builtin_seek(var* local,gc& ngc) {
if (!fd.objchk(nas_obj::file)) { if (!fd.objchk(nas_obj::file)) {
return nas_err("seek","not a valid filehandle"); 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) { var builtin_tell(var* local,gc& ngc) {
@ -630,7 +630,7 @@ var builtin_tell(var* local,gc& ngc) {
if (!fd.objchk(nas_obj::file)) { if (!fd.objchk(nas_obj::file)) {
return nas_err("tell","not a valid filehandle"); 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) { var builtin_readln(var* local,gc& ngc) {
@ -666,17 +666,17 @@ var builtin_stat(var* local,gc& ngc) {
} }
var ret=ngc.alloc(vm_vec); var ret=ngc.alloc(vm_vec);
ret.vec().elems={ ret.vec().elems={
{vm_num,(f64)buf.st_dev}, var::num((f64)buf.st_dev),
{vm_num,(f64)buf.st_ino}, var::num((f64)buf.st_ino),
{vm_num,(f64)buf.st_mode}, var::num((f64)buf.st_mode),
{vm_num,(f64)buf.st_nlink}, var::num((f64)buf.st_nlink),
{vm_num,(f64)buf.st_uid}, var::num((f64)buf.st_uid),
{vm_num,(f64)buf.st_gid}, var::num((f64)buf.st_gid),
{vm_num,(f64)buf.st_rdev}, var::num((f64)buf.st_rdev),
{vm_num,(f64)buf.st_size}, var::num((f64)buf.st_size),
{vm_num,(f64)buf.st_atime}, var::num((f64)buf.st_atime),
{vm_num,(f64)buf.st_mtime}, var::num((f64)buf.st_mtime),
{vm_num,(f64)buf.st_ctime} var::num((f64)buf.st_ctime)
}; };
return ret; return ret;
} }
@ -686,7 +686,7 @@ var builtin_eof(var* local,gc& ngc) {
if (!fd.objchk(nas_obj::file)) { if (!fd.objchk(nas_obj::file)) {
return nas_err("readln","not a valid filehandle"); 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) { var builtin_fld(var* local,gc& ngc) {
@ -714,7 +714,7 @@ var builtin_fld(var* local,gc& ngc) {
res|=1<<(bit+len-i-1); res|=1<<(bit+len-i-1);
} }
} }
return {vm_num,(f64)res}; return var::num((f64)res);
} }
var builtin_sfld(var* local,gc& ngc) { var builtin_sfld(var* local,gc& ngc) {
@ -746,7 +746,7 @@ var builtin_sfld(var* local,gc& ngc) {
if (res&(1<<(len-1))) { if (res&(1<<(len-1))) {
res|=~((1<<len)-1); res|=~((1<<len)-1);
} }
return {vm_num,(f64)((i32)res)}; return var::num((f64)((i32)res));
} }
var builtin_setfld(var* local,gc& ngc) { var builtin_setfld(var* local,gc& ngc) {
@ -808,8 +808,8 @@ var builtin_pipe(var* local,gc& ngc) {
if (pipe(fd)==-1) { if (pipe(fd)==-1) {
return nas_err("pipe","failed to create pipe"); return nas_err("pipe","failed to create pipe");
} }
res.vec().elems.push_back({vm_num,(f64)fd[0]}); res.vec().elems.push_back(var::num((f64)fd[0]));
res.vec().elems.push_back({vm_num,(f64)fd[1]}); res.vec().elems.push_back(var::num((f64)fd[1]));
return res; return res;
#endif #endif
return nas_err("pipe","not supported"); return nas_err("pipe","not supported");
@ -821,7 +821,7 @@ var builtin_fork(var* local,gc& ngc) {
if (res<0) { if (res<0) {
return nas_err("fork","failed to fork a process"); return nas_err("fork","failed to fork a process");
} }
return {vm_num,(f64)res}; return var::num((f64)res);
#endif #endif
return nas_err("fork","not supported"); return nas_err("fork","not supported");
} }
@ -836,8 +836,8 @@ var builtin_waitpid(var* local,gc& ngc) {
i32 ret_pid,status; i32 ret_pid,status;
ret_pid=waitpid(pid.num(),&status,nohang.num()==0?0:WNOHANG); ret_pid=waitpid(pid.num(),&status,nohang.num()==0?0:WNOHANG);
var vec=ngc.alloc(vm_vec); var vec=ngc.alloc(vm_vec);
vec.vec().elems.push_back({vm_num,(f64)ret_pid}); vec.vec().elems.push_back(var::num((f64)ret_pid));
vec.vec().elems.push_back({vm_num,(f64)status}); vec.vec().elems.push_back(var::num((f64)status));
return vec; return vec;
#endif #endif
return nas_err("waitpid","not supported"); return nas_err("waitpid","not supported");
@ -895,9 +895,9 @@ var builtin_closedir(var* local,gc& ngc) {
var builtin_chdir(var* local,gc& ngc) { var builtin_chdir(var* local,gc& ngc) {
var path=local[1]; var path=local[1];
if (path.type!=vm_str) { if (path.type!=vm_str) {
return {vm_num,(f64)-1}; return var::num((f64)-1);
} }
return {vm_num,(f64)chdir(path.str().c_str())}; return var::num((f64)chdir(path.str().c_str()));
} }
var builtin_environ(var* local,gc& ngc) { var builtin_environ(var* local,gc& ngc) {
@ -1136,9 +1136,9 @@ var builtin_cocreate(var* local,gc& ngc) {
cort.localr[0]=func.func().local[0]; cort.localr[0]=func.func().local[0];
cort.top[0]=nil; // old upvalr cort.top[0]=nil; // old upvalr
cort.top++; cort.top++;
cort.top[0]={vm_addr,(var*)nullptr}; // old localr cort.top[0]=var::addr((var*)nullptr); // old localr
cort.top++; cort.top++;
cort.top[0]={vm_ret,(u32)0}; // old pc, set to zero to make op_ret recognizing this as coroutine function cort.top[0]=var::ret(0); // old pc, set to zero to make op_ret recognizing this as coroutine function
cort.funcr=func; // make sure the coroutine function can use correct upvalues cort.funcr=func; // make sure the coroutine function can use correct upvalues
cort.status=nas_co::suspended; cort.status=nas_co::suspended;
@ -1216,7 +1216,7 @@ var builtin_millisec(var* local,gc& ngc) {
f64 res=std::chrono::duration_cast<std::chrono::milliseconds> f64 res=std::chrono::duration_cast<std::chrono::milliseconds>
(std::chrono::high_resolution_clock::now().time_since_epoch()) (std::chrono::high_resolution_clock::now().time_since_epoch())
.count(); .count();
return {vm_num,res}; return var::num(res);
} }
var builtin_sysargv(var* local,gc& ngc) { var builtin_sysargv(var* local,gc& ngc) {

View File

@ -39,6 +39,7 @@ enum vm_type:u8 {
vm_obj, vm_obj,
vm_co vm_co
}; };
const u32 gc_tsize=vm_co-vm_str+1; const u32 gc_tsize=vm_co-vm_str+1;
struct nas_vec; // vector struct nas_vec; // vector
@ -59,27 +60,27 @@ struct var {
nas_val* gcobj; nas_val* gcobj;
} val; } val;
// vm_none/vm_nil var() = default;
var(const u8 t=vm_none):type(t) {} var(const var&) = default;
// 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) {}
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;}
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 // number and string can be translated to each other
f64 tonum(); f64 tonum();
string tostr(); string tostr();
friend std::ostream& operator<<(std::ostream&,var&); 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(); var* addr();
u32 ret (); u32 ret ();
i64& cnt (); i64& cnt ();
@ -95,21 +96,25 @@ struct var {
struct nas_vec { struct nas_vec {
std::vector<var> elems; std::vector<var> elems;
// mark if this is printed, avoid stackoverflow
bool printed; bool printed;
nas_vec():printed(false) {} nas_vec():printed(false) {}
usize size() const {return elems.size();} usize size() const {return elems.size();}
var get_val(const i32); var get_val(const i32);
var* get_mem(const i32); var* get_mem(const i32);
}; };
struct nas_hash { struct nas_hash {
std::unordered_map<string,var> elems; std::unordered_map<string,var> elems;
// mark if this is printed, avoid stackoverflow
bool printed; bool printed;
nas_hash():printed(false) {} nas_hash():printed(false) {}
usize size() const {return elems.size();} usize size() const {return elems.size();}
var get_val(const string&); var get_val(const string&);
var* get_mem(const string&); var* get_mem(const string&);
}; };
@ -127,13 +132,16 @@ struct nas_func {
}; };
struct nas_upval { struct nas_upval {
// if on stack, use these three variables
bool onstk; bool onstk;
u32 size; u32 size;
var* stk; var* stk;
// if not on stack, use this
std::vector<var> elems; std::vector<var> elems;
nas_upval() {onstk=true;stk=nullptr;size=0;} 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;} void clear() {onstk=true;elems.clear();size=0;}
}; };
@ -194,6 +202,8 @@ struct nas_co {
running, running,
dead dead
}; };
// calculation stack
var stack[STACK_DEPTH]; var stack[STACK_DEPTH];
u32 pc; u32 pc;
@ -205,29 +215,30 @@ struct nas_co {
var upvalr; var upvalr;
u32 status; u32 status;
nas_co() { nas_co() {clear();}
clear();
}
void clear() { void clear() {
for(u32 i=0;i<STACK_DEPTH;++i) { for(u32 i=0;i<STACK_DEPTH;++i) {
stack[i]={vm_nil,(f64)0}; stack[i]=var::nil();
} }
pc=0; pc=0;
localr=nullptr; localr=nullptr;
memr=nullptr; memr=nullptr;
top=stack; top=stack;
status=nas_co::suspended; status=nas_co::suspended;
funcr={vm_nil,(f64)0}; funcr=var::nil();
upvalr={vm_nil,(f64)0}; upvalr=var::nil();
} }
}; };
const u8 GC_UNCOLLECTED=0;
const u8 GC_COLLECTED =1;
const u8 GC_FOUND =2;
struct nas_val { struct nas_val {
u8 mark; enum status:u8 {
u8 type; uncollected=0,
collected,
found
};
u8 mark; // mark if it is visited by gc or collected by gc
u8 type; // value type
u8 unmut; // used to mark if a string is unmutable u8 unmut; // used to mark if a string is unmutable
union { union {
string* str; string* str;
@ -247,7 +258,7 @@ struct nas_val {
var nas_vec::get_val(const i32 n) { var nas_vec::get_val(const i32 n) {
i32 size=elems.size(); i32 size=elems.size();
if (n<-size || n>=size) { if (n<-size || n>=size) {
return {vm_none}; return var::none();
} }
return elems[n>=0?n:n+size]; return elems[n>=0?n:n+size];
} }
@ -279,7 +290,7 @@ var nas_hash::get_val(const string& key) {
if (elems.count(key)) { if (elems.count(key)) {
return elems.at(key); return elems.at(key);
} else if (elems.count("parents")) { } else if (elems.count("parents")) {
var ret(vm_none); var ret=var::none();
var val=elems["parents"]; var val=elems["parents"];
if (val.type==vm_vec) { if (val.type==vm_vec) {
for(auto& i:val.vec().elems) { 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) { var* nas_hash::get_mem(const string& key) {
@ -338,7 +349,7 @@ void nas_func::clear() {
} }
nas_val::nas_val(u8 val_type) { nas_val::nas_val(u8 val_type) {
mark=GC_COLLECTED; mark=status::collected;
type=val_type; type=val_type;
unmut=0; unmut=0;
switch(val_type) { switch(val_type) {
@ -378,7 +389,7 @@ void nas_val::clear() {
} }
f64 var::tonum() { 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() { string var::tostr() {
@ -412,6 +423,54 @@ bool var::objchk(u32 objtype) {
return type==vm_obj && obj().type==objtype && obj().ptr; 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; } var* var::addr () {return val.addr; }
u32 var::ret () {return val.ret; } u32 var::ret () {return val.ret; }
i64& var::cnt () {return val.cnt; } 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_obj& var::obj () {return *val.gcobj->ptr.obj; }
nas_co& var::co () {return *val.gcobj->ptr.co; } nas_co& var::co () {return *val.gcobj->ptr.co; }
const var zero={vm_num,(f64)0}; const var zero=var::num(0);
const var one ={vm_num,(f64)1}; const var one =var::num(1);
const var nil ={vm_nil,(f64)0}; const var nil =var::nil();
struct gc { struct gc {
/* main context */ /* main context */
@ -461,6 +520,7 @@ struct gc {
std::vector<nas_val*> memory; // gc memory std::vector<nas_val*> memory; // gc memory
std::vector<nas_val*> unused[gc_tsize]; // gc free list std::vector<nas_val*> unused[gc_tsize]; // gc free list
// heap increase size
u32 incr[gc_tsize]={ u32 incr[gc_tsize]={
128, // vm_str 128, // vm_str
128, // vm_vec 128, // vm_vec
@ -488,10 +548,10 @@ struct gc {
void init(const std::vector<string>&,const std::vector<string>&); void init(const std::vector<string>&,const std::vector<string>&);
void clear(); void clear();
void info(); void info();
var alloc(const u8); var alloc(const u8);
var newstr(char); var newstr(char);
var newstr(const char*); var newstr(const char*);
var newstr(const string&); var newstr(const string&);
void ctxchg(nas_co&); void ctxchg(nas_co&);
void ctxreserve(); void ctxreserve();
}; };
@ -509,7 +569,9 @@ void gc::mark() {
bfs.push_back(funcr); bfs.push_back(funcr);
bfs.push_back(upvalr); bfs.push_back(upvalr);
bfs.push_back(temp); 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) { for(var* i=mctx.stack;i<=mctx.top;++i) {
bfs.push_back(*i); bfs.push_back(*i);
} }
@ -523,7 +585,7 @@ void gc::mark() {
if (tmp.type<=vm_num || tmp.val.gcobj->mark) { if (tmp.type<=vm_num || tmp.val.gcobj->mark) {
continue; continue;
} }
tmp.val.gcobj->mark=GC_FOUND; tmp.val.gcobj->mark=nas_val::status::found;
switch(tmp.type) { switch(tmp.type) {
case vm_vec: case vm_vec:
for(auto& i:tmp.vec().elems) { for(auto& i:tmp.vec().elems) {
@ -561,12 +623,12 @@ void gc::mark() {
void gc::sweep() { void gc::sweep() {
for(auto i:memory) { for(auto i:memory) {
if (i->mark==GC_UNCOLLECTED) { if (i->mark==nas_val::status::uncollected) {
i->clear(); i->clear();
unused[i->type-vm_str].push_back(i); unused[i->type-vm_str].push_back(i);
i->mark=GC_COLLECTED; i->mark=nas_val::status::collected;
} else if (i->mark==GC_FOUND) { } else if (i->mark==nas_val::status::found) {
i->mark=GC_UNCOLLECTED; i->mark=nas_val::status::uncollected;
} }
} }
} }
@ -586,25 +648,30 @@ void gc::extend(u8 type) {
} }
void gc::init(const std::vector<string>& s,const std::vector<string>& argv) { void gc::init(const std::vector<string>& s,const std::vector<string>& argv) {
// initiaize function register // initialize function register
funcr=nil; funcr=nil;
worktime=0; worktime=0;
// initialize counters
for(u8 i=0;i<gc_tsize;++i) { for(u8 i=0;i<gc_tsize;++i) {
size[i]=gcnt[i]=acnt[i]=0; size[i]=gcnt[i]=acnt[i]=0;
} }
// coroutine pointer set to nullpre
cort=nullptr; cort=nullptr;
// init constant strings // init constant strings
strs.resize(s.size()); strs.resize(s.size());
for(u32 i=0;i<strs.size();++i) { for(u32 i=0;i<strs.size();++i) {
strs[i]={vm_str,new nas_val(vm_str)}; strs[i]=var::gcobj(new nas_val(vm_str));
strs[i].val.gcobj->unmut=1; strs[i].val.gcobj->unmut=1;
strs[i].str()=s[i]; strs[i].str()=s[i];
} }
// record arguments // record arguments
env_argv.resize(argv.size()); env_argv.resize(argv.size());
for(usize i=0;i<argv.size();++i) { for(usize i=0;i<argv.size();++i) {
env_argv[i]={vm_str,new nas_val(vm_str)}; env_argv[i]=var::gcobj(new nas_val(vm_str));
env_argv[i].val.gcobj->unmut=1; env_argv[i].val.gcobj->unmut=1;
env_argv[i].str()=argv[i]; env_argv[i].str()=argv[i];
} }
@ -646,10 +713,10 @@ void gc::info() {
std::clog<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<size[i]<<"\n"; std::clog<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<size[i]<<"\n";
} }
} }
double t=worktime*1.0/1000000000; // seconds double sec=worktime*1.0/1000000000; // seconds
std::clog<<" time | "<<(t<0.1? t*1000:t)<<(t<0.1? " ms\n":" s\n"); std::clog<<" time | "<<(sec<0.1? sec*1000:sec)<<(sec<0.1? " ms\n":" s\n");
if (total) { if (total) {
std::clog<<" avg | "<<t/total*1000<<" ms\n"; std::clog<<" avg | "<<sec/total*1000<<" ms\n";
} }
} }
@ -666,8 +733,8 @@ var gc::alloc(u8 type) {
if (unused[index].empty()) { if (unused[index].empty()) {
extend(type); extend(type);
} }
var ret={type,unused[index].back()}; var ret=var::gcobj(unused[index].back());
ret.val.gcobj->mark=GC_UNCOLLECTED; ret.val.gcobj->mark=nas_val::status::uncollected;
unused[index].pop_back(); unused[index].pop_back();
return ret; return ret;
} }
@ -691,6 +758,7 @@ var gc::newstr(const string& buff) {
} }
void gc::ctxchg(nas_co& ctx) { void gc::ctxchg(nas_co& ctx) {
// store running state to main context
mctx.pc=pc; mctx.pc=pc;
mctx.top=top; mctx.top=top;
mctx.localr=localr; mctx.localr=localr;
@ -700,6 +768,7 @@ void gc::ctxchg(nas_co& ctx) {
mctx.canary=canary; mctx.canary=canary;
mctx.stack=stack; mctx.stack=stack;
// restore coroutine context state
pc=ctx.pc; pc=ctx.pc;
top=ctx.top; top=ctx.top;
localr=ctx.localr; localr=ctx.localr;
@ -710,12 +779,15 @@ void gc::ctxchg(nas_co& ctx) {
stack=ctx.stack; stack=ctx.stack;
cort=&ctx; cort=&ctx;
// set coroutine state to running
cort->status=nas_co::running; cort->status=nas_co::running;
} }
void gc::ctxreserve() { void gc::ctxreserve() {
// pc=0 means this coroutine is finished // pc=0 means this coroutine is finished
cort->status=pc? nas_co::suspended:nas_co::dead; cort->status=pc? nas_co::suspended:nas_co::dead;
// store running state to coroutine
cort->pc=pc; cort->pc=pc;
cort->localr=localr; cort->localr=localr;
cort->memr=memr; cort->memr=memr;
@ -724,6 +796,7 @@ void gc::ctxreserve() {
cort->canary=canary; cort->canary=canary;
cort->top=top; cort->top=top;
// restore main context state
pc=mctx.pc; pc=mctx.pc;
localr=mctx.localr; localr=mctx.localr;
memr=mctx.memr; memr=mctx.memr;
@ -738,7 +811,7 @@ void gc::ctxreserve() {
// use to print error log and return error value // use to print error log and return error value
var nas_err(const string& err_f,const string& info) { var nas_err(const string& err_f,const string& info) {
std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n"; std::cerr<<"[vm] "<<err_f<<": "<<info<<"\n";
return {vm_none}; return var::none();
} }
typedef var (*mod)(var*,usize,gc*); // module function type typedef var (*mod)(var*,usize,gc*); // module function type

View File

@ -366,7 +366,7 @@ void vm::o_loadu() {
} }
void vm::o_pnum() { void vm::o_pnum() {
(++top)[0]={vm_num,cnum[imm[pc]]}; (++top)[0]=var::num(cnum[imm[pc]]);
} }
void vm::o_pnil() { void vm::o_pnil() {
@ -421,7 +421,7 @@ void vm::o_para() {
nas_func& func=top[0].func(); nas_func& func=top[0].func();
// func->size has 1 place reserved for "me" // func->size has 1 place reserved for "me"
func.keys[imm[pc]]=func.psize; func.keys[imm[pc]]=func.psize;
func.local[func.psize++]={vm_none}; func.local[func.psize++]=var::none();
} }
void vm::o_deft() { void vm::o_deft() {
@ -444,7 +444,7 @@ void vm::o_unot() {
case vm_str:{ case vm_str:{
const f64 num=str2num(val.str().c_str()); const f64 num=str2num(val.str().c_str());
if (std::isnan(num)) { if (std::isnan(num)) {
top[0]={vm_num,(f64)val.str().empty()}; top[0]=var::num((f64)val.str().empty());
} else { } else {
top[0]=num?zero:one; top[0]=num?zero:one;
} }
@ -457,11 +457,11 @@ void vm::o_unot() {
} }
void vm::o_usub() { void vm::o_usub() {
top[0]={vm_num,-top[0].tonum()}; top[0]=var::num(-top[0].tonum());
} }
#define op_calc(type)\ #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; --top;
void vm::o_add() {op_calc(+);} void vm::o_add() {op_calc(+);}
@ -474,7 +474,7 @@ void vm::o_lnk() {
} }
#define op_calc_const(type)\ #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_addc() {op_calc_const(+);}
void vm::o_subc() {op_calc_const(-);} void vm::o_subc() {op_calc_const(-);}
@ -485,7 +485,7 @@ void vm::o_lnkc() {
} }
#define op_calc_eq(type)\ #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;\ memr=nullptr;\
top-=imm[pc]+1; top-=imm[pc]+1;
@ -500,7 +500,7 @@ void vm::o_lnkeq() {
} }
#define op_calc_eq_const(type)\ #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;\ memr=nullptr;\
top-=(imm[pc]>>31); top-=(imm[pc]>>31);
@ -601,7 +601,7 @@ void vm::o_cnt() {
die("must use vector in forindex/foreach"); die("must use vector in forindex/foreach");
return; return;
} }
(++top)[0]={vm_cnt,(i64)-1}; (++top)[0]=var::cnt(-1);
} }
void vm::o_findex() { void vm::o_findex() {
@ -609,7 +609,7 @@ void vm::o_findex() {
pc=imm[pc]-1; pc=imm[pc]-1;
return; return;
} }
top[1]={vm_num,(f64)top[0].cnt()}; top[1]=var::num(top[0].cnt());
++top; ++top;
} }
@ -666,7 +666,7 @@ void vm::o_callv() {
die("out of range:"+std::to_string(val.tonum())); die("out of range:"+std::to_string(val.tonum()));
return; 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 { } else {
die("must call a vector/hash/string"); die("must call a vector/hash/string");
return; return;
@ -753,8 +753,8 @@ void vm::o_callfv() {
} }
top[0]=upvalr; top[0]=upvalr;
(++top)[0]={vm_addr,localr}; (++top)[0]=var::addr(localr);
(++top)[0]={vm_ret,pc}; (++top)[0]=var::ret(pc);
pc=func.entry-1; pc=func.entry-1;
localr=local; localr=local;
upvalr=nil; upvalr=nil;
@ -797,8 +797,8 @@ void vm::o_callfh() {
} }
top[0]=upvalr; top[0]=upvalr;
(++top)[0]={vm_addr,localr}; (++top)[0]=var::addr(localr);
(++top)[0]={vm_ret,pc}; // rewrite top with vm_ret (++top)[0]=var::ret(pc); // rewrite top with vm_ret
pc=func.entry-1; pc=func.entry-1;
localr=local; localr=local;
upvalr=nil; upvalr=nil;
@ -806,12 +806,18 @@ void vm::o_callfh() {
void vm::o_callb() { void vm::o_callb() {
// reserve place for builtin function return, // reserve place for builtin function return,
// in fact this code is changed because of coroutine // this code is written for coroutine
(++top)[0]=nil; (++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) 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) { if (top[0].type==vm_none) {
die("native function error"); die("native function error");
return; return;