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
*/
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
#define in_builtin_find(val_name) \
#define builtin_find(name) \
(\
local_scope\
->ptr.scop\
->get_val\
(builtin_use_str_table[val_name])\
(builtin_use_str[name])\
)
// declaration of builtin functions
// to add new builtin function,declare it here and write the definition below
nasal_val* builtin_print(nasal_val*);
nasal_val* builtin_append(nasal_val*);
nasal_val* builtin_setsize(nasal_val*);
nasal_val* builtin_system(nasal_val*);
nasal_val* builtin_input(nasal_val*);
nasal_val* builtin_sleep(nasal_val*);
nasal_val* builtin_fin(nasal_val*);
nasal_val* builtin_fout(nasal_val*);
nasal_val* builtin_split(nasal_val*);
nasal_val* builtin_rand(nasal_val*);
nasal_val* builtin_id(nasal_val*);
nasal_val* builtin_int(nasal_val*);
nasal_val* builtin_num(nasal_val*);
nasal_val* builtin_pop(nasal_val*);
nasal_val* builtin_str(nasal_val*);
nasal_val* builtin_size(nasal_val*);
nasal_val* builtin_xor(nasal_val*);
nasal_val* builtin_and(nasal_val*);
nasal_val* builtin_or(nasal_val*);
nasal_val* builtin_nand(nasal_val*);
nasal_val* builtin_not(nasal_val*);
nasal_val* builtin_sin(nasal_val*);
nasal_val* builtin_cos(nasal_val*);
nasal_val* builtin_tan(nasal_val*);
nasal_val* builtin_exp(nasal_val*);
nasal_val* builtin_ln(nasal_val*);
nasal_val* builtin_sqrt(nasal_val*);
nasal_val* builtin_atan2(nasal_val*);
nasal_val* builtin_time(nasal_val*);
nasal_val* builtin_contains(nasal_val*);
nasal_val* builtin_delete(nasal_val*);
nasal_val* builtin_getkeys(nasal_val*);
nasal_val* builtin_import(nasal_val*);
nasal_val* builtin_die(nasal_val*);
nasal_val* builtin_type(nasal_val*);
nasal_val* builtin_substr(nasal_val*);
nasal_val* builtin_streq(nasal_val*);
nasal_val* builtin_left(nasal_val*);
nasal_val* builtin_right(nasal_val*);
nasal_val* builtin_cmp(nasal_val*);
nasal_val* builtin_chr(nasal_val*);
nasal_val* builtin_print(nasal_val*,nasal_gc&);
nasal_val* builtin_append(nasal_val*,nasal_gc&);
nasal_val* builtin_setsize(nasal_val*,nasal_gc&);
nasal_val* builtin_system(nasal_val*,nasal_gc&);
nasal_val* builtin_input(nasal_val*,nasal_gc&);
nasal_val* builtin_sleep(nasal_val*,nasal_gc&);
nasal_val* builtin_fin(nasal_val*,nasal_gc&);
nasal_val* builtin_fout(nasal_val*,nasal_gc&);
nasal_val* builtin_split(nasal_val*,nasal_gc&);
nasal_val* builtin_rand(nasal_val*,nasal_gc&);
nasal_val* builtin_id(nasal_val*,nasal_gc&);
nasal_val* builtin_int(nasal_val*,nasal_gc&);
nasal_val* builtin_num(nasal_val*,nasal_gc&);
nasal_val* builtin_pop(nasal_val*,nasal_gc&);
nasal_val* builtin_str(nasal_val*,nasal_gc&);
nasal_val* builtin_size(nasal_val*,nasal_gc&);
nasal_val* builtin_xor(nasal_val*,nasal_gc&);
nasal_val* builtin_and(nasal_val*,nasal_gc&);
nasal_val* builtin_or(nasal_val*,nasal_gc&);
nasal_val* builtin_nand(nasal_val*,nasal_gc&);
nasal_val* builtin_not(nasal_val*,nasal_gc&);
nasal_val* builtin_sin(nasal_val*,nasal_gc&);
nasal_val* builtin_cos(nasal_val*,nasal_gc&);
nasal_val* builtin_tan(nasal_val*,nasal_gc&);
nasal_val* builtin_exp(nasal_val*,nasal_gc&);
nasal_val* builtin_ln(nasal_val*,nasal_gc&);
nasal_val* builtin_sqrt(nasal_val*,nasal_gc&);
nasal_val* builtin_atan2(nasal_val*,nasal_gc&);
nasal_val* builtin_time(nasal_val*,nasal_gc&);
nasal_val* builtin_contains(nasal_val*,nasal_gc&);
nasal_val* builtin_delete(nasal_val*,nasal_gc&);
nasal_val* builtin_getkeys(nasal_val*,nasal_gc&);
nasal_val* builtin_import(nasal_val*,nasal_gc&);
nasal_val* builtin_die(nasal_val*,nasal_gc&);
nasal_val* builtin_type(nasal_val*,nasal_gc&);
nasal_val* builtin_substr(nasal_val*,nasal_gc&);
nasal_val* builtin_streq(nasal_val*,nasal_gc&);
nasal_val* builtin_left(nasal_val*,nasal_gc&);
nasal_val* builtin_right(nasal_val*,nasal_gc&);
nasal_val* builtin_cmp(nasal_val*,nasal_gc&);
nasal_val* builtin_chr(nasal_val*,nasal_gc&);
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
{
std::string name;
nasal_val* (*func)(nasal_val* x);
nasal_val* (*func)(nasal_val* x,nasal_gc&);
} builtin_func[]=
{
{"__builtin_std_cout", builtin_print },
@ -123,10 +123,10 @@ struct FUNC_TABLE
{"", nullptr }
};
nasal_val* builtin_print(nasal_val* local_scope)
nasal_val* builtin_print(nasal_val* local_scope,nasal_gc& gc)
{
// get arguments
nasal_val* vector_val_addr=in_builtin_find("elements");
nasal_val* vector_val_addr=builtin_find("elements");
// main process
std::vector<nasal_val*>& ref_vec=vector_val_addr->ptr.vec->elems;
int size=ref_vec.size();
@ -144,12 +144,12 @@ nasal_val* builtin_print(nasal_val* local_scope)
}
}
// 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* elem_addr=in_builtin_find("elements");
nasal_val* vec_addr=builtin_find("vector");
nasal_val* elem_addr=builtin_find("elements");
if(vec_addr->type!=vm_vec)
{
builtin_err("append","\"vector\" must be vector");
@ -160,12 +160,12 @@ nasal_val* builtin_append(nasal_val* local_scope)
int size=ref_elems.size();
for(int i=0;i<size;++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* size_addr=in_builtin_find("size");
nasal_val* vec_addr=builtin_find("vector");
nasal_val* size_addr=builtin_find("size");
if(vec_addr->type!=vm_vec)
{
builtin_err("setsize","\"vector\" must be vector");
@ -189,32 +189,32 @@ nasal_val* builtin_setsize(nasal_val* local_scope)
ref_vec.pop_back();
else if(num>vec_size)
for(int i=vec_size;i<num;++i)
ref_vec.push_back(nil_addr);
return nil_addr;
ref_vec.push_back(gc.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)
{
builtin_err("system","\"str\" must be string");
return nullptr;
}
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;
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)
{
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((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)
{
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::ifstream fin(filename);
nasal_val* ret_addr=gc_alloc(vm_str);
nasal_val* ret_addr=gc.gc_alloc(vm_str);
*ret_addr->ptr.str="";
if(!fin.fail())
while(!fin.eof())
@ -251,10 +251,10 @@ nasal_val* builtin_fin(nasal_val* local_scope)
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* str_addr=in_builtin_find("str");
nasal_val* val_addr=builtin_find("filename");
nasal_val* str_addr=builtin_find("str");
if(val_addr->type!=vm_str)
{
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.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* string_val_addr=in_builtin_find("string");
nasal_val* delimeter_val_addr=builtin_find("delimeter");
nasal_val* string_val_addr=builtin_find("string");
if(delimeter_val_addr->type!=vm_str)
{
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 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::string tmp="";
@ -303,7 +303,7 @@ nasal_val* builtin_split(nasal_val* local_scope)
{
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];
ref_vec.push_back(str_addr);
}
@ -325,7 +325,7 @@ nasal_val* builtin_split(nasal_val* local_scope)
{
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;
ref_vec.push_back(str_addr);
tmp="";
@ -337,16 +337,16 @@ nasal_val* builtin_split(nasal_val* local_scope)
}
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;
ref_vec.push_back(str_addr);
tmp="";
}
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)
{
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)
{
srand((unsigned int)val_addr->ptr.num);
return nil_addr;
return gc.nil_addr;
}
double num=0;
for(int i=0;i<5;++i)
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;
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* ret_addr=gc_alloc(vm_str);
nasal_val* val_addr=builtin_find("thing");
nasal_val* ret_addr=gc.gc_alloc(vm_str);
char buf[32];
sprintf(buf,"0x%p",val_addr);
*ret_addr->ptr.str=buf;
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)
{
builtin_err("int","\"value\" must be number");
return nullptr;
}
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;
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)
{
builtin_err("num","\"value\" must be string");
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();
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)
{
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();
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)
{
builtin_err("str","\"number\" must be number");
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();
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* ret_addr=gc_alloc(vm_num);
nasal_val* val_addr=builtin_find("object");
nasal_val* ret_addr=gc.gc_alloc(vm_num);
switch(val_addr->type)
{
case vm_nil: ret_addr->ptr.num=0; break;
@ -442,10 +442,10 @@ nasal_val* builtin_size(nasal_val* local_scope)
}
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* b_addr=in_builtin_find("b");
nasal_val* a_addr=builtin_find("a");
nasal_val* b_addr=builtin_find("b");
if(a_addr->type!=vm_num)
{
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_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);
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* b_addr=in_builtin_find("b");
nasal_val* a_addr=builtin_find("a");
nasal_val* b_addr=builtin_find("b");
if(a_addr->type!=vm_num)
{
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_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);
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* b_addr=in_builtin_find("b");
nasal_val* a_addr=builtin_find("a");
nasal_val* b_addr=builtin_find("b");
if(a_addr->type!=vm_num)
{
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_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);
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* b_addr=in_builtin_find("b");
nasal_val* a_addr=builtin_find("a");
nasal_val* b_addr=builtin_find("b");
if(a_addr->type!=vm_num)
{
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_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));
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)
{
builtin_err("not","\"a\" must be number");
return nullptr;
}
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);
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)
{
builtin_err("sin","\"x\" must be number");
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);
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)
{
builtin_err("cos","\"x\" must be number");
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);
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)
{
builtin_err("tan","\"x\" must be number");
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);
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)
{
builtin_err("exp","\"x\" must be number");
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);
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)
{
builtin_err("ln","\"x\" must be number");
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));
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)
{
builtin_err("sqrt","\"x\" must be number");
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);
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* y_val_addr=in_builtin_find("y");
nasal_val* x_val_addr=builtin_find("x");
nasal_val* y_val_addr=builtin_find("y");
if(x_val_addr->type!=vm_num)
{
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");
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);
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)
{
builtin_err("time","\"begin_time\" must be number");
return nullptr;
}
time_t begin_time=(time_t)val_addr->ptr.num;
nasal_val* ret_addr=gc_alloc(vm_num);
nasal_val* ret_addr=gc.gc_alloc(vm_num);
ret_addr->ptr.num=time(&begin_time);
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* key_addr=in_builtin_find("key");
nasal_val* hash_addr=builtin_find("hash");
nasal_val* key_addr=builtin_find("key");
if(hash_addr->type!=vm_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");
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);
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* key_addr=in_builtin_find("key");
nasal_val* hash_addr=builtin_find("hash");
nasal_val* key_addr=builtin_find("key");
if(hash_addr->type!=vm_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))
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)
{
builtin_err("keys","\"hash\" must be hash");
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::unordered_map<std::string,nasal_val*>& ref_hash=hash_addr->ptr.hash->elems;
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;
ref_vec.push_back(str_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 will return nothing when running.
builtin_err("import","cannot use import when running");
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)
{
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';
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* ret_addr=gc_alloc(vm_str);
nasal_val* val_addr=builtin_find("object");
nasal_val* ret_addr=gc.gc_alloc(vm_str);
switch(val_addr->type)
{
case vm_nil: *ret_addr->ptr.str="nil"; break;
@ -726,11 +726,11 @@ nasal_val* builtin_type(nasal_val* local_scope)
}
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* beg_addr=in_builtin_find("begin");
nasal_val* len_addr=in_builtin_find("length");
nasal_val* str_addr=builtin_find("str");
nasal_val* beg_addr=builtin_find("begin");
nasal_val* len_addr=builtin_find("length");
if(str_addr->type!=vm_str)
{
builtin_err("substr","\"str\" must be string");
@ -756,22 +756,22 @@ nasal_val* builtin_substr(nasal_val* local_scope)
}
if(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);
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* b_addr=in_builtin_find("b");
nasal_val* ret_addr=gc_alloc(vm_num);
nasal_val* a_addr=builtin_find("a");
nasal_val* b_addr=builtin_find("b");
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);
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* len_addr=in_builtin_find("length");
nasal_val* str_addr=builtin_find("string");
nasal_val* len_addr=builtin_find("length");
if(str_addr->type!=vm_str)
{
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;
if(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);
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* len_addr=in_builtin_find("length");
nasal_val* str_addr=builtin_find("string");
nasal_val* len_addr=builtin_find("length");
if(str_addr->type!=vm_str)
{
builtin_err("right","\"string\" must be string");
@ -811,14 +811,14 @@ nasal_val* builtin_right(nasal_val* local_scope)
len=srclen;
if(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);
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* b_addr=in_builtin_find("b");
nasal_val* a_addr=builtin_find("a");
nasal_val* b_addr=builtin_find("b");
if(a_addr->type!=vm_str)
{
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");
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());
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)
{
builtin_err("chr","\"code\" must be number");
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;
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_feach, // index counter on the top of forindex_stack plus 1 and get the value in vector
op_call, // call identifier
op_callg,
op_calll,
op_callv, // call vec[index]
op_callvi, // call vec[immediate] (used in multi-assign/multi-define)
op_callh, // call hash.label
@ -58,6 +60,8 @@ enum op_code
op_slc, // slice like vec[1]
op_slc2, // slice like vec[nil:10]
op_mcall, // get memory of identifier
op_mcallg,
op_mcalll,
op_mcallv, // get memory of vec[index]
op_mcallh, // get memory of hash.label
op_ret // return
@ -114,6 +118,8 @@ struct
{op_findex, "findx "},
{op_feach, "feach "},
{op_call, "call "},
{op_callg, "callg "},
{op_calll, "calll "},
{op_callv, "callv "},
{op_callvi, "callvi"},
{op_callh, "callh "},
@ -124,6 +130,8 @@ struct
{op_slc, "slc "},
{op_slc2, "slc2 "},
{op_mcall, "mcall "},
{op_mcallg, "mcallg"},
{op_mcalll, "mcalll"},
{op_mcallv, "mcallv"},
{op_mcallh, "mcallh"},
{op_ret, "ret "},
@ -161,9 +169,13 @@ private:
std::vector<opcode> exec_code;
std::list<std::vector<int> > continue_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_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 pop_gen();
void nil_gen();
@ -224,7 +236,7 @@ void nasal_codegen::regist_number(double num)
return;
}
void nasal_codegen::regist_string(std::string str)
void nasal_codegen::regist_string(std::string& str)
{
int size=string_table.size();
if(string_table.find(str)==string_table.end())
@ -232,6 +244,21 @@ void nasal_codegen::regist_string(std::string str)
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)
{
opcode opr(op,index);
@ -334,7 +361,11 @@ void nasal_codegen::func_gen(nasal_ast& ast)
int ptr=exec_code.size();
gen(op_jmp,0);
nasal_ast& block=ast.get_children()[1];
std::vector<std::string> new_scope;
local.push_front(new_scope);
block_gen(block);
local.pop_front();
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_return)
{
nil_gen();

View File

@ -18,25 +18,6 @@ struct nasal_func;
struct nasal_scop;
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
{
std::vector<nasal_val*> elems;
@ -183,9 +164,9 @@ nasal_val** nasal_hash::get_mem(std::string& key)
int size=vec_ref.size();
for(int i=0;i<size;++i)
{
nasal_val* tmp_val_addr=vec_ref[i];
if(tmp_val_addr->type==vm_hash)
mem_addr=tmp_val_addr->ptr.hash->get_mem(key);
nasal_val* tmp=vec_ref[i];
if(tmp->type==vm_hash)
mem_addr=tmp->ptr.hash->get_mem(key);
if(mem_addr)
return mem_addr;
}
@ -345,16 +326,37 @@ std::string nasal_val::to_string()
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;
bfs.push(zero_addr);
bfs.push(one_addr);
bfs.push(nil_addr);
bfs.push(global);
size=num_addrs.size();
int size=num_addrs.size();
for(int i=0;i<size;++i)
bfs.push(num_addrs[i]);
size=local.size();
@ -406,7 +408,7 @@ void mark()
}
return;
}
void sweep()
void nasal_gc::sweep()
{
int size=memory.size();
for(int i=0;i<size;++i)
@ -420,7 +422,7 @@ void sweep()
}
return;
}
void gc_init()
void nasal_gc::gc_init(std::vector<double>& nums)
{
for(int i=0;i<65536;++i)
{
@ -428,9 +430,35 @@ void gc_init()
memory.push_back(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;
}
void gc_clear()
void nasal_gc::gc_clear()
{
int size=memory.size();
for(int i=0;i<size;++i)
@ -441,9 +469,13 @@ void gc_clear()
memory.clear();
while(!free_list.empty())
free_list.pop();
global=nullptr;
delete []val_stack;
local.clear();
slice_stack.clear();
return;
}
nasal_val* gc_alloc(int type)
nasal_val* nasal_gc::gc_alloc(int type)
{
if(free_list.empty())
{

View File

@ -1,21 +1,24 @@
#ifndef __NASAL_VM_H__
#define __NASAL_VM_H__
#define STACK_MAX_DEPTH (65536<<4)
class nasal_vm
{
private:
std::vector<std::string> str_table; // symbols used in process
bool loop_mark; // when mark is false,break the main loop
/* reference from nasal_gc */
nasal_val**& stack_top; // stack top
/* values of nasal_vm */
int pc; // program counter
int me_index; // this is the index of "me" in str_table
int me; // this is the index of "me" in str_table
bool loop_mark; // when mark is false,break the main loop
std::stack<int> ret; // ptr stack stores address for function to return
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
std::stack<int> call_stack; // ptr stack stores address for function to return
std::stack<int> counter; // iterator stack for forindex/foreach
nasal_gc gc; //garbage collector
void die(std::string);
bool check_condition(nasal_val*);
bool condition(nasal_val*);
void opr_nop();
void opr_load();
void opr_loadg();
@ -61,6 +64,8 @@ private:
void opr_findex();
void opr_feach();
void opr_call();
void opr_callg();
void opr_calll();
void opr_callv();
void opr_callvi();
void opr_callh();
@ -71,10 +76,13 @@ private:
void opr_slc();
void opr_slc2();
void opr_mcall();
void opr_mcallg();
void opr_mcalll();
void opr_mcallv();
void opr_mcallh();
void opr_ret();
public:
nasal_vm();
void init(
std::vector<std::string>&,
std::vector<double>&,
@ -83,63 +91,36 @@ public:
void run();
};
nasal_vm::nasal_vm():stack_top(gc.stack_top)
{
return;
}
void nasal_vm::init(
std::vector<std::string>& strs,
std::vector<double>& nums,
std::vector<opcode>& exec)
{
gc_init();
gc.gc_init(nums);
str_table=strs; // get constant strings & symbols
exec_code=exec; // get bytecodes
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
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
builtin_use_str.clear(); // create map that builtin functions use
for(int i=0;i<str_table.size();++i)
builtin_use_str_table[str_table[i]]=i;
me_index=builtin_use_str_table.count("me")?builtin_use_str_table["me"]:-1; // get symbol index of 'me'
builtin_use_str[str_table[i]]=i;
me=builtin_use_str.count("me")?builtin_use_str["me"]:-1; // get symbol index of 'me'
loop_mark=true; // set loop mark to true
global=new nasal_val(vm_scop); // init global symbol table
memory.push_back(global);
return;
}
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())
addr_stack.pop();
local.clear();
slice_stack.clear();
while(!call_stack.empty())
call_stack.pop();
while(!ret.empty())
ret.pop();
while(!counter.empty())
counter.pop();
str_table.clear();
@ -152,7 +133,7 @@ void nasal_vm::die(std::string str)
loop_mark=false;
return;
}
bool nasal_vm::check_condition(nasal_val* value_addr)
bool nasal_vm::condition(nasal_val* value_addr)
{
int type=value_addr->type;
if(type==vm_num)
@ -175,65 +156,64 @@ void nasal_vm::opr_nop()
void nasal_vm::opr_load()
{
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;
}
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;
}
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;
}
void nasal_vm::opr_pnum()
{
nasal_val* val=num_addrs[exec_code[pc].num];
*(++stack_top)=val;
*(++stack_top)=gc.num_addrs[exec_code[pc].num];
return;
}
void nasal_vm::opr_pone()
{
*(++stack_top)=one_addr;
*(++stack_top)=gc.one_addr;
return;
}
void nasal_vm::opr_pzero()
{
*(++stack_top)=zero_addr;
*(++stack_top)=gc.zero_addr;
return;
}
void nasal_vm::opr_pnil()
{
*(++stack_top)=nil_addr;
*(++stack_top)=gc.nil_addr;
return;
}
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];
*(++stack_top)=val;
return;
}
void nasal_vm::opr_newv()
{
nasal_val* vec=gc_alloc(vm_vec);
nasal_val* vec=gc.gc_alloc(vm_vec);
*(++stack_top)=vec;
return;
}
void nasal_vm::opr_newh()
{
nasal_val* hash=gc_alloc(vm_hash);
nasal_val* hash=gc.gc_alloc(vm_hash);
*(++stack_top)=hash;
return;
}
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;
if(!local.empty())
val->ptr.func->closure=local.back()->ptr.scop->elems;
if(!gc.local.empty())
val->ptr.func->closure=gc.local.back()->ptr.scop->elems;
*(++stack_top)=val;
return;
}
@ -273,16 +253,16 @@ void nasal_vm::opr_unot()
nasal_val* new_val=nullptr;
int type=val->type;
if(type==vm_nil)
new_val=one_addr;
new_val=gc.one_addr;
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)
{
double number=trans_string_to_number(*val->ptr.str);
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
new_val=number?zero_addr:one_addr;
new_val=number?gc.zero_addr:gc.one_addr;
}
else
die("unot: incorrect value type");
@ -292,14 +272,14 @@ void nasal_vm::opr_unot()
void nasal_vm::opr_usub()
{
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();
*stack_top=new_val;
return;
}
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* val1=*stack_top;
new_val->ptr.num=val1->to_number()+val2->to_number();
@ -308,7 +288,7 @@ void nasal_vm::opr_add()
}
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* val1=*stack_top;
new_val->ptr.num=val1->to_number()-val2->to_number();
@ -317,7 +297,7 @@ void nasal_vm::opr_sub()
}
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* val1=*stack_top;
new_val->ptr.num=val1->to_number()*val2->to_number();
@ -326,7 +306,7 @@ void nasal_vm::opr_mul()
}
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* val1=*stack_top;
new_val->ptr.num=val1->to_number()/val2->to_number();
@ -335,7 +315,7 @@ void nasal_vm::opr_div()
}
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* val1=*stack_top;
*new_val->ptr.str=val1->to_string()+val2->to_string();
@ -348,7 +328,7 @@ void nasal_vm::opr_addeq()
addr_stack.pop();
nasal_val* val2=*stack_top;
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();
*stack_top=new_val;
*mem_addr=new_val;
@ -360,7 +340,7 @@ void nasal_vm::opr_subeq()
addr_stack.pop();
nasal_val* val2=*stack_top;
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();
*stack_top=new_val;
*mem_addr=new_val;
@ -372,7 +352,7 @@ void nasal_vm::opr_muleq()
addr_stack.pop();
nasal_val* val2=*stack_top;
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();
*stack_top=new_val;
*mem_addr=new_val;
@ -384,7 +364,7 @@ void nasal_vm::opr_diveq()
addr_stack.pop();
nasal_val* val2=*stack_top;
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();
*stack_top=new_val;
*mem_addr=new_val;
@ -396,7 +376,7 @@ void nasal_vm::opr_lnkeq()
addr_stack.pop();
nasal_val* val2=*stack_top;
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();
*stack_top=new_val;
*mem_addr=new_val;
@ -412,13 +392,13 @@ void nasal_vm::opr_meq()
}
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* val1=*stack_top;
int a_type=val1->type;
int b_type=val2->type;
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)
{
new_val->ptr.num=(*val1->ptr.str==*val2->ptr.str);
@ -438,13 +418,13 @@ void nasal_vm::opr_eq()
}
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* val1=*stack_top;
int a_type=val1->type;
int b_type=val2->type;
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)
{
new_val->ptr.num=(*val1->ptr.str!=*val2->ptr.str);
@ -464,7 +444,7 @@ void nasal_vm::opr_neq()
}
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* val1=*stack_top;
int a_type=val1->type;
@ -478,7 +458,7 @@ void nasal_vm::opr_less()
}
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* val1=*stack_top;
int a_type=val1->type;
@ -492,7 +472,7 @@ void nasal_vm::opr_leq()
}
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* val1=*stack_top;
int a_type=val1->type;
@ -506,7 +486,7 @@ void nasal_vm::opr_grt()
}
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* val1=*stack_top;
int a_type=val1->type;
@ -530,13 +510,13 @@ void nasal_vm::opr_jmp()
}
void nasal_vm::opr_jt()
{
if(check_condition(*stack_top))
if(condition(*stack_top))
pc=exec_code[pc].num-1;
return;
}
void nasal_vm::opr_jf()
{
if(!check_condition(*stack_top))
if(!condition(*stack_top))
pc=exec_code[pc].num-1;
--stack_top;
return;
@ -563,7 +543,7 @@ void nasal_vm::opr_findex()
pc=exec_code[pc].num-1;
return;
}
nasal_val* res=gc_alloc(vm_num);
nasal_val* res=gc.gc_alloc(vm_num);
res->ptr.num=counter.top();
*(++stack_top)=res;
return;
@ -585,14 +565,14 @@ void nasal_vm::opr_call()
{
nasal_val* val=nullptr;
int name_index=exec_code[pc].num;
if(!local.empty())
val=local.back()->ptr.scop->get_val(name_index);
if(!gc.local.empty())
val=gc.local.back()->ptr.scop->get_val(name_index);
if(val)
{
*(++stack_top)=val;
return;
}
val=global->ptr.scop->get_val(name_index);
val=gc.global->ptr.scop->get_val(name_index);
if(val)
{
*(++stack_top)=val;
@ -601,6 +581,16 @@ void nasal_vm::opr_call()
die("call: cannot find symbol named \""+str_table[name_index]+"\"");
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()
{
nasal_val* val=*stack_top--;
@ -632,7 +622,7 @@ void nasal_vm::opr_callv()
return;
}
if(res->type==vm_func)
res->ptr.func->closure[me_index]=val;
res->ptr.func->closure[me]=val;
*stack_top=res;
}
else if(type==vm_str)
@ -645,7 +635,7 @@ void nasal_vm::opr_callv()
die("callv: index out of range");
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]);
*stack_top=res;
}
@ -686,7 +676,7 @@ void nasal_vm::opr_callh()
return;
}
if(res->type==vm_func)
res->ptr.func->closure[me_index]=val;
res->ptr.func->closure[me]=val;
*stack_top=res;
return;
}
@ -701,8 +691,8 @@ void nasal_vm::opr_callf()
return;
}
// push new local scope
nasal_val* closure=gc_alloc(vm_scop);
local.push_back(closure);
nasal_val* closure=gc.gc_alloc(vm_scop);
gc.local.push_back(closure);
// load parameters
nasal_func& ref_func=*func_addr->ptr.func;
std::vector<int>& ref_para=ref_func.para;
@ -731,7 +721,7 @@ void nasal_vm::opr_callf()
}
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)
vec_addr->ptr.vec->elems.push_back(ref_vec[i]);
ref_closure[ref_func.dynpara]=vec_addr;
@ -760,28 +750,28 @@ void nasal_vm::opr_callf()
}
}
--stack_top;
call_stack.push(pc);
ret.push(pc);
pc=ref_func.entry-1;
return;
}
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;
loop_mark=res;
return;
}
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)
die("slcbegin: must slice a vector");
return;
}
void nasal_vm::opr_slcend()
{
*stack_top=slice_stack.back();
slice_stack.pop_back();
*stack_top=gc.slice_stack.back();
gc.slice_stack.pop_back();
return;
}
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);
if(res)
slice_stack.back()->ptr.vec->elems.push_back(res);
gc.slice_stack.back()->ptr.vec->elems.push_back(res);
else
die("slc: index out of range");
return;
@ -806,7 +796,7 @@ void nasal_vm::opr_slc2()
nasal_val* val2=*stack_top--;
nasal_val* val1=*stack_top--;
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 num1=val1->to_number();
@ -833,24 +823,21 @@ void nasal_vm::opr_slc2()
return;
}
for(int i=num1;i<=num2;++i)
{
nasal_val* tmp=ref[i];
aim.push_back(tmp);
}
aim.push_back(ref[i]);
return;
}
void nasal_vm::opr_mcall()
{
nasal_val** mem_addr=nullptr;
int name_index=exec_code[pc].num;
if(!local.empty())
mem_addr=local.back()->ptr.scop->get_mem(name_index);
if(!gc.local.empty())
mem_addr=gc.local.back()->ptr.scop->get_mem(name_index);
if(mem_addr)
{
addr_stack.push(mem_addr);
return;
}
mem_addr=global->ptr.scop->get_mem(name_index);
mem_addr=gc.global->ptr.scop->get_mem(name_index);
if(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]+"\"");
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()
{
nasal_val* val=*stack_top--;
@ -890,11 +887,11 @@ void nasal_vm::opr_mcallv()
return;
}
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);
if(!res)
{
ref.elems[str]=nil_addr;
ref.elems[str]=gc.nil_addr;
res=ref.get_mem(str);
}
addr_stack.push(res);
@ -921,7 +918,7 @@ void nasal_vm::opr_mcallh()
mem_addr=ref.get_mem(str);
if(!mem_addr) // create a new key
{
ref.elems[str]=nil_addr;
ref.elems[str]=gc.nil_addr;
mem_addr=ref.get_mem(str);
}
addr_stack.push(mem_addr);
@ -929,9 +926,9 @@ void nasal_vm::opr_mcallh()
}
void nasal_vm::opr_ret()
{
local.pop_back();
pc=call_stack.top();
call_stack.pop();
gc.local.pop_back();
pc=ret.top();
ret.pop();
nasal_val* ret_val=*stack_top--;
*stack_top=ret_val;
return;
@ -985,6 +982,8 @@ void nasal_vm::run()
&nasal_vm::opr_findex,
&nasal_vm::opr_feach,
&nasal_vm::opr_call,
&nasal_vm::opr_callg,
&nasal_vm::opr_calll,
&nasal_vm::opr_callv,
&nasal_vm::opr_callvi,
&nasal_vm::opr_callh,
@ -995,6 +994,8 @@ void nasal_vm::run()
&nasal_vm::opr_slc,
&nasal_vm::opr_slc2,
&nasal_vm::opr_mcall,
&nasal_vm::opr_mcallg,
&nasal_vm::opr_mcalll,
&nasal_vm::opr_mcallv,
&nasal_vm::opr_mcallh,
&nasal_vm::opr_ret
@ -1003,7 +1004,6 @@ void nasal_vm::run()
// main loop
for(pc=0;loop_mark;++pc)
(this->*opr_table[exec_code[pc].op])();
float total_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC;
std::cout<<">> [vm] process exited after "<<total_time<<"s.\n";
return;

View File

@ -137,7 +137,7 @@ while(error>0.001)
}
cnt+=1;
show+=1;
if(show==150)
if(show==200)
{
show=0;
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);