From 80cc8e9db738403a109153b2abb252907d03e690 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Tue, 17 Aug 2021 01:18:35 +0800 Subject: [PATCH] closure bugs fixed --- nasal_builtin.h | 346 ++++++++++++++++++++++++------------------------ nasal_gc.h | 97 +++++++------- nasal_vm.h | 117 +++++++++------- test/lexer.nas | 147 ++++++++++---------- 4 files changed, 366 insertions(+), 341 deletions(-) diff --git a/nasal_builtin.h b/nasal_builtin.h index c4340d2..9230eed 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -12,47 +12,47 @@ // declaration of builtin functions // to add new builtin function,declare it here and write the definition below -nasal_val* builtin_print(std::vector&,nasal_gc&); -nasal_val* builtin_append(std::vector&,nasal_gc&); -nasal_val* builtin_setsize(std::vector&,nasal_gc&); -nasal_val* builtin_system(std::vector&,nasal_gc&); -nasal_val* builtin_input(std::vector&,nasal_gc&); -nasal_val* builtin_sleep(std::vector&,nasal_gc&); -nasal_val* builtin_fin(std::vector&,nasal_gc&); -nasal_val* builtin_fout(std::vector&,nasal_gc&); -nasal_val* builtin_split(std::vector&,nasal_gc&); -nasal_val* builtin_rand(std::vector&,nasal_gc&); -nasal_val* builtin_id(std::vector&,nasal_gc&); -nasal_val* builtin_int(std::vector&,nasal_gc&); -nasal_val* builtin_num(std::vector&,nasal_gc&); -nasal_val* builtin_pop(std::vector&,nasal_gc&); -nasal_val* builtin_str(std::vector&,nasal_gc&); -nasal_val* builtin_size(std::vector&,nasal_gc&); -nasal_val* builtin_xor(std::vector&,nasal_gc&); -nasal_val* builtin_and(std::vector&,nasal_gc&); -nasal_val* builtin_or(std::vector&,nasal_gc&); -nasal_val* builtin_nand(std::vector&,nasal_gc&); -nasal_val* builtin_not(std::vector&,nasal_gc&); -nasal_val* builtin_sin(std::vector&,nasal_gc&); -nasal_val* builtin_cos(std::vector&,nasal_gc&); -nasal_val* builtin_tan(std::vector&,nasal_gc&); -nasal_val* builtin_exp(std::vector&,nasal_gc&); -nasal_val* builtin_ln(std::vector&,nasal_gc&); -nasal_val* builtin_sqrt(std::vector&,nasal_gc&); -nasal_val* builtin_atan2(std::vector&,nasal_gc&); -nasal_val* builtin_time(std::vector&,nasal_gc&); -nasal_val* builtin_contains(std::vector&,nasal_gc&); -nasal_val* builtin_delete(std::vector&,nasal_gc&); -nasal_val* builtin_keys(std::vector&,nasal_gc&); -nasal_val* builtin_import(std::vector&,nasal_gc&); -nasal_val* builtin_die(std::vector&,nasal_gc&); -nasal_val* builtin_type(std::vector&,nasal_gc&); -nasal_val* builtin_substr(std::vector&,nasal_gc&); -nasal_val* builtin_streq(std::vector&,nasal_gc&); -nasal_val* builtin_left(std::vector&,nasal_gc&); -nasal_val* builtin_right(std::vector&,nasal_gc&); -nasal_val* builtin_cmp(std::vector&,nasal_gc&); -nasal_val* builtin_chr(std::vector&,nasal_gc&); +nasal_ref builtin_print(std::vector&,nasal_gc&); +nasal_ref builtin_append(std::vector&,nasal_gc&); +nasal_ref builtin_setsize(std::vector&,nasal_gc&); +nasal_ref builtin_system(std::vector&,nasal_gc&); +nasal_ref builtin_input(std::vector&,nasal_gc&); +nasal_ref builtin_sleep(std::vector&,nasal_gc&); +nasal_ref builtin_fin(std::vector&,nasal_gc&); +nasal_ref builtin_fout(std::vector&,nasal_gc&); +nasal_ref builtin_split(std::vector&,nasal_gc&); +nasal_ref builtin_rand(std::vector&,nasal_gc&); +nasal_ref builtin_id(std::vector&,nasal_gc&); +nasal_ref builtin_int(std::vector&,nasal_gc&); +nasal_ref builtin_num(std::vector&,nasal_gc&); +nasal_ref builtin_pop(std::vector&,nasal_gc&); +nasal_ref builtin_str(std::vector&,nasal_gc&); +nasal_ref builtin_size(std::vector&,nasal_gc&); +nasal_ref builtin_xor(std::vector&,nasal_gc&); +nasal_ref builtin_and(std::vector&,nasal_gc&); +nasal_ref builtin_or(std::vector&,nasal_gc&); +nasal_ref builtin_nand(std::vector&,nasal_gc&); +nasal_ref builtin_not(std::vector&,nasal_gc&); +nasal_ref builtin_sin(std::vector&,nasal_gc&); +nasal_ref builtin_cos(std::vector&,nasal_gc&); +nasal_ref builtin_tan(std::vector&,nasal_gc&); +nasal_ref builtin_exp(std::vector&,nasal_gc&); +nasal_ref builtin_ln(std::vector&,nasal_gc&); +nasal_ref builtin_sqrt(std::vector&,nasal_gc&); +nasal_ref builtin_atan2(std::vector&,nasal_gc&); +nasal_ref builtin_time(std::vector&,nasal_gc&); +nasal_ref builtin_contains(std::vector&,nasal_gc&); +nasal_ref builtin_delete(std::vector&,nasal_gc&); +nasal_ref builtin_keys(std::vector&,nasal_gc&); +nasal_ref builtin_import(std::vector&,nasal_gc&); +nasal_ref builtin_die(std::vector&,nasal_gc&); +nasal_ref builtin_type(std::vector&,nasal_gc&); +nasal_ref builtin_substr(std::vector&,nasal_gc&); +nasal_ref builtin_streq(std::vector&,nasal_gc&); +nasal_ref builtin_left(std::vector&,nasal_gc&); +nasal_ref builtin_right(std::vector&,nasal_gc&); +nasal_ref builtin_cmp(std::vector&,nasal_gc&); +nasal_ref builtin_chr(std::vector&,nasal_gc&); #define builtin_err(func_name,info) std::cout<<"[vm] "<&,nasal_gc&); struct FUNC_TABLE { const char* name; - nasal_val* (*func)(std::vector&,nasal_gc&); + nasal_ref (*func)(std::vector&,nasal_gc&); } builtin_func[]= { {"__builtin_print", builtin_print }, @@ -108,11 +108,11 @@ struct FUNC_TABLE {nullptr, nullptr } }; -nasal_val* builtin_print(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_print(std::vector& local_scope,nasal_gc& gc) { // get arguments // local_scope[0] is reserved for 'me' - nasal_val* vec_addr=local_scope[1]; + nasal_ref vec_addr=local_scope[1]; // main process for(auto i:vec_addr->ptr.vec->elems) switch(i->type) @@ -128,24 +128,24 @@ nasal_val* builtin_print(std::vector& local_scope,nasal_gc& gc) // generate return value return gc.nil_addr; } -nasal_val* builtin_append(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_append(std::vector& local_scope,nasal_gc& gc) { - nasal_val* vec_addr=local_scope[1]; - nasal_val* elem_addr=local_scope[2]; + nasal_ref vec_addr=local_scope[1]; + nasal_ref elem_addr=local_scope[2]; if(vec_addr->type!=vm_vec) { builtin_err("append","\"vector\" must be vector"); return nullptr; } - std::vector& ref_vec=vec_addr->ptr.vec->elems; + std::vector& ref_vec=vec_addr->ptr.vec->elems; for(auto i:elem_addr->ptr.vec->elems) ref_vec.push_back(i); return gc.nil_addr; } -nasal_val* builtin_setsize(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_setsize(std::vector& local_scope,nasal_gc& gc) { - nasal_val* vec_addr=local_scope[1]; - nasal_val* size_addr=local_scope[2]; + nasal_ref vec_addr=local_scope[1]; + nasal_ref size_addr=local_scope[2]; if(vec_addr->type!=vm_vec) { builtin_err("setsize","\"vector\" must be vector"); @@ -166,10 +166,10 @@ nasal_val* builtin_setsize(std::vector& local_scope,nasal_gc& gc) return gc.nil_addr; } -nasal_val* builtin_system(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_system(std::vector& local_scope,nasal_gc& gc) { - nasal_val* ret_addr=gc.gc_alloc(vm_num); - nasal_val* str_addr=local_scope[1]; + nasal_ref ret_addr=gc.gc_alloc(vm_num); + nasal_ref str_addr=local_scope[1]; if(str_addr->type!=vm_str) { builtin_err("system","\"str\" must be string"); @@ -179,16 +179,16 @@ nasal_val* builtin_system(std::vector& local_scope,nasal_gc& gc) return ret_addr; } -nasal_val* builtin_input(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_input(std::vector& local_scope,nasal_gc& gc) { - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); std::cin>>*ret_addr->ptr.str; return ret_addr; } -nasal_val* builtin_sleep(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_sleep(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("sleep","\"duration\" must be number"); @@ -199,9 +199,9 @@ nasal_val* builtin_sleep(std::vector& local_scope,nasal_gc& gc) return gc.nil_addr; } -nasal_val* builtin_fin(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_fin(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_str) { builtin_err("io.fin","\"filename\" must be string"); @@ -209,7 +209,7 @@ nasal_val* builtin_fin(std::vector& local_scope,nasal_gc& gc) } std::string& filename=*val_addr->ptr.str; std::ifstream fin(filename); - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); *ret_addr->ptr.str=""; if(!fin.fail()) while(!fin.eof()) @@ -225,10 +225,10 @@ nasal_val* builtin_fin(std::vector& local_scope,nasal_gc& gc) return ret_addr; } -nasal_val* builtin_fout(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_fout(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; - nasal_val* str_addr=local_scope[2]; + nasal_ref val_addr=local_scope[1]; + nasal_ref str_addr=local_scope[2]; if(val_addr->type!=vm_str) { builtin_err("io.fout","\"filename\" must be string"); @@ -250,10 +250,10 @@ nasal_val* builtin_fout(std::vector& local_scope,nasal_gc& gc) return gc.nil_addr; } -nasal_val* builtin_split(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_split(std::vector& local_scope,nasal_gc& gc) { - nasal_val* deli_val_addr=local_scope[1]; - nasal_val* str_val_addr=local_scope[2]; + nasal_ref deli_val_addr=local_scope[1]; + nasal_ref str_val_addr=local_scope[2]; if(deli_val_addr->type!=vm_str) { builtin_err("split","\"delimeter\" must be string"); @@ -272,7 +272,7 @@ nasal_val* builtin_split(std::vector& local_scope,nasal_gc& gc) // push it to local scope to avoid being sweeped local_scope.push_back(gc.gc_alloc(vm_vec)); - std::vector& vec=local_scope.back()->ptr.vec->elems; + std::vector& vec=local_scope.back()->ptr.vec->elems; if(!delimeter_len) { for(int i=0;i& local_scope,nasal_gc& gc) } return local_scope.back(); } -nasal_val* builtin_rand(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_rand(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num && val_addr->type!=vm_nil) { builtin_err("rand","\"seed\" must be nil or number"); @@ -330,49 +330,49 @@ nasal_val* builtin_rand(std::vector& local_scope,nasal_gc& gc) return gc.nil_addr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=0; for(int i=0;i<5;++i) ret_addr->ptr.num=(ret_addr->ptr.num+rand())*(1.0/(RAND_MAX+1.0)); return ret_addr; } -nasal_val* builtin_id(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_id(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref val_addr=local_scope[1]; + nasal_ref ret_addr=gc.gc_alloc(vm_str); char buf[32]; sprintf(buf,"%p",val_addr); *ret_addr->ptr.str=buf; return ret_addr; } -nasal_val* builtin_int(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_int(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("int","\"value\" must be number"); return nullptr; } int number=(int)val_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(double)number; return ret_addr; } -nasal_val* builtin_num(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_num(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_str) { builtin_err("num","\"value\" must be string"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=val_addr->to_number(); return ret_addr; } -nasal_val* builtin_pop(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_pop(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_vec) { builtin_err("pop","\"vector\" must be vector"); @@ -380,28 +380,28 @@ nasal_val* builtin_pop(std::vector& local_scope,nasal_gc& gc) } if(val_addr->ptr.vec->elems.size()) { - nasal_val* tmp=val_addr->ptr.vec->elems.back(); + nasal_ref tmp=val_addr->ptr.vec->elems.back(); val_addr->ptr.vec->elems.pop_back(); return tmp; } return gc.nil_addr; } -nasal_val* builtin_str(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_str(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("str","\"number\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); *ret_addr->ptr.str=std::to_string(val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_size(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_size(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref val_addr=local_scope[1]; + nasal_ref ret_addr=gc.gc_alloc(vm_num); switch(val_addr->type) { case vm_nil: ret_addr->ptr.num=0; break; @@ -413,10 +413,10 @@ nasal_val* builtin_size(std::vector& local_scope,nasal_gc& gc) } return ret_addr; } -nasal_val* builtin_xor(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_xor(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; - nasal_val* b_addr=local_scope[2]; + nasal_ref a_addr=local_scope[1]; + nasal_ref b_addr=local_scope[2]; if(a_addr->type!=vm_num) { builtin_err("xor","\"a\" must be number"); @@ -429,14 +429,14 @@ nasal_val* builtin_xor(std::vector& local_scope,nasal_gc& gc) } int number_a=(int)a_addr->ptr.num; int number_b=(int)b_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(number_a^number_b); return ret_addr; } -nasal_val* builtin_and(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_and(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; - nasal_val* b_addr=local_scope[2]; + nasal_ref a_addr=local_scope[1]; + nasal_ref b_addr=local_scope[2]; if(a_addr->type!=vm_num) { builtin_err("and","\"a\" must be number"); @@ -449,14 +449,14 @@ nasal_val* builtin_and(std::vector& local_scope,nasal_gc& gc) } int number_a=(int)a_addr->ptr.num; int number_b=(int)b_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(number_a&number_b); return ret_addr; } -nasal_val* builtin_or(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_or(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; - nasal_val* b_addr=local_scope[2]; + nasal_ref a_addr=local_scope[1]; + nasal_ref b_addr=local_scope[2]; if(a_addr->type!=vm_num) { builtin_err("or","\"a\" must be number"); @@ -469,14 +469,14 @@ nasal_val* builtin_or(std::vector& local_scope,nasal_gc& gc) } int number_a=(int)a_addr->ptr.num; int number_b=(int)b_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(number_a|number_b); return ret_addr; } -nasal_val* builtin_nand(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_nand(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; - nasal_val* b_addr=local_scope[2]; + nasal_ref a_addr=local_scope[1]; + nasal_ref b_addr=local_scope[2]; if(a_addr->type!=vm_num) { builtin_err("nand","\"a\" must be number"); @@ -489,99 +489,99 @@ nasal_val* builtin_nand(std::vector& local_scope,nasal_gc& gc) } int number_a=(int)a_addr->ptr.num; int number_b=(int)b_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(~(number_a&number_b)); return ret_addr; } -nasal_val* builtin_not(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_not(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; + nasal_ref a_addr=local_scope[1]; if(a_addr->type!=vm_num) { builtin_err("not","\"a\" must be number"); return nullptr; } int number=(int)a_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(~number); return ret_addr; } -nasal_val* builtin_sin(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_sin(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("sin","\"x\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=sin(val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_cos(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_cos(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("cos","\"x\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=cos(val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_tan(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_tan(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("tan","\"x\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=tan(val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_exp(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_exp(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("exp","\"x\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=exp(val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_ln(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_ln(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("ln","\"x\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(log(val_addr->ptr.num)/log(2.7182818284590452354)); return ret_addr; } -nasal_val* builtin_sqrt(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_sqrt(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("sqrt","\"x\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=sqrt(val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_atan2(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_atan2(std::vector& local_scope,nasal_gc& gc) { - nasal_val* x_val_addr=local_scope[1]; - nasal_val* y_val_addr=local_scope[2]; + nasal_ref x_val_addr=local_scope[1]; + nasal_ref y_val_addr=local_scope[2]; if(x_val_addr->type!=vm_num) { builtin_err("atan2","\"x\" must be number"); @@ -592,27 +592,27 @@ nasal_val* builtin_atan2(std::vector& local_scope,nasal_gc& gc) builtin_err("atan2","\"y\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=atan2(y_val_addr->ptr.num,x_val_addr->ptr.num); return ret_addr; } -nasal_val* builtin_time(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_time(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; + nasal_ref val_addr=local_scope[1]; if(val_addr->type!=vm_num) { builtin_err("time","\"begin_time\" must be number"); return nullptr; } time_t begin_time=(time_t)val_addr->ptr.num; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=time(&begin_time); return ret_addr; } -nasal_val* builtin_contains(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_contains(std::vector& local_scope,nasal_gc& gc) { - nasal_val* hash_addr=local_scope[1]; - nasal_val* key_addr=local_scope[2]; + nasal_ref hash_addr=local_scope[1]; + nasal_ref key_addr=local_scope[2]; if(hash_addr->type!=vm_hash) { builtin_err("contains","\"hash\" must be hash"); @@ -625,10 +625,10 @@ nasal_val* builtin_contains(std::vector& local_scope,nasal_gc& gc) } return hash_addr->ptr.hash->elems.count(*key_addr->ptr.str)?gc.one_addr:gc.zero_addr; } -nasal_val* builtin_delete(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_delete(std::vector& local_scope,nasal_gc& gc) { - nasal_val* hash_addr=local_scope[1]; - nasal_val* key_addr=local_scope[2]; + nasal_ref hash_addr=local_scope[1]; + nasal_ref key_addr=local_scope[2]; if(hash_addr->type!=vm_hash) { builtin_err("delete","\"hash\" must be hash"); @@ -643,9 +643,9 @@ nasal_val* builtin_delete(std::vector& local_scope,nasal_gc& gc) hash_addr->ptr.hash->elems.erase(*key_addr->ptr.str); return gc.nil_addr; } -nasal_val* builtin_keys(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_keys(std::vector& local_scope,nasal_gc& gc) { - nasal_val* hash_addr=local_scope[1]; + nasal_ref hash_addr=local_scope[1]; if(hash_addr->type!=vm_hash) { builtin_err("keys","\"hash\" must be hash"); @@ -654,25 +654,25 @@ nasal_val* builtin_keys(std::vector& local_scope,nasal_gc& gc) // push vector into local scope to avoid being sweeped local_scope.push_back(gc.gc_alloc(vm_vec)); - std::vector& vec=local_scope.back()->ptr.vec->elems; + std::vector& vec=local_scope.back()->ptr.vec->elems; for(auto iter:hash_addr->ptr.hash->elems) { - nasal_val* str_addr=gc.gc_alloc(vm_str); + nasal_ref str_addr=gc.gc_alloc(vm_str); *str_addr->ptr.str=iter.first; vec.push_back(str_addr); } return local_scope.back(); } -nasal_val* builtin_import(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_import(std::vector& local_scope,nasal_gc& gc) { // this function is used in preprocessing. // this function will return nothing when running. builtin_err("import","must use this function in global scope"); return nullptr; } -nasal_val* builtin_die(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_die(std::vector& local_scope,nasal_gc& gc) { - nasal_val* str_addr=local_scope[1]; + nasal_ref str_addr=local_scope[1]; if(str_addr->type!=vm_str) { builtin_err("die","\"str\" must be string"); @@ -681,10 +681,10 @@ nasal_val* builtin_die(std::vector& local_scope,nasal_gc& gc) std::cout<<"[vm] error: "<<*str_addr->ptr.str<<'\n'; return nullptr; } -nasal_val* builtin_type(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_type(std::vector& local_scope,nasal_gc& gc) { - nasal_val* val_addr=local_scope[1]; - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref val_addr=local_scope[1]; + nasal_ref ret_addr=gc.gc_alloc(vm_str); switch(val_addr->type) { case vm_nil: *ret_addr->ptr.str="nil"; break; @@ -696,11 +696,11 @@ nasal_val* builtin_type(std::vector& local_scope,nasal_gc& gc) } return ret_addr; } -nasal_val* builtin_substr(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_substr(std::vector& local_scope,nasal_gc& gc) { - nasal_val* str_addr=local_scope[1]; - nasal_val* beg_addr=local_scope[2]; - nasal_val* len_addr=local_scope[3]; + nasal_ref str_addr=local_scope[1]; + nasal_ref beg_addr=local_scope[2]; + nasal_ref len_addr=local_scope[3]; if(str_addr->type!=vm_str) { builtin_err("substr","\"str\" must be string"); @@ -726,22 +726,22 @@ nasal_val* builtin_substr(std::vector& local_scope,nasal_gc& gc) } if(len<0) len=0; - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); *ret_addr->ptr.str=str.substr(beg,len); return ret_addr; } -nasal_val* builtin_streq(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_streq(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; - nasal_val* b_addr=local_scope[2]; - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref a_addr=local_scope[1]; + nasal_ref b_addr=local_scope[2]; + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=(a_addr->type!=vm_str || b_addr->type!=vm_str)?0:(*a_addr->ptr.str==*b_addr->ptr.str); return ret_addr; } -nasal_val* builtin_left(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_left(std::vector& local_scope,nasal_gc& gc) { - nasal_val* str_addr=local_scope[1]; - nasal_val* len_addr=local_scope[2]; + nasal_ref str_addr=local_scope[1]; + nasal_ref len_addr=local_scope[2]; if(str_addr->type!=vm_str) { builtin_err("left","\"string\" must be string"); @@ -756,14 +756,14 @@ nasal_val* builtin_left(std::vector& local_scope,nasal_gc& gc) int len=(int)len_addr->ptr.num; if(len<0) len=0; - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); *ret_addr->ptr.str=str.substr(0, len); return ret_addr; } -nasal_val* builtin_right(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_right(std::vector& local_scope,nasal_gc& gc) { - nasal_val* str_addr=local_scope[1]; - nasal_val* len_addr=local_scope[2]; + nasal_ref str_addr=local_scope[1]; + nasal_ref len_addr=local_scope[2]; if(str_addr->type!=vm_str) { builtin_err("right","\"string\" must be string"); @@ -781,14 +781,14 @@ nasal_val* builtin_right(std::vector& local_scope,nasal_gc& gc) len=srclen; if(len<0) len=0; - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); *ret_addr->ptr.str=str.substr(srclen-len, srclen); return ret_addr; } -nasal_val* builtin_cmp(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_cmp(std::vector& local_scope,nasal_gc& gc) { - nasal_val* a_addr=local_scope[1]; - nasal_val* b_addr=local_scope[2]; + nasal_ref a_addr=local_scope[1]; + nasal_ref b_addr=local_scope[2]; if(a_addr->type!=vm_str) { builtin_err("cmp","\"a\" must be string"); @@ -799,11 +799,11 @@ nasal_val* builtin_cmp(std::vector& local_scope,nasal_gc& gc) builtin_err("cmp","\"b\" must be string"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); + nasal_ref ret_addr=gc.gc_alloc(vm_num); ret_addr->ptr.num=strcmp(a_addr->ptr.str->c_str(),b_addr->ptr.str->c_str()); return ret_addr; } -nasal_val* builtin_chr(std::vector& local_scope,nasal_gc& gc) +nasal_ref builtin_chr(std::vector& local_scope,nasal_gc& gc) { const char* extend[]={ "€"," ","‚","ƒ","„","…","†","‡", @@ -823,13 +823,13 @@ nasal_val* builtin_chr(std::vector& local_scope,nasal_gc& gc) "ð","ñ","ò","ó","ô","õ","ö","÷", "ø","ù","ú","û","ü","ý","þ","ÿ" }; - nasal_val* code_addr=local_scope[1]; + nasal_ref code_addr=local_scope[1]; if(code_addr->type!=vm_num) { builtin_err("chr","\"code\" must be number"); return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_ref ret_addr=gc.gc_alloc(vm_str); int num=code_addr->ptr.num; if(0<=num && num<128) *ret_addr->ptr.str=(char)num; diff --git a/nasal_gc.h b/nasal_gc.h index 5985372..48559da 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -24,34 +24,37 @@ const int increment[vm_type_size]= 512 // vm_hash }; -struct nasal_val;//declaration of nasal_val +// declaration of nasal_val +struct nasal_val; +// define nasal_ref => nasal_val* +typedef nasal_val* nasal_ref; struct nasal_vec// 24 bytes { - std::vector elems; + std::vector elems; void print(); - nasal_val* get_val(int); - nasal_val** get_mem(int); + nasal_ref get_val(int); + nasal_ref* get_mem(int); }; struct nasal_hash// 56 bytes { - std::unordered_map elems; + std::unordered_map elems; void print(); - nasal_val* get_val(std::string&); - nasal_val** get_mem(std::string&); + nasal_ref get_val(std::string&); + nasal_ref* get_mem(std::string&); }; struct nasal_func// 120 bytes { - int32_t dynpara;// dynamic parameter name index in hash - uint32_t offset; // arguments will be loaded into local scope from this offset - uint32_t entry; // pc will set to entry-1 to call this function - std::vector default_para;// default value(nasal_val*) + int32_t dynpara; // dynamic parameter name index in hash + uint32_t offset; // arguments will be loaded into local scope from this offset + uint32_t entry; // pc will set to entry-1 to call this function + std::vector default_para;// default value(nasal_ref) std::unordered_map key_table;// parameter name hash - nasal_val* closure;// closure will be loaded to gc.local.back() as the local scope + nasal_ref closure; // closure will be loaded to gc.local.back() as the local scope nasal_func(); void clear(); @@ -80,14 +83,14 @@ struct nasal_val// 16 bytes }; /*functions of nasal_vec*/ -nasal_val* nasal_vec::get_val(int index) +nasal_ref nasal_vec::get_val(int index) { int vec_size=elems.size(); if(index<-vec_size || index>=vec_size) return nullptr; return elems[index>=0?index:index+vec_size]; } -nasal_val** nasal_vec::get_mem(int index) +nasal_ref* nasal_vec::get_mem(int index) { int vec_size=elems.size(); if(index<-vec_size || index>=vec_size) @@ -129,14 +132,14 @@ void nasal_vec::print() } /*functions of nasal_hash*/ -nasal_val* nasal_hash::get_val(std::string& key) +nasal_ref nasal_hash::get_val(std::string& key) { if(elems.count(key)) return elems[key]; else if(elems.count("parents")) { - nasal_val* ret_addr=nullptr; - nasal_val* val_addr=elems["parents"]; + nasal_ref ret_addr=nullptr; + nasal_ref val_addr=elems["parents"]; if(val_addr->type==vm_vec) for(auto i:val_addr->ptr.vec->elems) { @@ -148,14 +151,14 @@ nasal_val* nasal_hash::get_val(std::string& key) } return nullptr; } -nasal_val** nasal_hash::get_mem(std::string& key) +nasal_ref* nasal_hash::get_mem(std::string& key) { if(elems.count(key)) return &elems[key]; else if(elems.count("parents")) { - nasal_val** mem_addr=nullptr; - nasal_val* val_addr=elems["parents"]; + nasal_ref* mem_addr=nullptr; + nasal_ref val_addr=elems["parents"]; if(val_addr->type==vm_vec) for(auto i:val_addr->ptr.vec->elems) { @@ -187,7 +190,7 @@ void nasal_hash::print() for(auto& i:elems) { std::cout<type) { case vm_nil: std::cout<<"nil"; break; @@ -262,35 +265,35 @@ std::string nasal_val::to_string() struct nasal_gc { #define STACK_MAX_DEPTH (4080) - nasal_val* zero_addr; // reserved address of nasal_val,type vm_num, 0 - nasal_val* one_addr; // reserved address of nasal_val,type vm_num, 1 - nasal_val* nil_addr; // reserved address of nasal_val,type vm_nil - nasal_val* val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow - nasal_val** stack_top; // stack top - std::vector num_addrs; // reserved address for const vm_num - std::vector str_addrs; // reserved address for const vm_str - std::vector memory; // gc memory - std::queue free_list[vm_type_size]; // gc free list - std::vector local; - void mark(); - void sweep(); - void gc_init(std::vector&,std::vector&); - void gc_clear(); - nasal_val* gc_alloc(int); - nasal_val* builtin_alloc(int); + nasal_ref zero_addr; // reserved address of nasal_val,type vm_num, 0 + nasal_ref one_addr; // reserved address of nasal_val,type vm_num, 1 + nasal_ref nil_addr; // reserved address of nasal_val,type vm_nil + nasal_ref val_stack[STACK_MAX_DEPTH+16];// 16 reserved to avoid stack overflow + nasal_ref* stack_top; // stack top + std::vector num_addrs; // reserved address for const vm_num + std::vector str_addrs; // reserved address for const vm_str + std::vector memory; // gc memory + std::queue free_list[vm_type_size]; // gc free list + std::vector local; + void mark(); + void sweep(); + void gc_init(std::vector&,std::vector&); + void gc_clear(); + nasal_ref gc_alloc(int); + nasal_ref builtin_alloc(int); }; /* gc functions */ void nasal_gc::mark() { - std::queue bfs; + std::queue bfs; for(auto i:local) bfs.push(i); - for(nasal_val** i=val_stack;i<=stack_top;++i) + for(nasal_ref* i=val_stack;i<=stack_top;++i) bfs.push(*i); while(!bfs.empty()) { - nasal_val* tmp=bfs.front(); + nasal_ref tmp=bfs.front(); bfs.pop(); if(tmp->mark) continue; tmp->mark=GC_FOUND; @@ -340,7 +343,7 @@ void nasal_gc::gc_init(std::vector& nums,std::vector& strs) for(int i=vm_num;imark=GC_UNCOLLECTED; free_list[type].pop(); return ret; } -nasal_val* nasal_gc::builtin_alloc(int type) +nasal_ref nasal_gc::builtin_alloc(int type) { // when running a builtin function,alloc will run more than one time // this may cause mark-sweep in gc_alloc @@ -420,11 +423,11 @@ nasal_val* nasal_gc::builtin_alloc(int type) if(free_list[type].empty()) for(int i=0;imark=GC_UNCOLLECTED; free_list[type].pop(); return ret; diff --git a/nasal_vm.h b/nasal_vm.h index f168c00..7f2a484 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -5,15 +5,16 @@ class nasal_vm { private: /* reference from nasal_gc */ - nasal_val**& stack_top;// stack top + nasal_ref*& stack_top;// stack top /* values of nasal_vm */ uint32_t pc; // program counter + std::stack cls_stk; // stack to store closure,if same closures detected,load the local scope std::stack ret; // ptr stack stores address for function to return std::stack counter; // iterator stack for forindex/foreach std::vector num_table;// numbers used in process(const calculation) std::vector str_table;// symbols used in process std::vector imm; // immediate number - nasal_val** mem_addr; // used for mem_call + nasal_ref* mem_addr; // used for mem_call nasal_gc gc; // garbage collector /* values used for debug */ std::vector bytecode; // bytecode @@ -25,7 +26,7 @@ private: void die(std::string); void stackoverflow(); /* vm calculation functions*/ - bool condition(nasal_val*); + bool condition(nasal_ref); void opr_intg(); void opr_intl(); void opr_offset(); @@ -128,6 +129,8 @@ void nasal_vm::clear() gc.gc_clear(); while(!ret.empty()) ret.pop(); + while(!cls_stk.empty()) + cls_stk.pop(); while(!counter.empty()) counter.pop(); num_table.clear(); @@ -170,7 +173,7 @@ void nasal_vm::stackinfo(int limit) { printf("vm stack(limit %d):\n",limit); uint32_t same_cnt=0; - nasal_val* last_ptr=(nasal_val*)0xffff; + nasal_ref last_ptr=(nasal_ref)0xffff; for(int i=0;i=gc.val_stack;++i) { if(stack_top[-i]==last_ptr) @@ -211,7 +214,7 @@ void nasal_vm::die(std::string str) ret.push(pc); traceback(); stackinfo(10); - gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_val*)0xffff; + gc.val_stack[STACK_MAX_DEPTH-1]=(nasal_ref)0xffff; return; } void nasal_vm::stackoverflow() @@ -221,7 +224,7 @@ void nasal_vm::stackoverflow() stackinfo(10); return; } -inline bool nasal_vm::condition(nasal_val* val_addr) +inline bool nasal_vm::condition(nasal_ref val_addr) { if(val_addr->type==vm_num) return val_addr->ptr.num; @@ -295,8 +298,8 @@ inline void nasal_vm::opr_pstr() } inline void nasal_vm::opr_newv() { - nasal_val* vec_addr=gc.gc_alloc(vm_vec); - nasal_val** begin=stack_top-imm[pc]+1; + nasal_ref vec_addr=gc.gc_alloc(vm_vec); + nasal_ref* begin=stack_top-imm[pc]+1; auto& vec=vec_addr->ptr.vec->elems;// stack_top-imm[pc] stores the vector vec.resize(imm[pc]); for(uint32_t i=0;iptr.hash->elems[str_table[imm[pc]]]=val; return; } @@ -337,7 +340,7 @@ inline void nasal_vm::opr_para() } inline void nasal_vm::opr_defpara() { - nasal_val* def_val=stack_top[0]; + nasal_ref def_val=stack_top[0]; nasal_func* func=(--stack_top)[0]->ptr.func; int size=func->key_table.size(); func->key_table[str_table[imm[pc]]]=size; @@ -351,7 +354,7 @@ inline void nasal_vm::opr_dynpara() } inline void nasal_vm::opr_unot() { - nasal_val* val=stack_top[0]; + nasal_ref val=stack_top[0]; switch(val->type) { case vm_nil:stack_top[0]=gc.one_addr;break; @@ -371,14 +374,14 @@ inline void nasal_vm::opr_unot() } inline void nasal_vm::opr_usub() { - nasal_val* new_val=gc.gc_alloc(vm_num); + nasal_ref new_val=gc.gc_alloc(vm_num); new_val->ptr.num=-stack_top[0]->to_number(); stack_top[0]=new_val; return; } #define op_calc(type)\ - nasal_val* new_val=gc.gc_alloc(vm_num);\ + nasal_ref new_val=gc.gc_alloc(vm_num);\ new_val->ptr.num=stack_top[-1]->to_number() type stack_top[0]->to_number();\ (--stack_top)[0]=new_val; @@ -388,14 +391,14 @@ inline void nasal_vm::opr_mul(){op_calc(*);} inline void nasal_vm::opr_div(){op_calc(/);} inline void nasal_vm::opr_lnk() { - nasal_val* new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.gc_alloc(vm_str); *new_val->ptr.str=stack_top[-1]->to_string()+stack_top[0]->to_string(); (--stack_top)[0]=new_val; return; } #define op_calc_const(type)\ - nasal_val* new_val=gc.gc_alloc(vm_num);\ + nasal_ref new_val=gc.gc_alloc(vm_num);\ new_val->ptr.num=stack_top[0]->to_number() type num_table[imm[pc]];\ stack_top[0]=new_val; @@ -405,14 +408,14 @@ inline void nasal_vm::opr_mulc(){op_calc_const(*);} inline void nasal_vm::opr_divc(){op_calc_const(/);} inline void nasal_vm::opr_lnkc() { - nasal_val* new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.gc_alloc(vm_str); *new_val->ptr.str=stack_top[0]->to_string()+str_table[imm[pc]]; stack_top[0]=new_val; return; } #define op_calc_eq(type)\ - nasal_val* new_val=gc.gc_alloc(vm_num);\ + nasal_ref new_val=gc.gc_alloc(vm_num);\ new_val->ptr.num=mem_addr[0]->to_number() type stack_top[-1]->to_number();\ (--stack_top)[0]=mem_addr[0]=new_val; @@ -422,14 +425,14 @@ inline void nasal_vm::opr_muleq(){op_calc_eq(*);} inline void nasal_vm::opr_diveq(){op_calc_eq(/);} inline void nasal_vm::opr_lnkeq() { - nasal_val* new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.gc_alloc(vm_str); *new_val->ptr.str=mem_addr[0]->to_string()+stack_top[-1]->to_string(); (--stack_top)[0]=mem_addr[0]=new_val; return; } #define op_calc_eq_const(type)\ - nasal_val* new_val=gc.gc_alloc(vm_num);\ + nasal_ref new_val=gc.gc_alloc(vm_num);\ new_val->ptr.num=mem_addr[0]->to_number() type num_table[imm[pc]];\ stack_top[0]=mem_addr[0]=new_val; @@ -439,7 +442,7 @@ inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);} inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);} inline void nasal_vm::opr_lnkeqc() { - nasal_val* new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.gc_alloc(vm_str); *new_val->ptr.str=mem_addr[0]->to_string()+str_table[imm[pc]]; stack_top[0]=mem_addr[0]=new_val; return; @@ -452,8 +455,8 @@ inline void nasal_vm::opr_meq() } inline void nasal_vm::opr_eq() { - nasal_val* val2=stack_top[0]; - nasal_val* val1=(--stack_top)[0]; + nasal_ref val2=stack_top[0]; + nasal_ref val1=(--stack_top)[0]; int a_type=val1->type; int b_type=val2->type; if(a_type==vm_nil && b_type==vm_nil) @@ -468,8 +471,8 @@ inline void nasal_vm::opr_eq() } inline void nasal_vm::opr_neq() { - nasal_val* val2=stack_top[0]; - nasal_val* val1=(--stack_top)[0]; + nasal_ref val2=stack_top[0]; + nasal_ref val1=(--stack_top)[0]; int a_type=val1->type; int b_type=val2->type; if(a_type==vm_nil && b_type==vm_nil) @@ -547,7 +550,7 @@ inline void nasal_vm::opr_findex() } inline void nasal_vm::opr_feach() { - std::vector& ref=stack_top[0]->ptr.vec->elems; + std::vector& ref=stack_top[0]->ptr.vec->elems; if(++counter.top()>=ref.size()) { pc=imm[pc]-1; @@ -568,8 +571,8 @@ inline void nasal_vm::opr_calll() } inline void nasal_vm::opr_callv() { - nasal_val* val=stack_top[0]; - nasal_val* vec_addr=(--stack_top)[0]; + nasal_ref val=stack_top[0]; + nasal_ref vec_addr=(--stack_top)[0]; if(vec_addr->type==vm_vec) { stack_top[0]=vec_addr->ptr.vec->get_val(val->to_number()); @@ -611,7 +614,7 @@ inline void nasal_vm::opr_callv() } inline void nasal_vm::opr_callvi() { - nasal_val* val=stack_top[0]; + nasal_ref val=stack_top[0]; if(val->type!=vm_vec) { die("callvi: must use a vector"); @@ -625,7 +628,7 @@ inline void nasal_vm::opr_callvi() } inline void nasal_vm::opr_callh() { - nasal_val* val=stack_top[0]; + nasal_ref val=stack_top[0]; if(val->type!=vm_hash) { die("callh: must call a hash"); @@ -645,8 +648,8 @@ inline void nasal_vm::opr_callfv() { // get parameter list and function value uint32_t args_size=imm[pc]; - nasal_val** vec=stack_top-args_size+1; - nasal_val* func_addr=vec[-1]; + nasal_ref* vec=stack_top-args_size+1; + nasal_ref func_addr=vec[-1]; if(func_addr->type!=vm_func) { die("callfv: must call a function"); @@ -654,6 +657,7 @@ inline void nasal_vm::opr_callfv() } // push new local scope auto& ref_func=*func_addr->ptr.func; + cls_stk.push(func_addr->ptr.func->closure); gc.local.push_back(gc.gc_alloc(vm_vec)); gc.local.back()->ptr.vec->elems=ref_func.closure->ptr.vec->elems; // load parameters @@ -678,7 +682,7 @@ inline void nasal_vm::opr_callfv() // load dynamic argument if args_size>=para_size if(ref_func.dynpara>=0) { - nasal_val* vec_addr=gc.gc_alloc(vm_vec); + nasal_ref vec_addr=gc.gc_alloc(vm_vec); for(uint32_t i=para_size;iptr.vec->elems.push_back(vec[i]); ref_closure[para_size+offset]=vec_addr; @@ -693,7 +697,7 @@ inline void nasal_vm::opr_callfh() { // get parameter list and function value auto& ref_hash=stack_top[0]->ptr.hash->elems; - nasal_val* func_addr=stack_top[-1]; + nasal_ref func_addr=stack_top[-1]; if(func_addr->type!=vm_func) { die("callfh: must call a function"); @@ -701,6 +705,7 @@ inline void nasal_vm::opr_callfh() } // push new local scope auto& ref_func=*func_addr->ptr.func; + cls_stk.push(func_addr->ptr.func->closure); gc.local.push_back(gc.gc_alloc(vm_vec)); gc.local.back()->ptr.vec->elems=ref_func.closure->ptr.vec->elems; // load parameters @@ -757,8 +762,8 @@ inline void nasal_vm::opr_slcend() } inline void nasal_vm::opr_slc() { - nasal_val* val=(stack_top--)[0]; - nasal_val* res=stack_top[-1]->ptr.vec->get_val(val->to_number()); + nasal_ref val=(stack_top--)[0]; + nasal_ref res=stack_top[-1]->ptr.vec->get_val(val->to_number()); if(!res) die("slc: index out of range:"+std::to_string(val->to_number())); stack_top[0]->ptr.vec->elems.push_back(res); @@ -766,10 +771,10 @@ inline void nasal_vm::opr_slc() } inline void nasal_vm::opr_slc2() { - nasal_val* val2=(stack_top--)[0]; - nasal_val* val1=(stack_top--)[0]; - std::vector& ref=stack_top[-1]->ptr.vec->elems; - std::vector& aim=stack_top[0]->ptr.vec->elems; + nasal_ref val2=(stack_top--)[0]; + nasal_ref val1=(stack_top--)[0]; + std::vector& ref=stack_top[-1]->ptr.vec->elems; + std::vector& aim=stack_top[0]->ptr.vec->elems; int type1=val1->type,type2=val2->type; int num1=val1->to_number(); @@ -810,8 +815,8 @@ inline void nasal_vm::opr_mcalll() } inline void nasal_vm::opr_mcallv() { - nasal_val* val=stack_top[0]; - nasal_val* vec_addr=(--stack_top)[0]; + nasal_ref val=stack_top[0]; + nasal_ref vec_addr=(--stack_top)[0]; int type=vec_addr->type; if(type==vm_vec) { @@ -841,7 +846,7 @@ inline void nasal_vm::opr_mcallv() } inline void nasal_vm::opr_mcallh() { - nasal_val* hash_addr=stack_top[0]; + nasal_ref hash_addr=stack_top[0]; if(hash_addr->type!=vm_hash) { die("mcallh: must call a hash"); @@ -859,11 +864,27 @@ inline void nasal_vm::opr_mcallh() } inline void nasal_vm::opr_ret() { - auto& vec=stack_top[-1]->ptr.func->closure->ptr.vec->elems; - for(uint32_t i=0;iptr.func->offset;++i) - vec[i]=gc.local.back()->ptr.vec->elems[i]; - vec[0]=gc.nil_addr;// set 'me' to nil - gc.local.pop_back();// delete local scope + nasal_func* func=stack_top[-1]->ptr.func; + uint32_t offset=func->offset; + nasal_ref cls=cls_stk.top();cls_stk.pop(); + // same closure detected,update the last local scope instead of the closure + if(!cls_stk.empty() && cls_stk.top()==cls) + { + auto& vec=gc.local.back()->ptr.vec->elems; + auto& func_vec=func->closure->ptr.vec->elems; + gc.local.pop_back(); + for(uint32_t i=0;iptr.vec->elems[i]=func_vec[i]=vec[i]; + } + else + { + auto& vec=func->closure->ptr.vec->elems; + for(uint32_t i=0;iptr.vec->elems[i]; + gc.local.pop_back(); + vec[0]=gc.nil_addr;// set 'me' to nil + } + pc=ret.top();ret.pop();// fetch pc --stack_top; stack_top[0]=stack_top[1];// rewrite nasal_func with returned value @@ -910,7 +931,7 @@ void nasal_vm::run(std::vector& exec,bool op_cnt) goto *code[pc]; nop: - if(canary && canary!=(nasal_val*)0xffff) + if(canary && canary!=(nasal_ref)0xffff) stackoverflow(); if(op_cnt) { diff --git a/test/lexer.nas b/test/lexer.nas index 94304de..b66a9fa 100644 --- a/test/lexer.nas +++ b/test/lexer.nas @@ -2,23 +2,23 @@ import("lib.nas"); var lexer=func(file) { - var _={ptr:0,token:[]}; + var (ptr,token)=(0,[]); var s=io.fin(file); var len=size(s); return { jmp_note:func() { - while(_.ptr=len) + if(ptr>=len) print("read eof when generating string.\n"); - _.ptr+=1; - append(_.token,str); + ptr+=1; + append(token,str); }, num_gen:func() { - var number=chr(s[_.ptr]); - _.ptr+=1; - if(_.ptr' or c=='<' or c=='!' or c=='=') { var tmp=c; - _.ptr+=1; - if(_.ptr0) - append(_.token,c); - _.ptr+=1; + elsif(c!=' ' and c!='\t' and c!='\n' and c!='\r' and s[ptr]>0) + append(token,c); + ptr+=1; return; }, main:func() { - while(_.ptr