closure bugs fixed

This commit is contained in:
ValKmjolnir 2021-08-17 01:18:35 +08:00
parent b2be386be8
commit 80cc8e9db7
4 changed files with 366 additions and 341 deletions

View File

@ -12,47 +12,47 @@
// declaration of builtin functions
// to add new builtin function,declare it here and write the definition below
nasal_val* builtin_print(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_append(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_setsize(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_system(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_input(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_sleep(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_fin(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_fout(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_split(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_rand(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_id(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_int(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_num(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_pop(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_str(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_size(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_xor(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_and(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_or(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_nand(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_not(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_sin(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_cos(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_tan(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_exp(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_ln(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_sqrt(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_atan2(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_time(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_contains(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_delete(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_keys(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_import(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_die(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_type(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_substr(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_streq(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_left(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_right(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_cmp(std::vector<nasal_val*>&,nasal_gc&);
nasal_val* builtin_chr(std::vector<nasal_val*>&,nasal_gc&);
nasal_ref builtin_print(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_append(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_setsize(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_system(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_input(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_sleep(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_fin(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_fout(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_split(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_rand(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_id(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_int(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_num(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_pop(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_str(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_size(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_xor(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_and(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_or(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_nand(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_not(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_sin(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_cos(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_tan(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_exp(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_ln(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_sqrt(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_atan2(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_time(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_contains(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_delete(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_keys(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_import(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_die(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_type(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_substr(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_streq(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_left(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_right(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_cmp(std::vector<nasal_ref>&,nasal_gc&);
nasal_ref builtin_chr(std::vector<nasal_ref>&,nasal_gc&);
#define builtin_err(func_name,info) std::cout<<"[vm] "<<func_name<<": "<<info<<".\n"
@ -61,7 +61,7 @@ nasal_val* builtin_chr(std::vector<nasal_val*>&,nasal_gc&);
struct FUNC_TABLE
{
const char* name;
nasal_val* (*func)(std::vector<nasal_val*>&,nasal_gc&);
nasal_ref (*func)(std::vector<nasal_ref>&,nasal_gc&);
} builtin_func[]=
{
{"__builtin_print", builtin_print },
@ -108,11 +108,11 @@ struct FUNC_TABLE
{nullptr, nullptr }
};
nasal_val* builtin_print(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_print(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
// get arguments
// local_scope[0] is reserved for 'me'
nasal_val* vec_addr=local_scope[1];
nasal_ref vec_addr=local_scope[1];
// main process
for(auto i:vec_addr->ptr.vec->elems)
switch(i->type)
@ -128,24 +128,24 @@ nasal_val* builtin_print(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
// generate return value
return gc.nil_addr;
}
nasal_val* builtin_append(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_append(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* vec_addr=local_scope[1];
nasal_val* elem_addr=local_scope[2];
nasal_ref vec_addr=local_scope[1];
nasal_ref elem_addr=local_scope[2];
if(vec_addr->type!=vm_vec)
{
builtin_err("append","\"vector\" must be vector");
return nullptr;
}
std::vector<nasal_val*>& ref_vec=vec_addr->ptr.vec->elems;
std::vector<nasal_ref>& ref_vec=vec_addr->ptr.vec->elems;
for(auto i:elem_addr->ptr.vec->elems)
ref_vec.push_back(i);
return gc.nil_addr;
}
nasal_val* builtin_setsize(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_setsize(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* vec_addr=local_scope[1];
nasal_val* size_addr=local_scope[2];
nasal_ref vec_addr=local_scope[1];
nasal_ref size_addr=local_scope[2];
if(vec_addr->type!=vm_vec)
{
builtin_err("setsize","\"vector\" must be vector");
@ -166,10 +166,10 @@ nasal_val* builtin_setsize(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return gc.nil_addr;
}
nasal_val* builtin_system(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_system(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_val* str_addr=local_scope[1];
nasal_ref ret_addr=gc.gc_alloc(vm_num);
nasal_ref str_addr=local_scope[1];
if(str_addr->type!=vm_str)
{
builtin_err("system","\"str\" must be string");
@ -179,16 +179,16 @@ nasal_val* builtin_system(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return ret_addr;
}
nasal_val* builtin_input(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_input(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
std::cin>>*ret_addr->ptr.str;
return ret_addr;
}
nasal_val* builtin_sleep(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_sleep(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("sleep","\"duration\" must be number");
@ -199,9 +199,9 @@ nasal_val* builtin_sleep(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return gc.nil_addr;
}
nasal_val* builtin_fin(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_fin(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_str)
{
builtin_err("io.fin","\"filename\" must be string");
@ -209,7 +209,7 @@ nasal_val* builtin_fin(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
std::string& filename=*val_addr->ptr.str;
std::ifstream fin(filename);
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
*ret_addr->ptr.str="";
if(!fin.fail())
while(!fin.eof())
@ -225,10 +225,10 @@ nasal_val* builtin_fin(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return ret_addr;
}
nasal_val* builtin_fout(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_fout(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_val* str_addr=local_scope[2];
nasal_ref val_addr=local_scope[1];
nasal_ref str_addr=local_scope[2];
if(val_addr->type!=vm_str)
{
builtin_err("io.fout","\"filename\" must be string");
@ -250,10 +250,10 @@ nasal_val* builtin_fout(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return gc.nil_addr;
}
nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_split(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* deli_val_addr=local_scope[1];
nasal_val* str_val_addr=local_scope[2];
nasal_ref deli_val_addr=local_scope[1];
nasal_ref str_val_addr=local_scope[2];
if(deli_val_addr->type!=vm_str)
{
builtin_err("split","\"delimeter\" must be string");
@ -272,7 +272,7 @@ nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
// push it to local scope to avoid being sweeped
local_scope.push_back(gc.gc_alloc(vm_vec));
std::vector<nasal_val*>& vec=local_scope.back()->ptr.vec->elems;
std::vector<nasal_ref>& vec=local_scope.back()->ptr.vec->elems;
if(!delimeter_len)
{
for(int i=0;i<source_len;++i)
@ -316,9 +316,9 @@ nasal_val* builtin_split(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
return local_scope.back();
}
nasal_val* builtin_rand(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_rand(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num && val_addr->type!=vm_nil)
{
builtin_err("rand","\"seed\" must be nil or number");
@ -330,49 +330,49 @@ nasal_val* builtin_rand(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
return gc.nil_addr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=0;
for(int i=0;i<5;++i)
ret_addr->ptr.num=(ret_addr->ptr.num+rand())*(1.0/(RAND_MAX+1.0));
return ret_addr;
}
nasal_val* builtin_id(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_id(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref val_addr=local_scope[1];
nasal_ref ret_addr=gc.gc_alloc(vm_str);
char buf[32];
sprintf(buf,"%p",val_addr);
*ret_addr->ptr.str=buf;
return ret_addr;
}
nasal_val* builtin_int(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_int(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("int","\"value\" must be number");
return nullptr;
}
int number=(int)val_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(double)number;
return ret_addr;
}
nasal_val* builtin_num(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_num(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_str)
{
builtin_err("num","\"value\" must be string");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=val_addr->to_number();
return ret_addr;
}
nasal_val* builtin_pop(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_pop(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_vec)
{
builtin_err("pop","\"vector\" must be vector");
@ -380,28 +380,28 @@ nasal_val* builtin_pop(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
if(val_addr->ptr.vec->elems.size())
{
nasal_val* tmp=val_addr->ptr.vec->elems.back();
nasal_ref tmp=val_addr->ptr.vec->elems.back();
val_addr->ptr.vec->elems.pop_back();
return tmp;
}
return gc.nil_addr;
}
nasal_val* builtin_str(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_str(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("str","\"number\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
*ret_addr->ptr.str=std::to_string(val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_size(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_size(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref val_addr=local_scope[1];
nasal_ref ret_addr=gc.gc_alloc(vm_num);
switch(val_addr->type)
{
case vm_nil: ret_addr->ptr.num=0; break;
@ -413,10 +413,10 @@ nasal_val* builtin_size(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
return ret_addr;
}
nasal_val* builtin_xor(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_xor(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_val* b_addr=local_scope[2];
nasal_ref a_addr=local_scope[1];
nasal_ref b_addr=local_scope[2];
if(a_addr->type!=vm_num)
{
builtin_err("xor","\"a\" must be number");
@ -429,14 +429,14 @@ nasal_val* builtin_xor(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
int number_a=(int)a_addr->ptr.num;
int number_b=(int)b_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(number_a^number_b);
return ret_addr;
}
nasal_val* builtin_and(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_and(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_val* b_addr=local_scope[2];
nasal_ref a_addr=local_scope[1];
nasal_ref b_addr=local_scope[2];
if(a_addr->type!=vm_num)
{
builtin_err("and","\"a\" must be number");
@ -449,14 +449,14 @@ nasal_val* builtin_and(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
int number_a=(int)a_addr->ptr.num;
int number_b=(int)b_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(number_a&number_b);
return ret_addr;
}
nasal_val* builtin_or(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_or(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_val* b_addr=local_scope[2];
nasal_ref a_addr=local_scope[1];
nasal_ref b_addr=local_scope[2];
if(a_addr->type!=vm_num)
{
builtin_err("or","\"a\" must be number");
@ -469,14 +469,14 @@ nasal_val* builtin_or(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
int number_a=(int)a_addr->ptr.num;
int number_b=(int)b_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(number_a|number_b);
return ret_addr;
}
nasal_val* builtin_nand(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_nand(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_val* b_addr=local_scope[2];
nasal_ref a_addr=local_scope[1];
nasal_ref b_addr=local_scope[2];
if(a_addr->type!=vm_num)
{
builtin_err("nand","\"a\" must be number");
@ -489,99 +489,99 @@ nasal_val* builtin_nand(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
int number_a=(int)a_addr->ptr.num;
int number_b=(int)b_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(~(number_a&number_b));
return ret_addr;
}
nasal_val* builtin_not(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_not(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_ref a_addr=local_scope[1];
if(a_addr->type!=vm_num)
{
builtin_err("not","\"a\" must be number");
return nullptr;
}
int number=(int)a_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(~number);
return ret_addr;
}
nasal_val* builtin_sin(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_sin(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("sin","\"x\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=sin(val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_cos(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_cos(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("cos","\"x\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=cos(val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_tan(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_tan(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("tan","\"x\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=tan(val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_exp(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_exp(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("exp","\"x\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=exp(val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_ln(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_ln(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("ln","\"x\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(log(val_addr->ptr.num)/log(2.7182818284590452354));
return ret_addr;
}
nasal_val* builtin_sqrt(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_sqrt(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("sqrt","\"x\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=sqrt(val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_atan2(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_atan2(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* x_val_addr=local_scope[1];
nasal_val* y_val_addr=local_scope[2];
nasal_ref x_val_addr=local_scope[1];
nasal_ref y_val_addr=local_scope[2];
if(x_val_addr->type!=vm_num)
{
builtin_err("atan2","\"x\" must be number");
@ -592,27 +592,27 @@ nasal_val* builtin_atan2(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
builtin_err("atan2","\"y\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=atan2(y_val_addr->ptr.num,x_val_addr->ptr.num);
return ret_addr;
}
nasal_val* builtin_time(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_time(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_ref val_addr=local_scope[1];
if(val_addr->type!=vm_num)
{
builtin_err("time","\"begin_time\" must be number");
return nullptr;
}
time_t begin_time=(time_t)val_addr->ptr.num;
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=time(&begin_time);
return ret_addr;
}
nasal_val* builtin_contains(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_contains(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* hash_addr=local_scope[1];
nasal_val* key_addr=local_scope[2];
nasal_ref hash_addr=local_scope[1];
nasal_ref key_addr=local_scope[2];
if(hash_addr->type!=vm_hash)
{
builtin_err("contains","\"hash\" must be hash");
@ -625,10 +625,10 @@ nasal_val* builtin_contains(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
return hash_addr->ptr.hash->elems.count(*key_addr->ptr.str)?gc.one_addr:gc.zero_addr;
}
nasal_val* builtin_delete(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_delete(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* hash_addr=local_scope[1];
nasal_val* key_addr=local_scope[2];
nasal_ref hash_addr=local_scope[1];
nasal_ref key_addr=local_scope[2];
if(hash_addr->type!=vm_hash)
{
builtin_err("delete","\"hash\" must be hash");
@ -643,9 +643,9 @@ nasal_val* builtin_delete(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
hash_addr->ptr.hash->elems.erase(*key_addr->ptr.str);
return gc.nil_addr;
}
nasal_val* builtin_keys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_keys(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* hash_addr=local_scope[1];
nasal_ref hash_addr=local_scope[1];
if(hash_addr->type!=vm_hash)
{
builtin_err("keys","\"hash\" must be hash");
@ -654,25 +654,25 @@ nasal_val* builtin_keys(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
// push vector into local scope to avoid being sweeped
local_scope.push_back(gc.gc_alloc(vm_vec));
std::vector<nasal_val*>& vec=local_scope.back()->ptr.vec->elems;
std::vector<nasal_ref>& vec=local_scope.back()->ptr.vec->elems;
for(auto iter:hash_addr->ptr.hash->elems)
{
nasal_val* str_addr=gc.gc_alloc(vm_str);
nasal_ref str_addr=gc.gc_alloc(vm_str);
*str_addr->ptr.str=iter.first;
vec.push_back(str_addr);
}
return local_scope.back();
}
nasal_val* builtin_import(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_import(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
// this function is used in preprocessing.
// this function will return nothing when running.
builtin_err("import","must use this function in global scope");
return nullptr;
}
nasal_val* builtin_die(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_die(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* str_addr=local_scope[1];
nasal_ref str_addr=local_scope[1];
if(str_addr->type!=vm_str)
{
builtin_err("die","\"str\" must be string");
@ -681,10 +681,10 @@ nasal_val* builtin_die(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
std::cout<<"[vm] error: "<<*str_addr->ptr.str<<'\n';
return nullptr;
}
nasal_val* builtin_type(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_type(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* val_addr=local_scope[1];
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref val_addr=local_scope[1];
nasal_ref ret_addr=gc.gc_alloc(vm_str);
switch(val_addr->type)
{
case vm_nil: *ret_addr->ptr.str="nil"; break;
@ -696,11 +696,11 @@ nasal_val* builtin_type(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
return ret_addr;
}
nasal_val* builtin_substr(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_substr(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* str_addr=local_scope[1];
nasal_val* beg_addr=local_scope[2];
nasal_val* len_addr=local_scope[3];
nasal_ref str_addr=local_scope[1];
nasal_ref beg_addr=local_scope[2];
nasal_ref len_addr=local_scope[3];
if(str_addr->type!=vm_str)
{
builtin_err("substr","\"str\" must be string");
@ -726,22 +726,22 @@ nasal_val* builtin_substr(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
}
if(len<0)
len=0;
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
*ret_addr->ptr.str=str.substr(beg,len);
return ret_addr;
}
nasal_val* builtin_streq(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_streq(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_val* b_addr=local_scope[2];
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref a_addr=local_scope[1];
nasal_ref b_addr=local_scope[2];
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=(a_addr->type!=vm_str || b_addr->type!=vm_str)?0:(*a_addr->ptr.str==*b_addr->ptr.str);
return ret_addr;
}
nasal_val* builtin_left(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_left(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* str_addr=local_scope[1];
nasal_val* len_addr=local_scope[2];
nasal_ref str_addr=local_scope[1];
nasal_ref len_addr=local_scope[2];
if(str_addr->type!=vm_str)
{
builtin_err("left","\"string\" must be string");
@ -756,14 +756,14 @@ nasal_val* builtin_left(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
int len=(int)len_addr->ptr.num;
if(len<0)
len=0;
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
*ret_addr->ptr.str=str.substr(0, len);
return ret_addr;
}
nasal_val* builtin_right(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_right(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* str_addr=local_scope[1];
nasal_val* len_addr=local_scope[2];
nasal_ref str_addr=local_scope[1];
nasal_ref len_addr=local_scope[2];
if(str_addr->type!=vm_str)
{
builtin_err("right","\"string\" must be string");
@ -781,14 +781,14 @@ nasal_val* builtin_right(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
len=srclen;
if(len<0)
len=0;
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
*ret_addr->ptr.str=str.substr(srclen-len, srclen);
return ret_addr;
}
nasal_val* builtin_cmp(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_cmp(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
nasal_val* a_addr=local_scope[1];
nasal_val* b_addr=local_scope[2];
nasal_ref a_addr=local_scope[1];
nasal_ref b_addr=local_scope[2];
if(a_addr->type!=vm_str)
{
builtin_err("cmp","\"a\" must be string");
@ -799,11 +799,11 @@ nasal_val* builtin_cmp(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
builtin_err("cmp","\"b\" must be string");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_num);
nasal_ref ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=strcmp(a_addr->ptr.str->c_str(),b_addr->ptr.str->c_str());
return ret_addr;
}
nasal_val* builtin_chr(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
nasal_ref builtin_chr(std::vector<nasal_ref>& local_scope,nasal_gc& gc)
{
const char* extend[]={
""," ","","ƒ","","","","",
@ -823,13 +823,13 @@ nasal_val* builtin_chr(std::vector<nasal_val*>& local_scope,nasal_gc& gc)
"ð","ñ","ò","ó","ô","õ","ö","÷",
"ø","ù","ú","û","ü","ý","þ","ÿ"
};
nasal_val* code_addr=local_scope[1];
nasal_ref code_addr=local_scope[1];
if(code_addr->type!=vm_num)
{
builtin_err("chr","\"code\" must be number");
return nullptr;
}
nasal_val* ret_addr=gc.gc_alloc(vm_str);
nasal_ref ret_addr=gc.gc_alloc(vm_str);
int num=code_addr->ptr.num;
if(0<=num && num<128)
*ret_addr->ptr.str=(char)num;

View File

@ -24,34 +24,37 @@ const int increment[vm_type_size]=
512 // vm_hash
};
struct nasal_val;//declaration of nasal_val
// declaration of nasal_val
struct nasal_val;
// define nasal_ref => nasal_val*
typedef nasal_val* nasal_ref;
struct nasal_vec// 24 bytes
{
std::vector<nasal_val*> elems;
std::vector<nasal_ref> elems;
void print();
nasal_val* get_val(int);
nasal_val** get_mem(int);
nasal_ref get_val(int);
nasal_ref* get_mem(int);
};
struct nasal_hash// 56 bytes
{
std::unordered_map<std::string,nasal_val*> elems;
std::unordered_map<std::string,nasal_ref> elems;
void print();
nasal_val* get_val(std::string&);
nasal_val** get_mem(std::string&);
nasal_ref get_val(std::string&);
nasal_ref* get_mem(std::string&);
};
struct nasal_func// 120 bytes
{
int32_t dynpara;// dynamic parameter name index in hash
uint32_t offset; // arguments will be loaded into local scope from this offset
uint32_t entry; // pc will set to entry-1 to call this function
std::vector<nasal_val*> default_para;// default value(nasal_val*)
int32_t dynpara; // dynamic parameter name index in hash
uint32_t offset; // arguments will be loaded into local scope from this offset
uint32_t entry; // pc will set to entry-1 to call this function
std::vector<nasal_ref> default_para;// default value(nasal_ref)
std::unordered_map<std::string,int> key_table;// parameter name hash
nasal_val* closure;// closure will be loaded to gc.local.back() as the local scope
nasal_ref closure; // closure will be loaded to gc.local.back() as the local scope
nasal_func();
void clear();
@ -80,14 +83,14 @@ struct nasal_val// 16 bytes
};
/*functions of nasal_vec*/
nasal_val* nasal_vec::get_val(int index)
nasal_ref nasal_vec::get_val(int index)
{
int vec_size=elems.size();
if(index<-vec_size || index>=vec_size)
return nullptr;
return elems[index>=0?index:index+vec_size];
}
nasal_val** nasal_vec::get_mem(int index)
nasal_ref* nasal_vec::get_mem(int index)
{
int vec_size=elems.size();
if(index<-vec_size || index>=vec_size)
@ -129,14 +132,14 @@ void nasal_vec::print()
}
/*functions of nasal_hash*/
nasal_val* nasal_hash::get_val(std::string& key)
nasal_ref nasal_hash::get_val(std::string& key)
{
if(elems.count(key))
return elems[key];
else if(elems.count("parents"))
{
nasal_val* ret_addr=nullptr;
nasal_val* val_addr=elems["parents"];
nasal_ref ret_addr=nullptr;
nasal_ref val_addr=elems["parents"];
if(val_addr->type==vm_vec)
for(auto i:val_addr->ptr.vec->elems)
{
@ -148,14 +151,14 @@ nasal_val* nasal_hash::get_val(std::string& key)
}
return nullptr;
}
nasal_val** nasal_hash::get_mem(std::string& key)
nasal_ref* nasal_hash::get_mem(std::string& key)
{
if(elems.count(key))
return &elems[key];
else if(elems.count("parents"))
{
nasal_val** mem_addr=nullptr;
nasal_val* val_addr=elems["parents"];
nasal_ref* mem_addr=nullptr;
nasal_ref val_addr=elems["parents"];
if(val_addr->type==vm_vec)
for(auto i:val_addr->ptr.vec->elems)
{
@ -187,7 +190,7 @@ void nasal_hash::print()
for(auto& i:elems)
{
std::cout<<i.first<<':';
nasal_val* tmp=i.second;
nasal_ref tmp=i.second;
switch(tmp->type)
{
case vm_nil: std::cout<<"nil"; break;
@ -262,35 +265,35 @@ std::string nasal_val::to_string()
struct nasal_gc
{
#define STACK_MAX_DEPTH (4080)
nasal_val* zero_addr; // reserved address of nasal_val,type vm_num, 0
nasal_val* one_addr; // reserved address of nasal_val,type vm_num, 1
nasal_val* nil_addr; // reserved address of nasal_val,type vm_nil
nasal_val* val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow
nasal_val** stack_top; // stack top
std::vector<nasal_val*> num_addrs; // reserved address for const vm_num
std::vector<nasal_val*> str_addrs; // reserved address for const vm_str
std::vector<nasal_val*> memory; // gc memory
std::queue <nasal_val*> free_list[vm_type_size]; // gc free list
std::vector<nasal_val*> local;
void mark();
void sweep();
void gc_init(std::vector<double>&,std::vector<std::string>&);
void gc_clear();
nasal_val* gc_alloc(int);
nasal_val* builtin_alloc(int);
nasal_ref zero_addr; // reserved address of nasal_val,type vm_num, 0
nasal_ref one_addr; // reserved address of nasal_val,type vm_num, 1
nasal_ref nil_addr; // reserved address of nasal_val,type vm_nil
nasal_ref val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow
nasal_ref* stack_top; // stack top
std::vector<nasal_ref> num_addrs; // reserved address for const vm_num
std::vector<nasal_ref> str_addrs; // reserved address for const vm_str
std::vector<nasal_ref> memory; // gc memory
std::queue <nasal_ref> free_list[vm_type_size]; // gc free list
std::vector<nasal_ref> local;
void mark();
void sweep();
void gc_init(std::vector<double>&,std::vector<std::string>&);
void gc_clear();
nasal_ref gc_alloc(int);
nasal_ref builtin_alloc(int);
};
/* gc functions */
void nasal_gc::mark()
{
std::queue<nasal_val*> bfs;
std::queue<nasal_ref> bfs;
for(auto i:local)
bfs.push(i);
for(nasal_val** i=val_stack;i<=stack_top;++i)
for(nasal_ref* i=val_stack;i<=stack_top;++i)
bfs.push(*i);
while(!bfs.empty())
{
nasal_val* tmp=bfs.front();
nasal_ref tmp=bfs.front();
bfs.pop();
if(tmp->mark) continue;
tmp->mark=GC_FOUND;
@ -340,7 +343,7 @@ void nasal_gc::gc_init(std::vector<double>& nums,std::vector<std::string>& strs)
for(int i=vm_num;i<vm_type_size;++i)
for(int j=0;j<increment[i];++j)
{
nasal_val* tmp=new nasal_val(i);
nasal_ref tmp=new nasal_val(i);
memory.push_back(tmp);
free_list[i].push(tmp);
}
@ -392,7 +395,7 @@ void nasal_gc::gc_clear()
str_addrs.clear();
return;
}
nasal_val* nasal_gc::gc_alloc(int type)
nasal_ref nasal_gc::gc_alloc(int type)
{
if(free_list[type].empty())
{
@ -402,16 +405,16 @@ nasal_val* nasal_gc::gc_alloc(int type)
if(free_list[type].empty())
for(int i=0;i<increment[type];++i)
{
nasal_val* tmp=new nasal_val(type);
nasal_ref tmp=new nasal_val(type);
memory.push_back(tmp);
free_list[type].push(tmp);
}
nasal_val* ret=free_list[type].front();
nasal_ref ret=free_list[type].front();
ret->mark=GC_UNCOLLECTED;
free_list[type].pop();
return ret;
}
nasal_val* nasal_gc::builtin_alloc(int type)
nasal_ref nasal_gc::builtin_alloc(int type)
{
// when running a builtin function,alloc will run more than one time
// this may cause mark-sweep in gc_alloc
@ -420,11 +423,11 @@ nasal_val* nasal_gc::builtin_alloc(int type)
if(free_list[type].empty())
for(int i=0;i<increment[type];++i)
{
nasal_val* tmp=new nasal_val(type);
nasal_ref tmp=new nasal_val(type);
memory.push_back(tmp);
free_list[type].push(tmp);
}
nasal_val* ret=free_list[type].front();
nasal_ref ret=free_list[type].front();
ret->mark=GC_UNCOLLECTED;
free_list[type].pop();
return ret;

View File

@ -5,15 +5,16 @@ class nasal_vm
{
private:
/* reference from nasal_gc */
nasal_val**& stack_top;// stack top
nasal_ref*& stack_top;// stack top
/* values of nasal_vm */
uint32_t pc; // program counter
std::stack<nasal_ref> cls_stk; // stack to store closure,if same closures detected,load the local scope
std::stack<uint32_t> ret; // ptr stack stores address for function to return
std::stack<int> counter; // iterator stack for forindex/foreach
std::vector<double> num_table;// numbers used in process(const calculation)
std::vector<std::string> str_table;// symbols used in process
std::vector<uint32_t> imm; // immediate number
nasal_val** mem_addr; // used for mem_call
nasal_ref* mem_addr; // used for mem_call
nasal_gc gc; // garbage collector
/* values used for debug */
std::vector<opcode> bytecode; // bytecode
@ -25,7 +26,7 @@ private:
void die(std::string);
void stackoverflow();
/* vm calculation functions*/
bool condition(nasal_val*);
bool condition(nasal_ref);
void opr_intg();
void opr_intl();
void opr_offset();
@ -128,6 +129,8 @@ void nasal_vm::clear()
gc.gc_clear();
while(!ret.empty())
ret.pop();
while(!cls_stk.empty())
cls_stk.pop();
while(!counter.empty())
counter.pop();
num_table.clear();
@ -170,7 +173,7 @@ void nasal_vm::stackinfo(int limit)
{
printf("vm stack(limit %d):\n",limit);
uint32_t same_cnt=0;
nasal_val* last_ptr=(nasal_val*)0xffff;
nasal_ref last_ptr=(nasal_ref)0xffff;
for(int i=0;i<limit && stack_top-i>=gc.val_stack;++i)
{
if(stack_top[-i]==last_ptr)
@ -211,7 +214,7 @@ void nasal_vm::die(std::string str)
ret.push(pc);
traceback();
stackinfo(10);
gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_val*)0xffff;
gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_ref)0xffff;
return;
}
void nasal_vm::stackoverflow()
@ -221,7 +224,7 @@ void nasal_vm::stackoverflow()
stackinfo(10);
return;
}
inline bool nasal_vm::condition(nasal_val* val_addr)
inline bool nasal_vm::condition(nasal_ref val_addr)
{
if(val_addr->type==vm_num)
return val_addr->ptr.num;
@ -295,8 +298,8 @@ inline void nasal_vm::opr_pstr()
}
inline void nasal_vm::opr_newv()
{
nasal_val* vec_addr=gc.gc_alloc(vm_vec);
nasal_val** begin=stack_top-imm[pc]+1;
nasal_ref vec_addr=gc.gc_alloc(vm_vec);
nasal_ref* begin=stack_top-imm[pc]+1;
auto& vec=vec_addr->ptr.vec->elems;// stack_top-imm[pc] stores the vector
vec.resize(imm[pc]);
for(uint32_t i=0;i<imm[pc];++i)
@ -323,7 +326,7 @@ inline void nasal_vm::opr_newf()
}
inline void nasal_vm::opr_happ()
{
nasal_val* val=stack_top[0];
nasal_ref val=stack_top[0];
(--stack_top)[0]->ptr.hash->elems[str_table[imm[pc]]]=val;
return;
}
@ -337,7 +340,7 @@ inline void nasal_vm::opr_para()
}
inline void nasal_vm::opr_defpara()
{
nasal_val* def_val=stack_top[0];
nasal_ref def_val=stack_top[0];
nasal_func* func=(--stack_top)[0]->ptr.func;
int size=func->key_table.size();
func->key_table[str_table[imm[pc]]]=size;
@ -351,7 +354,7 @@ inline void nasal_vm::opr_dynpara()
}
inline void nasal_vm::opr_unot()
{
nasal_val* val=stack_top[0];
nasal_ref val=stack_top[0];
switch(val->type)
{
case vm_nil:stack_top[0]=gc.one_addr;break;
@ -371,14 +374,14 @@ inline void nasal_vm::opr_unot()
}
inline void nasal_vm::opr_usub()
{
nasal_val* new_val=gc.gc_alloc(vm_num);
nasal_ref new_val=gc.gc_alloc(vm_num);
new_val->ptr.num=-stack_top[0]->to_number();
stack_top[0]=new_val;
return;
}
#define op_calc(type)\
nasal_val* new_val=gc.gc_alloc(vm_num);\
nasal_ref new_val=gc.gc_alloc(vm_num);\
new_val->ptr.num=stack_top[-1]->to_number() type stack_top[0]->to_number();\
(--stack_top)[0]=new_val;
@ -388,14 +391,14 @@ inline void nasal_vm::opr_mul(){op_calc(*);}
inline void nasal_vm::opr_div(){op_calc(/);}
inline void nasal_vm::opr_lnk()
{
nasal_val* new_val=gc.gc_alloc(vm_str);
nasal_ref new_val=gc.gc_alloc(vm_str);
*new_val->ptr.str=stack_top[-1]->to_string()+stack_top[0]->to_string();
(--stack_top)[0]=new_val;
return;
}
#define op_calc_const(type)\
nasal_val* new_val=gc.gc_alloc(vm_num);\
nasal_ref new_val=gc.gc_alloc(vm_num);\
new_val->ptr.num=stack_top[0]->to_number() type num_table[imm[pc]];\
stack_top[0]=new_val;
@ -405,14 +408,14 @@ inline void nasal_vm::opr_mulc(){op_calc_const(*);}
inline void nasal_vm::opr_divc(){op_calc_const(/);}
inline void nasal_vm::opr_lnkc()
{
nasal_val* new_val=gc.gc_alloc(vm_str);
nasal_ref new_val=gc.gc_alloc(vm_str);
*new_val->ptr.str=stack_top[0]->to_string()+str_table[imm[pc]];
stack_top[0]=new_val;
return;
}
#define op_calc_eq(type)\
nasal_val* new_val=gc.gc_alloc(vm_num);\
nasal_ref new_val=gc.gc_alloc(vm_num);\
new_val->ptr.num=mem_addr[0]->to_number() type stack_top[-1]->to_number();\
(--stack_top)[0]=mem_addr[0]=new_val;
@ -422,14 +425,14 @@ inline void nasal_vm::opr_muleq(){op_calc_eq(*);}
inline void nasal_vm::opr_diveq(){op_calc_eq(/);}
inline void nasal_vm::opr_lnkeq()
{
nasal_val* new_val=gc.gc_alloc(vm_str);
nasal_ref new_val=gc.gc_alloc(vm_str);
*new_val->ptr.str=mem_addr[0]->to_string()+stack_top[-1]->to_string();
(--stack_top)[0]=mem_addr[0]=new_val;
return;
}
#define op_calc_eq_const(type)\
nasal_val* new_val=gc.gc_alloc(vm_num);\
nasal_ref new_val=gc.gc_alloc(vm_num);\
new_val->ptr.num=mem_addr[0]->to_number() type num_table[imm[pc]];\
stack_top[0]=mem_addr[0]=new_val;
@ -439,7 +442,7 @@ inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);}
inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);}
inline void nasal_vm::opr_lnkeqc()
{
nasal_val* new_val=gc.gc_alloc(vm_str);
nasal_ref new_val=gc.gc_alloc(vm_str);
*new_val->ptr.str=mem_addr[0]->to_string()+str_table[imm[pc]];
stack_top[0]=mem_addr[0]=new_val;
return;
@ -452,8 +455,8 @@ inline void nasal_vm::opr_meq()
}
inline void nasal_vm::opr_eq()
{
nasal_val* val2=stack_top[0];
nasal_val* val1=(--stack_top)[0];
nasal_ref val2=stack_top[0];
nasal_ref val1=(--stack_top)[0];
int a_type=val1->type;
int b_type=val2->type;
if(a_type==vm_nil && b_type==vm_nil)
@ -468,8 +471,8 @@ inline void nasal_vm::opr_eq()
}
inline void nasal_vm::opr_neq()
{
nasal_val* val2=stack_top[0];
nasal_val* val1=(--stack_top)[0];
nasal_ref val2=stack_top[0];
nasal_ref val1=(--stack_top)[0];
int a_type=val1->type;
int b_type=val2->type;
if(a_type==vm_nil && b_type==vm_nil)
@ -547,7 +550,7 @@ inline void nasal_vm::opr_findex()
}
inline void nasal_vm::opr_feach()
{
std::vector<nasal_val*>& ref=stack_top[0]->ptr.vec->elems;
std::vector<nasal_ref>& ref=stack_top[0]->ptr.vec->elems;
if(++counter.top()>=ref.size())
{
pc=imm[pc]-1;
@ -568,8 +571,8 @@ inline void nasal_vm::opr_calll()
}
inline void nasal_vm::opr_callv()
{
nasal_val* val=stack_top[0];
nasal_val* vec_addr=(--stack_top)[0];
nasal_ref val=stack_top[0];
nasal_ref vec_addr=(--stack_top)[0];
if(vec_addr->type==vm_vec)
{
stack_top[0]=vec_addr->ptr.vec->get_val(val->to_number());
@ -611,7 +614,7 @@ inline void nasal_vm::opr_callv()
}
inline void nasal_vm::opr_callvi()
{
nasal_val* val=stack_top[0];
nasal_ref val=stack_top[0];
if(val->type!=vm_vec)
{
die("callvi: must use a vector");
@ -625,7 +628,7 @@ inline void nasal_vm::opr_callvi()
}
inline void nasal_vm::opr_callh()
{
nasal_val* val=stack_top[0];
nasal_ref val=stack_top[0];
if(val->type!=vm_hash)
{
die("callh: must call a hash");
@ -645,8 +648,8 @@ inline void nasal_vm::opr_callfv()
{
// get parameter list and function value
uint32_t args_size=imm[pc];
nasal_val** vec=stack_top-args_size+1;
nasal_val* func_addr=vec[-1];
nasal_ref* vec=stack_top-args_size+1;
nasal_ref func_addr=vec[-1];
if(func_addr->type!=vm_func)
{
die("callfv: must call a function");
@ -654,6 +657,7 @@ inline void nasal_vm::opr_callfv()
}
// push new local scope
auto& ref_func=*func_addr->ptr.func;
cls_stk.push(func_addr->ptr.func->closure);
gc.local.push_back(gc.gc_alloc(vm_vec));
gc.local.back()->ptr.vec->elems=ref_func.closure->ptr.vec->elems;
// load parameters
@ -678,7 +682,7 @@ inline void nasal_vm::opr_callfv()
// load dynamic argument if args_size>=para_size
if(ref_func.dynpara>=0)
{
nasal_val* vec_addr=gc.gc_alloc(vm_vec);
nasal_ref vec_addr=gc.gc_alloc(vm_vec);
for(uint32_t i=para_size;i<args_size;++i)
vec_addr->ptr.vec->elems.push_back(vec[i]);
ref_closure[para_size+offset]=vec_addr;
@ -693,7 +697,7 @@ inline void nasal_vm::opr_callfh()
{
// get parameter list and function value
auto& ref_hash=stack_top[0]->ptr.hash->elems;
nasal_val* func_addr=stack_top[-1];
nasal_ref func_addr=stack_top[-1];
if(func_addr->type!=vm_func)
{
die("callfh: must call a function");
@ -701,6 +705,7 @@ inline void nasal_vm::opr_callfh()
}
// push new local scope
auto& ref_func=*func_addr->ptr.func;
cls_stk.push(func_addr->ptr.func->closure);
gc.local.push_back(gc.gc_alloc(vm_vec));
gc.local.back()->ptr.vec->elems=ref_func.closure->ptr.vec->elems;
// load parameters
@ -757,8 +762,8 @@ inline void nasal_vm::opr_slcend()
}
inline void nasal_vm::opr_slc()
{
nasal_val* val=(stack_top--)[0];
nasal_val* res=stack_top[-1]->ptr.vec->get_val(val->to_number());
nasal_ref val=(stack_top--)[0];
nasal_ref res=stack_top[-1]->ptr.vec->get_val(val->to_number());
if(!res)
die("slc: index out of range:"+std::to_string(val->to_number()));
stack_top[0]->ptr.vec->elems.push_back(res);
@ -766,10 +771,10 @@ inline void nasal_vm::opr_slc()
}
inline void nasal_vm::opr_slc2()
{
nasal_val* val2=(stack_top--)[0];
nasal_val* val1=(stack_top--)[0];
std::vector<nasal_val*>& ref=stack_top[-1]->ptr.vec->elems;
std::vector<nasal_val*>& aim=stack_top[0]->ptr.vec->elems;
nasal_ref val2=(stack_top--)[0];
nasal_ref val1=(stack_top--)[0];
std::vector<nasal_ref>& ref=stack_top[-1]->ptr.vec->elems;
std::vector<nasal_ref>& aim=stack_top[0]->ptr.vec->elems;
int type1=val1->type,type2=val2->type;
int num1=val1->to_number();
@ -810,8 +815,8 @@ inline void nasal_vm::opr_mcalll()
}
inline void nasal_vm::opr_mcallv()
{
nasal_val* val=stack_top[0];
nasal_val* vec_addr=(--stack_top)[0];
nasal_ref val=stack_top[0];
nasal_ref vec_addr=(--stack_top)[0];
int type=vec_addr->type;
if(type==vm_vec)
{
@ -841,7 +846,7 @@ inline void nasal_vm::opr_mcallv()
}
inline void nasal_vm::opr_mcallh()
{
nasal_val* hash_addr=stack_top[0];
nasal_ref hash_addr=stack_top[0];
if(hash_addr->type!=vm_hash)
{
die("mcallh: must call a hash");
@ -859,11 +864,27 @@ inline void nasal_vm::opr_mcallh()
}
inline void nasal_vm::opr_ret()
{
auto& vec=stack_top[-1]->ptr.func->closure->ptr.vec->elems;
for(uint32_t i=0;i<stack_top[-1]->ptr.func->offset;++i)
vec[i]=gc.local.back()->ptr.vec->elems[i];
vec[0]=gc.nil_addr;// set 'me' to nil
gc.local.pop_back();// delete local scope
nasal_func* func=stack_top[-1]->ptr.func;
uint32_t offset=func->offset;
nasal_ref cls=cls_stk.top();cls_stk.pop();
// same closure detected,update the last local scope instead of the closure
if(!cls_stk.empty() && cls_stk.top()==cls)
{
auto& vec=gc.local.back()->ptr.vec->elems;
auto& func_vec=func->closure->ptr.vec->elems;
gc.local.pop_back();
for(uint32_t i=0;i<offset;++i)
gc.local.back()->ptr.vec->elems[i]=func_vec[i]=vec[i];
}
else
{
auto& vec=func->closure->ptr.vec->elems;
for(uint32_t i=0;i<offset;++i)
vec[i]=gc.local.back()->ptr.vec->elems[i];
gc.local.pop_back();
vec[0]=gc.nil_addr;// set 'me' to nil
}
pc=ret.top();ret.pop();// fetch pc
--stack_top;
stack_top[0]=stack_top[1];// rewrite nasal_func with returned value
@ -910,7 +931,7 @@ void nasal_vm::run(std::vector<opcode>& exec,bool op_cnt)
goto *code[pc];
nop:
if(canary && canary!=(nasal_val*)0xffff)
if(canary && canary!=(nasal_ref)0xffff)
stackoverflow();
if(op_cnt)
{

View File

@ -2,23 +2,23 @@ import("lib.nas");
var lexer=func(file)
{
var _={ptr:0,token:[]};
var (ptr,token)=(0,[]);
var s=io.fin(file);
var len=size(s);
return
{
jmp_note:func()
{
while(_.ptr<len and chr(s[_.ptr])!='\n')
_.ptr+=1;
_.ptr+=1;
while(ptr<len and chr(s[ptr])!='\n')
ptr+=1;
ptr+=1;
},
id_gen:func()
{
var tmp="";
while(_.ptr<len)
while(ptr<len)
{
var c=s[_.ptr];
var c=s[ptr];
if(('a'[0]<=c and c<='z'[0])
or ('A'[0]<=c and c<='Z'[0])
or ('0'[0]<=c and c<='9'[0])
@ -26,21 +26,21 @@ var lexer=func(file)
tmp~=chr(c);
else
break;
_.ptr+=1;
ptr+=1;
}
append(_.token,tmp);
append(token,tmp);
},
str_gen:func()
{
var str="";
var mark=chr(s[_.ptr]);
_.ptr+=1;
while(_.ptr<len and chr(s[_.ptr])!=mark)
var mark=chr(s[ptr]);
ptr+=1;
while(ptr<len and chr(s[ptr])!=mark)
{
if(chr(s[_.ptr])=='\\')
if(chr(s[ptr])=='\\')
{
_.ptr+=1;
var c=chr(s[_.ptr]);
ptr+=1;
var c=chr(s[ptr]);
if (c=='a' ) str~='\a';
elsif(c=='b' ) str~='\b';
elsif(c=='f' ) str~='\f';
@ -56,116 +56,116 @@ var lexer=func(file)
else str~=c;
}
else
str~=chr(s[_.ptr]);
_.ptr+=1;
str~=chr(s[ptr]);
ptr+=1;
}
if(_.ptr>=len)
if(ptr>=len)
print("read eof when generating string.\n");
_.ptr+=1;
append(_.token,str);
ptr+=1;
append(token,str);
},
num_gen:func()
{
var number=chr(s[_.ptr]);
_.ptr+=1;
if(_.ptr<len and chr(s[_.ptr])=='x')
var number=chr(s[ptr]);
ptr+=1;
if(ptr<len and chr(s[ptr])=='x')
{
_.ptr+=1;
while(_.ptr<len and
('a'[0]<=s[_.ptr] and s[_.ptr]<='f'[0]
or '0'[0]<=s[_.ptr] and s[_.ptr]<='9'[0]))
ptr+=1;
while(ptr<len and
('a'[0]<=s[ptr] and s[ptr]<='f'[0]
or '0'[0]<=s[ptr] and s[ptr]<='9'[0]))
{
number~=chr(s[_.ptr]);
_.ptr+=1;
number~=chr(s[ptr]);
ptr+=1;
}
append(_.token,num(number));
append(token,num(number));
return;
}
elsif(_.ptr<len and chr(s[_.ptr])=='o')
elsif(ptr<len and chr(s[ptr])=='o')
{
_.ptr+=1;
while(_.ptr<len and ('0'[0]<=s[_.ptr] and s[_.ptr]<='7'[0]))
ptr+=1;
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='7'[0]))
{
number~=chr(s[_.ptr]);
_.ptr+=1;
number~=chr(s[ptr]);
ptr+=1;
}
append(_.token,num(number));
append(token,num(number));
return;
}
while(_.ptr<len and ('0'[0]<=s[_.ptr] and s[_.ptr]<='9'[0]))
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
{
number~=chr(s[_.ptr]);
_.ptr+=1;
number~=chr(s[ptr]);
ptr+=1;
}
if(_.ptr<len and chr(s[_.ptr])=='.')
if(ptr<len and chr(s[ptr])=='.')
{
number~=chr(s[_.ptr]);
_.ptr+=1;
while(_.ptr<len and ('0'[0]<=s[_.ptr] and s[_.ptr]<='9'[0]))
number~=chr(s[ptr]);
ptr+=1;
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
{
number~=chr(s[_.ptr]);
_.ptr+=1;
number~=chr(s[ptr]);
ptr+=1;
}
}
if(chr(s[_.ptr])=='e' or chr(s[_.ptr])=='E')
if(chr(s[ptr])=='e' or chr(s[ptr])=='E')
{
number~=chr(s[_.ptr]);
_.ptr+=1;
if(chr(s[_.ptr])=='-' or chr(s[_.ptr])=='+')
number~=chr(s[ptr]);
ptr+=1;
if(chr(s[ptr])=='-' or chr(s[ptr])=='+')
{
number~=chr(s[_.ptr]);
_.ptr+=1;
number~=chr(s[ptr]);
ptr+=1;
}
while(_.ptr<len and ('0'[0]<=s[_.ptr] and s[_.ptr]<='9'[0]))
while(ptr<len and ('0'[0]<=s[ptr] and s[ptr]<='9'[0]))
{
number~=chr(s[_.ptr]);
_.ptr+=1;
number~=chr(s[ptr]);
ptr+=1;
}
}
var last_c=chr(number[-1]);
if(last_c=='.' or last_c=='e' or last_c=='E' or last_c=='-' or last_c=='+')
println("error number: ",number);
append(_.token,num(number));
append(token,num(number));
},
opr_gen:func()
{
var c=chr(s[_.ptr]);
var c=chr(s[ptr]);
if(c=='+' or c=='-' or c=='~' or c=='/' or c=='*' or c=='>' or c=='<' or c=='!' or c=='=')
{
var tmp=c;
_.ptr+=1;
if(_.ptr<len and chr(s[_.ptr])=='=')
ptr+=1;
if(ptr<len and chr(s[ptr])=='=')
{
tmp~=chr(s[_.ptr]);
_.ptr+=1;
tmp~=chr(s[ptr]);
ptr+=1;
}
append(_.token,tmp);
append(token,tmp);
return;
}
elsif(c=='.')
{
if(_.ptr+2<len and chr(s[_.ptr+1])=='.' and chr(s[_.ptr+2])=='.')
if(ptr+2<len and chr(s[ptr+1])=='.' and chr(s[ptr+2])=='.')
{
append(_.token,"...");
_.ptr+=3;
append(token,"...");
ptr+=3;
}
else
{
append(_.token,".");
_.ptr+=1;
append(token,".");
ptr+=1;
}
return;
}
elsif(c!=' ' and c!='\t' and c!='\n' and c!='\r' and s[_.ptr]>0)
append(_.token,c);
_.ptr+=1;
elsif(c!=' ' and c!='\t' and c!='\n' and c!='\r' and s[ptr]>0)
append(token,c);
ptr+=1;
return;
},
main:func()
{
while(_.ptr<len)
while(ptr<len)
{
var c=s[_.ptr];
var c=s[ptr];
if(c=='#'[0])
me.jmp_note();
elsif('a'[0]<=c and c<='z'[0]
@ -181,12 +181,13 @@ var lexer=func(file)
}
return;
},
get_token:func(){return _.token;}
get_token:func(){return token;}
};
}
var nasal_lexer=lexer("test/lexer.nas");
nasal_lexer.main();
var info="";
foreach(var tok;nasal_lexer.get_token())
print(tok,' ');
println();
info~=tok~' ';
println(info);