bug fix & optimize test code & add lib function: subvec, floor, abs, isfunc, isghost, isint, isnum, isscalar, isstr, isvec, vecindex(unfinished)

This commit is contained in:
ValKmjolnir 2022-04-04 18:38:25 +08:00
parent a2b51fe212
commit aed5e27409
5 changed files with 160 additions and 66 deletions

58
lib.nas
View File

@ -60,6 +60,17 @@ var int=func(val){
return __builtin_int(val); return __builtin_int(val);
} }
# floor will get the integral number of input argument
# which is less than or equal to this argument
var floor=func(val){
return __builtin_floor(val);
}
# abs gets absolute number
var abs=func(n){
return n>0?n:-n;
}
# num will change all the other types into number. # num will change all the other types into number.
# mostly used to change a numerable string. # mostly used to change a numerable string.
var num=func(val){ var num=func(val){
@ -105,6 +116,9 @@ var keys=func(hash){
var time=func(begin){ var time=func(begin){
return __builtin_time(begin); return __builtin_time(begin);
} }
var systime=func(){
return time(0);
}
# die is a special native function. # die is a special native function.
# use it at where you want the program to crash immediately. # use it at where you want the program to crash immediately.
@ -118,6 +132,11 @@ var typeof=func(object){
return __builtin_type(object); return __builtin_type(object);
} }
# subvec is used to get part of a vector
var subvec=func(vec,begin,length=nil){
return vec[begin:(length==nil?nil:begin+length-1)];
}
# substr will get the sub-string. # substr will get the sub-string.
# it gets the string, the begin index and sub-string's length as arguments. # it gets the string, the begin index and sub-string's length as arguments.
var substr=func(str,begin,len){ var substr=func(str,begin,len){
@ -169,6 +188,45 @@ var println=func(elems...){
return __builtin_print(elems); return __builtin_print(elems);
} }
var isfunc=func(f){
return typeof(f)=="func";
}
var isghost=func(g){
die("this runtime have no ghost object");
return 0;
}
var ishash=func(h){
return typeof(h)=="hash";
}
var isint=func(x){
return x==floor(x);
}
var isnum=func(x){
return typeof(x)=="num" or !math.isnan(num(x));
}
var isscalar=func(s){
var t=typeof(s);
return t=="num" or t=="str";
}
var isstr=func(s){
return typeof(s)=="str";
}
var isvec=func(v){
return typeof(v)=="vec";
}
var vecindex=func(vec,val){
# unfinished
return nil;
}
var io= var io=
{ {
SEEK_SET:0, SEEK_SET:0,

View File

@ -20,6 +20,7 @@ nas_native(builtin_split);
nas_native(builtin_rand); nas_native(builtin_rand);
nas_native(builtin_id); nas_native(builtin_id);
nas_native(builtin_int); nas_native(builtin_int);
nas_native(builtin_floor);
nas_native(builtin_num); nas_native(builtin_num);
nas_native(builtin_pop); nas_native(builtin_pop);
nas_native(builtin_str); nas_native(builtin_str);
@ -108,6 +109,7 @@ struct
{"__builtin_rand", builtin_rand }, {"__builtin_rand", builtin_rand },
{"__builtin_id", builtin_id }, {"__builtin_id", builtin_id },
{"__builtin_int", builtin_int }, {"__builtin_int", builtin_int },
{"__builtin_floor", builtin_floor },
{"__builtin_num", builtin_num }, {"__builtin_num", builtin_num },
{"__builtin_pop", builtin_pop }, {"__builtin_pop", builtin_pop },
{"__builtin_str", builtin_str }, {"__builtin_str", builtin_str },
@ -363,6 +365,11 @@ nasal_ref builtin_int(nasal_ref* local,nasal_gc& gc)
int number=(int)val.num(); int number=(int)val.num();
return {vm_num,(double)number}; return {vm_num,(double)number};
} }
nasal_ref builtin_floor(nasal_ref* local,nasal_gc& gc)
{
nasal_ref val=local[1];
return {vm_num,std::floor(val.num())};
}
nasal_ref builtin_num(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_num(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref val=local[1]; nasal_ref val=local[1];

View File

@ -797,8 +797,8 @@ inline void nasal_vm::opr_slc2()
else if(type1!=vm_nil && type2==vm_nil) else if(type1!=vm_nil && type2==vm_nil)
num2=num1<0? -1:size-1; num2=num1<0? -1:size-1;
if(num1>=num2) if(num1>num2)
die("slc2: begin index must be less than end index"); die("slc2: begin index must be less than or equal to end index");
else if(num1<-size || num1>=size) else if(num1<-size || num1>=size)
die("slc2: begin index out of range: "+std::to_string(num1)); die("slc2: begin index out of range: "+std::to_string(num1));
else if(num2<-size || num2>=size) else if(num2<-size || num2>=size)

View File

@ -60,6 +60,17 @@ var int=func(val){
return __builtin_int(val); return __builtin_int(val);
} }
# floor will get the integral number of input argument
# which is less than or equal to this argument
var floor=func(val){
return __builtin_floor(val);
}
# abs gets absolute number
var abs=func(n){
return n>0?n:-n;
}
# num will change all the other types into number. # num will change all the other types into number.
# mostly used to change a numerable string. # mostly used to change a numerable string.
var num=func(val){ var num=func(val){
@ -105,6 +116,9 @@ var keys=func(hash){
var time=func(begin){ var time=func(begin){
return __builtin_time(begin); return __builtin_time(begin);
} }
var systime=func(){
return time(0);
}
# die is a special native function. # die is a special native function.
# use it at where you want the program to crash immediately. # use it at where you want the program to crash immediately.
@ -118,6 +132,11 @@ var typeof=func(object){
return __builtin_type(object); return __builtin_type(object);
} }
# subvec is used to get part of a vector
var subvec=func(vec,begin,length=nil){
return vec[begin:(length==nil?nil:begin+length-1)];
}
# substr will get the sub-string. # substr will get the sub-string.
# it gets the string, the begin index and sub-string's length as arguments. # it gets the string, the begin index and sub-string's length as arguments.
var substr=func(str,begin,len){ var substr=func(str,begin,len){
@ -169,6 +188,45 @@ var println=func(elems...){
return __builtin_print(elems); return __builtin_print(elems);
} }
var isfunc=func(f){
return typeof(f)=="func";
}
var isghost=func(g){
die("this runtime have no ghost object");
return 0;
}
var ishash=func(h){
return typeof(h)=="hash";
}
var isint=func(x){
return x==floor(x);
}
var isnum=func(x){
return typeof(x)=="num" or !math.isnan(num(x));
}
var isscalar=func(s){
var t=typeof(s);
return t=="num" or t=="str";
}
var isstr=func(s){
return typeof(s)=="str";
}
var isvec=func(v){
return typeof(v)=="vec";
}
var vecindex=func(vec,val){
# unfinished
return nil;
}
var io= var io=
{ {
SEEK_SET:0, SEEK_SET:0,

View File

@ -3,15 +3,15 @@ import("lib.nas");
var check=func(x){ var check=func(x){
if(x<0x100000000) if(x<0x100000000)
return x; return x;
return x-int(x/0x100000000)*0x100000000; return x-floor(x/0x100000000)*0x100000000;
} }
var u32_bits_and=func(x,y){ var u32_bits_and=func(x,y){
(x,y)=(check(x),check(y)); (x,y)=(check(x),check(y));
var (res,op)=(0,1); var (res,op)=(0,1);
for(var i=0;i<32;i+=1){ for(var i=0;i<32;i+=1){
var (tmpx,tmpy)=(x-int(x/2)*2,y-int(y/2)*2); var (tmpx,tmpy)=(x-floor(x/2)*2,y-floor(y/2)*2);
res+=op*(tmpx==1 and tmpy==1); res+=op*(tmpx==1 and tmpy==1);
(x,y)=(int(x/2),int(y/2)); (x,y)=(floor(x/2),floor(y/2));
op*=2; op*=2;
} }
return res; return res;
@ -20,9 +20,9 @@ var u32_bits_or=func(x,y){
(x,y)=(check(x),check(y)); (x,y)=(check(x),check(y));
var (res,op)=(0,1); var (res,op)=(0,1);
for(var i=0;i<32;i+=1){ for(var i=0;i<32;i+=1){
var (tmpx,tmpy)=(x-int(x/2)*2,y-int(y/2)*2); var (tmpx,tmpy)=(x-floor(x/2)*2,y-floor(y/2)*2);
res+=op*(tmpx==1 or tmpy==1); res+=op*(tmpx==1 or tmpy==1);
(x,y)=(int(x/2),int(y/2)); (x,y)=(floor(x/2),floor(y/2));
op*=2; op*=2;
} }
return res; return res;
@ -31,9 +31,9 @@ var u32_bits_xor=func(x,y){
(x,y)=(check(x),check(y)); (x,y)=(check(x),check(y));
var (res,op)=(0,1); var (res,op)=(0,1);
for(var i=0;i<32;i+=1){ for(var i=0;i<32;i+=1){
var (tmpx,tmpy)=(x-int(x/2)*2,y-int(y/2)*2); var (tmpx,tmpy)=(x-floor(x/2)*2,y-floor(y/2)*2);
res+=op*(tmpx!=tmpy); res+=op*(tmpx!=tmpy);
(x,y)=(int(x/2),int(y/2)); (x,y)=(floor(x/2),floor(y/2));
op*=2; op*=2;
} }
return res; return res;
@ -42,8 +42,8 @@ var u32_bits_not=func(x){
x=check(x); x=check(x);
var (res,op)=(0,1); var (res,op)=(0,1);
for(var i=0;i<32;i+=1){ for(var i=0;i<32;i+=1){
res+=op*((x-int(x/2)*2)==1?0:1); res+=op*((x-floor(x/2)*2)==1?0:1);
x=int(x/2); x=floor(x/2);
op*=2; op*=2;
} }
return res; return res;
@ -61,7 +61,7 @@ var hex32str=func(){
var res=""; var res="";
for(var i=0;i<4;i+=1){ for(var i=0;i<4;i+=1){
res~=tbl[u32_bits_and(num,0xff)]; res~=tbl[u32_bits_and(num,0xff)];
num=int(num/256); num=floor(num/256);
} }
return res; return res;
}; };
@ -103,7 +103,7 @@ var _md5=func(){
for(var i=0;i<cx;i+=1){ for(var i=0;i<cx;i+=1){
num=num/2; num=num/2;
} }
return int(num); return floor(num);
} }
var rol=func(num,cx){ var rol=func(num,cx){
return u32_bits_or(l(num,cx),r(num,32-cx)); return u32_bits_or(l(num,cx),r(num,32-cx));
@ -141,72 +141,43 @@ var _md5=func(){
]; ];
return func(s){ return func(s){
var len=size(s)*8; var (s_size,len,res)=(size(s),size(s)*8,[]);
var res=[]; setsize(res,s_size);
setsize(res,len); for(var i=0;i<s_size;i+=1){
for(var i=0;i<size(s);i+=1){ res[i]=s[i];
var c=s[i];
var v=128;
for(var j=0;j<8;j+=1){
res[i*8+j]=(bits.bitand(c,v)?1:0);
v=int(v/2);
}
} }
# +------len------+--1~512--+--64--+ # +------len------+--1~512--+--64--+
# | text | fill | size | # | text | fill | size |
# +---------------+---------+------+ N*512 # +---------------+---------+------+ N*512 bit
var mod=size(res)-int(size(res)/512)*512; var (mod,res_size)=(s_size-floor(s_size/64)*64,0);
if(mod==448){ if(mod==56){
var i=size(res); res_size=s_size+64;
setsize(res,i+512); }elsif(mod<56){
res[i]=1; res_size=floor(s_size/64)*64+56;
for(i+=1;i<size(res);i+=1) }elsif(mod>56){
res[i]=0; res_size=floor(s_size/64)*64+120; # 512+448=960 960/8=120
}elsif(mod<448){
var i=size(res);
setsize(res,int(i/512)*512+448);
res[i]=1;
for(i+=1;i<size(res);i+=1)
res[i]=0;
}elsif(mod>448){
var i=size(res);
setsize(res,int(i/512)*512+960); # 512+448=960
res[i]=1;
for(i+=1;i<size(res);i+=1)
res[i]=0;
} }
setsize(res,res_size);
res[s_size]=0x80;
for(var i=s_size+1;i<res_size;i+=1)
res[i]=0;
# translate bits to bytes and reserve 64bit space for string length # little endian
var (tmp,cnt,t,index)=([],0,0,0); setsize(res,size(res)+8);
setsize(tmp,int(size(res)/8)+8); var (s_size,lower32,higher32)=(size(res),check(len),check(len/math.pow(2,32)));
foreach(var i;res){
if(!cnt) t=i;
else t=t*2+i;
cnt+=1;
if(cnt==8){
tmp[index]=t;
index+=1;
cnt=0;
}
}
# little endian, this may have number overflow bug
# if the number is too large
var (tmp_size,lower32,higher32)=(size(tmp),check(len),check(len/math.pow(2,32)));
for(var i=4;i>0;i-=1){ for(var i=4;i>0;i-=1){
tmp[tmp_size-4-i]=int(lower32-int(lower32/256)*256); res[s_size-4-i]=floor(lower32-floor(lower32/256)*256);
lower32=int(lower32/256); lower32=floor(lower32/256);
} }
for(var i=4;i>0;i-=1){ for(var i=4;i>0;i-=1){
tmp[tmp_size-i]=int(higher32-int(higher32/256)*256); res[s_size-i]=floor(higher32-floor(higher32/256)*256);
higher32=int(higher32/256); higher32=floor(higher32/256);
} }
res=tmp;
# 1 block=>16 uint32=>64 byte=>512 bit # 1 block=>16 uint32=>64 byte=>512 bit
# because using double to discribe number # because using double to discribe number
# this may only work when string's length is under 1<<51 # this may only work when string's length is under 1<<51
tmp=[]; var tmp=[];
setsize(tmp,size(res)/4); setsize(tmp,size(res)/4);
for(var i=0;i<size(res);i+=4){ for(var i=0;i<size(res);i+=4){
tmp[i/4]=res[i+3]*math.pow(2,24)+ tmp[i/4]=res[i+3]*math.pow(2,24)+