change id name & add test file

This commit is contained in:
Valk Richard Li 2021-03-30 00:12:48 +08:00
parent be1bcdfe2c
commit c7316e9780
6 changed files with 421 additions and 348 deletions

View File

@ -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;
} }

View File

@ -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();

View File

@ -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())
{ {

View File

@ -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;

View File

@ -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');

10
test/pi.nas Normal file
View File

@ -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);