diff --git a/README.md b/README.md index 92c16ec..1268a3f 100644 --- a/README.md +++ b/README.md @@ -1035,13 +1035,13 @@ If you really want to change source code, check built-in functions in lib.nas an Definition: ```C++ -nasal_ref builtin_print(std::vector&,nasal_gc&); +nasal_ref builtin_print(nasal_ref*,nasal_gc&); ``` Then complete this function using C++: ```C++ -nasal_ref builtin_print(std::vector& local,nasal_gc& gc) +nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) { // find value with index begin from 1 // because local_scope[0] is reserved for value 'me' @@ -1074,7 +1074,7 @@ After that, register the built-in function's name(in nasal) and the function's p struct func { const char* name; - nasal_ref (*func)(std::vector&,nasal_gc&); + nasal_ref (*func)(nasal_ref*,nasal_gc&); } builtin_func[]= { {"__builtin_print",builtin_print}, @@ -1119,7 +1119,7 @@ this is a fatal error. So use `builtin_alloc` in builtin functions like this: ```C++ -nasal_ref builtin_keys(std::vector& local,nasal_gc& gc) +nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) { nasal_ref hash=local[1]; if(hash.type!=vm_hash) diff --git a/main.cpp b/main.cpp index b1a856a..5f89248 100644 --- a/main.cpp +++ b/main.cpp @@ -48,7 +48,7 @@ void logo() <<" / \\/ / _` / __|/ _` | | \n" <<" / /\\ / (_| \\__ \\ (_| | | \n" <<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n" - <<"nasal interpreter ver 8.0\n" + <<"nasal interpreter ver 9.0\n" <<"thanks to : https://github.com/andyross/nasal\n" <<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n" <<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n" diff --git a/nasal_builtin.h b/nasal_builtin.h index 4dfaab7..bee5e2a 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -16,7 +16,7 @@ enum obj_type }; // declaration of builtin functions // to add new builtin function, declare it here and write the definition below -#define nas_native(name) nasal_ref name(std::vector&,nasal_gc&) +#define nas_native(name) nasal_ref name(nasal_ref*,nasal_gc&) nas_native(builtin_print); nas_native(builtin_append); nas_native(builtin_setsize); @@ -97,7 +97,7 @@ nasal_ref builtin_err(const char* func_name,std::string info) struct { const char* name; - nasal_ref (*func)(std::vector&,nasal_gc&); + nasal_ref (*func)(nasal_ref*,nasal_gc&); } builtin[]= { {"__builtin_print", builtin_print }, @@ -171,7 +171,7 @@ struct {nullptr, nullptr } }; -nasal_ref builtin_print(std::vector& local,nasal_gc& gc) +nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) { // get arguments // local[0] is reserved for 'me' @@ -193,7 +193,7 @@ nasal_ref builtin_print(std::vector& local,nasal_gc& gc) // generate return value return nil; } -nasal_ref builtin_append(std::vector& local,nasal_gc& gc) +nasal_ref builtin_append(nasal_ref* local,nasal_gc& gc) { nasal_ref vec=local[1]; nasal_ref elem=local[2]; @@ -204,7 +204,7 @@ nasal_ref builtin_append(std::vector& local,nasal_gc& gc) ref_vec.push_back(i); return nil; } -nasal_ref builtin_setsize(std::vector& local,nasal_gc& gc) +nasal_ref builtin_setsize(nasal_ref* local,nasal_gc& gc) { nasal_ref vec=local[1]; nasal_ref size=local[2]; @@ -218,20 +218,20 @@ nasal_ref builtin_setsize(std::vector& local,nasal_gc& gc) vec.vec()->elems.resize(num,nil); return nil; } -nasal_ref builtin_system(std::vector& local,nasal_gc& gc) +nasal_ref builtin_system(nasal_ref* local,nasal_gc& gc) { nasal_ref str=local[1]; if(str.type!=vm_str) return builtin_err("system","\"str\" must be string"); return {vm_num,(double)system(str.str()->c_str())}; } -nasal_ref builtin_input(std::vector& local,nasal_gc& gc) +nasal_ref builtin_input(nasal_ref* local,nasal_gc& gc) { nasal_ref ret=gc.alloc(vm_str); std::cin>>*ret.str(); return ret; } -nasal_ref builtin_fin(std::vector& local,nasal_gc& gc) +nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_str) @@ -248,7 +248,7 @@ nasal_ref builtin_fin(std::vector& local,nasal_gc& gc) } return builtin_err("io.fin","cannot open \""+filename+"\""); } -nasal_ref builtin_fout(std::vector& local,nasal_gc& gc) +nasal_ref builtin_fout(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; nasal_ref str=local[2]; @@ -262,7 +262,7 @@ nasal_ref builtin_fout(std::vector& local,nasal_gc& gc) fout<<*str.str(); return nil; } -nasal_ref builtin_split(std::vector& local,nasal_gc& gc) +nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc) { nasal_ref deli_val=local[1]; nasal_ref str_val=local[2]; @@ -276,9 +276,11 @@ nasal_ref builtin_split(std::vector& local,nasal_gc& gc) size_t source_len=source.length(); // push it to local scope to avoid being sweeped - local.push_back(gc.alloc(vm_vec)); + if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) + builtin_err("split","expand temporary space error:stackoverflow"); + (++gc.top)[0]=gc.alloc(vm_vec); - std::vector& vec=local.back().vec()->elems; + std::vector& vec=gc.top[0].vec()->elems; if(!delimeter_len) { for(int i=0;i& local,nasal_gc& gc) vec.push_back(gc.alloc(vm_str)); *vec.back().str()=source[i]; } - return local.back(); + --gc.top; + return gc.top[1]; } std::string tmp=""; @@ -320,9 +323,10 @@ nasal_ref builtin_split(std::vector& local,nasal_gc& gc) *vec.back().str()=tmp; tmp=""; } - return local.back(); + --gc.top; + return gc.top[1]; } -nasal_ref builtin_rand(std::vector& local,nasal_gc& gc) +nasal_ref builtin_rand(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num && val.type!=vm_nil) @@ -337,7 +341,7 @@ nasal_ref builtin_rand(std::vector& local,nasal_gc& gc) num=(num+rand())*(1.0/(RAND_MAX+1.0)); return {vm_num,num}; } -nasal_ref builtin_id(std::vector& local,nasal_gc& gc) +nasal_ref builtin_id(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; nasal_ref ret=gc.alloc(vm_str); @@ -349,7 +353,7 @@ nasal_ref builtin_id(std::vector& local,nasal_gc& gc) *ret.str()=buf; return ret; } -nasal_ref builtin_int(std::vector& local,nasal_gc& gc) +nasal_ref builtin_int(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) @@ -357,7 +361,7 @@ nasal_ref builtin_int(std::vector& local,nasal_gc& gc) int number=(int)val.num(); return {vm_num,(double)number}; } -nasal_ref builtin_num(std::vector& local,nasal_gc& gc) +nasal_ref builtin_num(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type==vm_num) @@ -369,7 +373,7 @@ nasal_ref builtin_num(std::vector& local,nasal_gc& gc) return nil; return {vm_num,res}; } -nasal_ref builtin_pop(std::vector& local,nasal_gc& gc) +nasal_ref builtin_pop(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_vec) @@ -382,7 +386,7 @@ nasal_ref builtin_pop(std::vector& local,nasal_gc& gc) } return nil; } -nasal_ref builtin_str(std::vector& local,nasal_gc& gc) +nasal_ref builtin_str(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) @@ -391,7 +395,7 @@ nasal_ref builtin_str(std::vector& local,nasal_gc& gc) *ret.str()=std::to_string(val.num()); return ret; } -nasal_ref builtin_size(std::vector& local,nasal_gc& gc) +nasal_ref builtin_size(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; double num; @@ -404,7 +408,7 @@ nasal_ref builtin_size(std::vector& local,nasal_gc& gc) } return {vm_num,num}; } -nasal_ref builtin_xor(std::vector& local,nasal_gc& gc) +nasal_ref builtin_xor(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; nasal_ref b=local[2]; @@ -416,7 +420,7 @@ nasal_ref builtin_xor(std::vector& local,nasal_gc& gc) int number_b=(int)b.num(); return {vm_num,(double)(number_a^number_b)}; } -nasal_ref builtin_and(std::vector& local,nasal_gc& gc) +nasal_ref builtin_and(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; nasal_ref b=local[2]; @@ -428,7 +432,7 @@ nasal_ref builtin_and(std::vector& local,nasal_gc& gc) int number_b=(int)b.num(); return {vm_num,(double)(number_a&number_b)}; } -nasal_ref builtin_or(std::vector& local,nasal_gc& gc) +nasal_ref builtin_or(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; nasal_ref b=local[2]; @@ -440,7 +444,7 @@ nasal_ref builtin_or(std::vector& local,nasal_gc& gc) int number_b=(int)b.num(); return {vm_num,(double)(number_a|number_b)}; } -nasal_ref builtin_nand(std::vector& local,nasal_gc& gc) +nasal_ref builtin_nand(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; nasal_ref b=local[2]; @@ -452,7 +456,7 @@ nasal_ref builtin_nand(std::vector& local,nasal_gc& gc) int number_b=(int)b.num(); return {vm_num,(double)(~(number_a&number_b))}; } -nasal_ref builtin_not(std::vector& local,nasal_gc& gc) +nasal_ref builtin_not(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; if(a.type!=vm_num) @@ -460,56 +464,56 @@ nasal_ref builtin_not(std::vector& local,nasal_gc& gc) int number=(int)a.num(); return {vm_num,(double)(~number)}; } -nasal_ref builtin_sin(std::vector& local,nasal_gc& gc) +nasal_ref builtin_sin(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("sin","\"x\" must be number"); return {vm_num,sin(val.num())}; } -nasal_ref builtin_cos(std::vector& local,nasal_gc& gc) +nasal_ref builtin_cos(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("cos","\"x\" must be number"); return {vm_num,cos(val.num())}; } -nasal_ref builtin_tan(std::vector& local,nasal_gc& gc) +nasal_ref builtin_tan(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("tan","\"x\" must be number"); return {vm_num,tan(val.num())}; } -nasal_ref builtin_exp(std::vector& local,nasal_gc& gc) +nasal_ref builtin_exp(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("exp","\"x\" must be number"); return {vm_num,exp(val.num())}; } -nasal_ref builtin_lg(std::vector& local,nasal_gc& gc) +nasal_ref builtin_lg(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("ln","\"x\" must be number"); return {vm_num,log(val.num())/log(10.0)}; } -nasal_ref builtin_ln(std::vector& local,nasal_gc& gc) +nasal_ref builtin_ln(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("ln","\"x\" must be number"); return {vm_num,log(val.num())}; } -nasal_ref builtin_sqrt(std::vector& local,nasal_gc& gc) +nasal_ref builtin_sqrt(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("sqrt","\"x\" must be number"); return {vm_num,sqrt(val.num())}; } -nasal_ref builtin_atan2(std::vector& local,nasal_gc& gc) +nasal_ref builtin_atan2(nasal_ref* local,nasal_gc& gc) { nasal_ref x=local[1]; nasal_ref y=local[2]; @@ -519,12 +523,12 @@ nasal_ref builtin_atan2(std::vector& local,nasal_gc& gc) return builtin_err("atan2","\"y\" must be number"); return {vm_num,atan2(y.num(),x.num())}; } -nasal_ref builtin_isnan(std::vector& local,nasal_gc& gc) +nasal_ref builtin_isnan(nasal_ref* local,nasal_gc& gc) { nasal_ref x=local[1]; return (x.type==vm_num && std::isnan(x.num()))?one:zero; } -nasal_ref builtin_time(std::vector& local,nasal_gc& gc) +nasal_ref builtin_time(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) @@ -532,7 +536,7 @@ nasal_ref builtin_time(std::vector& local,nasal_gc& gc) time_t begin_time=(time_t)val.num(); return {vm_num,(double)time(&begin_time)}; } -nasal_ref builtin_contains(std::vector& local,nasal_gc& gc) +nasal_ref builtin_contains(nasal_ref* local,nasal_gc& gc) { nasal_ref hash=local[1]; nasal_ref key=local[2]; @@ -542,7 +546,7 @@ nasal_ref builtin_contains(std::vector& local,nasal_gc& gc) return builtin_err("contains","\"key\" must be string"); return hash.hash()->elems.count(*key.str())?one:zero; } -nasal_ref builtin_delete(std::vector& local,nasal_gc& gc) +nasal_ref builtin_delete(nasal_ref* local,nasal_gc& gc) { nasal_ref hash=local[1]; nasal_ref key=local[2]; @@ -554,23 +558,26 @@ nasal_ref builtin_delete(std::vector& local,nasal_gc& gc) hash.hash()->elems.erase(*key.str()); return nil; } -nasal_ref builtin_keys(std::vector& local,nasal_gc& gc) +nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) { nasal_ref hash=local[1]; if(hash.type!=vm_hash) return builtin_err("keys","\"hash\" must be hash"); // push vector into local scope to avoid being sweeped - local.push_back(gc.alloc(vm_vec)); - auto& vec=local.back().vec()->elems; + if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) + builtin_err("keys","expand temporary space error:stackoverflow"); + (++gc.top)[0]=gc.alloc(vm_vec); + auto& vec=gc.top[0].vec()->elems; for(auto& iter:hash.hash()->elems) { nasal_ref str=gc.alloc(vm_str); *str.str()=iter.first; vec.push_back(str); } - return local.back(); + --gc.top; + return gc.top[1]; } -nasal_ref builtin_import(std::vector& local,nasal_gc& gc) +nasal_ref builtin_import(nasal_ref* local,nasal_gc& gc) { // this function is used in preprocessing. // this function will return nothing when running. @@ -581,7 +588,7 @@ nasal_ref builtin_import(std::vector& local,nasal_gc& gc) "\n\tmake sure it has correct argument(only one arg allowed)" ); } -nasal_ref builtin_die(std::vector& local,nasal_gc& gc) +nasal_ref builtin_die(nasal_ref* local,nasal_gc& gc) { nasal_ref str=local[1]; if(str.type!=vm_str) @@ -589,7 +596,7 @@ nasal_ref builtin_die(std::vector& local,nasal_gc& gc) std::cerr<<"[vm] error: "<<*str.str()<<'\n'; return nasal_ref(vm_none); } -nasal_ref builtin_type(std::vector& local,nasal_gc& gc) +nasal_ref builtin_type(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; nasal_ref ret=gc.alloc(vm_str); @@ -606,7 +613,7 @@ nasal_ref builtin_type(std::vector& local,nasal_gc& gc) } return ret; } -nasal_ref builtin_substr(std::vector& local,nasal_gc& gc) +nasal_ref builtin_substr(nasal_ref* local,nasal_gc& gc) { nasal_ref str=local[1]; nasal_ref beg=local[2]; @@ -627,13 +634,13 @@ nasal_ref builtin_substr(std::vector& local,nasal_gc& gc) *ret.str()=str.str()->substr(begin,length); return ret; } -nasal_ref builtin_streq(std::vector& local,nasal_gc& gc) +nasal_ref builtin_streq(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; nasal_ref b=local[2]; return {vm_num,double((a.type!=vm_str || b.type!=vm_str)?0:(*a.str()==*b.str()))}; } -nasal_ref builtin_left(std::vector& local,nasal_gc& gc) +nasal_ref builtin_left(nasal_ref* local,nasal_gc& gc) { nasal_ref str=local[1]; nasal_ref len=local[2]; @@ -648,7 +655,7 @@ nasal_ref builtin_left(std::vector& local,nasal_gc& gc) *ret.str()=str.str()->substr(0,length); return ret; } -nasal_ref builtin_right(std::vector& local,nasal_gc& gc) +nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc) { nasal_ref str=local[1]; nasal_ref len=local[2]; @@ -666,7 +673,7 @@ nasal_ref builtin_right(std::vector& local,nasal_gc& gc) *ret.str()=str.str()->substr(srclen-length, srclen); return ret; } -nasal_ref builtin_cmp(std::vector& local,nasal_gc& gc) +nasal_ref builtin_cmp(nasal_ref* local,nasal_gc& gc) { nasal_ref a=local[1]; nasal_ref b=local[2]; @@ -676,7 +683,7 @@ nasal_ref builtin_cmp(std::vector& local,nasal_gc& gc) return builtin_err("cmp","\"b\" must be string"); return {vm_num,(double)strcmp(a.str()->c_str(),b.str()->c_str())}; } -nasal_ref builtin_chr(std::vector& local,nasal_gc& gc) +nasal_ref builtin_chr(nasal_ref* local,nasal_gc& gc) { const char* extend[]={ "€"," ","‚","ƒ","„","…","†","‡", @@ -709,7 +716,7 @@ nasal_ref builtin_chr(std::vector& local,nasal_gc& gc) *ret.str()=" "; return ret; } -nasal_ref builtin_open(std::vector& local,nasal_gc& gc) +nasal_ref builtin_open(nasal_ref* local,nasal_gc& gc) { nasal_ref filename=local[1]; nasal_ref mode=local[2]; @@ -725,7 +732,7 @@ nasal_ref builtin_open(std::vector& local,nasal_gc& gc) ret.obj()->ptr=(void*)res; return ret; } -nasal_ref builtin_close(std::vector& local,nasal_gc& gc) +nasal_ref builtin_close(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) @@ -733,7 +740,7 @@ nasal_ref builtin_close(std::vector& local,nasal_gc& gc) fclose((FILE*)filehandle.obj()->ptr); return nil; } -nasal_ref builtin_read(std::vector& local,nasal_gc& gc) +nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; nasal_ref buf=local[2]; @@ -754,7 +761,7 @@ nasal_ref builtin_read(std::vector& local,nasal_gc& gc) delete []buff; return {vm_num,res}; } -nasal_ref builtin_write(std::vector& local,nasal_gc& gc) +nasal_ref builtin_write(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; nasal_ref str=local[2]; @@ -765,7 +772,7 @@ nasal_ref builtin_write(std::vector& local,nasal_gc& gc) double res=(double)fwrite(str.str()->c_str(),1,str.str()->length(),(FILE*)filehandle.obj()->ptr); return {vm_num,res}; } -nasal_ref builtin_seek(std::vector& local,nasal_gc& gc) +nasal_ref builtin_seek(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; nasal_ref position=local[2]; @@ -779,7 +786,7 @@ nasal_ref builtin_seek(std::vector& local,nasal_gc& gc) double res=fseek((FILE*)filehandle.obj()->ptr,position.num(),whence.num()); return {vm_num,res}; } -nasal_ref builtin_tell(std::vector& local,nasal_gc& gc) +nasal_ref builtin_tell(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) @@ -787,7 +794,7 @@ nasal_ref builtin_tell(std::vector& local,nasal_gc& gc) double res=ftell((FILE*)filehandle.obj()->ptr); return {vm_num,res}; } -nasal_ref builtin_readln(std::vector& local,nasal_gc& gc) +nasal_ref builtin_readln(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) @@ -807,7 +814,7 @@ nasal_ref builtin_readln(std::vector& local,nasal_gc& gc) return str; return nil; } -nasal_ref builtin_stat(std::vector& local,nasal_gc& gc) +nasal_ref builtin_stat(nasal_ref* local,nasal_gc& gc) { nasal_ref filename=local[1]; if(filename.type!=vm_str) @@ -831,7 +838,7 @@ nasal_ref builtin_stat(std::vector& local,nasal_gc& gc) }; return ret; } -nasal_ref builtin_eof(std::vector& local,nasal_gc& gc) +nasal_ref builtin_eof(nasal_ref* local,nasal_gc& gc) { nasal_ref filehandle=local[1]; if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) @@ -839,7 +846,7 @@ nasal_ref builtin_eof(std::vector& local,nasal_gc& gc) double res=feof((FILE*)filehandle.obj()->ptr); return {vm_num,res}; } -nasal_ref builtin_fld(std::vector& local,nasal_gc& gc) +nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc) { // bits.fld(s,0,3); // if s stores 10100010(162) @@ -862,7 +869,7 @@ nasal_ref builtin_fld(std::vector& local,nasal_gc& gc) res|=1<<(bit+len-i-1); return {vm_num,(double)res}; } -nasal_ref builtin_sfld(std::vector& local,nasal_gc& gc) +nasal_ref builtin_sfld(nasal_ref* local,nasal_gc& gc) { // bits.sfld(s,0,3); // if s stores 10100010(162) @@ -888,7 +895,7 @@ nasal_ref builtin_sfld(std::vector& local,nasal_gc& gc) res|=~((1<& local,nasal_gc& gc) +nasal_ref builtin_setfld(nasal_ref* local,nasal_gc& gc) { // bits.setfld(s,0,8,69); // set 01000101(69) to string will get this: @@ -917,7 +924,7 @@ nasal_ref builtin_setfld(std::vector& local,nasal_gc& gc) } return nil; } -nasal_ref builtin_buf(std::vector& local,nasal_gc& gc) +nasal_ref builtin_buf(nasal_ref* local,nasal_gc& gc) { nasal_ref length=local[1]; if(length.type!=vm_num || length.num()<=0) @@ -927,7 +934,7 @@ nasal_ref builtin_buf(std::vector& local,nasal_gc& gc) s.resize(length.num(),'\0'); return str; } -nasal_ref builtin_sleep(std::vector& local,nasal_gc& gc) +nasal_ref builtin_sleep(nasal_ref* local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) @@ -935,7 +942,7 @@ nasal_ref builtin_sleep(std::vector& local,nasal_gc& gc) usleep((useconds_t)(val.num()*1e6)); return nil; } -nasal_ref builtin_opendir(std::vector& local,nasal_gc& gc) +nasal_ref builtin_opendir(nasal_ref* local,nasal_gc& gc) { nasal_ref path=local[1]; if(path.type!=vm_str) @@ -948,7 +955,7 @@ nasal_ref builtin_opendir(std::vector& local,nasal_gc& gc) ret.obj()->ptr=(void*)p; return ret; } -nasal_ref builtin_readdir(std::vector& local,nasal_gc& gc) +nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc) { nasal_ref handle=local[1]; if(handle.type!=vm_obj || handle.obj()->type!=obj_dir) @@ -960,7 +967,7 @@ nasal_ref builtin_readdir(std::vector& local,nasal_gc& gc) *ret.str()=p->d_name; return ret; } -nasal_ref builtin_closedir(std::vector& local,nasal_gc& gc) +nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc) { nasal_ref handle=local[1]; if(handle.type!=vm_obj || handle.obj()->type!=obj_dir) @@ -968,7 +975,7 @@ nasal_ref builtin_closedir(std::vector& local,nasal_gc& gc) closedir((DIR*)handle.obj()->ptr); return nil; } -nasal_ref builtin_chdir(std::vector& local,nasal_gc& gc) +nasal_ref builtin_chdir(nasal_ref* local,nasal_gc& gc) { nasal_ref path=local[1]; if(path.type!=vm_str) @@ -977,7 +984,7 @@ nasal_ref builtin_chdir(std::vector& local,nasal_gc& gc) return builtin_err("chdir","failed to execute chdir"); return nil; } -nasal_ref builtin_getcwd(std::vector& local,nasal_gc& gc) +nasal_ref builtin_getcwd(nasal_ref* local,nasal_gc& gc) { char buf[1024]; getcwd(buf,sizeof(buf)); @@ -985,7 +992,7 @@ nasal_ref builtin_getcwd(std::vector& local,nasal_gc& gc) *str.str()=buf; return str; } -nasal_ref builtin_getenv(std::vector& local,nasal_gc& gc) +nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) { nasal_ref envvar=local[1]; if(envvar.type!=vm_str) @@ -997,7 +1004,7 @@ nasal_ref builtin_getenv(std::vector& local,nasal_gc& gc) *str.str()=res; return str; } -nasal_ref builtin_dlopen(std::vector& local,nasal_gc& gc) +nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc) { nasal_ref dlname=local[1]; if(dlname.type!=vm_str) @@ -1019,7 +1026,7 @@ nasal_ref builtin_dlopen(std::vector& local,nasal_gc& gc) ret.obj()->ptr=ptr; return ret; } -nasal_ref builtin_dlsym(std::vector& local,nasal_gc& gc) +nasal_ref builtin_dlsym(nasal_ref* local,nasal_gc& gc) { nasal_ref libptr=local[1]; nasal_ref sym=local[2]; @@ -1039,7 +1046,7 @@ nasal_ref builtin_dlsym(std::vector& local,nasal_gc& gc) ret.obj()->ptr=func; return ret; } -nasal_ref builtin_dlclose(std::vector& local,nasal_gc& gc) +nasal_ref builtin_dlclose(nasal_ref* local,nasal_gc& gc) { nasal_ref libptr=local[1]; if(libptr.type!=vm_obj || libptr.obj()->type!=obj_dylib) @@ -1051,7 +1058,7 @@ nasal_ref builtin_dlclose(std::vector& local,nasal_gc& gc) #endif return nil; } -nasal_ref builtin_dlcall(std::vector& local,nasal_gc& gc) +nasal_ref builtin_dlcall(nasal_ref* local,nasal_gc& gc) { nasal_ref funcptr=local[1]; nasal_ref args=local[2]; @@ -1061,7 +1068,7 @@ nasal_ref builtin_dlcall(std::vector& local,nasal_gc& gc) extern_func func=(extern_func)funcptr.obj()->ptr; return func(args.vec()->elems,gc); } -nasal_ref builtin_platform(std::vector& local,nasal_gc& gc) +nasal_ref builtin_platform(nasal_ref* local,nasal_gc& gc) { nasal_ref ret=gc.alloc(vm_str); #if defined _WIN32 || defined _WIN64 @@ -1073,7 +1080,7 @@ nasal_ref builtin_platform(std::vector& local,nasal_gc& gc) #endif return ret; } -nasal_ref builtin_gc(std::vector& local,nasal_gc& gc) +nasal_ref builtin_gc(nasal_ref* local,nasal_gc& gc) { gc.mark(); gc.sweep(); diff --git a/nasal_dbg.h b/nasal_dbg.h index 2b72da3..03a9b86 100644 --- a/nasal_dbg.h +++ b/nasal_dbg.h @@ -212,7 +212,7 @@ void nasal_dbg::run( } // set canary and program counter - auto canary=gc.stack+STACK_MAX_DEPTH-1; + canary=gc.stack+STACK_MAX_DEPTH-1; pc=0; // goto the first operand goto *code[pc]; diff --git a/nasal_gc.h b/nasal_gc.h index 8abd4d6..f988709 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -302,7 +302,7 @@ inline nasal_hash* nasal_ref::hash(){return value.gcobj->ptr.hash;} inline nasal_func* nasal_ref::func(){return value.gcobj->ptr.func;} inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; } -const uint32_t STACK_MAX_DEPTH=4095; +const uint32_t STACK_MAX_DEPTH=8191; const nasal_ref zero={vm_num,(double)0}; const nasal_ref one ={vm_num,(double)1}; const nasal_ref nil ={vm_nil,nullptr}; @@ -313,7 +313,7 @@ struct nasal_gc std::vector strs; // reserved address for const vm_str std::vector memory; // gc memory std::queue free_list[vm_type_size]; // gc free list - std::vector local; + std::vector upvalue; uint64_t size[vm_type_size]; uint64_t count[vm_type_size]; void mark(); @@ -329,7 +329,7 @@ struct nasal_gc void nasal_gc::mark() { std::queue bfs; - for(auto& i:local) + for(auto& i:upvalue) bfs.push(i); for(nasal_ref* i=stack;i<=top;++i) bfs.push(*i); @@ -405,10 +405,10 @@ void nasal_gc::clear() for(auto i:memory) delete i; memory.clear(); + upvalue.clear(); for(uint8_t i=0;i fstk; // stack to store function, used to get upvalues - std::stack local_stk; + std::stack lstk; // stack to store local scopes' begin address std::vector imm; // immediate number nasal_ref* mem_addr; // used for mem_call /* garbage collector */ @@ -234,17 +234,16 @@ void nasal_vm::global_state() } void nasal_vm::local_state() { - if(gc.local.empty() || !gc.local.back().vec()->elems.size()) + if(lstk.empty() || !fstk.top()->lsize) { printf("no local value exists\n"); return; } printf("local:\n"); - auto& vec=gc.local.back().vec()->elems; - for(uint32_t i=0;ilsize;++i) { printf("[0x%.8x]",i); - valinfo(vec[i]); + valinfo(lstk.top()[i]); } } void nasal_vm::upval_state() @@ -335,7 +334,8 @@ inline void nasal_vm::opr_loadg() } inline void nasal_vm::opr_loadl() { - gc.local.back().vec()->elems[imm[pc]]=(gc.top--)[0]; + lstk.top()[imm[pc]]=(gc.top--)[0]; + //gc.local.back().vec()->elems[imm[pc]]=(gc.top--)[0]; } inline void nasal_vm::opr_loadu() { @@ -374,10 +374,17 @@ inline void nasal_vm::opr_newf() nasal_func* func=gc.top[0].func(); func->entry=imm[pc]; func->psize=1; - if(!gc.local.empty()) + + /* this means you create a new function in local scope */ + if(!lstk.empty()) { func->upvalue=fstk.top()->upvalue; - func->upvalue.push_back(gc.local.back()); + nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_vec):gc.upvalue.back(); + func->upvalue.push_back(upval); + gc.upvalue.back()=upval; + auto& vec=upval.vec()->elems; + for(uint32_t i=0;ilsize;++i) + vec.push_back(lstk.top()[i]); } } inline void nasal_vm::opr_happ() @@ -586,7 +593,7 @@ inline void nasal_vm::opr_callg() } inline void nasal_vm::opr_calll() { - (++gc.top)[0]=gc.local.back().vec()->elems[imm[pc]]; + (++gc.top)[0]=lstk.top()[imm[pc]]; } inline void nasal_vm::opr_upval() { @@ -651,58 +658,60 @@ inline void nasal_vm::opr_callh() inline void nasal_vm::opr_callfv() { uint32_t argc=imm[pc]; // arguments counter - nasal_ref* args=gc.top-argc+1;// arguments begin place + nasal_ref* args=gc.top-argc+1;// arguments begin address if(args[-1].type!=vm_func) die("callfv: must call a function"); nasal_func* func=args[-1].func(); - if(gc.top+func->lsize>=canary) - die("stackoverflow"); - fstk.push(func);// push called function into stack to provide upvalue - - gc.local.push_back(gc.alloc(vm_vec)); // get new vector as local scope - gc.local.back().vec()->elems=func->local;// copy data from func.local to local scope - auto& local=gc.local.back().vec()->elems; + if(gc.top-argc+func->lsize+1>=canary) // gc.top-argc+lsize(local) +1(pc) + die("stack overflow"); + fstk.push(func); // push called function into stack to provide upvalue + lstk.push(gc.top-argc+1); // store begin of local scope - uint32_t psize=func->psize-1;// parameter size is func->psize-1, 1 is reserved for "me" - // load arguments - // if the first default value is not vm_none,then values after it are not nullptr - // args_size+1 is because the first space is reserved for 'me' + uint32_t psize=func->psize-1; // parameter size is func->psize-1, 1 is reserved for "me" if(argclocal[argc+1].type==vm_none) die("callfv: lack argument(s)"); - // if args_size>para_size,for 0 to args_size will cause corruption - uint32_t min_size=std::min(psize,argc); - for(uint32_t i=0;i=para_size - if(func->dynpara>=0) + + nasal_ref* local=args; + nasal_ref dynamic=nil; + gc.top=local+func->lsize; + if(func->dynpara>=0)// load dynamic arguments { - nasal_ref vec=gc.alloc(vm_vec); + dynamic=gc.alloc(vm_vec); for(uint32_t i=psize;ielems.push_back(args[i]); - local[min_size+1]=vec; + dynamic.vec()->elems.push_back(args[i]); } - - gc.top-=argc; // pop arguments - (++gc.top)[0]={vm_ret,pc}; + uint32_t min_size=std::min(psize,argc); + for(uint32_t i=min_size;i>=1;--i)// load arguments + local[i]=local[i-1]; + local[0]=func->local[0];// load "me" + for(uint32_t i=min_size+1;ilsize;++i)// load local scope & default arguments + local[i]=func->local[i]; + if(func->dynpara>=0) + local[psize+1]=dynamic; + + gc.top[0]={vm_ret,pc}; pc=func->entry-1; + gc.upvalue.push_back(nil); } inline void nasal_vm::opr_callfh() { auto& hash=gc.top[0].hash()->elems; if(gc.top[-1].type!=vm_func) die("callfh: must call a function"); - // push function and new local scope + nasal_func* func=gc.top[-1].func(); - if(gc.top+func->lsize>=canary) - die("stackoverflow"); + if(gc.top+func->lsize>=canary) // gc.top -1(hash) +lsize(local) +1(pc) + die("stack overflow"); if(func->dynpara>=0) die("callfh: special call cannot use dynamic argument"); - fstk.push(func); + fstk.push(func); // push called function into stack to provide upvalue + lstk.push(gc.top); // store begin of local scope - gc.local.push_back(gc.alloc(vm_vec)); - gc.local.back().vec()->elems=func->local; - auto& local=gc.local.back().vec()->elems; + nasal_ref* local=gc.top; + gc.top+=func->lsize; + for(uint32_t i=0;ilsize;++i) + local[i]=func->local[i]; for(auto& i:func->keys) { @@ -714,10 +723,11 @@ inline void nasal_vm::opr_callfh() gc.top[0]={vm_ret,(uint32_t)pc}; // rewrite top with vm_ret pc=func->entry-1; + gc.upvalue.push_back(nil); } inline void nasal_vm::opr_callb() { - (++gc.top)[0]=(*builtin[imm[pc]].func)(gc.local.back().vec()->elems,gc); + (++gc.top)[0]=(*builtin[imm[pc]].func)(lstk.top(),gc); if(gc.top[0].type==vm_none) die("native function error."); } @@ -782,7 +792,7 @@ inline void nasal_vm::opr_mcallg() } inline void nasal_vm::opr_mcalll() { - mem_addr=&(gc.local.back().vec()->elems[imm[pc]]); + mem_addr=lstk.top()+imm[pc]; (++gc.top)[0]=mem_addr[0]; } inline void nasal_vm::opr_mupval() @@ -836,15 +846,21 @@ inline void nasal_vm::opr_ret() // +-----------------+ // | return address | <- gc.top[-1] // +-----------------+ - // | called function | <- gc.top[-2] funct is set on stack because gc may mark it + // | local scope | + // +-----------------+ <- local pointer stored in lstk + // | called function | <- funct is set on stack because gc may mark it // +-----------------+ + nasal_ref ret=gc.top[0]; pc=gc.top[-1].ret(); - gc.top[-2].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil - gc.top[-2]=gc.top[0]; // rewrite func with returned value - gc.top-=2; + + gc.top=lstk.top()-1; + lstk.pop(); + + gc.top[0].func()->local[0]={vm_nil,nullptr}; // get func and set 'me' to nil + gc.top[0]=ret; // rewrite func with returned value fstk.pop(); - gc.local.pop_back(); + gc.upvalue.pop_back(); } void nasal_vm::run( const nasal_codegen& gen, @@ -968,7 +984,7 @@ upval: exec_operand(opr_upval ,op_upval ); // +1 callv: exec_opnodie(opr_callv ,op_callv ); // -0 callvi: exec_opnodie(opr_callvi ,op_callvi ); // -0 callh: exec_opnodie(opr_callh ,op_callh ); // -0 -callfv: exec_operand(opr_callfv ,op_callfv ); // +1-imm[pc] call this will push >=0 arguments +callfv: exec_opnodie(opr_callfv ,op_callfv ); // check in the function callfh: exec_opnodie(opr_callfh ,op_callfh ); // -0 call this will push one hash callb: exec_opnodie(opr_callb ,op_callb ); // -0 slcbegin:exec_operand(opr_slcbegin,op_slcbegin); // +1 diff --git a/test/bf.nas b/test/bf.nas index cf65ad7..9481522 100644 --- a/test/bf.nas +++ b/test/bf.nas @@ -152,6 +152,15 @@ var (ptr,pc)=(0,0); var (code,inum,stack)=([],[],[]); var (add,mov,jt,jf,in,out)=(0,1,2,3,4,5); +var funcs=[ + func{paper[ptr]+=inum[pc];}, + func{ptr+=inum[pc];}, + func{if(paper[ptr])pc=inum[pc];}, + func{if(!paper[ptr])pc=inum[pc];}, + func{paper[ptr]=input()[0];}, + func{print(chr(paper[ptr]));} +]; + var bf=func(program){ setsize(paper,131072); var len=size(program); @@ -212,15 +221,8 @@ var bf=func(program){ return; } len=size(code); - for(pc=0;pc