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
// 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

View File

@ -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}

View File

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

View File

@ -73,14 +73,14 @@ public:
noecho_input this_window;
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) {
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) {
if (this_window.noecho_kbhit()) {
return {vm_num,(double)this_window.noecho_getch()};
return var::num((double)this_window.noecho_getch());
}
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)
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;
}
@ -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[]={

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)
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);

View File

@ -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<<len)-1);
}
return {vm_num,(f64)((i32)res)};
return var::num((f64)((i32)res));
}
var builtin_setfld(var* local,gc& ngc) {
@ -808,8 +808,8 @@ var builtin_pipe(var* local,gc& ngc) {
if (pipe(fd)==-1) {
return nas_err("pipe","failed to create pipe");
}
res.vec().elems.push_back({vm_num,(f64)fd[0]});
res.vec().elems.push_back({vm_num,(f64)fd[1]});
res.vec().elems.push_back(var::num((f64)fd[0]));
res.vec().elems.push_back(var::num((f64)fd[1]));
return res;
#endif
return nas_err("pipe","not supported");
@ -821,7 +821,7 @@ var builtin_fork(var* local,gc& ngc) {
if (res<0) {
return nas_err("fork","failed to fork a process");
}
return {vm_num,(f64)res};
return var::num((f64)res);
#endif
return nas_err("fork","not supported");
}
@ -836,8 +836,8 @@ var builtin_waitpid(var* local,gc& ngc) {
i32 ret_pid,status;
ret_pid=waitpid(pid.num(),&status,nohang.num()==0?0:WNOHANG);
var vec=ngc.alloc(vm_vec);
vec.vec().elems.push_back({vm_num,(f64)ret_pid});
vec.vec().elems.push_back({vm_num,(f64)status});
vec.vec().elems.push_back(var::num((f64)ret_pid));
vec.vec().elems.push_back(var::num((f64)status));
return vec;
#endif
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 path=local[1];
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) {
@ -1136,9 +1136,9 @@ var builtin_cocreate(var* local,gc& ngc) {
cort.localr[0]=func.func().local[0];
cort.top[0]=nil; // old upvalr
cort.top++;
cort.top[0]={vm_addr,(var*)nullptr}; // old localr
cort.top[0]=var::addr((var*)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
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.status=nas_co::suspended;
@ -1216,7 +1216,7 @@ var builtin_millisec(var* local,gc& ngc) {
f64 res=std::chrono::duration_cast<std::chrono::milliseconds>
(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) {

View File

@ -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();
string tostr();
friend std::ostream& operator<<(std::ostream&,var&);
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,6 +96,8 @@ struct var {
struct nas_vec {
std::vector<var> elems;
// mark if this is printed, avoid stackoverflow
bool printed;
nas_vec():printed(false) {}
@ -105,6 +108,8 @@ struct nas_vec {
struct nas_hash {
std::unordered_map<string,var> elems;
// mark if this is printed, avoid stackoverflow
bool printed;
nas_hash():printed(false) {}
@ -127,13 +132,16 @@ struct nas_func {
};
struct nas_upval {
// if on stack, use these three variables
bool onstk;
u32 size;
var* stk;
// if not on stack, use this
std::vector<var> 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<STACK_DEPTH;++i) {
stack[i]={vm_nil,(f64)0};
stack[i]=var::nil();
}
pc=0;
localr=nullptr;
memr=nullptr;
top=stack;
status=nas_co::suspended;
funcr={vm_nil,(f64)0};
upvalr={vm_nil,(f64)0};
funcr=var::nil();
upvalr=var::nil();
}
};
const u8 GC_UNCOLLECTED=0;
const u8 GC_COLLECTED =1;
const u8 GC_FOUND =2;
struct nas_val {
u8 mark;
u8 type;
enum status:u8 {
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
union {
string* str;
@ -247,7 +258,7 @@ struct nas_val {
var nas_vec::get_val(const i32 n) {
i32 size=elems.size();
if (n<-size || n>=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<nas_val*> memory; // gc memory
std::vector<nas_val*> unused[gc_tsize]; // gc free list
// heap increase size
u32 incr[gc_tsize]={
128, // vm_str
128, // vm_vec
@ -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<string>& s,const std::vector<string>& argv) {
// initiaize function register
// initialize function register
funcr=nil;
worktime=0;
// initialize counters
for(u8 i=0;i<gc_tsize;++i) {
size[i]=gcnt[i]=acnt[i]=0;
}
// coroutine pointer set to nullpre
cort=nullptr;
// init constant strings
strs.resize(s.size());
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].str()=s[i];
}
// record arguments
env_argv.resize(argv.size());
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].str()=argv[i];
}
@ -646,10 +713,10 @@ void gc::info() {
std::clog<<" | "<<std::left<<std::setw(maxlen)<<std::setfill(' ')<<size[i]<<"\n";
}
}
double t=worktime*1.0/1000000000; // seconds
std::clog<<" time | "<<(t<0.1? t*1000:t)<<(t<0.1? " ms\n":" s\n");
double sec=worktime*1.0/1000000000; // seconds
std::clog<<" time | "<<(sec<0.1? sec*1000:sec)<<(sec<0.1? " ms\n":" s\n");
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()) {
extend(type);
}
var ret={type,unused[index].back()};
ret.val.gcobj->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] "<<err_f<<": "<<info<<"\n";
return {vm_none};
return var::none();
}
typedef var (*mod)(var*,usize,gc*); // module function type

View File

@ -366,7 +366,7 @@ void vm::o_loadu() {
}
void vm::o_pnum() {
(++top)[0]={vm_num,cnum[imm[pc]]};
(++top)[0]=var::num(cnum[imm[pc]]);
}
void vm::o_pnil() {
@ -421,7 +421,7 @@ void vm::o_para() {
nas_func& func=top[0].func();
// func->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;