closure bugs fixed
This commit is contained in:
parent
b2be386be8
commit
80cc8e9db7
346
nasal_builtin.h
346
nasal_builtin.h
|
@ -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;
|
||||
|
|
97
nasal_gc.h
97
nasal_gc.h
|
@ -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;
|
||||
|
|
117
nasal_vm.h
117
nasal_vm.h
|
@ -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)
|
||||
{
|
||||
|
|
147
test/lexer.nas
147
test/lexer.nas
|
@ -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);
|
Loading…
Reference in New Issue