diff --git a/README.md b/README.md index b3e711c..09cca42 100644 --- a/README.md +++ b/README.md @@ -637,14 +637,14 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) for(auto& i:vec.vec().elems) switch(i.type) { - case vm_none: std::cout<<"undefined"; break; - case vm_nil: std::cout<<"nil"; break; - case vm_num: std::cout<"; break; + case vm_none: std::cout<<"undefined"; break; + case vm_nil: std::cout<<"nil"; break; + case vm_num: std::cout<"; break; } std::cout<"; break; + case vm_none: std::cout<<"undefined"; break; + case vm_nil: std::cout<<"nil"; break; + case vm_num: std::cout<"; break; } std::cout<& elems) for(auto& i:elems) switch(i.type) { - case vm_none: std::cout<<"null"; break; - case vm_nil: std::cout<<"nil"; break; - case vm_num: std::cout<"; break; - case vm_co: std::cout<<""; break; + case vm_none: std::cout<<"null"; break; + case vm_nil: std::cout<<"nil"; break; + case vm_num: std::cout<"; break; + case vm_co: std::cout<<""; break; } } nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc) @@ -290,15 +290,14 @@ nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc) nasal_ref val=local[1]; if(val.type!=vm_str) return builtin_err("io.fin","\"filename\" must be string"); - std::string& filename=val.str(); - std::ifstream fin(filename); + std::ifstream fin(val.str()); if(!fin.fail()) { std::stringstream rd; rd<"); } nasal_ref builtin_fout(nasal_ref* local,nasal_gc& gc) { @@ -310,7 +309,7 @@ nasal_ref builtin_fout(nasal_ref* local,nasal_gc& gc) return builtin_err("io.fout","\"str\" must be string"); std::ofstream fout(val.str()); if(fout.fail()) - return builtin_err("io.fout","cannot open \""+val.str()+"\""); + return builtin_err("io.fout","cannot open <"+val.str()+">"); fout<vm_num) - ss<<"0x"<"); nasal_ref ret=gc.alloc(vm_obj); - ret.obj().type=nasal_obj::file; - ret.obj().ptr=(void*)res; - ret.obj().destructor=obj_file_destructor; + ret.obj().set(nasal_obj::file,res,obj_file_dtor); return ret; } nasal_ref builtin_close(nasal_ref* local,nasal_gc& gc) @@ -793,7 +790,7 @@ nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc) return builtin_err("read","not a valid filehandle"); if(buf.type!=vm_str) return builtin_err("read","\"buf\" must be string"); - if(buf.value.gcobj->unmut) + if(buf.val.gcobj->unmut) return builtin_err("read","\"buf\" is not a mutable string"); if(len.type!=vm_num) return builtin_err("read","\"len\" must be number"); @@ -889,8 +886,7 @@ nasal_ref builtin_eof(nasal_ref* local,nasal_gc& gc) nasal_ref fd=local[1]; if(!fd.objchk(nasal_obj::file)) return builtin_err("readln","not a valid filehandle"); - double res=feof((FILE*)fd.obj().ptr); - return {vm_num,res}; + return {vm_num,(double)feof((FILE*)fd.obj().ptr)}; } nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc) { @@ -900,7 +896,7 @@ nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc) nasal_ref str=local[1]; nasal_ref startbit=local[2]; nasal_ref length=local[3]; - if(str.type!=vm_str || str.value.gcobj->unmut) + if(str.type!=vm_str || str.val.gcobj->unmut) return builtin_err("fld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num) return builtin_err("fld","\"startbit\",\"len\" must be number"); @@ -924,7 +920,7 @@ nasal_ref builtin_sfld(nasal_ref* local,nasal_gc& gc) nasal_ref str=local[1]; nasal_ref startbit=local[2]; nasal_ref length=local[3]; - if(str.type!=vm_str || str.value.gcobj->unmut) + if(str.type!=vm_str || str.val.gcobj->unmut) return builtin_err("sfld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num) return builtin_err("sfld","\"startbit\",\"len\" must be number"); @@ -951,7 +947,7 @@ nasal_ref builtin_setfld(nasal_ref* local,nasal_gc& gc) nasal_ref startbit=local[2]; nasal_ref length=local[3]; nasal_ref value=local[4]; - if(str.type!=vm_str || str.value.gcobj->unmut) + if(str.type!=vm_str || str.val.gcobj->unmut) return builtin_err("setfld","\"str\" must be mutable string"); if(startbit.type!=vm_num || length.type!=vm_num || value.type!=vm_num) return builtin_err("setfld","\"startbit\",\"len\",\"val\" must be number"); @@ -974,7 +970,7 @@ nasal_ref builtin_buf(nasal_ref* local,nasal_gc& gc) { nasal_ref length=local[1]; if(length.type!=vm_num || length.num()<=0) - return builtin_err("buf","\"len\" must be a number greater than 9"); + return builtin_err("buf","\"len\" must be a number greater than 0"); nasal_ref str=gc.alloc(vm_str); auto& s=str.str(); s.resize(length.num(),'\0'); @@ -999,7 +995,7 @@ nasal_ref builtin_pipe(nasal_ref* local,nasal_gc& gc) res.vec().elems.push_back({vm_num,(double)fd[1]}); return res; #endif - return builtin_err("pipe","not supported for windows platform"); + return builtin_err("pipe","not supported for windows"); } nasal_ref builtin_fork(nasal_ref* local,nasal_gc& gc) { @@ -1009,7 +1005,7 @@ nasal_ref builtin_fork(nasal_ref* local,nasal_gc& gc) return builtin_err("fork","failed to fork a process"); return {vm_num,(double)res}; #endif - return builtin_err("fork","not supported for windows platform"); + return builtin_err("fork","not supported for windows"); } nasal_ref builtin_waitpid(nasal_ref* local,nasal_gc& gc) { @@ -1026,9 +1022,9 @@ nasal_ref builtin_waitpid(nasal_ref* local,nasal_gc& gc) vec.vec().elems.push_back({vm_num,(double)status}); return vec; #endif - return builtin_err("waitpid","not supported for windows platform"); + return builtin_err("waitpid","not supported for windows"); } -void obj_dir_destructor(void* ptr) +void obj_dir_dtor(void* ptr) { #ifndef _MSC_VER closedir((DIR*)ptr); @@ -1053,9 +1049,7 @@ nasal_ref builtin_opendir(nasal_ref* local,nasal_gc& gc) return builtin_err("opendir","cannot open dir <"+path.str()+">"); #endif nasal_ref ret=gc.alloc(vm_obj); - ret.obj().type=nasal_obj::dir; - ret.obj().ptr=(void*)p; - ret.obj().destructor=obj_dir_destructor; + ret.obj().set(nasal_obj::dir,p,obj_dir_dtor); return ret; } nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc) @@ -1127,7 +1121,7 @@ nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) return nil; return gc.newstr(res); } -void obj_dylib_destructor(void* ptr) +void obj_dylib_dtor(void* ptr) { #ifdef _WIN32 FreeLibrary((HMODULE)ptr); @@ -1152,29 +1146,26 @@ nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc) if(!ptr) return builtin_err("dlopen","cannot open dynamic lib <"+dlname.str()+">"); nasal_ref ret=gc.alloc(vm_obj); - ret.obj().type=nasal_obj::dylib; - ret.obj().ptr=ptr; - ret.obj().destructor=obj_dylib_destructor; + ret.obj().set(nasal_obj::dylib,ptr,obj_dylib_dtor); return ret; } nasal_ref builtin_dlsym(nasal_ref* local,nasal_gc& gc) { - nasal_ref libptr=local[1]; + nasal_ref lib=local[1]; nasal_ref sym=local[2]; - if(!libptr.objchk(nasal_obj::dylib)) + if(!lib.objchk(nasal_obj::dylib)) return builtin_err("dlsym","\"lib\" is not a valid dynamic lib"); if(sym.type!=vm_str) return builtin_err("dlsym","\"sym\" must be string"); #ifdef _WIN32 - void* func=(void*)GetProcAddress((HMODULE)libptr.obj().ptr,sym.str().c_str()); + void* func=(void*)GetProcAddress((HMODULE)lib.obj().ptr,sym.str().c_str()); #else - void* func=dlsym(libptr.obj().ptr,sym.str().c_str()); + void* func=dlsym(lib.obj().ptr,sym.str().c_str()); #endif if(!func) return builtin_err("dlsym","cannot find symbol \""+sym.str()+"\""); nasal_ref ret=gc.alloc(vm_obj); - ret.obj().type=nasal_obj::faddr; - ret.obj().ptr=func; + ret.obj().set(nasal_obj::faddr,func); return ret; } nasal_ref builtin_dlclose(nasal_ref* local,nasal_gc& gc) diff --git a/nasal_gc.h b/nasal_gc.h index 151c9b4..fc9216a 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -61,29 +61,29 @@ struct nasal_ref double num; nasal_ref* addr; nasal_val* gcobj; - } value; + } val; // vm_none/vm_nil nasal_ref(const uint8_t t=vm_none):type(t){} // vm_ret - nasal_ref(const uint8_t t,const uint32_t n):type(t){value.ret=n;} + nasal_ref(const uint8_t t,const uint32_t n):type(t){val.ret=n;} // vm_cnt - nasal_ref(const uint8_t t,const int64_t n):type(t){value.cnt=n;} + nasal_ref(const uint8_t t,const int64_t n):type(t){val.cnt=n;} // vm_num - nasal_ref(const uint8_t t,const double n):type(t){value.num=n;} + nasal_ref(const uint8_t t,const double n):type(t){val.num=n;} // vm_str/vm_func/vm_vec/vm_hash/vm_upval/vm_obj - nasal_ref(const uint8_t t,nasal_val* n):type(t){value.gcobj=n;} + nasal_ref(const uint8_t t,nasal_val* n):type(t){val.gcobj=n;} // vm_addr - nasal_ref(const uint8_t t,nasal_ref* n):type(t){value.addr=n;} - nasal_ref(const nasal_ref& nr):type(nr.type),value(nr.value){} + nasal_ref(const uint8_t t,nasal_ref* n):type(t){val.addr=n;} + nasal_ref(const nasal_ref& nr):type(nr.type),val(nr.val){} nasal_ref& operator=(const nasal_ref& nr) { type=nr.type; - value=nr.value; + val=nr.val; return *this; } - bool operator==(const nasal_ref& nr){return type==nr.type && value.gcobj==nr.value.gcobj;} - bool operator!=(const nasal_ref& nr){return type!=nr.type || value.gcobj!=nr.value.gcobj;} + bool operator==(const nasal_ref& nr){return type==nr.type && val.gcobj==nr.val.gcobj;} + bool operator!=(const nasal_ref& nr){return type!=nr.type || val.gcobj!=nr.val.gcobj;} // number and string can be translated to each other double tonum(); std::string tostr(); @@ -154,7 +154,7 @@ struct nasal_upval struct nasal_obj { - enum obj_type + enum obj_t:std::uint32_t { null, file, @@ -166,20 +166,25 @@ struct nasal_obj /* new object is initialized when creating */ uint32_t type; void* ptr; - /* RAII destroyer */ /* default destroyer does nothing */ typedef void (*dest)(void*); - dest destructor; + dest dtor; - nasal_obj():type(obj_type::null),ptr(nullptr),destructor(nullptr){} + nasal_obj():type(obj_t::null),ptr(nullptr),dtor(nullptr){} ~nasal_obj(){clear();} + void set(uint32_t t=obj_t::null,void* p=nullptr,dest d=nullptr) + { + type=t; + ptr=p; + dtor=d; + } void clear() { - if(destructor && ptr) - destructor(ptr); + if(dtor && ptr) + dtor(ptr); ptr=nullptr; - destructor=nullptr; + dtor=nullptr; } }; @@ -382,7 +387,7 @@ nasal_val::~nasal_val() } double nasal_ref::tonum() { - return type!=vm_str?value.num:str2num(str().c_str()); + return type!=vm_str?val.num:str2num(str().c_str()); } std::string nasal_ref::tostr() { @@ -403,7 +408,7 @@ void nasal_ref::print() { case vm_none: std::cout<<"undefined"; break; case vm_nil: std::cout<<"nil"; break; - case vm_num: std::cout<ptr.str; } -inline nasal_vec& nasal_ref::vec (){return *value.gcobj->ptr.vec; } -inline nasal_hash& nasal_ref::hash (){return *value.gcobj->ptr.hash; } -inline nasal_func& nasal_ref::func (){return *value.gcobj->ptr.func; } -inline nasal_upval& nasal_ref::upval(){return *value.gcobj->ptr.upval;} -inline nasal_obj& nasal_ref::obj (){return *value.gcobj->ptr.obj; } -inline nasal_co& nasal_ref::co (){return *value.gcobj->ptr.co; } +inline nasal_ref* nasal_ref::addr (){return val.addr; } +inline uint32_t nasal_ref::ret (){return val.ret; } +inline int64_t& nasal_ref::cnt (){return val.cnt; } +inline double nasal_ref::num (){return val.num; } +inline std::string& nasal_ref::str (){return *val.gcobj->ptr.str; } +inline nasal_vec& nasal_ref::vec (){return *val.gcobj->ptr.vec; } +inline nasal_hash& nasal_ref::hash (){return *val.gcobj->ptr.hash; } +inline nasal_func& nasal_ref::func (){return *val.gcobj->ptr.func; } +inline nasal_upval& nasal_ref::upval(){return *val.gcobj->ptr.upval;} +inline nasal_obj& nasal_ref::obj (){return *val.gcobj->ptr.obj; } +inline nasal_co& nasal_ref::co (){return *val.gcobj->ptr.co; } const nasal_ref zero={vm_num,(double)0}; const nasal_ref one ={vm_num,(double)1}; @@ -517,8 +522,8 @@ void nasal_gc::mark() { nasal_ref tmp=bfs.front(); bfs.pop(); - if(tmp.type<=vm_num || tmp.value.gcobj->mark) continue; - tmp.value.gcobj->mark=GC_FOUND; + if(tmp.type<=vm_num || tmp.val.gcobj->mark) continue; + tmp.val.gcobj->mark=GC_FOUND; switch(tmp.type) { case vm_vec: @@ -591,7 +596,7 @@ void nasal_gc::init(const std::vector& s,const std::vectorunmut=1; + strs[i].val.gcobj->unmut=1; strs[i].str()=s[i]; } // record arguments @@ -599,7 +604,7 @@ void nasal_gc::init(const std::vector& s,const std::vectorunmut=1; + env_argv[i].val.gcobj->unmut=1; env_argv[i].str()=argv[i]; } } @@ -612,7 +617,7 @@ void nasal_gc::clear() while(!unused[i].empty()) unused[i].pop(); for(auto& i:strs) - delete i.value.gcobj; + delete i.val.gcobj; strs.clear(); env_argv.clear(); } @@ -648,7 +653,7 @@ nasal_ref nasal_gc::alloc(uint8_t type) } } nasal_ref ret={type,unused[index].front()}; - ret.value.gcobj->mark=GC_UNCOLLECTED; + ret.val.gcobj->mark=GC_UNCOLLECTED; unused[index].pop(); return ret; } diff --git a/nasal_vm.h b/nasal_vm.h index d0eb356..5bb8385 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -157,7 +157,7 @@ void nasal_vm::init( } void nasal_vm::valinfo(nasal_ref& val) { - const nasal_val* p=val.value.gcobj; + const nasal_val* p=val.val.gcobj; std::cout<<"\t"; switch(val.type) { @@ -670,7 +670,7 @@ inline void nasal_vm::opr_callv() die("callv: must use string as the key"); top[0]=vec.hash().get_val(val.str()); if(top[0].type==vm_none) - die("callv: cannot find member \""+val.str()+"\" of this hash"); + die("callv: cannot find member \""+val.str()+"\""); if(top[0].type==vm_func) top[0].func().local[0]=val;// 'me' } @@ -958,8 +958,9 @@ inline void nasal_vm::opr_ret() auto& upval=up.upval(); auto size=func.func().lsize; upval.onstk=false; + upval.elems.resize(size); for(uint32_t i=0;i