diff --git a/README.md b/README.md index c3b3696..92c16ec 100644 --- a/README.md +++ b/README.md @@ -1063,8 +1063,8 @@ nasal_ref builtin_print(std::vector& local,nasal_gc& gc) } std::cout<& local,nasal_gc& gc) } std::cout<& local,nasal_gc& gc) { @@ -200,7 +200,7 @@ nasal_ref builtin_append(std::vector& local,nasal_gc& gc) auto& ref_vec=vec.vec()->elems; for(auto& i:elem.vec()->elems) ref_vec.push_back(i); - return gc.nil; + return nil; } nasal_ref builtin_setsize(std::vector& local,nasal_gc& gc) { @@ -213,8 +213,8 @@ nasal_ref builtin_setsize(std::vector& local,nasal_gc& gc) int num=(int)size.num(); if(num<0) return builtin_err("setsize","\"size\" must be greater than -1"); - vec.vec()->elems.resize(num,gc.nil); - return gc.nil; + vec.vec()->elems.resize(num,nil); + return nil; } nasal_ref builtin_system(std::vector& local,nasal_gc& gc) { @@ -258,7 +258,7 @@ nasal_ref builtin_fout(std::vector& local,nasal_gc& gc) if(fout.fail()) return builtin_err("io.fout","cannot open \""+*val.str()+"\""); fout<<*str.str(); - return gc.nil; + return nil; } nasal_ref builtin_split(std::vector& local,nasal_gc& gc) { @@ -328,7 +328,7 @@ nasal_ref builtin_rand(std::vector& local,nasal_gc& gc) if(val.type==vm_num) { srand((unsigned int)val.num()); - return gc.nil; + return nil; } double num=0; for(int i=0;i<5;++i) @@ -351,7 +351,7 @@ nasal_ref builtin_int(std::vector& local,nasal_gc& gc) { nasal_ref val=local[1]; if(val.type!=vm_num) - return gc.nil; + return nil; int number=(int)val.num(); return {vm_num,(double)number}; } @@ -361,10 +361,10 @@ nasal_ref builtin_num(std::vector& local,nasal_gc& gc) if(val.type==vm_num) return val; if(val.type!=vm_str) - return gc.nil; + return nil; double res=val.to_number(); if(std::isnan(res)) - return gc.nil; + return nil; return {vm_num,res}; } nasal_ref builtin_pop(std::vector& local,nasal_gc& gc) @@ -378,7 +378,7 @@ nasal_ref builtin_pop(std::vector& local,nasal_gc& gc) val.vec()->elems.pop_back(); return tmp; } - return gc.nil; + return nil; } nasal_ref builtin_str(std::vector& local,nasal_gc& gc) { @@ -520,7 +520,7 @@ nasal_ref builtin_atan2(std::vector& local,nasal_gc& gc) nasal_ref builtin_isnan(std::vector& local,nasal_gc& gc) { nasal_ref x=local[1]; - return (x.type==vm_num && std::isnan(x.num()))?gc.one:gc.zero; + return (x.type==vm_num && std::isnan(x.num()))?one:zero; } nasal_ref builtin_time(std::vector& local,nasal_gc& gc) { @@ -538,7 +538,7 @@ nasal_ref builtin_contains(std::vector& local,nasal_gc& gc) return builtin_err("contains","\"hash\" must be hash"); if(key.type!=vm_str) return builtin_err("contains","\"key\" must be string"); - return hash.hash()->elems.count(*key.str())?gc.one:gc.zero; + return hash.hash()->elems.count(*key.str())?one:zero; } nasal_ref builtin_delete(std::vector& local,nasal_gc& gc) { @@ -550,7 +550,7 @@ nasal_ref builtin_delete(std::vector& local,nasal_gc& gc) return builtin_err("delete","\"key\" must be string"); if(hash.hash()->elems.count(*key.str())) hash.hash()->elems.erase(*key.str()); - return gc.nil; + return nil; } nasal_ref builtin_keys(std::vector& local,nasal_gc& gc) { @@ -729,7 +729,7 @@ nasal_ref builtin_close(std::vector& local,nasal_gc& gc) if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) return builtin_err("close","not a correct filehandle"); fclose((FILE*)filehandle.obj()->ptr); - return gc.nil; + return nil; } nasal_ref builtin_read(std::vector& local,nasal_gc& gc) { @@ -803,7 +803,7 @@ nasal_ref builtin_readln(std::vector& local,nasal_gc& gc) } if(s.length()) return str; - return gc.nil; + return nil; } nasal_ref builtin_stat(std::vector& local,nasal_gc& gc) { @@ -913,7 +913,7 @@ nasal_ref builtin_setfld(std::vector& local,nasal_gc& gc) else s[i>>3]&=~(1<<(7-(i&7))); } - return gc.nil; + return nil; } nasal_ref builtin_buf(std::vector& local,nasal_gc& gc) { @@ -931,7 +931,7 @@ nasal_ref builtin_sleep(std::vector& local,nasal_gc& gc) if(val.type!=vm_num) return builtin_err("sleep","\"duration\" must be number"); usleep((useconds_t)(val.num()*1e6)); - return gc.nil; + return nil; } nasal_ref builtin_opendir(std::vector& local,nasal_gc& gc) { @@ -953,7 +953,7 @@ nasal_ref builtin_readdir(std::vector& local,nasal_gc& gc) return builtin_err("readdir","not a correct dir handle"); dirent* p=readdir((DIR*)handle.obj()->ptr); if(!p) - return gc.nil; + return nil; nasal_ref ret=gc.alloc(vm_str); *ret.str()=p->d_name; return ret; @@ -964,7 +964,7 @@ nasal_ref builtin_closedir(std::vector& local,nasal_gc& gc) if(handle.type!=vm_obj || handle.obj()->type!=obj_dir) return builtin_err("closedir","not a correct dir handle"); closedir((DIR*)handle.obj()->ptr); - return gc.nil; + return nil; } nasal_ref builtin_chdir(std::vector& local,nasal_gc& gc) { @@ -973,7 +973,7 @@ nasal_ref builtin_chdir(std::vector& local,nasal_gc& gc) return builtin_err("chdir","\"path\" must be string"); if(chdir(path.str()->c_str())<0) return builtin_err("chdir","failed to execute chdir"); - return gc.nil; + return nil; } nasal_ref builtin_getcwd(std::vector& local,nasal_gc& gc) { @@ -990,7 +990,7 @@ nasal_ref builtin_getenv(std::vector& local,nasal_gc& gc) return builtin_err("getenv","\"envvar\" must be string"); char* res=getenv(envvar.str()->c_str()); if(!res) - return gc.nil; + return nil; nasal_ref str=gc.alloc(vm_str); *str.str()=res; return str; @@ -1047,7 +1047,7 @@ nasal_ref builtin_dlclose(std::vector& local,nasal_gc& gc) #else dlclose(libptr.obj()->ptr); #endif - return gc.nil; + return nil; } nasal_ref builtin_dlcall(std::vector& local,nasal_gc& gc) { diff --git a/nasal_gc.h b/nasal_gc.h index 3a60dc4..2602347 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -30,17 +30,17 @@ const uint32_t increment[vm_type_size]= 0, // vm_num /* gc object */ 512, // vm_str - 512, // vm_func - 512, // vm_vec - 512, // vm_hash - 64 // vm_obj + 1024,// vm_func + 4096,// vm_vec + 256, // vm_hash + 16 // vm_obj }; struct nasal_vec; struct nasal_hash; struct nasal_func; struct nasal_obj; -struct nasal_val; +struct nasal_val; // nasal_val includes gc-managed types struct nasal_ref { @@ -118,9 +118,9 @@ struct nasal_obj void clear(){ptr=nullptr;} }; -constexpr uint8_t GC_UNCOLLECTED=0; -constexpr uint8_t GC_COLLECTED =1; -constexpr uint8_t GC_FOUND =2; +const uint8_t GC_UNCOLLECTED=0; +const uint8_t GC_COLLECTED =1; +const uint8_t GC_FOUND =2; struct nasal_val { uint8_t mark; @@ -316,12 +316,12 @@ 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; } -constexpr uint32_t STACK_MAX_DEPTH=4095; +const uint32_t STACK_MAX_DEPTH=4095; +const nasal_ref zero={vm_num,(double)0}; +const nasal_ref one ={vm_num,(double)1}; +const nasal_ref nil ={vm_nil,nullptr}; struct nasal_gc { - nasal_ref zero; - nasal_ref one; - nasal_ref nil; nasal_ref stack[STACK_MAX_DEPTH+1];// 1 reserved to avoid stack overflow nasal_ref* top; // stack top std::vector strs; // reserved address for const vm_str @@ -399,13 +399,7 @@ void nasal_gc::init(const std::vector& s) memory.push_back(tmp); free_list[i].push(tmp); } - - top=stack; // set top to stack - - zero={vm_num,(double)0}; // init constant 0 - one ={vm_num,(double)1}; // init constant 1 - nil ={vm_nil,nullptr}; // init constant nil - + top=stack; // init constant strings strs.resize(s.size()); for(uint32_t i=0;ilocal.resize(imm[pc],gc.nil); + gc.top[0].func()->local.resize(imm[pc],nil); } inline void nasal_vm::opr_loadg() { @@ -403,15 +403,15 @@ inline void nasal_vm::opr_unot() nasal_ref val=gc.top[0]; switch(val.type) { - case vm_nil:gc.top[0]=gc.one;break; - case vm_num:gc.top[0]=val.num()?gc.zero:gc.one;break; + case vm_nil:gc.top[0]=one;break; + case vm_num:gc.top[0]=val.num()?zero:one;break; case vm_str: { double num=str2num(val.str()->c_str()); if(std::isnan(num)) gc.top[0]={vm_num,(double)val.str()->empty()}; else - gc.top[0]=num?gc.zero:gc.one; + gc.top[0]=num?zero:one; } break; default:die("unot: incorrect value type");break; @@ -491,31 +491,31 @@ inline void nasal_vm::opr_eq() nasal_ref val2=gc.top[0]; nasal_ref val1=(--gc.top)[0]; if(val1.type==vm_nil && val2.type==vm_nil) - gc.top[0]=gc.one; + gc.top[0]=one; else if(val1.type==vm_str && val2.type==vm_str) - gc.top[0]=(*val1.str()==*val2.str())?gc.one:gc.zero; + gc.top[0]=(*val1.str()==*val2.str())?one:zero; else if(val1.type==vm_num || val2.type==vm_num) - gc.top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero; + gc.top[0]=(val1.to_number()==val2.to_number())?one:zero; else - gc.top[0]=(val1==val2)?gc.one:gc.zero; + gc.top[0]=(val1==val2)?one:zero; } inline void nasal_vm::opr_neq() { nasal_ref val2=gc.top[0]; nasal_ref val1=(--gc.top)[0]; if(val1.type==vm_nil && val2.type==vm_nil) - gc.top[0]=gc.zero; + gc.top[0]=zero; else if(val1.type==vm_str && val2.type==vm_str) - gc.top[0]=(*val1.str()!=*val2.str())?gc.one:gc.zero; + gc.top[0]=(*val1.str()!=*val2.str())?one:zero; else if(val1.type==vm_num || val2.type==vm_num) - gc.top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero; + gc.top[0]=(val1.to_number()!=val2.to_number())?one:zero; else - gc.top[0]=(val1!=val2)?gc.one:gc.zero; + gc.top[0]=(val1!=val2)?one:zero; } #define op_cmp(type)\ --gc.top;\ - gc.top[0]=(gc.top[0].to_number() type gc.top[1].to_number())?gc.one:gc.zero; + gc.top[0]=(gc.top[0].to_number() type gc.top[1].to_number())?one:zero; inline void nasal_vm::opr_less(){op_cmp(<);} inline void nasal_vm::opr_leq(){op_cmp(<=);} @@ -523,7 +523,7 @@ inline void nasal_vm::opr_grt(){op_cmp(>);} inline void nasal_vm::opr_geq(){op_cmp(>=);} #define op_cmp_const(type)\ - gc.top[0]=(gc.top[0].to_number() type num_table[imm[pc]])?gc.one:gc.zero; + gc.top[0]=(gc.top[0].to_number() type num_table[imm[pc]])?one:zero; inline void nasal_vm::opr_lessc(){op_cmp_const(<);} inline void nasal_vm::opr_leqc(){op_cmp_const(<=);} @@ -650,17 +650,18 @@ inline void nasal_vm::opr_callfv() nasal_ref* args=gc.top-args_size+1; if(args[-1].type!=vm_func) die("callfv: must call a function"); - // push function and new local scope - func_stk.push(args[-1].func()); + + func_stk.push(args[-1].func());// push called function into stack to provide upvalue auto& func=*args[-1].func(); - gc.local.push_back(gc.alloc(vm_vec)); - gc.local.back().vec()->elems=func.local; + 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; uint32_t para_size=func.keys.size(); // load arguments // if the first default value is not vm_none,then values after it are not nullptr - if(args_sizepara_size,for 0 to args_size will cause corruption uint32_t min_size=std::min(para_size,args_size); @@ -697,7 +698,7 @@ inline void nasal_vm::opr_callfh() { if(hash.count(i.first)) local[i.second+1]=hash[i.first]; - else if(func.local[i.second+1/*1 is reserved for 'me'*/].type==vm_none) + else if(local[i.second+1].type==vm_none) die("callfh: lack argument(s): \""+i.first+"\""); }