change nasal_ref value option functions' output types from pointers to references

This commit is contained in:
ValKmjolnir 2022-03-09 22:54:54 +08:00
parent d8156e839b
commit e54ef9620f
4 changed files with 248 additions and 245 deletions

View File

@ -535,15 +535,15 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
// main process // main process
// also check number of arguments and type here // also check number of arguments and type here
// if get an error,use builtin_err // if get an error,use builtin_err
for(auto i:vec.vec()->elems) for(auto i:vec.vec().elems)
switch(i.type) switch(i.type)
{ {
case vm_none: std::cout<<"undefined"; break; case vm_none: std::cout<<"undefined"; break;
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<i.num(); break; case vm_num: std::cout<<i.num(); break;
case vm_str: std::cout<<*i.str(); break; case vm_str: std::cout<<i.str(); break;
case vm_vec: i.vec()->print(); break; case vm_vec: i.vec().print(); break;
case vm_hash: i.hash()->print(); break; case vm_hash: i.hash().print(); break;
case vm_func: std::cout<<"func(...){...}"; break; case vm_func: std::cout<<"func(...){...}"; break;
case vm_obj: std::cout<<"<object>"; break; case vm_obj: std::cout<<"<object>"; break;
} }
@ -609,21 +609,20 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref hash=local[1]; nasal_ref hash=local[1];
if(hash.type!=vm_hash) if(hash.type!=vm_hash)
{ return builtin_err("keys","\"hash\" must be hash");
builtin_err("keys","\"hash\" must be hash");
return nasal_ref(vm_none);
}
// push vector into local scope to avoid being sweeped // push vector into local scope to avoid being sweeped
local.push_back(gc.alloc(vm_vec)); if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
std::vector<nasal_ref>& vec=local.back().vec()->elems; builtin_err("keys","expand temporary space error:stackoverflow");
for(auto& iter:hash.hash()->elems) (++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash().elems)
{ {
nasal_ref str=gc.builtin_alloc(vm_str); nasal_ref str=gc.alloc(vm_str);
*str.str()=iter.first; str.str()=iter.first;
vec.push_back(str); vec.push_back(str);
} }
return local.back(); --gc.top;
return gc.top[1];
} }
``` ```

View File

@ -189,15 +189,15 @@ nasal_ref builtin_print(nasal_ref* local,nasal_gc& gc)
// local[0] is reserved for 'me' // local[0] is reserved for 'me'
nasal_ref vec=local[1]; nasal_ref vec=local[1];
// main process // main process
for(auto& i:vec.vec()->elems) for(auto& i:vec.vec().elems)
switch(i.type) switch(i.type)
{ {
case vm_none: std::cout<<"null"; break; case vm_none: std::cout<<"null"; break;
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<i.num(); break; case vm_num: std::cout<<i.num(); break;
case vm_str: std::cout<<*i.str(); break; case vm_str: std::cout<<i.str(); break;
case vm_vec: i.vec()->print(); break; case vm_vec: i.vec().print(); break;
case vm_hash: i.hash()->print(); break; case vm_hash: i.hash().print(); break;
case vm_func: std::cout<<"func(...){...}"; break; case vm_func: std::cout<<"func(...){...}"; break;
case vm_obj: std::cout<<"<object>"; break; case vm_obj: std::cout<<"<object>"; break;
} }
@ -211,8 +211,8 @@ nasal_ref builtin_append(nasal_ref* local,nasal_gc& gc)
nasal_ref elem=local[2]; nasal_ref elem=local[2];
if(vec.type!=vm_vec) if(vec.type!=vm_vec)
return builtin_err("append","\"vector\" must be vector"); return builtin_err("append","\"vector\" must be vector");
auto& ref_vec=vec.vec()->elems; auto& ref_vec=vec.vec().elems;
for(auto& i:elem.vec()->elems) for(auto& i:elem.vec().elems)
ref_vec.push_back(i); ref_vec.push_back(i);
return nil; return nil;
} }
@ -227,7 +227,7 @@ nasal_ref builtin_setsize(nasal_ref* local,nasal_gc& gc)
int num=(int)size.num(); int num=(int)size.num();
if(num<0) if(num<0)
return builtin_err("setsize","\"size\" must be greater than -1"); return builtin_err("setsize","\"size\" must be greater than -1");
vec.vec()->elems.resize(num,nil); vec.vec().elems.resize(num,nil);
return nil; return nil;
} }
nasal_ref builtin_system(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_system(nasal_ref* local,nasal_gc& gc)
@ -235,12 +235,12 @@ nasal_ref builtin_system(nasal_ref* local,nasal_gc& gc)
nasal_ref str=local[1]; nasal_ref str=local[1];
if(str.type!=vm_str) if(str.type!=vm_str)
return builtin_err("system","\"str\" must be string"); return builtin_err("system","\"str\" must be string");
return {vm_num,(double)system(str.str()->c_str())}; return {vm_num,(double)system(str.str().c_str())};
} }
nasal_ref builtin_input(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_input(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
std::cin>>*ret.str(); std::cin>>ret.str();
return ret; return ret;
} }
nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc)
@ -248,14 +248,14 @@ nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc)
nasal_ref val=local[1]; nasal_ref val=local[1];
if(val.type!=vm_str) if(val.type!=vm_str)
return builtin_err("io.fin","\"filename\" must be string"); return builtin_err("io.fin","\"filename\" must be string");
std::string& filename=*val.str(); std::string& filename=val.str();
std::ifstream fin(filename); std::ifstream fin(filename);
if(!fin.fail()) if(!fin.fail())
{ {
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
std::stringstream rd; std::stringstream rd;
rd<<fin.rdbuf(); rd<<fin.rdbuf();
*ret.str()=rd.str(); ret.str()=rd.str();
return ret; return ret;
} }
return builtin_err("io.fin","cannot open \""+filename+"\""); return builtin_err("io.fin","cannot open \""+filename+"\"");
@ -268,10 +268,10 @@ nasal_ref builtin_fout(nasal_ref* local,nasal_gc& gc)
return builtin_err("io.fout","\"filename\" must be string"); return builtin_err("io.fout","\"filename\" must be string");
if(str.type!=vm_str) if(str.type!=vm_str)
return builtin_err("io.fout","\"str\" must be string"); return builtin_err("io.fout","\"str\" must be string");
std::ofstream fout(*val.str()); std::ofstream fout(val.str());
if(fout.fail()) if(fout.fail())
return builtin_err("io.fout","cannot open \""+*val.str()+"\""); return builtin_err("io.fout","cannot open \""+val.str()+"\"");
fout<<*str.str(); fout<<str.str();
return nil; return nil;
} }
nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
@ -282,8 +282,8 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
return builtin_err("split","\"separator\" must be string"); return builtin_err("split","\"separator\" must be string");
if(str_val.type!=vm_str) if(str_val.type!=vm_str)
return builtin_err("split","\"str\" must be string"); return builtin_err("split","\"str\" must be string");
std::string& delimeter=*deli_val.str(); std::string& delimeter=deli_val.str();
std::string& source=*str_val.str(); std::string& source=str_val.str();
size_t delimeter_len=delimeter.length(); size_t delimeter_len=delimeter.length();
size_t source_len=source.length(); size_t source_len=source.length();
@ -292,13 +292,13 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
builtin_err("split","expand temporary space error:stackoverflow"); builtin_err("split","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
std::vector<nasal_ref>& vec=gc.top[0].vec()->elems; std::vector<nasal_ref>& vec=gc.top[0].vec().elems;
if(!delimeter_len) if(!delimeter_len)
{ {
for(int i=0;i<source_len;++i) for(int i=0;i<source_len;++i)
{ {
vec.push_back(gc.alloc(vm_str)); vec.push_back(gc.alloc(vm_str));
*vec.back().str()=source[i]; vec.back().str()=source[i];
} }
--gc.top; --gc.top;
return gc.top[1]; return gc.top[1];
@ -321,7 +321,7 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
if(tmp.length()) if(tmp.length())
{ {
vec.push_back(gc.alloc(vm_str)); vec.push_back(gc.alloc(vm_str));
*vec.back().str()=tmp; vec.back().str()=tmp;
tmp=""; tmp="";
} }
i+=delimeter_len-1; i+=delimeter_len-1;
@ -332,7 +332,7 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
if(tmp.length()) if(tmp.length())
{ {
vec.push_back(gc.alloc(vm_str)); vec.push_back(gc.alloc(vm_str));
*vec.back().str()=tmp; vec.back().str()=tmp;
tmp=""; tmp="";
} }
--gc.top; --gc.top;
@ -362,7 +362,7 @@ nasal_ref builtin_id(nasal_ref* local,nasal_gc& gc)
sprintf(buf,"%p",val.value.gcobj); sprintf(buf,"%p",val.value.gcobj);
else else
sprintf(buf,"0"); sprintf(buf,"0");
*ret.str()=buf; ret.str()=buf;
return ret; return ret;
} }
nasal_ref builtin_int(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_int(nasal_ref* local,nasal_gc& gc)
@ -390,10 +390,11 @@ nasal_ref builtin_pop(nasal_ref* local,nasal_gc& gc)
nasal_ref val=local[1]; nasal_ref val=local[1];
if(val.type!=vm_vec) if(val.type!=vm_vec)
return builtin_err("pop","\"vector\" must be vector"); return builtin_err("pop","\"vector\" must be vector");
if(val.vec()->elems.size()) auto& vec=val.vec().elems;
if(vec.size())
{ {
nasal_ref tmp=val.vec()->elems.back(); nasal_ref tmp=vec.back();
val.vec()->elems.pop_back(); vec.pop_back();
return tmp; return tmp;
} }
return nil; return nil;
@ -407,7 +408,7 @@ nasal_ref builtin_str(nasal_ref* local,nasal_gc& gc)
tmp.erase(tmp.find_last_not_of('0')+1,std::string::npos); tmp.erase(tmp.find_last_not_of('0')+1,std::string::npos);
tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos); tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos);
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
*ret.str()=tmp; ret.str()=tmp;
return ret; return ret;
} }
nasal_ref builtin_size(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_size(nasal_ref* local,nasal_gc& gc)
@ -416,10 +417,10 @@ nasal_ref builtin_size(nasal_ref* local,nasal_gc& gc)
double num; double num;
switch(val.type) switch(val.type)
{ {
case vm_num: num=val.num(); break; case vm_num: num=val.num(); break;
case vm_str: num=val.str()->length(); break; case vm_str: num=val.str().length(); break;
case vm_vec: num=val.vec()->elems.size(); break; case vm_vec: num=val.vec().elems.size(); break;
case vm_hash: num=val.hash()->elems.size();break; case vm_hash: num=val.hash().elems.size();break;
} }
return {vm_num,num}; return {vm_num,num};
} }
@ -559,7 +560,7 @@ nasal_ref builtin_contains(nasal_ref* local,nasal_gc& gc)
return builtin_err("contains","\"hash\" must be hash"); return builtin_err("contains","\"hash\" must be hash");
if(key.type!=vm_str) if(key.type!=vm_str)
return builtin_err("contains","\"key\" must be string"); return builtin_err("contains","\"key\" must be string");
return hash.hash()->elems.count(*key.str())?one:zero; return hash.hash().elems.count(key.str())?one:zero;
} }
nasal_ref builtin_delete(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_delete(nasal_ref* local,nasal_gc& gc)
{ {
@ -569,8 +570,8 @@ nasal_ref builtin_delete(nasal_ref* local,nasal_gc& gc)
return builtin_err("delete","\"hash\" must be hash"); return builtin_err("delete","\"hash\" must be hash");
if(key.type!=vm_str) if(key.type!=vm_str)
return builtin_err("delete","\"key\" must be string"); return builtin_err("delete","\"key\" must be string");
if(hash.hash()->elems.count(*key.str())) if(hash.hash().elems.count(key.str()))
hash.hash()->elems.erase(*key.str()); hash.hash().elems.erase(key.str());
return nil; return nil;
} }
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
@ -582,11 +583,11 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1) if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
builtin_err("keys","expand temporary space error:stackoverflow"); builtin_err("keys","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec()->elems; auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash()->elems) for(auto& iter:hash.hash().elems)
{ {
nasal_ref str=gc.alloc(vm_str); nasal_ref str=gc.alloc(vm_str);
*str.str()=iter.first; str.str()=iter.first;
vec.push_back(str); vec.push_back(str);
} }
--gc.top; --gc.top;
@ -608,7 +609,7 @@ nasal_ref builtin_die(nasal_ref* local,nasal_gc& gc)
nasal_ref str=local[1]; nasal_ref str=local[1];
if(str.type!=vm_str) if(str.type!=vm_str)
return builtin_err("die","\"str\" must be string"); return builtin_err("die","\"str\" must be string");
std::cerr<<"[vm] error: "<<*str.str()<<'\n'; std::cerr<<"[vm] error: "<<str.str()<<'\n';
return nasal_ref(vm_none); return nasal_ref(vm_none);
} }
nasal_ref builtin_type(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_type(nasal_ref* local,nasal_gc& gc)
@ -617,14 +618,14 @@ nasal_ref builtin_type(nasal_ref* local,nasal_gc& gc)
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
switch(val.type) switch(val.type)
{ {
case vm_none: *ret.str()="undefined";break; case vm_none: ret.str()="undefined";break;
case vm_nil: *ret.str()="nil"; break; case vm_nil: ret.str()="nil"; break;
case vm_num: *ret.str()="num"; break; case vm_num: ret.str()="num"; break;
case vm_str: *ret.str()="str"; break; case vm_str: ret.str()="str"; break;
case vm_vec: *ret.str()="vec"; break; case vm_vec: ret.str()="vec"; break;
case vm_hash: *ret.str()="hash"; break; case vm_hash: ret.str()="hash"; break;
case vm_func: *ret.str()="func"; break; case vm_func: ret.str()="func"; break;
case vm_obj: *ret.str()="obj"; break; case vm_obj: ret.str()="obj"; break;
} }
return ret; return ret;
} }
@ -641,19 +642,19 @@ nasal_ref builtin_substr(nasal_ref* local,nasal_gc& gc)
return builtin_err("substr","\"length\" must be number"); return builtin_err("substr","\"length\" must be number");
int begin=(int)beg.num(); int begin=(int)beg.num();
int length=(int)len.num(); int length=(int)len.num();
if(begin>=str.str()->length() || begin+length-1>=str.str()->length()) if(begin>=str.str().length() || begin+length-1>=str.str().length())
return builtin_err("susbtr","index out of range"); return builtin_err("susbtr","index out of range");
if(length<0) if(length<0)
length=0; length=0;
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
*ret.str()=str.str()->substr(begin,length); ret.str()=str.str().substr(begin,length);
return ret; return ret;
} }
nasal_ref builtin_streq(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_streq(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref a=local[1]; nasal_ref a=local[1];
nasal_ref b=local[2]; nasal_ref b=local[2];
return {vm_num,double((a.type!=vm_str || b.type!=vm_str)?0:(*a.str()==*b.str()))}; return {vm_num,double((a.type!=vm_str || b.type!=vm_str)?0:(a.str()==b.str()))};
} }
nasal_ref builtin_left(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_left(nasal_ref* local,nasal_gc& gc)
{ {
@ -667,7 +668,7 @@ nasal_ref builtin_left(nasal_ref* local,nasal_gc& gc)
if(length<0) if(length<0)
length=0; length=0;
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
*ret.str()=str.str()->substr(0,length); ret.str()=str.str().substr(0,length);
return ret; return ret;
} }
nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc)
@ -679,13 +680,13 @@ nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc)
if(len.type!=vm_num) if(len.type!=vm_num)
return builtin_err("right","\"length\" must be number"); return builtin_err("right","\"length\" must be number");
int length=(int)len.num(); int length=(int)len.num();
int srclen=str.str()->length(); int srclen=str.str().length();
if(length>srclen) if(length>srclen)
length=srclen; length=srclen;
if(length<0) if(length<0)
length=0; length=0;
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
*ret.str()=str.str()->substr(srclen-length, srclen); ret.str()=str.str().substr(srclen-length, srclen);
return ret; return ret;
} }
nasal_ref builtin_cmp(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_cmp(nasal_ref* local,nasal_gc& gc)
@ -696,7 +697,7 @@ nasal_ref builtin_cmp(nasal_ref* local,nasal_gc& gc)
return builtin_err("cmp","\"a\" must be string"); return builtin_err("cmp","\"a\" must be string");
if(b.type!=vm_str) if(b.type!=vm_str)
return builtin_err("cmp","\"b\" must be string"); return builtin_err("cmp","\"b\" must be string");
return {vm_num,(double)strcmp(a.str()->c_str(),b.str()->c_str())}; return {vm_num,(double)strcmp(a.str().c_str(),b.str().c_str())};
} }
nasal_ref builtin_chr(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_chr(nasal_ref* local,nasal_gc& gc)
{ {
@ -724,11 +725,11 @@ nasal_ref builtin_chr(nasal_ref* local,nasal_gc& gc)
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
int num=code.num(); int num=code.num();
if(0<=num && num<128) if(0<=num && num<128)
*ret.str()=(char)num; ret.str()=(char)num;
else if(128<=num && num<256) else if(128<=num && num<256)
*ret.str()=extend[num-128]; ret.str()=extend[num-128];
else else
*ret.str()=" "; ret.str()=" ";
return ret; return ret;
} }
nasal_ref builtin_open(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_open(nasal_ref* local,nasal_gc& gc)
@ -739,20 +740,20 @@ nasal_ref builtin_open(nasal_ref* local,nasal_gc& gc)
return builtin_err("open","\"filename\" must be string"); return builtin_err("open","\"filename\" must be string");
if(mode.type!=vm_str) if(mode.type!=vm_str)
return builtin_err("open","\"mode\" must be string"); return builtin_err("open","\"mode\" must be string");
FILE* res=fopen(filename.str()->c_str(),mode.str()->c_str()); FILE* res=fopen(filename.str().c_str(),mode.str().c_str());
if(!res) if(!res)
return builtin_err("open","failed to open file <"+*filename.str()+"> errno "+std::to_string(errno)); return builtin_err("open","failed to open file <"+filename.str()+"> errno "+std::to_string(errno));
nasal_ref ret=gc.alloc(vm_obj); nasal_ref ret=gc.alloc(vm_obj);
ret.obj()->type=obj_file; ret.obj().type=obj_file;
ret.obj()->ptr=(void*)res; ret.obj().ptr=(void*)res;
return ret; return ret;
} }
nasal_ref builtin_close(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_close(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("close","not a correct filehandle"); return builtin_err("close","not a correct filehandle");
fclose((FILE*)filehandle.obj()->ptr); fclose((FILE*)filehandle.obj().ptr);
return nil; return nil;
} }
nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc)
@ -760,7 +761,7 @@ nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc)
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
nasal_ref buf=local[2]; nasal_ref buf=local[2];
nasal_ref len=local[3]; nasal_ref len=local[3];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("read","not a correct filehandle"); return builtin_err("read","not a correct filehandle");
if(buf.type!=vm_str) if(buf.type!=vm_str)
return builtin_err("read","\"buf\" must be string"); return builtin_err("read","\"buf\" must be string");
@ -773,8 +774,8 @@ nasal_ref builtin_read(nasal_ref* local,nasal_gc& gc)
char* buff=new char[(size_t)len.num()+1]; char* buff=new char[(size_t)len.num()+1];
if(!buff) if(!buff)
return builtin_err("read","memory allocation error"); return builtin_err("read","memory allocation error");
double res=fread(buff,1,len.num(),(FILE*)filehandle.obj()->ptr); double res=fread(buff,1,len.num(),(FILE*)filehandle.obj().ptr);
*buf.str()=buff; buf.str()=buff;
delete []buff; delete []buff;
return {vm_num,res}; return {vm_num,res};
} }
@ -782,11 +783,11 @@ nasal_ref builtin_write(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
nasal_ref str=local[2]; nasal_ref str=local[2];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("write","not a correct filehandle"); return builtin_err("write","not a correct filehandle");
if(str.type!=vm_str) if(str.type!=vm_str)
return builtin_err("write","\"str\" must be string"); return builtin_err("write","\"str\" must be string");
double res=(double)fwrite(str.str()->c_str(),1,str.str()->length(),(FILE*)filehandle.obj()->ptr); double res=(double)fwrite(str.str().c_str(),1,str.str().length(),(FILE*)filehandle.obj().ptr);
return {vm_num,res}; return {vm_num,res};
} }
nasal_ref builtin_seek(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_seek(nasal_ref* local,nasal_gc& gc)
@ -794,32 +795,32 @@ nasal_ref builtin_seek(nasal_ref* local,nasal_gc& gc)
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
nasal_ref position=local[2]; nasal_ref position=local[2];
nasal_ref whence=local[3]; nasal_ref whence=local[3];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("seek","not a correct filehandle"); return builtin_err("seek","not a correct filehandle");
if(position.type!=vm_num) if(position.type!=vm_num)
return builtin_err("seek","\"pos\" must be number"); return builtin_err("seek","\"pos\" must be number");
if(whence.type!=vm_num || whence.num()<0 || whence.num()>2) if(whence.type!=vm_num || whence.num()<0 || whence.num()>2)
return builtin_err("seek","\"whence\" must be number between 0 and 2"); return builtin_err("seek","\"whence\" must be number between 0 and 2");
double res=fseek((FILE*)filehandle.obj()->ptr,position.num(),whence.num()); double res=fseek((FILE*)filehandle.obj().ptr,position.num(),whence.num());
return {vm_num,res}; return {vm_num,res};
} }
nasal_ref builtin_tell(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_tell(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("tell","not a correct filehandle"); return builtin_err("tell","not a correct filehandle");
double res=ftell((FILE*)filehandle.obj()->ptr); double res=ftell((FILE*)filehandle.obj().ptr);
return {vm_num,res}; return {vm_num,res};
} }
nasal_ref builtin_readln(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_readln(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("readln","not a correct filehandle"); return builtin_err("readln","not a correct filehandle");
nasal_ref str=gc.alloc(vm_str); nasal_ref str=gc.alloc(vm_str);
auto& s=*str.str(); auto& s=str.str();
char c; char c;
while((c=fgetc((FILE*)filehandle.obj()->ptr))!=EOF) while((c=fgetc((FILE*)filehandle.obj().ptr))!=EOF)
{ {
if(c=='\r') if(c=='\r')
continue; continue;
@ -837,10 +838,10 @@ nasal_ref builtin_stat(nasal_ref* local,nasal_gc& gc)
if(filename.type!=vm_str) if(filename.type!=vm_str)
return builtin_err("stat","\"filename\" must be string"); return builtin_err("stat","\"filename\" must be string");
struct stat buf; struct stat buf;
if(stat(filename.str()->c_str(),&buf)<0) if(stat(filename.str().c_str(),&buf)<0)
return builtin_err("stat","failed to open file <"+*filename.str()+">"); return builtin_err("stat","failed to open file <"+filename.str()+">");
nasal_ref ret=gc.alloc(vm_vec); nasal_ref ret=gc.alloc(vm_vec);
ret.vec()->elems={ ret.vec().elems={
{vm_num,(double)buf.st_dev}, {vm_num,(double)buf.st_dev},
{vm_num,(double)buf.st_ino}, {vm_num,(double)buf.st_ino},
{vm_num,(double)buf.st_mode}, {vm_num,(double)buf.st_mode},
@ -858,9 +859,9 @@ nasal_ref builtin_stat(nasal_ref* local,nasal_gc& gc)
nasal_ref builtin_eof(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_eof(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref filehandle=local[1]; nasal_ref filehandle=local[1];
if(filehandle.type!=vm_obj || filehandle.obj()->type!=obj_file) if(filehandle.type!=vm_obj || filehandle.obj().type!=obj_file)
return builtin_err("readln","not a correct filehandle"); return builtin_err("readln","not a correct filehandle");
double res=feof((FILE*)filehandle.obj()->ptr); double res=feof((FILE*)filehandle.obj().ptr);
return {vm_num,res}; return {vm_num,res};
} }
nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc)
@ -877,10 +878,10 @@ nasal_ref builtin_fld(nasal_ref* local,nasal_gc& gc)
return builtin_err("fld","\"startbit\",\"len\" must be number"); return builtin_err("fld","\"startbit\",\"len\" must be number");
uint32_t bit=(uint32_t)startbit.num(); uint32_t bit=(uint32_t)startbit.num();
uint32_t len=(uint32_t)length.num(); uint32_t len=(uint32_t)length.num();
if(bit+len>8*str.str()->length()) if(bit+len>8*str.str().length())
return builtin_err("fld","bitfield out of bounds"); return builtin_err("fld","bitfield out of bounds");
uint32_t res=0; uint32_t res=0;
auto& s=*str.str(); auto& s=str.str();
for(uint32_t i=bit;i<bit+len;++i) for(uint32_t i=bit;i<bit+len;++i)
if(s[i>>3]&(1<<(7-(i&7)))) if(s[i>>3]&(1<<(7-(i&7))))
res|=1<<(bit+len-i-1); res|=1<<(bit+len-i-1);
@ -901,10 +902,10 @@ nasal_ref builtin_sfld(nasal_ref* local,nasal_gc& gc)
return builtin_err("sfld","\"startbit\",\"len\" must be number"); return builtin_err("sfld","\"startbit\",\"len\" must be number");
uint32_t bit=(uint32_t)startbit.num(); uint32_t bit=(uint32_t)startbit.num();
uint32_t len=(uint32_t)length.num(); uint32_t len=(uint32_t)length.num();
if(bit+len>8*str.str()->length()) if(bit+len>8*str.str().length())
return builtin_err("sfld","bitfield out of bounds"); return builtin_err("sfld","bitfield out of bounds");
uint32_t res=0; uint32_t res=0;
auto& s=*str.str(); auto& s=str.str();
for(uint32_t i=bit;i<bit+len;++i) for(uint32_t i=bit;i<bit+len;++i)
if(s[i>>3]&(1<<(7-(i&7)))) if(s[i>>3]&(1<<(7-(i&7))))
res|=1<<(bit+len-i-1); res|=1<<(bit+len-i-1);
@ -929,9 +930,9 @@ nasal_ref builtin_setfld(nasal_ref* local,nasal_gc& gc)
uint32_t bit=(uint32_t)startbit.num(); uint32_t bit=(uint32_t)startbit.num();
uint32_t len=(uint32_t)length.num(); uint32_t len=(uint32_t)length.num();
uint64_t val=(uint64_t)value.num(); uint64_t val=(uint64_t)value.num();
if(bit+len>8*str.str()->length()) if(bit+len>8*str.str().length())
return builtin_err("setfld","bitfield out of bounds"); return builtin_err("setfld","bitfield out of bounds");
auto& s=*str.str(); auto& s=str.str();
for(uint32_t i=bit;i<bit+len;++i) for(uint32_t i=bit;i<bit+len;++i)
{ {
if(val&(1<<(i-bit))) if(val&(1<<(i-bit)))
@ -947,7 +948,7 @@ nasal_ref builtin_buf(nasal_ref* local,nasal_gc& gc)
if(length.type!=vm_num || length.num()<=0) 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 9");
nasal_ref str=gc.alloc(vm_str); nasal_ref str=gc.alloc(vm_str);
auto& s=*str.str(); auto& s=str.str();
s.resize(length.num(),'\0'); s.resize(length.num(),'\0');
return str; return str;
} }
@ -966,8 +967,8 @@ nasal_ref builtin_pipe(nasal_ref* local,nasal_gc& gc)
#ifndef _WIN32 #ifndef _WIN32
if(pipe(fd)==-1) if(pipe(fd)==-1)
return builtin_err("pipe","failed to create pipe"); return builtin_err("pipe","failed to create pipe");
res.vec()->elems.push_back({vm_num,(double)fd[0]}); res.vec().elems.push_back({vm_num,(double)fd[0]});
res.vec()->elems.push_back({vm_num,(double)fd[1]}); res.vec().elems.push_back({vm_num,(double)fd[1]});
return res; return res;
#endif #endif
return builtin_err("pipe","not supported yet"); return builtin_err("pipe","not supported yet");
@ -984,32 +985,32 @@ nasal_ref builtin_opendir(nasal_ref* local,nasal_gc& gc)
nasal_ref path=local[1]; nasal_ref path=local[1];
if(path.type!=vm_str) if(path.type!=vm_str)
return builtin_err("opendir","\"path\" must be string"); return builtin_err("opendir","\"path\" must be string");
DIR* p=opendir(path.str()->c_str()); DIR* p=opendir(path.str().c_str());
if(!p) if(!p)
return builtin_err("opendir","cannot open dir <"+*path.str()+"> errno "+std::to_string(errno)); return builtin_err("opendir","cannot open dir <"+path.str()+"> errno "+std::to_string(errno));
nasal_ref ret=gc.alloc(vm_obj); nasal_ref ret=gc.alloc(vm_obj);
ret.obj()->type=obj_dir; ret.obj().type=obj_dir;
ret.obj()->ptr=(void*)p; ret.obj().ptr=(void*)p;
return ret; return ret;
} }
nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref handle=local[1]; nasal_ref handle=local[1];
if(handle.type!=vm_obj || handle.obj()->type!=obj_dir) if(handle.type!=vm_obj || handle.obj().type!=obj_dir)
return builtin_err("readdir","not a correct dir handle"); return builtin_err("readdir","not a correct dir handle");
dirent* p=readdir((DIR*)handle.obj()->ptr); dirent* p=readdir((DIR*)handle.obj().ptr);
if(!p) if(!p)
return nil; return nil;
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
*ret.str()=p->d_name; ret.str()=p->d_name;
return ret; return ret;
} }
nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref handle=local[1]; nasal_ref handle=local[1];
if(handle.type!=vm_obj || handle.obj()->type!=obj_dir) if(handle.type!=vm_obj || handle.obj().type!=obj_dir)
return builtin_err("closedir","not a correct dir handle"); return builtin_err("closedir","not a correct dir handle");
closedir((DIR*)handle.obj()->ptr); closedir((DIR*)handle.obj().ptr);
return nil; return nil;
} }
nasal_ref builtin_chdir(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_chdir(nasal_ref* local,nasal_gc& gc)
@ -1017,19 +1018,21 @@ nasal_ref builtin_chdir(nasal_ref* local,nasal_gc& gc)
nasal_ref path=local[1]; nasal_ref path=local[1];
if(path.type!=vm_str) if(path.type!=vm_str)
return builtin_err("chdir","\"path\" must be string"); return builtin_err("chdir","\"path\" must be string");
if(chdir(path.str()->c_str())<0) if(chdir(path.str().c_str())<0)
return builtin_err("chdir","failed to execute chdir"); return builtin_err("chdir","failed to execute chdir");
return nil; return nil;
} }
nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc)
{ {
char** env=environ; char** env=environ;
if(gc.top+1>=gc.stack+STACK_MAX_DEPTH-1)
builtin_err("environ","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec); (++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec()->elems; auto& vec=gc.top[0].vec().elems;
while(*env) while(*env)
{ {
auto s=gc.alloc(vm_str); auto s=gc.alloc(vm_str);
*s.str()=*env; s.str()=*env;
vec.push_back(s); vec.push_back(s);
++env; ++env;
} }
@ -1041,7 +1044,7 @@ nasal_ref builtin_getcwd(nasal_ref* local,nasal_gc& gc)
char buf[1024]; char buf[1024];
getcwd(buf,sizeof(buf)); getcwd(buf,sizeof(buf));
nasal_ref str=gc.alloc(vm_str); nasal_ref str=gc.alloc(vm_str);
*str.str()=buf; str.str()=buf;
return str; return str;
} }
nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc)
@ -1049,11 +1052,11 @@ nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc)
nasal_ref envvar=local[1]; nasal_ref envvar=local[1];
if(envvar.type!=vm_str) if(envvar.type!=vm_str)
return builtin_err("getenv","\"envvar\" must be string"); return builtin_err("getenv","\"envvar\" must be string");
char* res=getenv(envvar.str()->c_str()); char* res=getenv(envvar.str().c_str());
if(!res) if(!res)
return nil; return nil;
nasal_ref str=gc.alloc(vm_str); nasal_ref str=gc.alloc(vm_str);
*str.str()=res; str.str()=res;
return str; return str;
} }
nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc)
@ -1062,50 +1065,50 @@ nasal_ref builtin_dlopen(nasal_ref* local,nasal_gc& gc)
if(dlname.type!=vm_str) if(dlname.type!=vm_str)
return builtin_err("dlopen","\"libname\" must be string"); return builtin_err("dlopen","\"libname\" must be string");
#ifdef _WIN32 #ifdef _WIN32
wchar_t* str=new wchar_t[dlname.str()->size()+1]; wchar_t* str=new wchar_t[dlname.str().size()+1];
memset(str,0,sizeof(wchar_t)*dlname.str()->size()+1); memset(str,0,sizeof(wchar_t)*dlname.str().size()+1);
mbstowcs(str,dlname.str()->c_str(),dlname.str()->size()+1); mbstowcs(str,dlname.str().c_str(),dlname.str().size()+1);
void* ptr=LoadLibraryW(str); void* ptr=LoadLibraryW(str);
delete []str; delete []str;
#else #else
void* ptr=dlopen(dlname.str()->c_str(),RTLD_LOCAL|RTLD_LAZY); void* ptr=dlopen(dlname.str().c_str(),RTLD_LOCAL|RTLD_LAZY);
#endif #endif
if(!ptr) if(!ptr)
return builtin_err("dlopen","cannot open dynamic lib <"+*dlname.str()+">"); return builtin_err("dlopen","cannot open dynamic lib <"+dlname.str()+">");
nasal_ref ret=gc.alloc(vm_obj); nasal_ref ret=gc.alloc(vm_obj);
ret.obj()->type=obj_dylib; ret.obj().type=obj_dylib;
ret.obj()->ptr=ptr; ret.obj().ptr=ptr;
return ret; return ret;
} }
nasal_ref builtin_dlsym(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_dlsym(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref libptr=local[1]; nasal_ref libptr=local[1];
nasal_ref sym=local[2]; nasal_ref sym=local[2];
if(libptr.type!=vm_obj || libptr.obj()->type!=obj_dylib) if(libptr.type!=vm_obj || libptr.obj().type!=obj_dylib)
return builtin_err("dlsym","\"lib\" is not a correct dynamic lib entry"); return builtin_err("dlsym","\"lib\" is not a correct dynamic lib entry");
if(sym.type!=vm_str) if(sym.type!=vm_str)
return builtin_err("dlsym","\"sym\" must be string"); return builtin_err("dlsym","\"sym\" must be string");
#ifdef _WIN32 #ifdef _WIN32
void* func=(void*)GetProcAddress((HMODULE)libptr.obj()->ptr,sym.str()->c_str()); void* func=(void*)GetProcAddress((HMODULE)libptr.obj().ptr,sym.str().c_str());
#else #else
void* func=dlsym(libptr.obj()->ptr,sym.str()->c_str()); void* func=dlsym(libptr.obj().ptr,sym.str().c_str());
#endif #endif
if(!func) if(!func)
return builtin_err("dlsym","cannot find symbol \""+*sym.str()+"\""); return builtin_err("dlsym","cannot find symbol \""+sym.str()+"\"");
nasal_ref ret=gc.alloc(vm_obj); nasal_ref ret=gc.alloc(vm_obj);
ret.obj()->type=obj_extern; ret.obj().type=obj_extern;
ret.obj()->ptr=func; ret.obj().ptr=func;
return ret; return ret;
} }
nasal_ref builtin_dlclose(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_dlclose(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref libptr=local[1]; nasal_ref libptr=local[1];
if(libptr.type!=vm_obj || libptr.obj()->type!=obj_dylib) if(libptr.type!=vm_obj || libptr.obj().type!=obj_dylib)
return builtin_err("dlclose","\"lib\" is not a correct dynamic lib entry"); return builtin_err("dlclose","\"lib\" is not a correct dynamic lib entry");
#ifdef _WIN32 #ifdef _WIN32
FreeLibrary((HMODULE)libptr.obj()->ptr); FreeLibrary((HMODULE)libptr.obj().ptr);
#else #else
dlclose(libptr.obj()->ptr); dlclose(libptr.obj().ptr);
#endif #endif
return nil; return nil;
} }
@ -1113,21 +1116,21 @@ nasal_ref builtin_dlcall(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref funcptr=local[1]; nasal_ref funcptr=local[1];
nasal_ref args=local[2]; nasal_ref args=local[2];
if(funcptr.type!=vm_obj || funcptr.obj()->type!=obj_extern) if(funcptr.type!=vm_obj || funcptr.obj().type!=obj_extern)
return builtin_err("dlcall","\"funcptr\" is not a correct function pointer"); return builtin_err("dlcall","\"funcptr\" is not a correct function pointer");
typedef nasal_ref (*extern_func)(std::vector<nasal_ref>&,nasal_gc&); typedef nasal_ref (*extern_func)(std::vector<nasal_ref>&,nasal_gc&);
extern_func func=(extern_func)funcptr.obj()->ptr; extern_func func=(extern_func)funcptr.obj().ptr;
return func(args.vec()->elems,gc); return func(args.vec().elems,gc);
} }
nasal_ref builtin_platform(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_platform(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref ret=gc.alloc(vm_str); nasal_ref ret=gc.alloc(vm_str);
#if defined _WIN32 || defined _WIN64 #if defined _WIN32 || defined _WIN64
*ret.str()="windows"; ret.str()="windows";
#elif defined __linux__ #elif defined __linux__
*ret.str()="linux"; ret.str()="linux";
#elif defined __APPLE__ #elif defined __APPLE__
*ret.str()="macOS"; ret.str()="macOS";
#endif #endif
return ret; return ret;
} }

View File

@ -87,13 +87,13 @@ struct nasal_ref
inline nasal_ref* addr(); inline nasal_ref* addr();
inline uint32_t ret (); inline uint32_t ret ();
inline int64_t& cnt (); inline int64_t& cnt ();
inline double& num (); inline double num ();
inline std::string* str (); inline std::string& str ();
inline nasal_vec* vec (); inline nasal_vec& vec ();
inline nasal_hash* hash(); inline nasal_hash& hash();
inline nasal_func* func(); inline nasal_func& func();
inline nasal_upval& upval(); inline nasal_upval& upval();
inline nasal_obj* obj (); inline nasal_obj& obj ();
}; };
struct nasal_vec struct nasal_vec
@ -223,10 +223,10 @@ nasal_ref nasal_hash::get_val(const std::string& key)
nasal_ref ret(vm_none); nasal_ref ret(vm_none);
nasal_ref val=elems["parents"]; nasal_ref 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)
{ {
if(i.type==vm_hash) if(i.type==vm_hash)
ret=i.hash()->get_val(key); ret=i.hash().get_val(key);
if(ret.type!=vm_none) if(ret.type!=vm_none)
return ret; return ret;
} }
@ -242,10 +242,10 @@ nasal_ref* nasal_hash::get_mem(const std::string& key)
nasal_ref* addr=nullptr; nasal_ref* addr=nullptr;
nasal_ref val=elems["parents"]; nasal_ref 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)
{ {
if(i.type==vm_hash) if(i.type==vm_hash)
addr=i.hash()->get_mem(key); addr=i.hash().get_mem(key);
if(addr) if(addr)
return addr; return addr;
} }
@ -316,12 +316,12 @@ nasal_val::~nasal_val()
} }
double nasal_ref::to_number() double nasal_ref::to_number()
{ {
return type!=vm_str?value.num:str2num(str()->c_str()); return type!=vm_str?value.num:str2num(str().c_str());
} }
std::string nasal_ref::to_string() std::string nasal_ref::to_string()
{ {
if(type==vm_str) if(type==vm_str)
return *str(); return str();
else if(type==vm_num) else if(type==vm_num)
{ {
std::string tmp=std::to_string(num()); std::string tmp=std::to_string(num());
@ -338,9 +338,9 @@ void nasal_ref::print()
case vm_none: std::cout<<"undefined"; break; case vm_none: std::cout<<"undefined"; break;
case vm_nil: std::cout<<"nil"; break; case vm_nil: std::cout<<"nil"; break;
case vm_num: std::cout<<value.num; break; case vm_num: std::cout<<value.num; break;
case vm_str: std::cout<<*(this->str());break; case vm_str: std::cout<<str(); break;
case vm_vec: this->vec()->print(); break; case vm_vec: vec().print(); break;
case vm_hash: this->hash()->print(); break; case vm_hash: hash().print(); break;
case vm_func: std::cout<<"func(..){..}";break; case vm_func: std::cout<<"func(..){..}";break;
case vm_obj: std::cout<<"<object>"; break; case vm_obj: std::cout<<"<object>"; break;
} }
@ -348,13 +348,13 @@ void nasal_ref::print()
inline nasal_ref* nasal_ref::addr (){return value.addr; } inline nasal_ref* nasal_ref::addr (){return value.addr; }
inline uint32_t nasal_ref::ret (){return value.ret; } inline uint32_t nasal_ref::ret (){return value.ret; }
inline int64_t& nasal_ref::cnt (){return value.cnt; } inline int64_t& nasal_ref::cnt (){return value.cnt; }
inline double& nasal_ref::num (){return value.num; } inline double nasal_ref::num (){return value.num; }
inline std::string* nasal_ref::str (){return value.gcobj->ptr.str; } inline std::string& nasal_ref::str (){return *value.gcobj->ptr.str; }
inline nasal_vec* nasal_ref::vec (){return value.gcobj->ptr.vec; } inline nasal_vec& nasal_ref::vec (){return *value.gcobj->ptr.vec; }
inline nasal_hash* nasal_ref::hash (){return value.gcobj->ptr.hash; } inline nasal_hash& nasal_ref::hash (){return *value.gcobj->ptr.hash; }
inline nasal_func* nasal_ref::func (){return value.gcobj->ptr.func; } inline nasal_func& nasal_ref::func (){return *value.gcobj->ptr.func; }
inline nasal_upval& nasal_ref::upval(){return *value.gcobj->ptr.upval;} inline nasal_upval& nasal_ref::upval(){return *value.gcobj->ptr.upval;}
inline nasal_obj* nasal_ref::obj (){return value.gcobj->ptr.obj; } inline nasal_obj& nasal_ref::obj (){return *value.gcobj->ptr.obj; }
const uint32_t STACK_MAX_DEPTH=8191; const uint32_t STACK_MAX_DEPTH=8191;
const nasal_ref zero={vm_num,(double)0}; const nasal_ref zero={vm_num,(double)0};
@ -403,17 +403,17 @@ void nasal_gc::mark()
switch(tmp.type) switch(tmp.type)
{ {
case vm_vec: case vm_vec:
for(auto& i:tmp.vec()->elems) for(auto& i:tmp.vec().elems)
bfs.push(i); bfs.push(i);
break; break;
case vm_hash: case vm_hash:
for(auto& i:tmp.hash()->elems) for(auto& i:tmp.hash().elems)
bfs.push(i.second); bfs.push(i.second);
break; break;
case vm_func: case vm_func:
for(auto& i:tmp.func()->local) for(auto& i:tmp.func().local)
bfs.push(i); bfs.push(i);
for(auto& i:tmp.func()->upvalue) for(auto& i:tmp.func().upvalue)
bfs.push(i); bfs.push(i);
break; break;
case vm_upval: case vm_upval:
@ -446,6 +446,7 @@ void nasal_gc::sweep()
} }
void nasal_gc::init(const std::vector<std::string>& s) void nasal_gc::init(const std::vector<std::string>& s)
{ {
// initiaize function register
funcr=nil; funcr=nil;
for(uint8_t i=0;i<vm_type_size;++i) for(uint8_t i=0;i<vm_type_size;++i)
@ -464,7 +465,7 @@ void nasal_gc::init(const std::vector<std::string>& s)
{ {
strs[i]={vm_str,new nasal_val(vm_str)}; strs[i]={vm_str,new nasal_val(vm_str)};
strs[i].value.gcobj->unmut=1; strs[i].value.gcobj->unmut=1;
*strs[i].str()=s[i]; strs[i].str()=s[i];
} }
} }
void nasal_gc::clear() void nasal_gc::clear()

View File

@ -152,11 +152,11 @@ void nasal_vm::valinfo(nasal_ref& val)
case vm_cnt: printf("| cnt | %ld\n",val.cnt());break; case vm_cnt: printf("| cnt | %ld\n",val.cnt());break;
case vm_nil: printf("| nil |\n");break; case vm_nil: printf("| nil |\n");break;
case vm_num: printf("| num | ");std::cout<<val.num()<<'\n';break; case vm_num: printf("| num | ");std::cout<<val.num()<<'\n';break;
case vm_str: printf("| str | <0x%lx> %s\n",(uint64_t)p,rawstr(*val.str()).c_str());break; case vm_str: printf("| str | <0x%lx> %s\n",(uint64_t)p,rawstr(val.str()).c_str());break;
case vm_func: printf("| func | <0x%lx> entry:0x%x\n",(uint64_t)p,val.func()->entry);break; case vm_func: printf("| func | <0x%lx> entry:0x%x\n",(uint64_t)p,val.func().entry);break;
case vm_vec: printf("| vec | <0x%lx> [%lu val]\n",(uint64_t)p,val.vec()->elems.size());break; case vm_vec: printf("| vec | <0x%lx> [%lu val]\n",(uint64_t)p,val.vec().elems.size());break;
case vm_hash: printf("| hash | <0x%lx> {%lu val}\n",(uint64_t)p,val.hash()->elems.size());break; case vm_hash: printf("| hash | <0x%lx> {%lu val}\n",(uint64_t)p,val.hash().elems.size());break;
case vm_obj: printf("| obj | <0x%lx> obj:0x%lx\n",(uint64_t)p,(uint64_t)val.obj()->ptr);break; case vm_obj: printf("| obj | <0x%lx> obj:0x%lx\n",(uint64_t)p,(uint64_t)val.obj().ptr);break;
default: printf("| err | <0x%lx> unknown object\n",(uint64_t)p);break; default: printf("| err | <0x%lx> unknown object\n",(uint64_t)p);break;
} }
} }
@ -243,9 +243,9 @@ void nasal_vm::global_state()
} }
void nasal_vm::local_state() void nasal_vm::local_state()
{ {
if(!localr || !gc.funcr.func()->lsize) if(!localr || !gc.funcr.func().lsize)
return; return;
uint32_t lsize=gc.funcr.func()->lsize; uint32_t lsize=gc.funcr.func().lsize;
printf("local(0x%lx<sp+%ld>):\n",(uint64_t)localr,localr-gc.stack); printf("local(0x%lx<sp+%ld>):\n",(uint64_t)localr,localr-gc.stack);
for(uint32_t i=0;i<lsize;++i) for(uint32_t i=0;i<lsize;++i)
{ {
@ -255,10 +255,10 @@ void nasal_vm::local_state()
} }
void nasal_vm::upval_state() void nasal_vm::upval_state()
{ {
if(gc.funcr.type==vm_nil || gc.funcr.func()->upvalue.empty()) if(gc.funcr.type==vm_nil || gc.funcr.func().upvalue.empty())
return; return;
printf("upvalue:\n"); printf("upvalue:\n");
auto& upval=gc.funcr.func()->upvalue; auto& upval=gc.funcr.func().upvalue;
for(uint32_t i=0;i<upval.size();++i) for(uint32_t i=0;i<upval.size();++i)
{ {
printf("-> upval[%u]:\n",i); printf("-> upval[%u]:\n",i);
@ -279,7 +279,7 @@ void nasal_vm::detail()
else else
printf("funcr(<0x%lx> entry:0x%x)\n", printf("funcr(<0x%lx> entry:0x%x)\n",
(uint64_t)gc.funcr.value.gcobj, (uint64_t)gc.funcr.value.gcobj,
gc.funcr.func()->entry); gc.funcr.func().entry);
global_state(); global_state();
local_state(); local_state();
upval_state(); upval_state();
@ -320,9 +320,9 @@ inline bool nasal_vm::condition(nasal_ref val)
return val.value.num; return val.value.num;
else if(val.type==vm_str) else if(val.type==vm_str)
{ {
double num=str2num(val.str()->c_str()); double num=str2num(val.str().c_str());
if(std::isnan(num)) if(std::isnan(num))
return !val.str()->empty(); return !val.str().empty();
return num; return num;
} }
return false; return false;
@ -336,8 +336,8 @@ inline void nasal_vm::opr_intg()
} }
inline void nasal_vm::opr_intl() inline void nasal_vm::opr_intl()
{ {
gc.top[0].func()->local.resize(imm[pc],nil); gc.top[0].func().local.resize(imm[pc],nil);
gc.top[0].func()->lsize=imm[pc]; gc.top[0].func().lsize=imm[pc];
} }
inline void nasal_vm::opr_loadg() inline void nasal_vm::opr_loadg()
{ {
@ -349,7 +349,7 @@ inline void nasal_vm::opr_loadl()
} }
inline void nasal_vm::opr_loadu() inline void nasal_vm::opr_loadu()
{ {
gc.funcr.func()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]=(gc.top--)[0]; gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]=(gc.top--)[0];
} }
inline void nasal_vm::opr_pnum() inline void nasal_vm::opr_pnum()
{ {
@ -366,7 +366,7 @@ inline void nasal_vm::opr_pstr()
inline void nasal_vm::opr_newv() inline void nasal_vm::opr_newv()
{ {
nasal_ref newv=gc.alloc(vm_vec); nasal_ref newv=gc.alloc(vm_vec);
auto& vec=newv.vec()->elems; auto& vec=newv.vec().elems;
vec.resize(imm[pc]); vec.resize(imm[pc]);
// use top-=imm[pc]-1 here will cause error if imm[pc] is 0 // use top-=imm[pc]-1 here will cause error if imm[pc] is 0
gc.top=gc.top-imm[pc]+1; gc.top=gc.top-imm[pc]+1;
@ -381,42 +381,42 @@ inline void nasal_vm::opr_newh()
inline void nasal_vm::opr_newf() inline void nasal_vm::opr_newf()
{ {
(++gc.top)[0]=gc.alloc(vm_func); (++gc.top)[0]=gc.alloc(vm_func);
nasal_func* func=gc.top[0].func(); nasal_func& func=gc.top[0].func();
func->entry=imm[pc]; func.entry=imm[pc];
func->psize=1; func.psize=1;
/* this means you create a new function in local scope */ /* this means you create a new function in local scope */
if(localr) if(localr)
{ {
func->upvalue=gc.funcr.func()->upvalue; func.upvalue=gc.funcr.func().upvalue;
nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back(); nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back();
upval.upval().size=gc.funcr.func()->lsize; upval.upval().size=gc.funcr.func().lsize;
upval.upval().stk=localr; upval.upval().stk=localr;
func->upvalue.push_back(upval); func.upvalue.push_back(upval);
gc.upvalue.back()=upval; gc.upvalue.back()=upval;
} }
} }
inline void nasal_vm::opr_happ() inline void nasal_vm::opr_happ()
{ {
gc.top[-1].hash()->elems[str_table[imm[pc]]]=gc.top[0]; gc.top[-1].hash().elems[str_table[imm[pc]]]=gc.top[0];
--gc.top; --gc.top;
} }
inline void nasal_vm::opr_para() inline void nasal_vm::opr_para()
{ {
nasal_func* func=gc.top[0].func(); nasal_func& func=gc.top[0].func();
func->keys[str_table[imm[pc]]]=func->psize;// func->size has 1 place reserved for "me" func.keys[str_table[imm[pc]]]=func.psize;// func->size has 1 place reserved for "me"
func->local[func->psize++]={vm_none}; func.local[func.psize++]={vm_none};
} }
inline void nasal_vm::opr_defpara() inline void nasal_vm::opr_defpara()
{ {
nasal_ref val=gc.top[0]; nasal_ref val=gc.top[0];
nasal_func* func=(--gc.top)[0].func(); nasal_func& func=(--gc.top)[0].func();
func->keys[str_table[imm[pc]]]=func->psize;// func->size has 1 place reserved for "me" func.keys[str_table[imm[pc]]]=func.psize;// func->size has 1 place reserved for "me"
func->local[func->psize++]=val; func.local[func.psize++]=val;
} }
inline void nasal_vm::opr_dynpara() inline void nasal_vm::opr_dynpara()
{ {
gc.top[0].func()->dynpara=imm[pc]; gc.top[0].func().dynpara=imm[pc];
} }
inline void nasal_vm::opr_unot() inline void nasal_vm::opr_unot()
{ {
@ -427,9 +427,9 @@ inline void nasal_vm::opr_unot()
case vm_num:gc.top[0]=val.num()?zero:one;break; case vm_num:gc.top[0]=val.num()?zero:one;break;
case vm_str: case vm_str:
{ {
double num=str2num(val.str()->c_str()); double num=str2num(val.str().c_str());
if(std::isnan(num)) if(std::isnan(num))
gc.top[0]={vm_num,(double)val.str()->empty()}; gc.top[0]={vm_num,(double)val.str().empty()};
else else
gc.top[0]=num?zero:one; gc.top[0]=num?zero:one;
} }
@ -453,7 +453,7 @@ inline void nasal_vm::opr_div(){op_calc(/);}
inline void nasal_vm::opr_lnk() inline void nasal_vm::opr_lnk()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.alloc(vm_str);
*val.str()=gc.top[-1].to_string()+gc.top[0].to_string(); val.str()=gc.top[-1].to_string()+gc.top[0].to_string();
(--gc.top)[0]=val; (--gc.top)[0]=val;
} }
@ -468,7 +468,7 @@ inline void nasal_vm::opr_divc(){op_calc_const(/);}
inline void nasal_vm::opr_lnkc() inline void nasal_vm::opr_lnkc()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.alloc(vm_str);
*val.str()=gc.top[0].to_string()+str_table[imm[pc]]; val.str()=gc.top[0].to_string()+str_table[imm[pc]];
gc.top[0]=val; gc.top[0]=val;
} }
@ -484,7 +484,7 @@ inline void nasal_vm::opr_diveq(){op_calc_eq(/);}
inline void nasal_vm::opr_lnkeq() inline void nasal_vm::opr_lnkeq()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.alloc(vm_str);
*val.str()=mem_addr[0].to_string()+gc.top[-1].to_string(); val.str()=mem_addr[0].to_string()+gc.top[-1].to_string();
(--gc.top)[0]=mem_addr[0]=val; (--gc.top)[0]=mem_addr[0]=val;
mem_addr=nullptr; mem_addr=nullptr;
} }
@ -501,7 +501,7 @@ inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);}
inline void nasal_vm::opr_lnkeqc() inline void nasal_vm::opr_lnkeqc()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.alloc(vm_str);
*val.str()=mem_addr[0].to_string()+str_table[imm[pc]]; val.str()=mem_addr[0].to_string()+str_table[imm[pc]];
gc.top[0]=mem_addr[0]=val; gc.top[0]=mem_addr[0]=val;
mem_addr=nullptr; mem_addr=nullptr;
} }
@ -518,7 +518,7 @@ inline void nasal_vm::opr_eq()
if(val1.type==vm_nil && val2.type==vm_nil) if(val1.type==vm_nil && val2.type==vm_nil)
gc.top[0]=one; gc.top[0]=one;
else if(val1.type==vm_str && val2.type==vm_str) else if(val1.type==vm_str && val2.type==vm_str)
gc.top[0]=(*val1.str()==*val2.str())?one:zero; gc.top[0]=(val1.str()==val2.str())?one:zero;
else if(val1.type==vm_num || val2.type==vm_num) else if(val1.type==vm_num || val2.type==vm_num)
gc.top[0]=(val1.to_number()==val2.to_number())?one:zero; gc.top[0]=(val1.to_number()==val2.to_number())?one:zero;
else else
@ -531,7 +531,7 @@ inline void nasal_vm::opr_neq()
if(val1.type==vm_nil && val2.type==vm_nil) if(val1.type==vm_nil && val2.type==vm_nil)
gc.top[0]=zero; gc.top[0]=zero;
else if(val1.type==vm_str && val2.type==vm_str) else if(val1.type==vm_str && val2.type==vm_str)
gc.top[0]=(*val1.str()!=*val2.str())?one:zero; gc.top[0]=(val1.str()!=val2.str())?one:zero;
else if(val1.type==vm_num || val2.type==vm_num) else if(val1.type==vm_num || val2.type==vm_num)
gc.top[0]=(val1.to_number()!=val2.to_number())?one:zero; gc.top[0]=(val1.to_number()!=val2.to_number())?one:zero;
else else
@ -582,7 +582,7 @@ inline void nasal_vm::opr_counter()
} }
inline void nasal_vm::opr_findex() inline void nasal_vm::opr_findex()
{ {
if(++gc.top[0].cnt()>=gc.top[-1].vec()->elems.size()) if(++gc.top[0].cnt()>=gc.top[-1].vec().elems.size())
{ {
pc=imm[pc]-1; pc=imm[pc]-1;
return; return;
@ -592,7 +592,7 @@ inline void nasal_vm::opr_findex()
} }
inline void nasal_vm::opr_feach() inline void nasal_vm::opr_feach()
{ {
std::vector<nasal_ref>& ref=gc.top[-1].vec()->elems; std::vector<nasal_ref>& ref=gc.top[-1].vec().elems;
if(++gc.top[0].cnt()>=ref.size()) if(++gc.top[0].cnt()>=ref.size())
{ {
pc=imm[pc]-1; pc=imm[pc]-1;
@ -611,7 +611,7 @@ inline void nasal_vm::opr_calll()
} }
inline void nasal_vm::opr_upval() inline void nasal_vm::opr_upval()
{ {
(++gc.top)[0]=gc.funcr.func()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]; (++gc.top)[0]=gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff];
} }
inline void nasal_vm::opr_callv() inline void nasal_vm::opr_callv()
{ {
@ -619,7 +619,7 @@ inline void nasal_vm::opr_callv()
nasal_ref vec=(--gc.top)[0]; nasal_ref vec=(--gc.top)[0];
if(vec.type==vm_vec) if(vec.type==vm_vec)
{ {
gc.top[0]=vec.vec()->get_val(val.to_number()); gc.top[0]=vec.vec().get_val(val.to_number());
if(gc.top[0].type==vm_none) if(gc.top[0].type==vm_none)
die("callv: index out of range:"+std::to_string(val.to_number())); die("callv: index out of range:"+std::to_string(val.to_number()));
} }
@ -627,15 +627,15 @@ inline void nasal_vm::opr_callv()
{ {
if(val.type!=vm_str) if(val.type!=vm_str)
die("callv: must use string as the key"); die("callv: must use string as the key");
gc.top[0]=vec.hash()->get_val(*val.str()); gc.top[0]=vec.hash().get_val(val.str());
if(gc.top[0].type==vm_none) if(gc.top[0].type==vm_none)
die("callv: cannot find member \""+*val.str()+"\" of this hash"); die("callv: cannot find member \""+val.str()+"\" of this hash");
if(gc.top[0].type==vm_func) if(gc.top[0].type==vm_func)
gc.top[0].func()->local[0]=val;// 'me' gc.top[0].func().local[0]=val;// 'me'
} }
else if(vec.type==vm_str) else if(vec.type==vm_str)
{ {
std::string& str=*vec.str(); std::string& str=vec.str();
int num=val.to_number(); int num=val.to_number();
int str_size=str.length(); int str_size=str.length();
if(num<-str_size || num>=str_size) if(num<-str_size || num>=str_size)
@ -652,7 +652,7 @@ inline void nasal_vm::opr_callvi()
die("callvi: must use a vector"); die("callvi: must use a vector");
// cannot use operator[],because this may cause overflow // cannot use operator[],because this may cause overflow
(++gc.top)[0]=val.vec()->get_val(imm[pc]); (++gc.top)[0]=val.vec().get_val(imm[pc]);
if(gc.top[0].type==vm_none) if(gc.top[0].type==vm_none)
die("callvi: index out of range:"+std::to_string(imm[pc])); die("callvi: index out of range:"+std::to_string(imm[pc]));
} }
@ -662,12 +662,12 @@ inline void nasal_vm::opr_callh()
if(val.type!=vm_hash) if(val.type!=vm_hash)
die("callh: must call a hash"); die("callh: must call a hash");
gc.top[0]=val.hash()->get_val(str_table[imm[pc]]); gc.top[0]=val.hash().get_val(str_table[imm[pc]]);
if(gc.top[0].type==vm_none) if(gc.top[0].type==vm_none)
die("callh: member \""+str_table[imm[pc]]+"\" does not exist"); die("callh: member \""+str_table[imm[pc]]+"\" does not exist");
if(gc.top[0].type==vm_func) if(gc.top[0].type==vm_func)
gc.top[0].func()->local[0]=val;// 'me' gc.top[0].func().local[0]=val;// 'me'
} }
inline void nasal_vm::opr_callfv() inline void nasal_vm::opr_callfv()
{ {
@ -676,61 +676,61 @@ inline void nasal_vm::opr_callfv()
if(local[-1].type!=vm_func) if(local[-1].type!=vm_func)
die("callfv: must call a function"); die("callfv: must call a function");
nasal_func* func=local[-1].func(); nasal_func& func=local[-1].func();
nasal_ref tmp=local[-1]; nasal_ref tmp=local[-1];
local[-1]=gc.funcr; local[-1]=gc.funcr;
gc.funcr=tmp; gc.funcr=tmp;
if(gc.top-argc+func->lsize+2>=canary) // gc.top-argc+lsize(local) +1(old pc) +1(old localr) if(gc.top-argc+func.lsize+2>=canary) // gc.top-argc+lsize(local) +1(old pc) +1(old localr)
die("stack overflow"); die("stack overflow");
uint32_t psize=func->psize-1; // parameter size is func->psize-1, 1 is reserved for "me" uint32_t psize=func.psize-1; // parameter size is func->psize-1, 1 is reserved for "me"
if(argc<psize && func->local[argc+1].type==vm_none) if(argc<psize && func.local[argc+1].type==vm_none)
die("callfv: lack argument(s)"); die("callfv: lack argument(s)");
nasal_ref dynamic=nil; nasal_ref dynamic=nil;
gc.top=local+func->lsize; gc.top=local+func.lsize;
if(func->dynpara>=0)// load dynamic arguments if(func.dynpara>=0)// load dynamic arguments
{ {
dynamic=gc.alloc(vm_vec); dynamic=gc.alloc(vm_vec);
for(uint32_t i=psize;i<argc;++i) for(uint32_t i=psize;i<argc;++i)
dynamic.vec()->elems.push_back(local[i]); dynamic.vec().elems.push_back(local[i]);
} }
uint32_t min_size=std::min(psize,argc); uint32_t min_size=std::min(psize,argc);
for(uint32_t i=min_size;i>=1;--i)// load arguments for(uint32_t i=min_size;i>=1;--i)// load arguments
local[i]=local[i-1]; local[i]=local[i-1];
local[0]=func->local[0];// load "me" local[0]=func.local[0];// load "me"
for(uint32_t i=min_size+1;i<func->lsize;++i)// load local scope & default arguments for(uint32_t i=min_size+1;i<func.lsize;++i)// load local scope & default arguments
local[i]=func->local[i]; local[i]=func.local[i];
if(func->dynpara>=0) if(func.dynpara>=0)
local[psize+1]=dynamic; local[psize+1]=dynamic;
gc.top[0]={vm_addr,localr}; gc.top[0]={vm_addr,localr};
(++gc.top)[0]={vm_ret,pc}; (++gc.top)[0]={vm_ret,pc};
pc=func->entry-1; pc=func.entry-1;
localr=local; localr=local;
gc.upvalue.push_back(nil); gc.upvalue.push_back(nil);
} }
inline void nasal_vm::opr_callfh() inline void nasal_vm::opr_callfh()
{ {
auto& hash=gc.top[0].hash()->elems; auto& hash=gc.top[0].hash().elems;
if(gc.top[-1].type!=vm_func) if(gc.top[-1].type!=vm_func)
die("callfh: must call a function"); die("callfh: must call a function");
nasal_func* func=gc.top[-1].func(); nasal_func& func=gc.top[-1].func();
nasal_ref tmp=gc.top[-1]; nasal_ref tmp=gc.top[-1];
gc.top[-1]=gc.funcr; gc.top[-1]=gc.funcr;
gc.funcr=tmp; gc.funcr=tmp;
if(gc.top+func->lsize+1>=canary) // gc.top -1(hash) +lsize(local) +1(old pc) +1(old localr) if(gc.top+func.lsize+1>=canary) // gc.top -1(hash) +lsize(local) +1(old pc) +1(old localr)
die("stack overflow"); die("stack overflow");
if(func->dynpara>=0) if(func.dynpara>=0)
die("callfh: special call cannot use dynamic argument"); die("callfh: special call cannot use dynamic argument");
nasal_ref* local=gc.top; nasal_ref* local=gc.top;
gc.top+=func->lsize; gc.top+=func.lsize;
for(uint32_t i=0;i<func->lsize;++i) for(uint32_t i=0;i<func.lsize;++i)
local[i]=func->local[i]; local[i]=func.local[i];
for(auto& i:func->keys) for(auto& i:func.keys)
{ {
if(hash.count(i.first)) if(hash.count(i.first))
local[i.second]=hash[i.first]; local[i.second]=hash[i.first];
@ -740,7 +740,7 @@ inline void nasal_vm::opr_callfh()
gc.top[0]={vm_addr,localr}; gc.top[0]={vm_addr,localr};
(++gc.top)[0]={vm_ret,pc}; // rewrite top with vm_ret (++gc.top)[0]={vm_ret,pc}; // rewrite top with vm_ret
pc=func->entry-1; pc=func.entry-1;
localr=local; localr=local;
gc.upvalue.push_back(nil); gc.upvalue.push_back(nil);
} }
@ -769,17 +769,17 @@ inline void nasal_vm::opr_slcend()
inline void nasal_vm::opr_slc() inline void nasal_vm::opr_slc()
{ {
nasal_ref val=(gc.top--)[0]; nasal_ref val=(gc.top--)[0];
nasal_ref res=gc.top[-1].vec()->get_val(val.to_number()); nasal_ref res=gc.top[-1].vec().get_val(val.to_number());
if(res.type==vm_none) if(res.type==vm_none)
die("slc: index out of range:"+std::to_string(val.to_number())); die("slc: index out of range:"+std::to_string(val.to_number()));
gc.top[0].vec()->elems.push_back(res); gc.top[0].vec().elems.push_back(res);
} }
inline void nasal_vm::opr_slc2() inline void nasal_vm::opr_slc2()
{ {
nasal_ref val2=(gc.top--)[0]; nasal_ref val2=(gc.top--)[0];
nasal_ref val1=(gc.top--)[0]; nasal_ref val1=(gc.top--)[0];
std::vector<nasal_ref>& ref=gc.top[-1].vec()->elems; std::vector<nasal_ref>& ref=gc.top[-1].vec().elems;
std::vector<nasal_ref>& aim=gc.top[0].vec()->elems; std::vector<nasal_ref>& aim=gc.top[0].vec().elems;
uint8_t type1=val1.type,type2=val2.type; uint8_t type1=val1.type,type2=val2.type;
int num1=val1.to_number(); int num1=val1.to_number();
@ -817,7 +817,7 @@ inline void nasal_vm::opr_mcalll()
} }
inline void nasal_vm::opr_mupval() inline void nasal_vm::opr_mupval()
{ {
mem_addr=&(gc.funcr.func()->upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]); mem_addr=&(gc.funcr.func().upvalue[(imm[pc]>>16)&0xffff].upval()[imm[pc]&0xffff]);
(++gc.top)[0]=mem_addr[0]; (++gc.top)[0]=mem_addr[0];
} }
inline void nasal_vm::opr_mcallv() inline void nasal_vm::opr_mcallv()
@ -826,7 +826,7 @@ inline void nasal_vm::opr_mcallv()
nasal_ref vec=(--gc.top)[0]; nasal_ref vec=(--gc.top)[0];
if(vec.type==vm_vec) if(vec.type==vm_vec)
{ {
mem_addr=vec.vec()->get_mem(val.to_number()); mem_addr=vec.vec().get_mem(val.to_number());
if(!mem_addr) if(!mem_addr)
die("mcallv: index out of range:"+std::to_string(val.to_number())); die("mcallv: index out of range:"+std::to_string(val.to_number()));
} }
@ -834,8 +834,8 @@ inline void nasal_vm::opr_mcallv()
{ {
if(val.type!=vm_str) if(val.type!=vm_str)
die("mcallv: must use string as the key"); die("mcallv: must use string as the key");
nasal_hash& ref=*vec.hash(); nasal_hash& ref=vec.hash();
std::string& str=*val.str(); std::string& str=val.str();
mem_addr=ref.get_mem(str); mem_addr=ref.get_mem(str);
if(!mem_addr) if(!mem_addr)
{ {
@ -851,7 +851,7 @@ inline void nasal_vm::opr_mcallh()
nasal_ref hash=gc.top[0]; nasal_ref hash=gc.top[0];
if(hash.type!=vm_hash) if(hash.type!=vm_hash)
die("mcallh: must call a hash"); die("mcallh: must call a hash");
nasal_hash& ref=*hash.hash(); nasal_hash& ref=hash.hash();
const std::string& str=str_table[imm[pc]]; const std::string& str=str_table[imm[pc]];
mem_addr=ref.get_mem(str); mem_addr=ref.get_mem(str);
if(!mem_addr) // create a new key if(!mem_addr) // create a new key
@ -882,7 +882,7 @@ inline void nasal_vm::opr_ret()
localr=gc.top[-2].addr(); localr=gc.top[-2].addr();
gc.top=local-1; gc.top=local-1;
func.func()->local[0]=nil;// get func and set 'me' to nil func.func().local[0]=nil;// get func and set 'me' to nil
gc.funcr=gc.top[0]; gc.funcr=gc.top[0];
gc.top[0]=ret; // rewrite func with returned value gc.top[0]=ret; // rewrite func with returned value
@ -890,7 +890,7 @@ inline void nasal_vm::opr_ret()
if(gc.upvalue.back().type==vm_upval) // synchronize upvalue if(gc.upvalue.back().type==vm_upval) // synchronize upvalue
{ {
auto& upval=gc.upvalue.back().upval(); auto& upval=gc.upvalue.back().upval();
auto size=func.func()->lsize; auto size=func.func().lsize;
upval.onstk=false; upval.onstk=false;
for(uint32_t i=0;i<size;++i) for(uint32_t i=0;i<size;++i)
upval.elems.push_back(local[i]); upval.elems.push_back(local[i]);