✨ use new way of constructing var objects
This commit is contained in:
parent
48611c50f7
commit
268a03864e
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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[]={
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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[]={
|
||||||
|
|
|
@ -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);
|
||||||
|
|
122
nasal_builtin.h
122
nasal_builtin.h
|
@ -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) {
|
||||||
|
|
189
nasal_gc.h
189
nasal_gc.h
|
@ -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
|
||||||
|
|
44
nasal_vm.h
44
nasal_vm.h
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue