change id name & add test file
This commit is contained in:
parent
be1bcdfe2c
commit
c7316e9780
374
nasal_builtin.h
374
nasal_builtin.h
|
@ -10,60 +10,60 @@
|
||||||
builtin function __builtin_std_cout is wrapped up by print
|
builtin function __builtin_std_cout is wrapped up by print
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::unordered_map<std::string,int> builtin_use_str_table;
|
std::unordered_map<std::string,int> builtin_use_str;
|
||||||
// used to find values that builtin function uses
|
// used to find values that builtin function uses
|
||||||
#define in_builtin_find(val_name) \
|
#define builtin_find(name) \
|
||||||
(\
|
(\
|
||||||
local_scope\
|
local_scope\
|
||||||
->ptr.scop\
|
->ptr.scop\
|
||||||
->get_val\
|
->get_val\
|
||||||
(builtin_use_str_table[val_name])\
|
(builtin_use_str[name])\
|
||||||
)
|
)
|
||||||
|
|
||||||
// declaration of builtin functions
|
// declaration of builtin functions
|
||||||
// to add new builtin function,declare it here and write the definition below
|
// to add new builtin function,declare it here and write the definition below
|
||||||
|
|
||||||
nasal_val* builtin_print(nasal_val*);
|
nasal_val* builtin_print(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_append(nasal_val*);
|
nasal_val* builtin_append(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_setsize(nasal_val*);
|
nasal_val* builtin_setsize(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_system(nasal_val*);
|
nasal_val* builtin_system(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_input(nasal_val*);
|
nasal_val* builtin_input(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_sleep(nasal_val*);
|
nasal_val* builtin_sleep(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_fin(nasal_val*);
|
nasal_val* builtin_fin(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_fout(nasal_val*);
|
nasal_val* builtin_fout(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_split(nasal_val*);
|
nasal_val* builtin_split(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_rand(nasal_val*);
|
nasal_val* builtin_rand(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_id(nasal_val*);
|
nasal_val* builtin_id(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_int(nasal_val*);
|
nasal_val* builtin_int(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_num(nasal_val*);
|
nasal_val* builtin_num(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_pop(nasal_val*);
|
nasal_val* builtin_pop(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_str(nasal_val*);
|
nasal_val* builtin_str(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_size(nasal_val*);
|
nasal_val* builtin_size(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_xor(nasal_val*);
|
nasal_val* builtin_xor(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_and(nasal_val*);
|
nasal_val* builtin_and(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_or(nasal_val*);
|
nasal_val* builtin_or(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_nand(nasal_val*);
|
nasal_val* builtin_nand(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_not(nasal_val*);
|
nasal_val* builtin_not(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_sin(nasal_val*);
|
nasal_val* builtin_sin(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_cos(nasal_val*);
|
nasal_val* builtin_cos(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_tan(nasal_val*);
|
nasal_val* builtin_tan(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_exp(nasal_val*);
|
nasal_val* builtin_exp(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_ln(nasal_val*);
|
nasal_val* builtin_ln(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_sqrt(nasal_val*);
|
nasal_val* builtin_sqrt(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_atan2(nasal_val*);
|
nasal_val* builtin_atan2(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_time(nasal_val*);
|
nasal_val* builtin_time(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_contains(nasal_val*);
|
nasal_val* builtin_contains(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_delete(nasal_val*);
|
nasal_val* builtin_delete(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_getkeys(nasal_val*);
|
nasal_val* builtin_getkeys(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_import(nasal_val*);
|
nasal_val* builtin_import(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_die(nasal_val*);
|
nasal_val* builtin_die(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_type(nasal_val*);
|
nasal_val* builtin_type(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_substr(nasal_val*);
|
nasal_val* builtin_substr(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_streq(nasal_val*);
|
nasal_val* builtin_streq(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_left(nasal_val*);
|
nasal_val* builtin_left(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_right(nasal_val*);
|
nasal_val* builtin_right(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_cmp(nasal_val*);
|
nasal_val* builtin_cmp(nasal_val*,nasal_gc&);
|
||||||
nasal_val* builtin_chr(nasal_val*);
|
nasal_val* builtin_chr(nasal_val*,nasal_gc&);
|
||||||
|
|
||||||
void builtin_err(std::string func_name,std::string info)
|
void builtin_err(std::string func_name,std::string info)
|
||||||
{
|
{
|
||||||
|
@ -76,7 +76,7 @@ void builtin_err(std::string func_name,std::string info)
|
||||||
struct FUNC_TABLE
|
struct FUNC_TABLE
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
nasal_val* (*func)(nasal_val* x);
|
nasal_val* (*func)(nasal_val* x,nasal_gc&);
|
||||||
} builtin_func[]=
|
} builtin_func[]=
|
||||||
{
|
{
|
||||||
{"__builtin_std_cout", builtin_print },
|
{"__builtin_std_cout", builtin_print },
|
||||||
|
@ -123,10 +123,10 @@ struct FUNC_TABLE
|
||||||
{"", nullptr }
|
{"", nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
nasal_val* builtin_print(nasal_val* local_scope)
|
nasal_val* builtin_print(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
// get arguments
|
// get arguments
|
||||||
nasal_val* vector_val_addr=in_builtin_find("elements");
|
nasal_val* vector_val_addr=builtin_find("elements");
|
||||||
// main process
|
// main process
|
||||||
std::vector<nasal_val*>& ref_vec=vector_val_addr->ptr.vec->elems;
|
std::vector<nasal_val*>& ref_vec=vector_val_addr->ptr.vec->elems;
|
||||||
int size=ref_vec.size();
|
int size=ref_vec.size();
|
||||||
|
@ -144,12 +144,12 @@ nasal_val* builtin_print(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// generate return value
|
// generate return value
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_append(nasal_val* local_scope)
|
nasal_val* builtin_append(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* vec_addr=in_builtin_find("vector");
|
nasal_val* vec_addr=builtin_find("vector");
|
||||||
nasal_val* elem_addr=in_builtin_find("elements");
|
nasal_val* elem_addr=builtin_find("elements");
|
||||||
if(vec_addr->type!=vm_vec)
|
if(vec_addr->type!=vm_vec)
|
||||||
{
|
{
|
||||||
builtin_err("append","\"vector\" must be vector");
|
builtin_err("append","\"vector\" must be vector");
|
||||||
|
@ -160,12 +160,12 @@ nasal_val* builtin_append(nasal_val* local_scope)
|
||||||
int size=ref_elems.size();
|
int size=ref_elems.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
ref_vec.push_back(ref_elems[i]);
|
ref_vec.push_back(ref_elems[i]);
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_setsize(nasal_val* local_scope)
|
nasal_val* builtin_setsize(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* vec_addr=in_builtin_find("vector");
|
nasal_val* vec_addr=builtin_find("vector");
|
||||||
nasal_val* size_addr=in_builtin_find("size");
|
nasal_val* size_addr=builtin_find("size");
|
||||||
if(vec_addr->type!=vm_vec)
|
if(vec_addr->type!=vm_vec)
|
||||||
{
|
{
|
||||||
builtin_err("setsize","\"vector\" must be vector");
|
builtin_err("setsize","\"vector\" must be vector");
|
||||||
|
@ -189,32 +189,32 @@ nasal_val* builtin_setsize(nasal_val* local_scope)
|
||||||
ref_vec.pop_back();
|
ref_vec.pop_back();
|
||||||
else if(num>vec_size)
|
else if(num>vec_size)
|
||||||
for(int i=vec_size;i<num;++i)
|
for(int i=vec_size;i<num;++i)
|
||||||
ref_vec.push_back(nil_addr);
|
ref_vec.push_back(gc.nil_addr);
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_val* builtin_system(nasal_val* local_scope)
|
nasal_val* builtin_system(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=in_builtin_find("str");
|
nasal_val* str_addr=builtin_find("str");
|
||||||
if(str_addr->type!=vm_str)
|
if(str_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("system","\"str\" must be string");
|
builtin_err("system","\"str\" must be string");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
system(str_addr->ptr.str->data());
|
system(str_addr->ptr.str->data());
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_val* builtin_input(nasal_val* local_scope)
|
nasal_val* builtin_input(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
std::cin>>*ret_addr->ptr.str;
|
std::cin>>*ret_addr->ptr.str;
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_val* builtin_sleep(nasal_val* local_scope)
|
nasal_val* builtin_sleep(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("duration");
|
nasal_val* val_addr=builtin_find("duration");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("sleep","\"duration\" must be number");
|
builtin_err("sleep","\"duration\" must be number");
|
||||||
|
@ -222,12 +222,12 @@ nasal_val* builtin_sleep(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
// sleep in unistd.h will make this progress sleep sleep_time seconds.
|
// sleep in unistd.h will make this progress sleep sleep_time seconds.
|
||||||
sleep((unsigned long)val_addr->ptr.num);
|
sleep((unsigned long)val_addr->ptr.num);
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_val* builtin_fin(nasal_val* local_scope)
|
nasal_val* builtin_fin(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("filename");
|
nasal_val* val_addr=builtin_find("filename");
|
||||||
if(val_addr->type!=vm_str)
|
if(val_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("io.fin","\"filename\" must be string");
|
builtin_err("io.fin","\"filename\" must be string");
|
||||||
|
@ -235,7 +235,7 @@ nasal_val* builtin_fin(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
std::string& filename=*val_addr->ptr.str;
|
std::string& filename=*val_addr->ptr.str;
|
||||||
std::ifstream fin(filename);
|
std::ifstream fin(filename);
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
*ret_addr->ptr.str="";
|
*ret_addr->ptr.str="";
|
||||||
if(!fin.fail())
|
if(!fin.fail())
|
||||||
while(!fin.eof())
|
while(!fin.eof())
|
||||||
|
@ -251,10 +251,10 @@ nasal_val* builtin_fin(nasal_val* local_scope)
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_val* builtin_fout(nasal_val* local_scope)
|
nasal_val* builtin_fout(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("filename");
|
nasal_val* val_addr=builtin_find("filename");
|
||||||
nasal_val* str_addr=in_builtin_find("str");
|
nasal_val* str_addr=builtin_find("str");
|
||||||
if(val_addr->type!=vm_str)
|
if(val_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("io.fout","\"filename\" must be string");
|
builtin_err("io.fout","\"filename\" must be string");
|
||||||
|
@ -273,13 +273,13 @@ nasal_val* builtin_fout(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
fout<<*str_addr->ptr.str;
|
fout<<*str_addr->ptr.str;
|
||||||
fout.close();
|
fout.close();
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nasal_val* builtin_split(nasal_val* local_scope)
|
nasal_val* builtin_split(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* delimeter_val_addr=in_builtin_find("delimeter");
|
nasal_val* delimeter_val_addr=builtin_find("delimeter");
|
||||||
nasal_val* string_val_addr=in_builtin_find("string");
|
nasal_val* string_val_addr=builtin_find("string");
|
||||||
if(delimeter_val_addr->type!=vm_str)
|
if(delimeter_val_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("split","\"delimeter\" must be string");
|
builtin_err("split","\"delimeter\" must be string");
|
||||||
|
@ -295,7 +295,7 @@ nasal_val* builtin_split(nasal_val* local_scope)
|
||||||
int delimeter_len=delimeter.length();
|
int delimeter_len=delimeter.length();
|
||||||
int source_len=source.length();
|
int source_len=source.length();
|
||||||
|
|
||||||
nasal_val* ret_addr=gc_alloc(vm_vec);
|
nasal_val* ret_addr=gc.gc_alloc(vm_vec);
|
||||||
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
|
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
|
||||||
std::string tmp="";
|
std::string tmp="";
|
||||||
|
|
||||||
|
@ -303,7 +303,7 @@ nasal_val* builtin_split(nasal_val* local_scope)
|
||||||
{
|
{
|
||||||
for(int i=0;i<source_len;++i)
|
for(int i=0;i<source_len;++i)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=gc_alloc(vm_str);
|
nasal_val* str_addr=gc.gc_alloc(vm_str);
|
||||||
*str_addr->ptr.str=source[i];
|
*str_addr->ptr.str=source[i];
|
||||||
ref_vec.push_back(str_addr);
|
ref_vec.push_back(str_addr);
|
||||||
}
|
}
|
||||||
|
@ -325,7 +325,7 @@ nasal_val* builtin_split(nasal_val* local_scope)
|
||||||
{
|
{
|
||||||
if(tmp.length())
|
if(tmp.length())
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=gc_alloc(vm_str);
|
nasal_val* str_addr=gc.gc_alloc(vm_str);
|
||||||
*str_addr->ptr.str=tmp;
|
*str_addr->ptr.str=tmp;
|
||||||
ref_vec.push_back(str_addr);
|
ref_vec.push_back(str_addr);
|
||||||
tmp="";
|
tmp="";
|
||||||
|
@ -337,16 +337,16 @@ nasal_val* builtin_split(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
if(tmp.length())
|
if(tmp.length())
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=gc_alloc(vm_str);
|
nasal_val* str_addr=gc.gc_alloc(vm_str);
|
||||||
*str_addr->ptr.str=tmp;
|
*str_addr->ptr.str=tmp;
|
||||||
ref_vec.push_back(str_addr);
|
ref_vec.push_back(str_addr);
|
||||||
tmp="";
|
tmp="";
|
||||||
}
|
}
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_rand(nasal_val* local_scope)
|
nasal_val* builtin_rand(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("seed");
|
nasal_val* val_addr=builtin_find("seed");
|
||||||
if(val_addr->type!=vm_num && val_addr->type!=vm_nil)
|
if(val_addr->type!=vm_num && val_addr->type!=vm_nil)
|
||||||
{
|
{
|
||||||
builtin_err("rand","\"seed\" must be nil or number");
|
builtin_err("rand","\"seed\" must be nil or number");
|
||||||
|
@ -355,52 +355,52 @@ nasal_val* builtin_rand(nasal_val* local_scope)
|
||||||
if(val_addr->type==vm_num)
|
if(val_addr->type==vm_num)
|
||||||
{
|
{
|
||||||
srand((unsigned int)val_addr->ptr.num);
|
srand((unsigned int)val_addr->ptr.num);
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
double num=0;
|
double num=0;
|
||||||
for(int i=0;i<5;++i)
|
for(int i=0;i<5;++i)
|
||||||
num=(num+rand())*(1.0/(RAND_MAX+1.0));
|
num=(num+rand())*(1.0/(RAND_MAX+1.0));
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=num;
|
ret_addr->ptr.num=num;
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_id(nasal_val* local_scope)
|
nasal_val* builtin_id(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("thing");
|
nasal_val* val_addr=builtin_find("thing");
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
char buf[32];
|
char buf[32];
|
||||||
sprintf(buf,"0x%p",val_addr);
|
sprintf(buf,"0x%p",val_addr);
|
||||||
*ret_addr->ptr.str=buf;
|
*ret_addr->ptr.str=buf;
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_int(nasal_val* local_scope)
|
nasal_val* builtin_int(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("value");
|
nasal_val* val_addr=builtin_find("value");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("int","\"value\" must be number");
|
builtin_err("int","\"value\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
int number=(int)val_addr->ptr.num;
|
int number=(int)val_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(double)number;
|
ret_addr->ptr.num=(double)number;
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_num(nasal_val* local_scope)
|
nasal_val* builtin_num(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("value");
|
nasal_val* val_addr=builtin_find("value");
|
||||||
if(val_addr->type!=vm_str)
|
if(val_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("num","\"value\" must be string");
|
builtin_err("num","\"value\" must be string");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=val_addr->to_number();
|
ret_addr->ptr.num=val_addr->to_number();
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_pop(nasal_val* local_scope)
|
nasal_val* builtin_pop(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("vector");
|
nasal_val* val_addr=builtin_find("vector");
|
||||||
if(val_addr->type!=vm_vec)
|
if(val_addr->type!=vm_vec)
|
||||||
{
|
{
|
||||||
builtin_err("pop","\"vector\" must be vector");
|
builtin_err("pop","\"vector\" must be vector");
|
||||||
|
@ -412,24 +412,24 @@ nasal_val* builtin_pop(nasal_val* local_scope)
|
||||||
val_addr->ptr.vec->elems.pop_back();
|
val_addr->ptr.vec->elems.pop_back();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_str(nasal_val* local_scope)
|
nasal_val* builtin_str(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("number");
|
nasal_val* val_addr=builtin_find("number");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("str","\"number\" must be number");
|
builtin_err("str","\"number\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
*ret_addr->ptr.str=val_addr->to_string();
|
*ret_addr->ptr.str=val_addr->to_string();
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_size(nasal_val* local_scope)
|
nasal_val* builtin_size(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("object");
|
nasal_val* val_addr=builtin_find("object");
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
switch(val_addr->type)
|
switch(val_addr->type)
|
||||||
{
|
{
|
||||||
case vm_nil: ret_addr->ptr.num=0; break;
|
case vm_nil: ret_addr->ptr.num=0; break;
|
||||||
|
@ -442,10 +442,10 @@ nasal_val* builtin_size(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_xor(nasal_val* local_scope)
|
nasal_val* builtin_xor(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
nasal_val* b_addr=in_builtin_find("b");
|
nasal_val* b_addr=builtin_find("b");
|
||||||
if(a_addr->type!=vm_num)
|
if(a_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("xor","\"a\" must be number");
|
builtin_err("xor","\"a\" must be number");
|
||||||
|
@ -458,14 +458,14 @@ nasal_val* builtin_xor(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
int number_a=(int)a_addr->ptr.num;
|
int number_a=(int)a_addr->ptr.num;
|
||||||
int number_b=(int)b_addr->ptr.num;
|
int number_b=(int)b_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(number_a^number_b);
|
ret_addr->ptr.num=(number_a^number_b);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_and(nasal_val* local_scope)
|
nasal_val* builtin_and(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
nasal_val* b_addr=in_builtin_find("b");
|
nasal_val* b_addr=builtin_find("b");
|
||||||
if(a_addr->type!=vm_num)
|
if(a_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("and","\"a\" must be number");
|
builtin_err("and","\"a\" must be number");
|
||||||
|
@ -478,14 +478,14 @@ nasal_val* builtin_and(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
int number_a=(int)a_addr->ptr.num;
|
int number_a=(int)a_addr->ptr.num;
|
||||||
int number_b=(int)b_addr->ptr.num;
|
int number_b=(int)b_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(number_a&number_b);
|
ret_addr->ptr.num=(number_a&number_b);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_or(nasal_val* local_scope)
|
nasal_val* builtin_or(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
nasal_val* b_addr=in_builtin_find("b");
|
nasal_val* b_addr=builtin_find("b");
|
||||||
if(a_addr->type!=vm_num)
|
if(a_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("or","\"a\" must be number");
|
builtin_err("or","\"a\" must be number");
|
||||||
|
@ -498,14 +498,14 @@ nasal_val* builtin_or(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
int number_a=(int)a_addr->ptr.num;
|
int number_a=(int)a_addr->ptr.num;
|
||||||
int number_b=(int)b_addr->ptr.num;
|
int number_b=(int)b_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(number_a|number_b);
|
ret_addr->ptr.num=(number_a|number_b);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_nand(nasal_val* local_scope)
|
nasal_val* builtin_nand(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
nasal_val* b_addr=in_builtin_find("b");
|
nasal_val* b_addr=builtin_find("b");
|
||||||
if(a_addr->type!=vm_num)
|
if(a_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("nand","\"a\" must be number");
|
builtin_err("nand","\"a\" must be number");
|
||||||
|
@ -518,99 +518,99 @@ nasal_val* builtin_nand(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
int number_a=(int)a_addr->ptr.num;
|
int number_a=(int)a_addr->ptr.num;
|
||||||
int number_b=(int)b_addr->ptr.num;
|
int number_b=(int)b_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(~(number_a&number_b));
|
ret_addr->ptr.num=(~(number_a&number_b));
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_not(nasal_val* local_scope)
|
nasal_val* builtin_not(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
if(a_addr->type!=vm_num)
|
if(a_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("not","\"a\" must be number");
|
builtin_err("not","\"a\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
int number=(int)a_addr->ptr.num;
|
int number=(int)a_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(~number);
|
ret_addr->ptr.num=(~number);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_sin(nasal_val* local_scope)
|
nasal_val* builtin_sin(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("x");
|
nasal_val* val_addr=builtin_find("x");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("sin","\"x\" must be number");
|
builtin_err("sin","\"x\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=sin(val_addr->ptr.num);
|
ret_addr->ptr.num=sin(val_addr->ptr.num);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_cos(nasal_val* local_scope)
|
nasal_val* builtin_cos(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("x");
|
nasal_val* val_addr=builtin_find("x");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("cos","\"x\" must be number");
|
builtin_err("cos","\"x\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=cos(val_addr->ptr.num);
|
ret_addr->ptr.num=cos(val_addr->ptr.num);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_tan(nasal_val* local_scope)
|
nasal_val* builtin_tan(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("x");
|
nasal_val* val_addr=builtin_find("x");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("tan","\"x\" must be number");
|
builtin_err("tan","\"x\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=tan(val_addr->ptr.num);
|
ret_addr->ptr.num=tan(val_addr->ptr.num);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_exp(nasal_val* local_scope)
|
nasal_val* builtin_exp(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("x");
|
nasal_val* val_addr=builtin_find("x");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("exp","\"x\" must be number");
|
builtin_err("exp","\"x\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=exp(val_addr->ptr.num);
|
ret_addr->ptr.num=exp(val_addr->ptr.num);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_ln(nasal_val* local_scope)
|
nasal_val* builtin_ln(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("x");
|
nasal_val* val_addr=builtin_find("x");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("ln","\"x\" must be number");
|
builtin_err("ln","\"x\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=(log(val_addr->ptr.num)/log(2.7182818284590452354));
|
ret_addr->ptr.num=(log(val_addr->ptr.num)/log(2.7182818284590452354));
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_sqrt(nasal_val* local_scope)
|
nasal_val* builtin_sqrt(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("x");
|
nasal_val* val_addr=builtin_find("x");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("sqrt","\"x\" must be number");
|
builtin_err("sqrt","\"x\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=sqrt(val_addr->ptr.num);
|
ret_addr->ptr.num=sqrt(val_addr->ptr.num);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_atan2(nasal_val* local_scope)
|
nasal_val* builtin_atan2(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* x_val_addr=in_builtin_find("x");
|
nasal_val* x_val_addr=builtin_find("x");
|
||||||
nasal_val* y_val_addr=in_builtin_find("y");
|
nasal_val* y_val_addr=builtin_find("y");
|
||||||
if(x_val_addr->type!=vm_num)
|
if(x_val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("atan2","\"x\" must be number");
|
builtin_err("atan2","\"x\" must be number");
|
||||||
|
@ -621,27 +621,27 @@ nasal_val* builtin_atan2(nasal_val* local_scope)
|
||||||
builtin_err("atan2","\"y\" must be number");
|
builtin_err("atan2","\"y\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=atan2(y_val_addr->ptr.num,x_val_addr->ptr.num);
|
ret_addr->ptr.num=atan2(y_val_addr->ptr.num,x_val_addr->ptr.num);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_time(nasal_val* local_scope)
|
nasal_val* builtin_time(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("begin_time");
|
nasal_val* val_addr=builtin_find("begin_time");
|
||||||
if(val_addr->type!=vm_num)
|
if(val_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("time","\"begin_time\" must be number");
|
builtin_err("time","\"begin_time\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
time_t begin_time=(time_t)val_addr->ptr.num;
|
time_t begin_time=(time_t)val_addr->ptr.num;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=time(&begin_time);
|
ret_addr->ptr.num=time(&begin_time);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_contains(nasal_val* local_scope)
|
nasal_val* builtin_contains(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* hash_addr=in_builtin_find("hash");
|
nasal_val* hash_addr=builtin_find("hash");
|
||||||
nasal_val* key_addr=in_builtin_find("key");
|
nasal_val* key_addr=builtin_find("key");
|
||||||
if(hash_addr->type!=vm_hash)
|
if(hash_addr->type!=vm_hash)
|
||||||
{
|
{
|
||||||
builtin_err("contains","\"hash\" must be hash");
|
builtin_err("contains","\"hash\" must be hash");
|
||||||
|
@ -652,14 +652,14 @@ nasal_val* builtin_contains(nasal_val* local_scope)
|
||||||
builtin_err("contains","\"key\" must be string");
|
builtin_err("contains","\"key\" must be string");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=hash_addr->ptr.hash->check_contain(*key_addr->ptr.str);
|
ret_addr->ptr.num=hash_addr->ptr.hash->check_contain(*key_addr->ptr.str);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_delete(nasal_val* local_scope)
|
nasal_val* builtin_delete(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* hash_addr=in_builtin_find("hash");
|
nasal_val* hash_addr=builtin_find("hash");
|
||||||
nasal_val* key_addr=in_builtin_find("key");
|
nasal_val* key_addr=builtin_find("key");
|
||||||
if(hash_addr->type!=vm_hash)
|
if(hash_addr->type!=vm_hash)
|
||||||
{
|
{
|
||||||
builtin_err("delete","\"hash\" must be hash");
|
builtin_err("delete","\"hash\" must be hash");
|
||||||
|
@ -672,37 +672,37 @@ nasal_val* builtin_delete(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
if(hash_addr->ptr.hash->elems.count(*key_addr->ptr.str))
|
if(hash_addr->ptr.hash->elems.count(*key_addr->ptr.str))
|
||||||
hash_addr->ptr.hash->elems.erase(*key_addr->ptr.str);
|
hash_addr->ptr.hash->elems.erase(*key_addr->ptr.str);
|
||||||
return nil_addr;
|
return gc.nil_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_getkeys(nasal_val* local_scope)
|
nasal_val* builtin_getkeys(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* hash_addr=in_builtin_find("hash");
|
nasal_val* hash_addr=builtin_find("hash");
|
||||||
if(hash_addr->type!=vm_hash)
|
if(hash_addr->type!=vm_hash)
|
||||||
{
|
{
|
||||||
builtin_err("keys","\"hash\" must be hash");
|
builtin_err("keys","\"hash\" must be hash");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_vec);
|
nasal_val* ret_addr=gc.gc_alloc(vm_vec);
|
||||||
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
|
std::vector<nasal_val*>& ref_vec=ret_addr->ptr.vec->elems;
|
||||||
std::unordered_map<std::string,nasal_val*>& ref_hash=hash_addr->ptr.hash->elems;
|
std::unordered_map<std::string,nasal_val*>& ref_hash=hash_addr->ptr.hash->elems;
|
||||||
for(auto iter=ref_hash.begin();iter!=ref_hash.end();++iter)
|
for(auto iter=ref_hash.begin();iter!=ref_hash.end();++iter)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=gc_alloc(vm_str);
|
nasal_val* str_addr=gc.gc_alloc(vm_str);
|
||||||
*str_addr->ptr.str=iter->first;
|
*str_addr->ptr.str=iter->first;
|
||||||
ref_vec.push_back(str_addr);
|
ref_vec.push_back(str_addr);
|
||||||
}
|
}
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_import(nasal_val* local_scope)
|
nasal_val* builtin_import(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
// this function is used in preprocessing.
|
// this function is used in preprocessing.
|
||||||
// this function will return nothing when running.
|
// this function will return nothing when running.
|
||||||
builtin_err("import","cannot use import when running");
|
builtin_err("import","cannot use import when running");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_die(nasal_val* local_scope)
|
nasal_val* builtin_die(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=in_builtin_find("str");
|
nasal_val* str_addr=builtin_find("str");
|
||||||
if(str_addr->type!=vm_str)
|
if(str_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("die","\"str\" must be string");
|
builtin_err("die","\"str\" must be string");
|
||||||
|
@ -711,10 +711,10 @@ nasal_val* builtin_die(nasal_val* local_scope)
|
||||||
std::cout<<">> [vm] error: "<<str_addr->ptr.str<<'\n';
|
std::cout<<">> [vm] error: "<<str_addr->ptr.str<<'\n';
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_type(nasal_val* local_scope)
|
nasal_val* builtin_type(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* val_addr=in_builtin_find("object");
|
nasal_val* val_addr=builtin_find("object");
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
switch(val_addr->type)
|
switch(val_addr->type)
|
||||||
{
|
{
|
||||||
case vm_nil: *ret_addr->ptr.str="nil"; break;
|
case vm_nil: *ret_addr->ptr.str="nil"; break;
|
||||||
|
@ -726,11 +726,11 @@ nasal_val* builtin_type(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_substr(nasal_val* local_scope)
|
nasal_val* builtin_substr(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=in_builtin_find("str");
|
nasal_val* str_addr=builtin_find("str");
|
||||||
nasal_val* beg_addr=in_builtin_find("begin");
|
nasal_val* beg_addr=builtin_find("begin");
|
||||||
nasal_val* len_addr=in_builtin_find("length");
|
nasal_val* len_addr=builtin_find("length");
|
||||||
if(str_addr->type!=vm_str)
|
if(str_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("substr","\"str\" must be string");
|
builtin_err("substr","\"str\" must be string");
|
||||||
|
@ -756,22 +756,22 @@ nasal_val* builtin_substr(nasal_val* local_scope)
|
||||||
}
|
}
|
||||||
if(len<0)
|
if(len<0)
|
||||||
len=0;
|
len=0;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
*ret_addr->ptr.str=str.substr(beg,len);
|
*ret_addr->ptr.str=str.substr(beg,len);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_streq(nasal_val* local_scope)
|
nasal_val* builtin_streq(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
nasal_val* b_addr=in_builtin_find("b");
|
nasal_val* b_addr=builtin_find("b");
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* 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);
|
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;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_left(nasal_val* local_scope)
|
nasal_val* builtin_left(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=in_builtin_find("string");
|
nasal_val* str_addr=builtin_find("string");
|
||||||
nasal_val* len_addr=in_builtin_find("length");
|
nasal_val* len_addr=builtin_find("length");
|
||||||
if(str_addr->type!=vm_str)
|
if(str_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("left","\"string\" must be string");
|
builtin_err("left","\"string\" must be string");
|
||||||
|
@ -786,14 +786,14 @@ nasal_val* builtin_left(nasal_val* local_scope)
|
||||||
int len=(int)len_addr->ptr.num;
|
int len=(int)len_addr->ptr.num;
|
||||||
if(len<0)
|
if(len<0)
|
||||||
len=0;
|
len=0;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
*ret_addr->ptr.str=str.substr(0, len);
|
*ret_addr->ptr.str=str.substr(0, len);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_right(nasal_val* local_scope)
|
nasal_val* builtin_right(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* str_addr=in_builtin_find("string");
|
nasal_val* str_addr=builtin_find("string");
|
||||||
nasal_val* len_addr=in_builtin_find("length");
|
nasal_val* len_addr=builtin_find("length");
|
||||||
if(str_addr->type!=vm_str)
|
if(str_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("right","\"string\" must be string");
|
builtin_err("right","\"string\" must be string");
|
||||||
|
@ -811,14 +811,14 @@ nasal_val* builtin_right(nasal_val* local_scope)
|
||||||
len=srclen;
|
len=srclen;
|
||||||
if(len<0)
|
if(len<0)
|
||||||
len=0;
|
len=0;
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
*ret_addr->ptr.str=str.substr(srclen-len, srclen);
|
*ret_addr->ptr.str=str.substr(srclen-len, srclen);
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_cmp(nasal_val* local_scope)
|
nasal_val* builtin_cmp(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* a_addr=in_builtin_find("a");
|
nasal_val* a_addr=builtin_find("a");
|
||||||
nasal_val* b_addr=in_builtin_find("b");
|
nasal_val* b_addr=builtin_find("b");
|
||||||
if(a_addr->type!=vm_str)
|
if(a_addr->type!=vm_str)
|
||||||
{
|
{
|
||||||
builtin_err("cmp","\"a\" must be string");
|
builtin_err("cmp","\"a\" must be string");
|
||||||
|
@ -829,19 +829,19 @@ nasal_val* builtin_cmp(nasal_val* local_scope)
|
||||||
builtin_err("cmp","\"b\" must be string");
|
builtin_err("cmp","\"b\" must be string");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_num);
|
nasal_val* ret_addr=gc.gc_alloc(vm_num);
|
||||||
ret_addr->ptr.num=strcmp(a_addr->ptr.str->data(),b_addr->ptr.str->data());
|
ret_addr->ptr.num=strcmp(a_addr->ptr.str->data(),b_addr->ptr.str->data());
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
nasal_val* builtin_chr(nasal_val* local_scope)
|
nasal_val* builtin_chr(nasal_val* local_scope,nasal_gc& gc)
|
||||||
{
|
{
|
||||||
nasal_val* code_addr=in_builtin_find("code");
|
nasal_val* code_addr=builtin_find("code");
|
||||||
if(code_addr->type!=vm_num)
|
if(code_addr->type!=vm_num)
|
||||||
{
|
{
|
||||||
builtin_err("chr","\"code\" must be number");
|
builtin_err("chr","\"code\" must be number");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
nasal_val* ret_addr=gc_alloc(vm_str);
|
nasal_val* ret_addr=gc.gc_alloc(vm_str);
|
||||||
*ret_addr->ptr.str=(char)code_addr->ptr.num;
|
*ret_addr->ptr.str=(char)code_addr->ptr.num;
|
||||||
return ret_addr;
|
return ret_addr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ enum op_code
|
||||||
op_findex, // index counter on the top of forindex_stack plus 1
|
op_findex, // index counter on the top of forindex_stack plus 1
|
||||||
op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector
|
op_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector
|
||||||
op_call, // call identifier
|
op_call, // call identifier
|
||||||
|
op_callg,
|
||||||
|
op_calll,
|
||||||
op_callv, // call vec[index]
|
op_callv, // call vec[index]
|
||||||
op_callvi, // call vec[immediate] (used in multi-assign/multi-define)
|
op_callvi, // call vec[immediate] (used in multi-assign/multi-define)
|
||||||
op_callh, // call hash.label
|
op_callh, // call hash.label
|
||||||
|
@ -58,6 +60,8 @@ enum op_code
|
||||||
op_slc, // slice like vec[1]
|
op_slc, // slice like vec[1]
|
||||||
op_slc2, // slice like vec[nil:10]
|
op_slc2, // slice like vec[nil:10]
|
||||||
op_mcall, // get memory of identifier
|
op_mcall, // get memory of identifier
|
||||||
|
op_mcallg,
|
||||||
|
op_mcalll,
|
||||||
op_mcallv, // get memory of vec[index]
|
op_mcallv, // get memory of vec[index]
|
||||||
op_mcallh, // get memory of hash.label
|
op_mcallh, // get memory of hash.label
|
||||||
op_ret // return
|
op_ret // return
|
||||||
|
@ -114,6 +118,8 @@ struct
|
||||||
{op_findex, "findx "},
|
{op_findex, "findx "},
|
||||||
{op_feach, "feach "},
|
{op_feach, "feach "},
|
||||||
{op_call, "call "},
|
{op_call, "call "},
|
||||||
|
{op_callg, "callg "},
|
||||||
|
{op_calll, "calll "},
|
||||||
{op_callv, "callv "},
|
{op_callv, "callv "},
|
||||||
{op_callvi, "callvi"},
|
{op_callvi, "callvi"},
|
||||||
{op_callh, "callh "},
|
{op_callh, "callh "},
|
||||||
|
@ -124,6 +130,8 @@ struct
|
||||||
{op_slc, "slc "},
|
{op_slc, "slc "},
|
||||||
{op_slc2, "slc2 "},
|
{op_slc2, "slc2 "},
|
||||||
{op_mcall, "mcall "},
|
{op_mcall, "mcall "},
|
||||||
|
{op_mcallg, "mcallg"},
|
||||||
|
{op_mcalll, "mcalll"},
|
||||||
{op_mcallv, "mcallv"},
|
{op_mcallv, "mcallv"},
|
||||||
{op_mcallh, "mcallh"},
|
{op_mcallh, "mcallh"},
|
||||||
{op_ret, "ret "},
|
{op_ret, "ret "},
|
||||||
|
@ -154,16 +162,20 @@ private:
|
||||||
int error;
|
int error;
|
||||||
int in_forindex;
|
int in_forindex;
|
||||||
int in_foreach;
|
int in_foreach;
|
||||||
std::unordered_map<double,int> number_table;
|
std::unordered_map<double,int> number_table;
|
||||||
std::unordered_map<std::string,int> string_table;
|
std::unordered_map<std::string,int> string_table;
|
||||||
std::vector<double> num_res_table;
|
std::vector<double> num_res_table;
|
||||||
std::vector<std::string> str_res_table;
|
std::vector<std::string> str_res_table;
|
||||||
std::vector<opcode> exec_code;
|
std::vector<opcode> exec_code;
|
||||||
std::list<std::vector<int> > continue_ptr;
|
std::list<std::vector<int> > continue_ptr;
|
||||||
std::list<std::vector<int> > break_ptr;
|
std::list<std::vector<int> > break_ptr;
|
||||||
|
std::vector<std::string> global;
|
||||||
|
std::list<std::vector<std::string> > local;
|
||||||
|
|
||||||
void regist_number(double);
|
void regist_number(double);
|
||||||
void regist_string(std::string);
|
void regist_string(std::string&);
|
||||||
|
void add_sym(std::string&);
|
||||||
|
bool find_sym(std::string&);
|
||||||
void gen(unsigned char,unsigned int);
|
void gen(unsigned char,unsigned int);
|
||||||
void pop_gen();
|
void pop_gen();
|
||||||
void nil_gen();
|
void nil_gen();
|
||||||
|
@ -224,7 +236,7 @@ void nasal_codegen::regist_number(double num)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nasal_codegen::regist_string(std::string str)
|
void nasal_codegen::regist_string(std::string& str)
|
||||||
{
|
{
|
||||||
int size=string_table.size();
|
int size=string_table.size();
|
||||||
if(string_table.find(str)==string_table.end())
|
if(string_table.find(str)==string_table.end())
|
||||||
|
@ -232,6 +244,21 @@ void nasal_codegen::regist_string(std::string str)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nasal_codegen::add_sym(std::string&)
|
||||||
|
{
|
||||||
|
if(local.empty())
|
||||||
|
;
|
||||||
|
else
|
||||||
|
;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nasal_codegen::find_sym(std::string&)
|
||||||
|
{
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void nasal_codegen::gen(unsigned char op,unsigned int index)
|
void nasal_codegen::gen(unsigned char op,unsigned int index)
|
||||||
{
|
{
|
||||||
opcode opr(op,index);
|
opcode opr(op,index);
|
||||||
|
@ -334,7 +361,11 @@ void nasal_codegen::func_gen(nasal_ast& ast)
|
||||||
int ptr=exec_code.size();
|
int ptr=exec_code.size();
|
||||||
gen(op_jmp,0);
|
gen(op_jmp,0);
|
||||||
nasal_ast& block=ast.get_children()[1];
|
nasal_ast& block=ast.get_children()[1];
|
||||||
|
|
||||||
|
std::vector<std::string> new_scope;
|
||||||
|
local.push_front(new_scope);
|
||||||
block_gen(block);
|
block_gen(block);
|
||||||
|
local.pop_front();
|
||||||
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return)
|
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return)
|
||||||
{
|
{
|
||||||
nil_gen();
|
nil_gen();
|
||||||
|
|
90
nasal_gc.h
90
nasal_gc.h
|
@ -18,25 +18,6 @@ struct nasal_func;
|
||||||
struct nasal_scop;
|
struct nasal_scop;
|
||||||
struct nasal_val;
|
struct nasal_val;
|
||||||
|
|
||||||
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* global; // global scope address,type vm_scop
|
|
||||||
nasal_val** val_stack; // main stack
|
|
||||||
nasal_val** stack_top; // stack top
|
|
||||||
std::vector<nasal_val*> num_addrs; // reserved address for const vm_num
|
|
||||||
std::vector<nasal_val*> local; // local scope for function block
|
|
||||||
std::vector<nasal_val*> slice_stack; // slice stack for vec[val,val,val:val]
|
|
||||||
std::vector<nasal_val*> memory; // gc memory
|
|
||||||
std::queue<nasal_val*> free_list; // gc free list
|
|
||||||
|
|
||||||
/* gc functions */
|
|
||||||
void mark();
|
|
||||||
void sweep();
|
|
||||||
void gc_init();
|
|
||||||
void gc_clear();
|
|
||||||
nasal_val* gc_alloc(int);
|
|
||||||
|
|
||||||
struct nasal_vec
|
struct nasal_vec
|
||||||
{
|
{
|
||||||
std::vector<nasal_val*> elems;
|
std::vector<nasal_val*> elems;
|
||||||
|
@ -183,9 +164,9 @@ nasal_val** nasal_hash::get_mem(std::string& key)
|
||||||
int size=vec_ref.size();
|
int size=vec_ref.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
{
|
{
|
||||||
nasal_val* tmp_val_addr=vec_ref[i];
|
nasal_val* tmp=vec_ref[i];
|
||||||
if(tmp_val_addr->type==vm_hash)
|
if(tmp->type==vm_hash)
|
||||||
mem_addr=tmp_val_addr->ptr.hash->get_mem(key);
|
mem_addr=tmp->ptr.hash->get_mem(key);
|
||||||
if(mem_addr)
|
if(mem_addr)
|
||||||
return mem_addr;
|
return mem_addr;
|
||||||
}
|
}
|
||||||
|
@ -345,16 +326,37 @@ std::string nasal_val::to_string()
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark()
|
struct nasal_gc
|
||||||
|
{
|
||||||
|
#define STACK_MAX_DEPTH (65536<<4)
|
||||||
|
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* global; // global scope address,type vm_scop
|
||||||
|
nasal_val** val_stack; // main stack
|
||||||
|
nasal_val** stack_top; // stack top
|
||||||
|
std::vector<nasal_val*> num_addrs; // reserved address for const vm_num
|
||||||
|
std::vector<nasal_val*> local; // local scope for function block
|
||||||
|
std::vector<nasal_val*> slice_stack; // slice stack for vec[val,val,val:val]
|
||||||
|
std::vector<nasal_val*> memory; // gc memory
|
||||||
|
std::queue<nasal_val*> free_list; // gc free list
|
||||||
|
void mark();
|
||||||
|
void sweep();
|
||||||
|
void gc_init(std::vector<double>&);
|
||||||
|
void gc_clear();
|
||||||
|
nasal_val* gc_alloc(int);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* gc functions */
|
||||||
|
void nasal_gc::mark()
|
||||||
{
|
{
|
||||||
int size;
|
|
||||||
std::queue<nasal_val*> bfs;
|
std::queue<nasal_val*> bfs;
|
||||||
bfs.push(zero_addr);
|
bfs.push(zero_addr);
|
||||||
bfs.push(one_addr);
|
bfs.push(one_addr);
|
||||||
bfs.push(nil_addr);
|
bfs.push(nil_addr);
|
||||||
bfs.push(global);
|
bfs.push(global);
|
||||||
|
|
||||||
size=num_addrs.size();
|
int size=num_addrs.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
bfs.push(num_addrs[i]);
|
bfs.push(num_addrs[i]);
|
||||||
size=local.size();
|
size=local.size();
|
||||||
|
@ -406,7 +408,7 @@ void mark()
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void sweep()
|
void nasal_gc::sweep()
|
||||||
{
|
{
|
||||||
int size=memory.size();
|
int size=memory.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
|
@ -420,7 +422,7 @@ void sweep()
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void gc_init()
|
void nasal_gc::gc_init(std::vector<double>& nums)
|
||||||
{
|
{
|
||||||
for(int i=0;i<65536;++i)
|
for(int i=0;i<65536;++i)
|
||||||
{
|
{
|
||||||
|
@ -428,9 +430,35 @@ void gc_init()
|
||||||
memory.push_back(tmp);
|
memory.push_back(tmp);
|
||||||
free_list.push(tmp);
|
free_list.push(tmp);
|
||||||
}
|
}
|
||||||
|
val_stack=new nasal_val*[STACK_MAX_DEPTH]; // init runtime stack
|
||||||
|
stack_top=val_stack; // set stack_top to val_stack
|
||||||
|
|
||||||
|
zero_addr=new nasal_val(vm_num); // init constant 0
|
||||||
|
zero_addr->ptr.num=0;
|
||||||
|
memory.push_back(zero_addr);
|
||||||
|
|
||||||
|
one_addr=new nasal_val(vm_num); // init constant 1
|
||||||
|
one_addr->ptr.num=1;
|
||||||
|
memory.push_back(one_addr);
|
||||||
|
|
||||||
|
nil_addr=new nasal_val(vm_nil); // init nil
|
||||||
|
memory.push_back(nil_addr);
|
||||||
|
|
||||||
|
*val_stack=nil_addr; // the first space will not store any values,but gc checks
|
||||||
|
|
||||||
|
global=new nasal_val(vm_scop); // init global symbol table
|
||||||
|
memory.push_back(global);
|
||||||
|
|
||||||
|
num_addrs.clear(); // init constant numbers
|
||||||
|
for(int i=0;i<nums.size();++i)
|
||||||
|
{
|
||||||
|
nasal_val* tmp=new nasal_val(vm_num);
|
||||||
|
tmp->ptr.num=nums[i];
|
||||||
|
num_addrs.push_back(tmp);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void gc_clear()
|
void nasal_gc::gc_clear()
|
||||||
{
|
{
|
||||||
int size=memory.size();
|
int size=memory.size();
|
||||||
for(int i=0;i<size;++i)
|
for(int i=0;i<size;++i)
|
||||||
|
@ -441,9 +469,13 @@ void gc_clear()
|
||||||
memory.clear();
|
memory.clear();
|
||||||
while(!free_list.empty())
|
while(!free_list.empty())
|
||||||
free_list.pop();
|
free_list.pop();
|
||||||
|
global=nullptr;
|
||||||
|
delete []val_stack;
|
||||||
|
local.clear();
|
||||||
|
slice_stack.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nasal_val* gc_alloc(int type)
|
nasal_val* nasal_gc::gc_alloc(int type)
|
||||||
{
|
{
|
||||||
if(free_list.empty())
|
if(free_list.empty())
|
||||||
{
|
{
|
||||||
|
|
244
nasal_vm.h
244
nasal_vm.h
|
@ -1,21 +1,24 @@
|
||||||
#ifndef __NASAL_VM_H__
|
#ifndef __NASAL_VM_H__
|
||||||
#define __NASAL_VM_H__
|
#define __NASAL_VM_H__
|
||||||
#define STACK_MAX_DEPTH (65536<<4)
|
|
||||||
|
|
||||||
class nasal_vm
|
class nasal_vm
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> str_table; // symbols used in process
|
/* reference from nasal_gc */
|
||||||
bool loop_mark; // when mark is false,break the main loop
|
nasal_val**& stack_top; // stack top
|
||||||
int pc; // program counter
|
/* values of nasal_vm */
|
||||||
int me_index; // this is the index of "me" in str_table
|
int pc; // program counter
|
||||||
std::vector<opcode> exec_code; // byte codes store here
|
int me; // this is the index of "me" in str_table
|
||||||
std::stack<nasal_val**> addr_stack; // stack for mem_call
|
bool loop_mark; // when mark is false,break the main loop
|
||||||
std::stack<int> call_stack; // ptr stack stores address for function to return
|
std::stack<int> ret; // ptr stack stores address for function to return
|
||||||
std::stack<int> counter; // iterator stack for forindex/foreach
|
std::stack<int> counter; // iterator stack for forindex/foreach
|
||||||
|
std::vector<std::string> str_table; // symbols used in process
|
||||||
|
std::vector<opcode> exec_code; // byte codes store here
|
||||||
|
std::stack<nasal_val**> addr_stack; // stack for mem_call
|
||||||
|
nasal_gc gc; //garbage collector
|
||||||
|
|
||||||
void die(std::string);
|
void die(std::string);
|
||||||
bool check_condition(nasal_val*);
|
bool condition(nasal_val*);
|
||||||
void opr_nop();
|
void opr_nop();
|
||||||
void opr_load();
|
void opr_load();
|
||||||
void opr_loadg();
|
void opr_loadg();
|
||||||
|
@ -61,6 +64,8 @@ private:
|
||||||
void opr_findex();
|
void opr_findex();
|
||||||
void opr_feach();
|
void opr_feach();
|
||||||
void opr_call();
|
void opr_call();
|
||||||
|
void opr_callg();
|
||||||
|
void opr_calll();
|
||||||
void opr_callv();
|
void opr_callv();
|
||||||
void opr_callvi();
|
void opr_callvi();
|
||||||
void opr_callh();
|
void opr_callh();
|
||||||
|
@ -71,10 +76,13 @@ private:
|
||||||
void opr_slc();
|
void opr_slc();
|
||||||
void opr_slc2();
|
void opr_slc2();
|
||||||
void opr_mcall();
|
void opr_mcall();
|
||||||
|
void opr_mcallg();
|
||||||
|
void opr_mcalll();
|
||||||
void opr_mcallv();
|
void opr_mcallv();
|
||||||
void opr_mcallh();
|
void opr_mcallh();
|
||||||
void opr_ret();
|
void opr_ret();
|
||||||
public:
|
public:
|
||||||
|
nasal_vm();
|
||||||
void init(
|
void init(
|
||||||
std::vector<std::string>&,
|
std::vector<std::string>&,
|
||||||
std::vector<double>&,
|
std::vector<double>&,
|
||||||
|
@ -83,63 +91,36 @@ public:
|
||||||
void run();
|
void run();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nasal_vm::nasal_vm():stack_top(gc.stack_top)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void nasal_vm::init(
|
void nasal_vm::init(
|
||||||
std::vector<std::string>& strs,
|
std::vector<std::string>& strs,
|
||||||
std::vector<double>& nums,
|
std::vector<double>& nums,
|
||||||
std::vector<opcode>& exec)
|
std::vector<opcode>& exec)
|
||||||
{
|
{
|
||||||
gc_init();
|
gc.gc_init(nums);
|
||||||
str_table=strs; // get constant strings & symbols
|
str_table=strs; // get constant strings & symbols
|
||||||
exec_code=exec; // get bytecodes
|
exec_code=exec; // get bytecodes
|
||||||
|
|
||||||
val_stack=new nasal_val*[STACK_MAX_DEPTH]; // init runtime stack
|
builtin_use_str.clear(); // create map that builtin functions use
|
||||||
stack_top=val_stack; // set stack_top to val_stack
|
|
||||||
|
|
||||||
zero_addr=new nasal_val(vm_num); // init constant 0
|
|
||||||
zero_addr->ptr.num=0;
|
|
||||||
memory.push_back(zero_addr);
|
|
||||||
|
|
||||||
one_addr=new nasal_val(vm_num); // init constant 1
|
|
||||||
one_addr->ptr.num=1;
|
|
||||||
memory.push_back(one_addr);
|
|
||||||
|
|
||||||
nil_addr=new nasal_val(vm_nil); // init nil
|
|
||||||
memory.push_back(nil_addr);
|
|
||||||
|
|
||||||
*val_stack=nil_addr; // the first space will not store any values,but gc checks
|
|
||||||
|
|
||||||
num_addrs.clear(); // init constant numbers
|
|
||||||
for(int i=0;i<nums.size();++i)
|
|
||||||
{
|
|
||||||
nasal_val* tmp=new nasal_val(vm_num);
|
|
||||||
tmp->ptr.num=nums[i];
|
|
||||||
num_addrs.push_back(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
builtin_use_str_table.clear(); // create map that builtin functions use
|
|
||||||
for(int i=0;i<str_table.size();++i)
|
for(int i=0;i<str_table.size();++i)
|
||||||
builtin_use_str_table[str_table[i]]=i;
|
builtin_use_str[str_table[i]]=i;
|
||||||
me_index=builtin_use_str_table.count("me")?builtin_use_str_table["me"]:-1; // get symbol index of 'me'
|
me=builtin_use_str.count("me")?builtin_use_str["me"]:-1; // get symbol index of 'me'
|
||||||
|
|
||||||
loop_mark=true; // set loop mark to true
|
loop_mark=true; // set loop mark to true
|
||||||
|
|
||||||
global=new nasal_val(vm_scop); // init global symbol table
|
|
||||||
memory.push_back(global);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::clear()
|
void nasal_vm::clear()
|
||||||
{
|
{
|
||||||
gc_clear();
|
gc.gc_clear();
|
||||||
|
|
||||||
global=nullptr; // set global to null
|
|
||||||
|
|
||||||
delete []val_stack; // free runtime stack
|
|
||||||
while(!addr_stack.empty())
|
while(!addr_stack.empty())
|
||||||
addr_stack.pop();
|
addr_stack.pop();
|
||||||
local.clear();
|
while(!ret.empty())
|
||||||
slice_stack.clear();
|
ret.pop();
|
||||||
while(!call_stack.empty())
|
|
||||||
call_stack.pop();
|
|
||||||
while(!counter.empty())
|
while(!counter.empty())
|
||||||
counter.pop();
|
counter.pop();
|
||||||
str_table.clear();
|
str_table.clear();
|
||||||
|
@ -152,7 +133,7 @@ void nasal_vm::die(std::string str)
|
||||||
loop_mark=false;
|
loop_mark=false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool nasal_vm::check_condition(nasal_val* value_addr)
|
bool nasal_vm::condition(nasal_val* value_addr)
|
||||||
{
|
{
|
||||||
int type=value_addr->type;
|
int type=value_addr->type;
|
||||||
if(type==vm_num)
|
if(type==vm_num)
|
||||||
|
@ -175,65 +156,64 @@ void nasal_vm::opr_nop()
|
||||||
void nasal_vm::opr_load()
|
void nasal_vm::opr_load()
|
||||||
{
|
{
|
||||||
nasal_val* val=*stack_top--;
|
nasal_val* val=*stack_top--;
|
||||||
(local.empty()?global:local.back())->ptr.scop->elems[exec_code[pc].num]=val;
|
(gc.local.empty()?gc.global:gc.local.back())->ptr.scop->elems[exec_code[pc].num]=val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_loadg()
|
void nasal_vm::opr_loadg()
|
||||||
{
|
{
|
||||||
global->ptr.scop->elems[exec_code[pc].num]=*stack_top--;
|
gc.global->ptr.scop->elems[exec_code[pc].num]=*stack_top--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_loadl()
|
void nasal_vm::opr_loadl()
|
||||||
{
|
{
|
||||||
local.back()->ptr.scop->elems[exec_code[pc].num]=*stack_top--;
|
gc.local.back()->ptr.scop->elems[exec_code[pc].num]=*stack_top--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_pnum()
|
void nasal_vm::opr_pnum()
|
||||||
{
|
{
|
||||||
nasal_val* val=num_addrs[exec_code[pc].num];
|
*(++stack_top)=gc.num_addrs[exec_code[pc].num];
|
||||||
*(++stack_top)=val;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_pone()
|
void nasal_vm::opr_pone()
|
||||||
{
|
{
|
||||||
*(++stack_top)=one_addr;
|
*(++stack_top)=gc.one_addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_pzero()
|
void nasal_vm::opr_pzero()
|
||||||
{
|
{
|
||||||
*(++stack_top)=zero_addr;
|
*(++stack_top)=gc.zero_addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_pnil()
|
void nasal_vm::opr_pnil()
|
||||||
{
|
{
|
||||||
*(++stack_top)=nil_addr;
|
*(++stack_top)=gc.nil_addr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_pstr()
|
void nasal_vm::opr_pstr()
|
||||||
{
|
{
|
||||||
nasal_val* val=gc_alloc(vm_str);
|
nasal_val* val=gc.gc_alloc(vm_str);
|
||||||
*val->ptr.str=str_table[exec_code[pc].num];
|
*val->ptr.str=str_table[exec_code[pc].num];
|
||||||
*(++stack_top)=val;
|
*(++stack_top)=val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_newv()
|
void nasal_vm::opr_newv()
|
||||||
{
|
{
|
||||||
nasal_val* vec=gc_alloc(vm_vec);
|
nasal_val* vec=gc.gc_alloc(vm_vec);
|
||||||
*(++stack_top)=vec;
|
*(++stack_top)=vec;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_newh()
|
void nasal_vm::opr_newh()
|
||||||
{
|
{
|
||||||
nasal_val* hash=gc_alloc(vm_hash);
|
nasal_val* hash=gc.gc_alloc(vm_hash);
|
||||||
*(++stack_top)=hash;
|
*(++stack_top)=hash;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_newf()
|
void nasal_vm::opr_newf()
|
||||||
{
|
{
|
||||||
nasal_val* val=gc_alloc(vm_func);
|
nasal_val* val=gc.gc_alloc(vm_func);
|
||||||
val->ptr.func->entry=exec_code[pc].num;
|
val->ptr.func->entry=exec_code[pc].num;
|
||||||
if(!local.empty())
|
if(!gc.local.empty())
|
||||||
val->ptr.func->closure=local.back()->ptr.scop->elems;
|
val->ptr.func->closure=gc.local.back()->ptr.scop->elems;
|
||||||
*(++stack_top)=val;
|
*(++stack_top)=val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -273,16 +253,16 @@ void nasal_vm::opr_unot()
|
||||||
nasal_val* new_val=nullptr;
|
nasal_val* new_val=nullptr;
|
||||||
int type=val->type;
|
int type=val->type;
|
||||||
if(type==vm_nil)
|
if(type==vm_nil)
|
||||||
new_val=one_addr;
|
new_val=gc.one_addr;
|
||||||
else if(type==vm_num)
|
else if(type==vm_num)
|
||||||
new_val=val->ptr.num?zero_addr:one_addr;
|
new_val=val->ptr.num?gc.zero_addr:gc.one_addr;
|
||||||
else if(type==vm_str)
|
else if(type==vm_str)
|
||||||
{
|
{
|
||||||
double number=trans_string_to_number(*val->ptr.str);
|
double number=trans_string_to_number(*val->ptr.str);
|
||||||
if(std::isnan(number))
|
if(std::isnan(number))
|
||||||
new_val=val->ptr.str->length()?zero_addr:one_addr;
|
new_val=val->ptr.str->length()?gc.zero_addr:gc.one_addr;
|
||||||
else
|
else
|
||||||
new_val=number?zero_addr:one_addr;
|
new_val=number?gc.zero_addr:gc.one_addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
die("unot: incorrect value type");
|
die("unot: incorrect value type");
|
||||||
|
@ -292,14 +272,14 @@ void nasal_vm::opr_unot()
|
||||||
void nasal_vm::opr_usub()
|
void nasal_vm::opr_usub()
|
||||||
{
|
{
|
||||||
nasal_val* val=*stack_top;
|
nasal_val* val=*stack_top;
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
new_val->ptr.num=-val->to_number();
|
new_val->ptr.num=-val->to_number();
|
||||||
*stack_top=new_val;
|
*stack_top=new_val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_add()
|
void nasal_vm::opr_add()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
new_val->ptr.num=val1->to_number()+val2->to_number();
|
new_val->ptr.num=val1->to_number()+val2->to_number();
|
||||||
|
@ -308,7 +288,7 @@ void nasal_vm::opr_add()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_sub()
|
void nasal_vm::opr_sub()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
new_val->ptr.num=val1->to_number()-val2->to_number();
|
new_val->ptr.num=val1->to_number()-val2->to_number();
|
||||||
|
@ -317,7 +297,7 @@ void nasal_vm::opr_sub()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_mul()
|
void nasal_vm::opr_mul()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
new_val->ptr.num=val1->to_number()*val2->to_number();
|
new_val->ptr.num=val1->to_number()*val2->to_number();
|
||||||
|
@ -326,7 +306,7 @@ void nasal_vm::opr_mul()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_div()
|
void nasal_vm::opr_div()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
new_val->ptr.num=val1->to_number()/val2->to_number();
|
new_val->ptr.num=val1->to_number()/val2->to_number();
|
||||||
|
@ -335,7 +315,7 @@ void nasal_vm::opr_div()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_lnk()
|
void nasal_vm::opr_lnk()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_str);
|
nasal_val* new_val=gc.gc_alloc(vm_str);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
*new_val->ptr.str=val1->to_string()+val2->to_string();
|
*new_val->ptr.str=val1->to_string()+val2->to_string();
|
||||||
|
@ -348,7 +328,7 @@ void nasal_vm::opr_addeq()
|
||||||
addr_stack.pop();
|
addr_stack.pop();
|
||||||
nasal_val* val2=*stack_top;
|
nasal_val* val2=*stack_top;
|
||||||
nasal_val* val1=*mem_addr;
|
nasal_val* val1=*mem_addr;
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
new_val->ptr.num=val1->to_number()+val2->to_number();
|
new_val->ptr.num=val1->to_number()+val2->to_number();
|
||||||
*stack_top=new_val;
|
*stack_top=new_val;
|
||||||
*mem_addr=new_val;
|
*mem_addr=new_val;
|
||||||
|
@ -360,7 +340,7 @@ void nasal_vm::opr_subeq()
|
||||||
addr_stack.pop();
|
addr_stack.pop();
|
||||||
nasal_val* val2=*stack_top;
|
nasal_val* val2=*stack_top;
|
||||||
nasal_val* val1=*mem_addr;
|
nasal_val* val1=*mem_addr;
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
new_val->ptr.num=val1->to_number()-val2->to_number();
|
new_val->ptr.num=val1->to_number()-val2->to_number();
|
||||||
*stack_top=new_val;
|
*stack_top=new_val;
|
||||||
*mem_addr=new_val;
|
*mem_addr=new_val;
|
||||||
|
@ -372,7 +352,7 @@ void nasal_vm::opr_muleq()
|
||||||
addr_stack.pop();
|
addr_stack.pop();
|
||||||
nasal_val* val2=*stack_top;
|
nasal_val* val2=*stack_top;
|
||||||
nasal_val* val1=*mem_addr;
|
nasal_val* val1=*mem_addr;
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
new_val->ptr.num=val1->to_number()*val2->to_number();
|
new_val->ptr.num=val1->to_number()*val2->to_number();
|
||||||
*stack_top=new_val;
|
*stack_top=new_val;
|
||||||
*mem_addr=new_val;
|
*mem_addr=new_val;
|
||||||
|
@ -384,7 +364,7 @@ void nasal_vm::opr_diveq()
|
||||||
addr_stack.pop();
|
addr_stack.pop();
|
||||||
nasal_val* val2=*stack_top;
|
nasal_val* val2=*stack_top;
|
||||||
nasal_val* val1=*mem_addr;
|
nasal_val* val1=*mem_addr;
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
new_val->ptr.num=val1->to_number()/val2->to_number();
|
new_val->ptr.num=val1->to_number()/val2->to_number();
|
||||||
*stack_top=new_val;
|
*stack_top=new_val;
|
||||||
*mem_addr=new_val;
|
*mem_addr=new_val;
|
||||||
|
@ -396,7 +376,7 @@ void nasal_vm::opr_lnkeq()
|
||||||
addr_stack.pop();
|
addr_stack.pop();
|
||||||
nasal_val* val2=*stack_top;
|
nasal_val* val2=*stack_top;
|
||||||
nasal_val* val1=*mem_addr;
|
nasal_val* val1=*mem_addr;
|
||||||
nasal_val* new_val=gc_alloc(vm_str);
|
nasal_val* new_val=gc.gc_alloc(vm_str);
|
||||||
*new_val->ptr.str=val1->to_string()+val2->to_string();
|
*new_val->ptr.str=val1->to_string()+val2->to_string();
|
||||||
*stack_top=new_val;
|
*stack_top=new_val;
|
||||||
*mem_addr=new_val;
|
*mem_addr=new_val;
|
||||||
|
@ -412,13 +392,13 @@ void nasal_vm::opr_meq()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_eq()
|
void nasal_vm::opr_eq()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
int a_type=val1->type;
|
||||||
int b_type=val2->type;
|
int b_type=val2->type;
|
||||||
if(a_type==vm_nil && b_type==vm_nil)
|
if(a_type==vm_nil && b_type==vm_nil)
|
||||||
*stack_top=one_addr;
|
*stack_top=gc.one_addr;
|
||||||
else if(a_type==vm_str && b_type==vm_str)
|
else if(a_type==vm_str && b_type==vm_str)
|
||||||
{
|
{
|
||||||
new_val->ptr.num=(*val1->ptr.str==*val2->ptr.str);
|
new_val->ptr.num=(*val1->ptr.str==*val2->ptr.str);
|
||||||
|
@ -438,13 +418,13 @@ void nasal_vm::opr_eq()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_neq()
|
void nasal_vm::opr_neq()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
int a_type=val1->type;
|
||||||
int b_type=val2->type;
|
int b_type=val2->type;
|
||||||
if(a_type==vm_nil && b_type==vm_nil)
|
if(a_type==vm_nil && b_type==vm_nil)
|
||||||
*stack_top=zero_addr;
|
*stack_top=gc.zero_addr;
|
||||||
else if(a_type==vm_str && b_type==vm_str)
|
else if(a_type==vm_str && b_type==vm_str)
|
||||||
{
|
{
|
||||||
new_val->ptr.num=(*val1->ptr.str!=*val2->ptr.str);
|
new_val->ptr.num=(*val1->ptr.str!=*val2->ptr.str);
|
||||||
|
@ -464,7 +444,7 @@ void nasal_vm::opr_neq()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_less()
|
void nasal_vm::opr_less()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
int a_type=val1->type;
|
||||||
|
@ -478,7 +458,7 @@ void nasal_vm::opr_less()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_leq()
|
void nasal_vm::opr_leq()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
int a_type=val1->type;
|
||||||
|
@ -492,7 +472,7 @@ void nasal_vm::opr_leq()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_grt()
|
void nasal_vm::opr_grt()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
int a_type=val1->type;
|
||||||
|
@ -506,7 +486,7 @@ void nasal_vm::opr_grt()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_geq()
|
void nasal_vm::opr_geq()
|
||||||
{
|
{
|
||||||
nasal_val* new_val=gc_alloc(vm_num);
|
nasal_val* new_val=gc.gc_alloc(vm_num);
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top;
|
nasal_val* val1=*stack_top;
|
||||||
int a_type=val1->type;
|
int a_type=val1->type;
|
||||||
|
@ -530,13 +510,13 @@ void nasal_vm::opr_jmp()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_jt()
|
void nasal_vm::opr_jt()
|
||||||
{
|
{
|
||||||
if(check_condition(*stack_top))
|
if(condition(*stack_top))
|
||||||
pc=exec_code[pc].num-1;
|
pc=exec_code[pc].num-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_jf()
|
void nasal_vm::opr_jf()
|
||||||
{
|
{
|
||||||
if(!check_condition(*stack_top))
|
if(!condition(*stack_top))
|
||||||
pc=exec_code[pc].num-1;
|
pc=exec_code[pc].num-1;
|
||||||
--stack_top;
|
--stack_top;
|
||||||
return;
|
return;
|
||||||
|
@ -563,7 +543,7 @@ void nasal_vm::opr_findex()
|
||||||
pc=exec_code[pc].num-1;
|
pc=exec_code[pc].num-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nasal_val* res=gc_alloc(vm_num);
|
nasal_val* res=gc.gc_alloc(vm_num);
|
||||||
res->ptr.num=counter.top();
|
res->ptr.num=counter.top();
|
||||||
*(++stack_top)=res;
|
*(++stack_top)=res;
|
||||||
return;
|
return;
|
||||||
|
@ -585,14 +565,14 @@ void nasal_vm::opr_call()
|
||||||
{
|
{
|
||||||
nasal_val* val=nullptr;
|
nasal_val* val=nullptr;
|
||||||
int name_index=exec_code[pc].num;
|
int name_index=exec_code[pc].num;
|
||||||
if(!local.empty())
|
if(!gc.local.empty())
|
||||||
val=local.back()->ptr.scop->get_val(name_index);
|
val=gc.local.back()->ptr.scop->get_val(name_index);
|
||||||
if(val)
|
if(val)
|
||||||
{
|
{
|
||||||
*(++stack_top)=val;
|
*(++stack_top)=val;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
val=global->ptr.scop->get_val(name_index);
|
val=gc.global->ptr.scop->get_val(name_index);
|
||||||
if(val)
|
if(val)
|
||||||
{
|
{
|
||||||
*(++stack_top)=val;
|
*(++stack_top)=val;
|
||||||
|
@ -601,6 +581,16 @@ void nasal_vm::opr_call()
|
||||||
die("call: cannot find symbol named \""+str_table[name_index]+"\"");
|
die("call: cannot find symbol named \""+str_table[name_index]+"\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
void nasal_vm::opr_callg()
|
||||||
|
{
|
||||||
|
*(++stack_top)=gc.global->ptr.scop->elems[exec_code[pc].num];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void nasal_vm::opr_calll()
|
||||||
|
{
|
||||||
|
*(++stack_top)=gc.local.back()->ptr.scop->elems[exec_code[pc].num];
|
||||||
|
return;
|
||||||
|
}
|
||||||
void nasal_vm::opr_callv()
|
void nasal_vm::opr_callv()
|
||||||
{
|
{
|
||||||
nasal_val* val=*stack_top--;
|
nasal_val* val=*stack_top--;
|
||||||
|
@ -632,7 +622,7 @@ void nasal_vm::opr_callv()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(res->type==vm_func)
|
if(res->type==vm_func)
|
||||||
res->ptr.func->closure[me_index]=val;
|
res->ptr.func->closure[me]=val;
|
||||||
*stack_top=res;
|
*stack_top=res;
|
||||||
}
|
}
|
||||||
else if(type==vm_str)
|
else if(type==vm_str)
|
||||||
|
@ -645,7 +635,7 @@ void nasal_vm::opr_callv()
|
||||||
die("callv: index out of range");
|
die("callv: index out of range");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nasal_val* res=gc_alloc(vm_num);
|
nasal_val* res=gc.gc_alloc(vm_num);
|
||||||
res->ptr.num=(str[num>=0? num:num+str_size]);
|
res->ptr.num=(str[num>=0? num:num+str_size]);
|
||||||
*stack_top=res;
|
*stack_top=res;
|
||||||
}
|
}
|
||||||
|
@ -686,7 +676,7 @@ void nasal_vm::opr_callh()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(res->type==vm_func)
|
if(res->type==vm_func)
|
||||||
res->ptr.func->closure[me_index]=val;
|
res->ptr.func->closure[me]=val;
|
||||||
*stack_top=res;
|
*stack_top=res;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -701,8 +691,8 @@ void nasal_vm::opr_callf()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// push new local scope
|
// push new local scope
|
||||||
nasal_val* closure=gc_alloc(vm_scop);
|
nasal_val* closure=gc.gc_alloc(vm_scop);
|
||||||
local.push_back(closure);
|
gc.local.push_back(closure);
|
||||||
// load parameters
|
// load parameters
|
||||||
nasal_func& ref_func=*func_addr->ptr.func;
|
nasal_func& ref_func=*func_addr->ptr.func;
|
||||||
std::vector<int>& ref_para=ref_func.para;
|
std::vector<int>& ref_para=ref_func.para;
|
||||||
|
@ -731,7 +721,7 @@ void nasal_vm::opr_callf()
|
||||||
}
|
}
|
||||||
if(ref_func.dynpara>=0)
|
if(ref_func.dynpara>=0)
|
||||||
{
|
{
|
||||||
nasal_val* vec_addr=gc_alloc(vm_vec);
|
nasal_val* vec_addr=gc.gc_alloc(vm_vec);
|
||||||
for(int i=para_size;i<vec_size;++i)
|
for(int i=para_size;i<vec_size;++i)
|
||||||
vec_addr->ptr.vec->elems.push_back(ref_vec[i]);
|
vec_addr->ptr.vec->elems.push_back(ref_vec[i]);
|
||||||
ref_closure[ref_func.dynpara]=vec_addr;
|
ref_closure[ref_func.dynpara]=vec_addr;
|
||||||
|
@ -760,28 +750,28 @@ void nasal_vm::opr_callf()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
--stack_top;
|
--stack_top;
|
||||||
call_stack.push(pc);
|
ret.push(pc);
|
||||||
pc=ref_func.entry-1;
|
pc=ref_func.entry-1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_callb()
|
void nasal_vm::opr_callb()
|
||||||
{
|
{
|
||||||
nasal_val* res=(*builtin_func[exec_code[pc].num].func)(local.back());
|
nasal_val* res=(*builtin_func[exec_code[pc].num].func)(gc.local.back(),gc);
|
||||||
*(++stack_top)=res;
|
*(++stack_top)=res;
|
||||||
loop_mark=res;
|
loop_mark=res;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_slcbegin()
|
void nasal_vm::opr_slcbegin()
|
||||||
{
|
{
|
||||||
slice_stack.push_back(gc_alloc(vm_vec));
|
gc.slice_stack.push_back(gc.gc_alloc(vm_vec));
|
||||||
if((*stack_top)->type!=vm_vec)
|
if((*stack_top)->type!=vm_vec)
|
||||||
die("slcbegin: must slice a vector");
|
die("slcbegin: must slice a vector");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_slcend()
|
void nasal_vm::opr_slcend()
|
||||||
{
|
{
|
||||||
*stack_top=slice_stack.back();
|
*stack_top=gc.slice_stack.back();
|
||||||
slice_stack.pop_back();
|
gc.slice_stack.pop_back();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_slc()
|
void nasal_vm::opr_slc()
|
||||||
|
@ -796,7 +786,7 @@ void nasal_vm::opr_slc()
|
||||||
}
|
}
|
||||||
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
|
nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num);
|
||||||
if(res)
|
if(res)
|
||||||
slice_stack.back()->ptr.vec->elems.push_back(res);
|
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
|
||||||
else
|
else
|
||||||
die("slc: index out of range");
|
die("slc: index out of range");
|
||||||
return;
|
return;
|
||||||
|
@ -806,7 +796,7 @@ void nasal_vm::opr_slc2()
|
||||||
nasal_val* val2=*stack_top--;
|
nasal_val* val2=*stack_top--;
|
||||||
nasal_val* val1=*stack_top--;
|
nasal_val* val1=*stack_top--;
|
||||||
std::vector<nasal_val*>& ref=(*stack_top)->ptr.vec->elems;
|
std::vector<nasal_val*>& ref=(*stack_top)->ptr.vec->elems;
|
||||||
std::vector<nasal_val*>& aim=slice_stack.back()->ptr.vec->elems;
|
std::vector<nasal_val*>& aim=gc.slice_stack.back()->ptr.vec->elems;
|
||||||
|
|
||||||
int type1=val1->type,type2=val2->type;
|
int type1=val1->type,type2=val2->type;
|
||||||
int num1=val1->to_number();
|
int num1=val1->to_number();
|
||||||
|
@ -833,24 +823,21 @@ void nasal_vm::opr_slc2()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(int i=num1;i<=num2;++i)
|
for(int i=num1;i<=num2;++i)
|
||||||
{
|
aim.push_back(ref[i]);
|
||||||
nasal_val* tmp=ref[i];
|
|
||||||
aim.push_back(tmp);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_mcall()
|
void nasal_vm::opr_mcall()
|
||||||
{
|
{
|
||||||
nasal_val** mem_addr=nullptr;
|
nasal_val** mem_addr=nullptr;
|
||||||
int name_index=exec_code[pc].num;
|
int name_index=exec_code[pc].num;
|
||||||
if(!local.empty())
|
if(!gc.local.empty())
|
||||||
mem_addr=local.back()->ptr.scop->get_mem(name_index);
|
mem_addr=gc.local.back()->ptr.scop->get_mem(name_index);
|
||||||
if(mem_addr)
|
if(mem_addr)
|
||||||
{
|
{
|
||||||
addr_stack.push(mem_addr);
|
addr_stack.push(mem_addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mem_addr=global->ptr.scop->get_mem(name_index);
|
mem_addr=gc.global->ptr.scop->get_mem(name_index);
|
||||||
if(mem_addr)
|
if(mem_addr)
|
||||||
{
|
{
|
||||||
addr_stack.push(mem_addr);
|
addr_stack.push(mem_addr);
|
||||||
|
@ -859,6 +846,16 @@ void nasal_vm::opr_mcall()
|
||||||
die("mcall: cannot find symbol named \""+str_table[name_index]+"\"");
|
die("mcall: cannot find symbol named \""+str_table[name_index]+"\"");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
void nasal_vm::opr_mcallg()
|
||||||
|
{
|
||||||
|
addr_stack.push(&gc.global->ptr.scop->elems[exec_code[pc].num]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void nasal_vm::opr_mcalll()
|
||||||
|
{
|
||||||
|
addr_stack.push(&gc.local.back()->ptr.scop->elems[exec_code[pc].num]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
void nasal_vm::opr_mcallv()
|
void nasal_vm::opr_mcallv()
|
||||||
{
|
{
|
||||||
nasal_val* val=*stack_top--;
|
nasal_val* val=*stack_top--;
|
||||||
|
@ -890,11 +887,11 @@ void nasal_vm::opr_mcallv()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nasal_hash& ref=*(*vec_addr)->ptr.hash;
|
nasal_hash& ref=*(*vec_addr)->ptr.hash;
|
||||||
std::string str=*val->ptr.str;
|
std::string& str=*val->ptr.str;
|
||||||
nasal_val** res=ref.get_mem(str);
|
nasal_val** res=ref.get_mem(str);
|
||||||
if(!res)
|
if(!res)
|
||||||
{
|
{
|
||||||
ref.elems[str]=nil_addr;
|
ref.elems[str]=gc.nil_addr;
|
||||||
res=ref.get_mem(str);
|
res=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
addr_stack.push(res);
|
addr_stack.push(res);
|
||||||
|
@ -921,7 +918,7 @@ void nasal_vm::opr_mcallh()
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
if(!mem_addr) // create a new key
|
if(!mem_addr) // create a new key
|
||||||
{
|
{
|
||||||
ref.elems[str]=nil_addr;
|
ref.elems[str]=gc.nil_addr;
|
||||||
mem_addr=ref.get_mem(str);
|
mem_addr=ref.get_mem(str);
|
||||||
}
|
}
|
||||||
addr_stack.push(mem_addr);
|
addr_stack.push(mem_addr);
|
||||||
|
@ -929,9 +926,9 @@ void nasal_vm::opr_mcallh()
|
||||||
}
|
}
|
||||||
void nasal_vm::opr_ret()
|
void nasal_vm::opr_ret()
|
||||||
{
|
{
|
||||||
local.pop_back();
|
gc.local.pop_back();
|
||||||
pc=call_stack.top();
|
pc=ret.top();
|
||||||
call_stack.pop();
|
ret.pop();
|
||||||
nasal_val* ret_val=*stack_top--;
|
nasal_val* ret_val=*stack_top--;
|
||||||
*stack_top=ret_val;
|
*stack_top=ret_val;
|
||||||
return;
|
return;
|
||||||
|
@ -985,6 +982,8 @@ void nasal_vm::run()
|
||||||
&nasal_vm::opr_findex,
|
&nasal_vm::opr_findex,
|
||||||
&nasal_vm::opr_feach,
|
&nasal_vm::opr_feach,
|
||||||
&nasal_vm::opr_call,
|
&nasal_vm::opr_call,
|
||||||
|
&nasal_vm::opr_callg,
|
||||||
|
&nasal_vm::opr_calll,
|
||||||
&nasal_vm::opr_callv,
|
&nasal_vm::opr_callv,
|
||||||
&nasal_vm::opr_callvi,
|
&nasal_vm::opr_callvi,
|
||||||
&nasal_vm::opr_callh,
|
&nasal_vm::opr_callh,
|
||||||
|
@ -995,6 +994,8 @@ void nasal_vm::run()
|
||||||
&nasal_vm::opr_slc,
|
&nasal_vm::opr_slc,
|
||||||
&nasal_vm::opr_slc2,
|
&nasal_vm::opr_slc2,
|
||||||
&nasal_vm::opr_mcall,
|
&nasal_vm::opr_mcall,
|
||||||
|
&nasal_vm::opr_mcallg,
|
||||||
|
&nasal_vm::opr_mcalll,
|
||||||
&nasal_vm::opr_mcallv,
|
&nasal_vm::opr_mcallv,
|
||||||
&nasal_vm::opr_mcallh,
|
&nasal_vm::opr_mcallh,
|
||||||
&nasal_vm::opr_ret
|
&nasal_vm::opr_ret
|
||||||
|
@ -1003,7 +1004,6 @@ void nasal_vm::run()
|
||||||
// main loop
|
// main loop
|
||||||
for(pc=0;loop_mark;++pc)
|
for(pc=0;loop_mark;++pc)
|
||||||
(this->*opr_table[exec_code[pc].op])();
|
(this->*opr_table[exec_code[pc].op])();
|
||||||
|
|
||||||
float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC;
|
float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC;
|
||||||
std::cout<<">> [vm] process exited after "<<total_time<<"s.\n";
|
std::cout<<">> [vm] process exited after "<<total_time<<"s.\n";
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -137,7 +137,7 @@ while(error>0.001)
|
||||||
}
|
}
|
||||||
cnt+=1;
|
cnt+=1;
|
||||||
show+=1;
|
show+=1;
|
||||||
if(show==150)
|
if(show==200)
|
||||||
{
|
{
|
||||||
show=0;
|
show=0;
|
||||||
print('epoch ',cnt,':',error,'\r');
|
print('epoch ',cnt,':',error,'\r');
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import("lib.nas");
|
||||||
|
|
||||||
|
var t=1;
|
||||||
|
var res=0;
|
||||||
|
for(var m=1;m<1e6;m+=2)
|
||||||
|
{
|
||||||
|
res+=t*1/m;
|
||||||
|
t*=-1;
|
||||||
|
}
|
||||||
|
println(res*4);
|
Loading…
Reference in New Issue