From 144e6f45da896b039e37d79082952129d84d2c21 Mon Sep 17 00:00:00 2001 From: Valk Richard Li <48872266+ValKmjolnir@users.noreply.github.com> Date: Sat, 27 Mar 2021 01:08:05 +0800 Subject: [PATCH] gc changed to mark-sweep --- README.md | 2 +- lib.nas | 84 ++-- main.cpp | 24 +- nasal.h | 13 +- nasal_ast.h | 72 ++-- nasal_builtin.h | 816 +++++++++++++++++------------------ nasal_codegen.h | 580 +++++++++++++------------ nasal_gc.h | 686 +++++++++++------------------ nasal_parse.h | 24 +- nasal_vm.h | 1093 ++++++++++++++++++++--------------------------- test/bp.nas | 15 +- test/class.nas | 30 +- test/fib.nas | 34 +- test/lexer.nas | 121 +++--- test/lib.nas | 84 ++-- 15 files changed, 1678 insertions(+), 2000 deletions(-) diff --git a/README.md b/README.md index fcf580d..2a0da0f 100644 --- a/README.md +++ b/README.md @@ -342,7 +342,7 @@ struct FUNC_TABLE nasal_val* (*func_pointer)(nasal_val* x,nasal_gc& gc); } builtin_func_table[]= { - {"nasal_call_builtin_std_cout",builtin_print}, + {"__builtin_std_cout",builtin_print}, {"",NULL} }; ``` diff --git a/lib.nas b/lib.nas index 3a0029d..2974927 100644 --- a/lib.nas +++ b/lib.nas @@ -1,157 +1,157 @@ var import=func(filename) { - nasal_call_import(filename); + __builtin_import(filename); return nil; } var print=func(elements...) { - nasal_call_builtin_std_cout(elements); + __builtin_std_cout(elements); return nil; }; var println=func(elements...) { - nasal_call_builtin_std_cout(elements); + __builtin_std_cout(elements); print('\n'); return nil; } var append=func(vector,elements...) { - nasal_call_builtin_push_back(vector,elements); + __builtin_push_back(vector,elements); return nil; } var setsize=func(vector,size) { - nasal_call_builtin_set_size(vector,size); + __builtin_set_size(vector,size); return nil; } var system=func(str) { - nasal_call_builtin_system(str); + __builtin_system(str); return; } var input=func() { - return nasal_call_builtin_input(); + return __builtin_input(); } var sleep=func(duration) { - nasal_call_builtin_sleep(duration); + __builtin_sleep(duration); return; } var split=func(delimeter,string) { - return nasal_call_builtin_split(delimeter,string); + return __builtin_split(delimeter,string); } var rand=func(seed=nil) { - return nasal_call_builtin_rand(seed); + return __builtin_rand(seed); } var id=func(thing) { - return nasal_call_builtin_get_id(thing); + return __builtin_get_id(thing); } var int=func(value) { - return nasal_call_builtin_trans_int(value); + return __builtin_int(value); } var num=func(value) { - return nasal_call_builtin_trans_num(value); + return __builtin_num(value); } var pop=func(vector) { - return nasal_call_builtin_pop_back(vector); + return __builtin_pop_back(vector); } var str=func(number) { - return nasal_call_builtin_trans_str(number); + return __builtin_str(number); } var size=func(object) { - return nasal_call_builtin_size(object); + return __builtin_size(object); } var contains=func(hash,key) { - return nasal_call_builtin_contains(hash,key); + return __builtin_contains(hash,key); } var delete=func(hash,key) { - nasal_call_builtin_delete(hash,key); + __builtin_delete(hash,key); return; } var keys=func(hash) { - return nasal_call_builtin_get_keys(hash); + return __builtin_get_keys(hash); } var time=func(begin_time) { - return nasal_call_builtin_time(begin_time); + return __builtin_time(begin_time); } var die=func(str) { - nasal_call_builtin_die(str); + __builtin_die(str); return nil; } var typeof=func(object) { - return nasal_call_builtin_type(object); + return __builtin_type(object); } var substr=func(str,begin,length) { - return nasal_call_builtin_substr(str,begin,length); + return __builtin_substr(str,begin,length); } var streq=func(a,b) { - return nasal_call_builtin_streq(a,b); + return __builtin_streq(a,b); } var left=func(string,length) { - return nasal_call_builtin_left(string,length); + return __builtin_left(string,length); } var right=func(string,length) { - return nasal_call_builtin_right(string,length); + return __builtin_right(string,length); } var cmp=func(a,b) { - return nasal_call_builtin_cmp(a,b); + return __builtin_cmp(a,b); } var chr=func(code) #//Unlike in FG, this chr does not support Extended ASCII { - return nasal_call_builtin_chr(code); + return __builtin_chr(code); } var io= { fin:func(filename) { - return nasal_call_builtin_finput(filename); + return __builtin_fin(filename); }, fout:func(filename,str) { - nasal_call_builtin_foutput(filename,str); + __builtin_fout(filename,str); return; } }; var bits= { - bitxor: func(a,b){return nasal_call_builtin_xor(a,b); }, - bitand: func(a,b){return nasal_call_builtin_and(a,b); }, - bitor: func(a,b){return nasal_call_builtin_or(a,b); }, - bitnand: func(a,b){return nasal_call_builtin_nand(a,b);}, - bitnot: func(a) {return nasal_call_builtin_not(a); } + bitxor: func(a,b){return __builtin_xor(a,b); }, + bitand: func(a,b){return __builtin_and(a,b); }, + bitor: func(a,b){return __builtin_or(a,b); }, + bitnand: func(a,b){return __builtin_nand(a,b);}, + bitnot: func(a) {return __builtin_not(a); } }; var math= { e: 2.7182818284590452354, pi: 3.14159265358979323846264338327950288, - sin: func(x) {return nasal_call_builtin_sin(x); }, - cos: func(x) {return nasal_call_builtin_cos(x); }, - tan: func(x) {return nasal_call_builtin_tan(x); }, - exp: func(x) {return nasal_call_builtin_exp(x); }, - ln: func(x) {return nasal_call_builtin_cpp_math_ln(x); }, - sqrt: func(x) {return nasal_call_builtin_cpp_math_sqrt(x);}, - atan2: func(x,y){return nasal_call_builtin_cpp_atan2(x,y); } + sin: func(x) {return __builtin_sin(x); }, + cos: func(x) {return __builtin_cos(x); }, + tan: func(x) {return __builtin_tan(x); }, + exp: func(x) {return __builtin_exp(x); }, + ln: func(x) {return __builtin_ln(x); }, + sqrt: func(x) {return __builtin_sqrt(x); }, + atan2: func(x,y){return __builtin_atan2(x,y);} }; diff --git a/main.cpp b/main.cpp index 7b806bb..2ce3eba 100644 --- a/main.cpp +++ b/main.cpp @@ -10,15 +10,15 @@ nasal_vm vm; void help() { std::cout - <<">> [\"file\"] input a file name.\n" - <<">> [help ] show help.\n" - <<">> [clear ] clear the screen.\n" - <<">> [lex ] use lexer to turn code into tokens.\n" + <<">> [\"file\"] input a file name. \n" + <<">> [help ] show help. \n" + <<">> [clear ] clear the screen. \n" + <<">> [lex ] use lexer to turn code into tokens. \n" <<">> [ast ] do parsing and check the abstract syntax tree.\n" - <<">> [code ] show byte code.\n" - <<">> [exec ] execute program on bytecode vm.\n" - <<">> [logo ] print logo of nasal .\n" - <<">> [exit ] quit nasal interpreter.\n"; + <<">> [code ] show byte code. \n" + <<">> [exec ] execute program on bytecode vm. \n" + <<">> [logo ] print logo of nasal . \n" + <<">> [exit ] quit nasal interpreter. \n"; return; } @@ -90,11 +90,13 @@ void execute(std::string& command) codegen.print_byte_code(); return; } - vm.run( - codegen.get_string_table(), - codegen.get_number_table(), + vm.init( + codegen.get_str_table(), + codegen.get_num_table(), codegen.get_exec_code() ); + vm.run(); + vm.clear(); return; } diff --git a/nasal.h b/nasal.h index ccd55c3..9c2d0ab 100644 --- a/nasal.h +++ b/nasal.h @@ -25,7 +25,7 @@ check if a string can be converted to a number if this string cannot be converted to a number,it will return nan */ -inline double hex_to_double(std::string str) +inline double hex_to_double(std::string& str) { double ret=0; for(int i=2;str[i];++i) @@ -42,7 +42,7 @@ inline double hex_to_double(std::string str) } return ret; } -inline double oct_to_double(std::string str) +inline double oct_to_double(std::string& str) { double ret=0; for(int i=2;str[i];++i) @@ -55,7 +55,7 @@ inline double oct_to_double(std::string str) } return ret; } -inline double dec_to_double(std::string str,int len) +inline double dec_to_double(std::string& str,int len) { double ret=0; int i=0; @@ -96,14 +96,13 @@ inline double dec_to_double(std::string str,int len) } double trans_string_to_number(std::string str) { - double is_negative=1; + bool is_negative=false; int len=str.length(); double ret_num=0; - if(!len) return std::nan(""); if(str[0]=='-' || str[0]=='+') { if(len==1) return std::nan(""); - is_negative=(str[0]=='-'?-1:1); + is_negative=(str[0]=='-'); str=str.substr(1,len--); } if(len>1 && str[0]=='0' && str[1]=='x') @@ -112,7 +111,7 @@ double trans_string_to_number(std::string str) ret_num=oct_to_double(str); else ret_num=dec_to_double(str,len); - return is_negative*ret_num; + return is_negative?-ret_num:ret_num; } /* diff --git a/nasal_ast.h b/nasal_ast.h index 8b1a7b4..b3965f8 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -3,7 +3,9 @@ enum ast_node { - ast_null=0,ast_root,ast_block, + ast_null=0, + ast_root, + ast_block, ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec, ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec, ast_args,ast_default_arg,ast_dynamic_id, @@ -116,68 +118,68 @@ public: nasal_ast::nasal_ast(int init_line=0,int init_type=ast_null) { - this->line=init_line; - this->type=init_type; + line=init_line; + type=init_type; return; } nasal_ast::nasal_ast(const nasal_ast& tmp) { - this->line=tmp.line; - this->type=tmp.type; - this->str=tmp.str; - this->num=tmp.num; - this->children=tmp.children; + line=tmp.line; + type=tmp.type; + str=tmp.str; + num=tmp.num; + children=tmp.children; return; } nasal_ast::~nasal_ast() { - this->children.clear(); + children.clear(); return; } nasal_ast& nasal_ast::operator=(const nasal_ast& tmp) { - this->line=tmp.line; - this->type=tmp.type; - this->str=tmp.str; - this->num=tmp.num; - this->children=tmp.children; + line=tmp.line; + type=tmp.type; + str=tmp.str; + num=tmp.num; + children=tmp.children; return *this; } void nasal_ast::clear() { - this->line=0; - this->str=""; - this->num=0; - this->type=ast_null; - this->children.clear(); + line=0; + str=""; + num=0; + type=ast_null; + children.clear(); return; } void nasal_ast::set_line(int l) { - this->line=l; + line=l; return; } void nasal_ast::set_type(int t) { - this->type=t; + type=t; return; } void nasal_ast::set_str(std::string& s) { - this->str=s; + str=s; return; } void nasal_ast::set_num(double n) { - this->num=n; + num=n; return; } @@ -189,43 +191,43 @@ void nasal_ast::add_child(nasal_ast ast) int nasal_ast::get_line() { - return this->line; + return line; } int nasal_ast::get_type() { - return this->type; + return type; } std::string nasal_ast::get_str() { - return this->str; + return str; } double nasal_ast::get_num() { - return this->num; + return num; } std::vector& nasal_ast::get_children() { - return this->children; + return children; } void nasal_ast::print_ast(int depth) { std::string indentation=""; for(int i=0;itype); + indentation+=ast_name(type); std::cout<type==ast_str || this->type==ast_id || this->type==ast_dynamic_id || this->type==ast_callh) - std::cout<<":"<str; - else if(this->type==ast_num) - std::cout<<":"<num; + if(type==ast_str || type==ast_id || type==ast_dynamic_id || type==ast_callh) + std::cout<<":"<children.size(); + int child_size=children.size(); for(int i=0;ichildren[i].print_ast(depth+1); + children[i].print_ast(depth+1); return; } diff --git a/nasal_builtin.h b/nasal_builtin.h index 21b4c68..66d49e1 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -1,73 +1,72 @@ #ifndef __NASAL_BUILTIN_H__ #define __NASAL_BUILTIN_H__ +/* + builtin functions must be called inside a outer function like this: + var print=func(elements...) + { + __builtin_std_cout(elements); + return nil; + } + builtin function __builtin_std_cout is wrapped up by print +*/ -// builtin functions must be called inside a outer function like this: -// var print=func(elements...) -// { -// nasal_call_builtin_std_cout(elements); -// return nil; -// } -// builtin function nasal_call_builtin_std_cout is wrapped up by print - -std::unordered_map builtin_use_string_table; +std::unordered_map builtin_use_str_table; // used to find values that builtin function uses -#define in_builtin_find(value_name_string) \ +#define in_builtin_find(val_name) \ (\ local_scope_addr\ - ->get_closure()\ - .get_value_address\ - (builtin_use_string_table[value_name_string])\ + ->ptr.scop\ + ->get_val\ + (builtin_use_str_table[val_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_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_finput(nasal_val*,nasal_gc&); -nasal_val* builtin_foutput(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&); -bool builtin_die_state;// used in builtin_die -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&); +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*); void builtin_error_occurred(std::string func_name,std::string info) { - builtin_die_state=true; std::cout<<">> [vm] "<get_vector(); + std::vector& ref_vec=vector_value_addr->ptr.vec->elems; int size=ref_vec.size(); for(int i=0;iget_type()) + switch(tmp->type) { - case vm_nil: std::cout<<"nil"; break; - case vm_num: std::cout<get_number(); break; - case vm_str: std::cout<get_string(); break; - case vm_vec: tmp->get_vector().print(); break; - case vm_hash: tmp->get_hash().print(); break; - case vm_func: std::cout<<"func(...){...}"; break; + case vm_nil: std::cout<<"nil"; break; + case vm_num: std::cout<ptr.num; break; + case vm_str: std::cout<<*tmp->ptr.str; break; + case vm_vec: tmp->ptr.vec->print(); break; + case vm_hash: tmp->ptr.hash->print(); break; + case vm_func: std::cout<<"func(...){...}"; break; } } // generate return value - return gc.gc_alloc(vm_nil); + return nil_addr; } -nasal_val* builtin_append(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_append(nasal_val* local_scope_addr) { nasal_val* vector_value_addr=in_builtin_find("vector"); nasal_val* elem_value_addr=in_builtin_find("elements"); - if(vector_value_addr->get_type()!=vm_vec) + if(vector_value_addr->type!=vm_vec) { builtin_error_occurred("append","\"vector\" must be vector"); - return NULL; + return nullptr; } - nasal_vec& ref_vector=vector_value_addr->get_vector(); - nasal_vec& ref_elements=elem_value_addr->get_vector(); - int size=ref_elements.size(); + nasal_vec& ref_vector=*vector_value_addr->ptr.vec; + nasal_vec& ref_elements=*elem_value_addr->ptr.vec; + int size=ref_elements.elems.size(); for(int i=0;iget_type()!=vm_vec) + if(vector_value_addr->type!=vm_vec) { builtin_error_occurred("setsize","\"vector\" must be vector"); - return NULL; + return nullptr; } - int type=size_value_addr->get_type(); + int type=size_value_addr->type; if(type!=vm_num) { builtin_error_occurred("setsize","\"size\" is not a number"); - return NULL; + return nullptr; } - int number=size_value_addr->get_number(); + int number=size_value_addr->ptr.num; if(number<0) { builtin_error_occurred("setsize","\"size\" must be greater than -1"); - return NULL; + return nullptr; } - nasal_vec& ref_vector=vector_value_addr->get_vector(); - int vec_size=ref_vector.size(); + nasal_vec& ref_vector=*vector_value_addr->ptr.vec; + int vec_size=ref_vector.elems.size(); if(numbervec_size) for(int i=vec_size;iget_type()!=vm_str) + if(str_value_addr->type!=vm_str) { builtin_error_occurred("system","\"str\" must be string"); - return NULL; + return nullptr; } - std::string str=str_value_addr->get_string(); - system(str.data()); - nasal_val* ret_addr=gc.gc_alloc(vm_nil); + system(str_value_addr->ptr.str->data()); + nasal_val* ret_addr=nil_addr; return ret_addr; } -nasal_val* builtin_input(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_input(nasal_val* local_scope_addr) { - nasal_val* ret_addr=gc.gc_alloc(vm_str); - std::string str; - std::cin>>str; - ret_addr->set_string(str); + nasal_val* ret_addr=gc_alloc(vm_str); + std::cin>>*ret_addr->ptr.str; return ret_addr; } -nasal_val* builtin_sleep(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_sleep(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("duration"); - int type=value_addr->get_type(); + int type=value_addr->type; if(type!=vm_num) { builtin_error_occurred("sleep","\"duration\" must be number"); - return NULL; + return nullptr; } // sleep in unistd.h will make this progress sleep sleep_time seconds. - sleep((unsigned long)value_addr->get_number()); - nasal_val* ret_addr=gc.gc_alloc(vm_nil); - return ret_addr; + sleep((unsigned long)value_addr->ptr.num); + return nil_addr; } -nasal_val* builtin_finput(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_fin(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("filename"); - if(value_addr->get_type()!=vm_str) + if(value_addr->type!=vm_str) { builtin_error_occurred("io.fin","\"filename\" must be string"); - return NULL; + return nullptr; } - std::string filename=value_addr->get_string(); + std::string& filename=*value_addr->ptr.str; std::ifstream fin(filename); - std::string file_content=""; + nasal_val* ret_addr=gc_alloc(vm_str); + *ret_addr->ptr.str=""; if(!fin.fail()) while(!fin.eof()) { char c=fin.get(); if(fin.eof()) break; - file_content.push_back(c); + ret_addr->ptr.str->push_back(c); } else - builtin_error_occurred("io.fin","cannot open \""+filename+"\"."); + builtin_error_occurred("io.fin","cannot open \""+filename+"\""); fin.close(); - nasal_val* ret_addr=gc.gc_alloc(vm_str); - ret_addr->set_string(file_content); return ret_addr; } -nasal_val* builtin_foutput(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_fout(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("filename"); nasal_val* str_value_addr=in_builtin_find("str"); - if(value_addr->get_type()!=vm_str) + if(value_addr->type!=vm_str) { builtin_error_occurred("io.fout","\"filename\" must be string"); - return NULL; + return nullptr; } - if(str_value_addr->get_type()!=vm_str) + if(str_value_addr->type!=vm_str) { builtin_error_occurred("io.fout","\"str\" must be string"); - return NULL; + return nullptr; } - std::string filename=value_addr->get_string(); - std::string file_content=str_value_addr->get_string(); - std::ofstream fout(filename); - fout<ptr.str); + if(fout.fail()) + { + builtin_error_occurred("io.fout","cannot open \""+*value_addr->ptr.str+"\""); + return nullptr; + } + fout<<*str_value_addr->ptr.str; fout.close(); - nasal_val* ret_addr=gc.gc_alloc(vm_nil); - return ret_addr; + return nil_addr; } -nasal_val* builtin_split(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_split(nasal_val* local_scope_addr) { nasal_val* delimeter_value_addr=in_builtin_find("delimeter"); nasal_val* string_value_addr=in_builtin_find("string"); - if(delimeter_value_addr->get_type()!=vm_str) + if(delimeter_value_addr->type!=vm_str) { builtin_error_occurred("split","\"delimeter\" must be string"); - return NULL; + return nullptr; } - if(string_value_addr->get_type()!=vm_str) + if(string_value_addr->type!=vm_str) { builtin_error_occurred("split","\"string\" must be string"); - return NULL; + return nullptr; } - std::string delimeter=delimeter_value_addr->get_string(); - std::string source=string_value_addr->get_string(); + std::string delimeter=*delimeter_value_addr->ptr.str; + std::string source=*string_value_addr->ptr.str; int delimeter_len=delimeter.length(); int source_len=source.length(); - nasal_val* ret_addr=gc.gc_alloc(vm_vec); - nasal_vec& ref_vec=ret_addr->get_vector(); + nasal_val* ret_addr=gc_alloc(vm_vec); + nasal_vec& ref_vec=*ret_addr->ptr.vec; std::string tmp=""; if(!delimeter_len) { for(int i=0;iset_string(tmp); - ref_vec.add_elem(str_addr); + nasal_val* str_addr=gc_alloc(vm_str); + *str_addr->ptr.str=source[i]; + ref_vec.elems.push_back(str_addr); } return ret_addr; } @@ -344,9 +334,9 @@ nasal_val* builtin_split(nasal_val* local_scope_addr,nasal_gc& gc) { if(tmp.length()) { - nasal_val* str_addr=gc.gc_alloc(vm_str); - str_addr->set_string(tmp); - ref_vec.add_elem(str_addr); + nasal_val* str_addr=gc_alloc(vm_str); + *str_addr->ptr.str=tmp; + ref_vec.elems.push_back(str_addr); tmp=""; } i+=delimeter_len-1; @@ -356,527 +346,517 @@ nasal_val* builtin_split(nasal_val* local_scope_addr,nasal_gc& gc) } if(tmp.length()) { - nasal_val* str_addr=gc.gc_alloc(vm_str); - str_addr->set_string(tmp); - ref_vec.add_elem(str_addr); + nasal_val* str_addr=gc_alloc(vm_str); + *str_addr->ptr.str=tmp; + ref_vec.elems.push_back(str_addr); tmp=""; } return ret_addr; } -nasal_val* builtin_rand(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_rand(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("seed"); - if(value_addr->get_type()!=vm_num && value_addr->get_type()!=vm_nil) + if(value_addr->type!=vm_num && value_addr->type!=vm_nil) { builtin_error_occurred("rand","\"seed\" must be nil or number"); - return NULL; + return nullptr; } - if(value_addr->get_type()==vm_num) + if(value_addr->type==vm_num) { - unsigned int number=(unsigned int)value_addr->get_number(); + unsigned int number=(unsigned int)value_addr->ptr.num; srand(number); - nasal_val* ret_addr=gc.gc_alloc(vm_nil); + nasal_val* ret_addr=nil_addr; return ret_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.gc_alloc(vm_num); - ret_addr->set_number(num); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=num; return ret_addr; } -nasal_val* builtin_id(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_id(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("thing"); - nasal_val* ret_addr=gc.gc_alloc(vm_str); + nasal_val* ret_addr=gc_alloc(vm_str); char buf[32]; sprintf(buf,"0x%p",value_addr); - ret_addr->set_string(buf); + *ret_addr->ptr.str=buf; return ret_addr; } -nasal_val* builtin_int(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_int(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("value"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("int","\"value\" must be number"); - return NULL; + return nullptr; } - int number=(int)value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)number); + int number=(int)value_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(double)number; return ret_addr; } -nasal_val* builtin_num(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_num(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("value"); - if(value_addr->get_type()!=vm_str) + if(value_addr->type!=vm_str) { builtin_error_occurred("num","\"value\" must be string"); - return NULL; + return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(value_addr->to_number()); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=value_addr->to_number(); return ret_addr; } -nasal_val* builtin_pop(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_pop(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("vector"); - if(value_addr->get_type()!=vm_vec) + if(value_addr->type!=vm_vec) { builtin_error_occurred("pop","\"vector\" must be vector"); - return NULL; + return nullptr; } - nasal_val* ret_addr=value_addr->get_vector().del_elem(); - return ret_addr; + if(value_addr->ptr.vec->elems.size()) + { + nasal_val* tmp=value_addr->ptr.vec->elems.back(); + value_addr->ptr.vec->elems.pop_back(); + return tmp; + } + return nil_addr; } -nasal_val* builtin_str(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_str(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("number"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("str","\"number\" must be number"); - return NULL; + return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_string(value_addr->to_string()); + nasal_val* ret_addr=gc_alloc(vm_num); + *ret_addr->ptr.str=value_addr->to_string(); return ret_addr; } -nasal_val* builtin_size(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_size(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("object"); - int type=value_addr->get_type(); + int type=value_addr->type; int number=-1; switch(type) { case vm_nil: case vm_num: case vm_func: - case vm_scop: return gc.gc_alloc(vm_nil); break; - case vm_str: number=value_addr->get_string().length(); break; - case vm_vec: number=value_addr->get_vector().size(); break; - case vm_hash: number=value_addr->get_hash().size(); break; + case vm_scop: return nil_addr; break; + case vm_str: number=value_addr->ptr.str->length(); break; + case vm_vec: number=value_addr->ptr.vec->elems.size(); break; + case vm_hash: number=value_addr->ptr.hash->elems.size();break; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)number); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=number; return ret_addr; } -nasal_val* builtin_xor(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_xor(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); nasal_val* b_addr=in_builtin_find("b"); - if(a_addr->get_type()!=vm_num) + if(a_addr->type!=vm_num) { builtin_error_occurred("xor","\"a\" must be number"); - return NULL; + return nullptr; } - if(b_addr->get_type()!=vm_num) + if(b_addr->type!=vm_num) { builtin_error_occurred("xor","\"b\" must be number"); - return NULL; + return nullptr; } - int number_a=(int)a_addr->get_number(); - int number_b=(int)b_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)(number_a^number_b)); + int number_a=(int)a_addr->ptr.num; + int number_b=(int)b_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(number_a^number_b); return ret_addr; } -nasal_val* builtin_and(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_and(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); nasal_val* b_addr=in_builtin_find("b"); - if(a_addr->get_type()!=vm_num) + if(a_addr->type!=vm_num) { builtin_error_occurred("and","\"a\" must be number"); - return NULL; + return nullptr; } - if(b_addr->get_type()!=vm_num) + if(b_addr->type!=vm_num) { builtin_error_occurred("and","\"b\" must be number"); - return NULL; + return nullptr; } - int number_a=(int)a_addr->get_number(); - int number_b=(int)b_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)(number_a&number_b)); + int number_a=(int)a_addr->ptr.num; + int number_b=(int)b_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(number_a&number_b); return ret_addr; } -nasal_val* builtin_or(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_or(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); nasal_val* b_addr=in_builtin_find("b"); - if(a_addr->get_type()!=vm_num) + if(a_addr->type!=vm_num) { builtin_error_occurred("or","\"a\" must be number"); - return NULL; + return nullptr; } - if(b_addr->get_type()!=vm_num) + if(b_addr->type!=vm_num) { builtin_error_occurred("or","\"b\" must be number"); - return NULL; + return nullptr; } - int number_a=(int)a_addr->get_number(); - int number_b=(int)b_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)(number_a|number_b)); + int number_a=(int)a_addr->ptr.num; + int number_b=(int)b_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(number_a|number_b); return ret_addr; } -nasal_val* builtin_nand(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_nand(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); nasal_val* b_addr=in_builtin_find("b"); - if(a_addr->get_type()!=vm_num) + if(a_addr->type!=vm_num) { builtin_error_occurred("nand","\"a\" must be number"); - return NULL; + return nullptr; } - if(b_addr->get_type()!=vm_num) + if(b_addr->type!=vm_num) { builtin_error_occurred("nand","\"b\" must be number"); - return NULL; + return nullptr; } - int number_a=(int)a_addr->get_number(); - int number_b=(int)b_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)(~(number_a&number_b))); + int number_a=(int)a_addr->ptr.num; + int number_b=(int)b_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(~(number_a&number_b)); return ret_addr; } -nasal_val* builtin_not(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_not(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); - if(a_addr->get_type()!=vm_num) + if(a_addr->type!=vm_num) { builtin_error_occurred("not","\"a\" must be number"); - return NULL; + return nullptr; } - int number=(int)a_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)(~number)); + int number=(int)a_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(~number); return ret_addr; } -nasal_val* builtin_sin(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_sin(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("x"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("sin","\"x\" must be number"); - return NULL; + return nullptr; } - double number=value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(sin(number)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=sin(value_addr->ptr.num); return ret_addr; } -nasal_val* builtin_cos(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_cos(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("x"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("cos","\"x\" must be number"); - return NULL; + return nullptr; } - double number=value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(cos(number)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=cos(value_addr->ptr.num); return ret_addr; } -nasal_val* builtin_tan(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_tan(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("x"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("tan","\"x\" must be number"); - return NULL; + return nullptr; } - double number=value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(tan(number)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=tan(value_addr->ptr.num); return ret_addr; } -nasal_val* builtin_exp(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_exp(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("x"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("exp","\"x\" must be number"); - return NULL; + return nullptr; } - double number=value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(exp(number)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=exp(value_addr->ptr.num); return ret_addr; } -nasal_val* builtin_ln(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_ln(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("x"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("ln","\"x\" must be number"); - return NULL; + return nullptr; } - double number=value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(log(number)/log(2.7182818284590452354)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=(log(value_addr->ptr.num)/log(2.7182818284590452354)); return ret_addr; } -nasal_val* builtin_sqrt(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_sqrt(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("x"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("sqrt","\"x\" must be number"); - return NULL; + return nullptr; } - double number=value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(sqrt(number)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=sqrt(value_addr->ptr.num); return ret_addr; } -nasal_val* builtin_atan2(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_atan2(nasal_val* local_scope_addr) { nasal_val* x_value_addr=in_builtin_find("x"); nasal_val* y_value_addr=in_builtin_find("y"); - if(x_value_addr->get_type()!=vm_num) + if(x_value_addr->type!=vm_num) { builtin_error_occurred("atan2","\"x\" must be number"); - return NULL; + return nullptr; } - if(y_value_addr->get_type()!=vm_num) + if(y_value_addr->type!=vm_num) { builtin_error_occurred("atan2","\"y\" must be number"); - return NULL; + return nullptr; } - double x=x_value_addr->get_number(); - double y=y_value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(atan2(y,x)); + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=atan2(y_value_addr->ptr.num,x_value_addr->ptr.num); return ret_addr; } -nasal_val* builtin_time(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_time(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("begin_time"); - if(value_addr->get_type()!=vm_num) + if(value_addr->type!=vm_num) { builtin_error_occurred("time","\"begin_time\" must be number"); - return NULL; + return nullptr; } - time_t begin_time=(time_t)value_addr->get_number(); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)time(&begin_time)); + time_t begin_time=(time_t)value_addr->ptr.num; + nasal_val* ret_addr=gc_alloc(vm_num); + ret_addr->ptr.num=time(&begin_time); return ret_addr; } -nasal_val* builtin_contains(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_contains(nasal_val* local_scope_addr) { nasal_val* hash_addr=in_builtin_find("hash"); nasal_val* key_addr=in_builtin_find("key"); - if(hash_addr->get_type()!=vm_hash) + if(hash_addr->type!=vm_hash) { builtin_error_occurred("contains","\"hash\" must be hash"); - return NULL; + return nullptr; } - if(key_addr->get_type()!=vm_str) + if(key_addr->type!=vm_str) { builtin_error_occurred("contains","\"key\" must be string"); - return NULL; + return nullptr; } - bool contains=hash_addr->get_hash().check_contain(key_addr->get_string()); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number((double)contains); + nasal_val* ret_addr=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_addr,nasal_gc& gc) +nasal_val* builtin_delete(nasal_val* local_scope_addr) { nasal_val* hash_addr=in_builtin_find("hash"); nasal_val* key_addr=in_builtin_find("key"); - if(hash_addr->get_type()!=vm_hash) + if(hash_addr->type!=vm_hash) { builtin_error_occurred("delete","\"hash\" must be hash"); - return NULL; + return nullptr; } - if(key_addr->get_type()!=vm_str) + if(key_addr->type!=vm_str) { builtin_error_occurred("delete","\"key\" must be string"); - return NULL; + return nullptr; } - hash_addr->get_hash().del_elem(key_addr->get_string()); - nasal_val* ret_addr=gc.gc_alloc(vm_nil); - return ret_addr; + if(hash_addr->ptr.hash->elems.count(*key_addr->ptr.str)) + hash_addr->ptr.hash->elems.erase(*key_addr->ptr.str); + return nil_addr; } -nasal_val* builtin_getkeys(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_getkeys(nasal_val* local_scope_addr) { nasal_val* hash_addr=in_builtin_find("hash"); - if(hash_addr->get_type()!=vm_hash) + if(hash_addr->type!=vm_hash) { builtin_error_occurred("keys","\"hash\" must be hash"); - return NULL; + return nullptr; } - nasal_val* ret_addr=hash_addr->get_hash().get_keys(); - return ret_addr; + return hash_addr->ptr.hash->get_keys(); } -nasal_val* builtin_import(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_import(nasal_val* local_scope_addr) { // this function is used in preprocessing. // this function will return nothing when running. builtin_error_occurred("import","cannot use import when running"); - nasal_val* ret_addr=gc.gc_alloc(vm_nil); - return ret_addr; + return nullptr; } -nasal_val* builtin_die(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_die(nasal_val* local_scope_addr) { nasal_val* str_addr=in_builtin_find("str"); - if(str_addr->get_type()!=vm_str) + if(str_addr->type!=vm_str) { builtin_error_occurred("die","\"str\" must be string"); - return NULL; + return nullptr; } - builtin_die_state=true; - std::cout<<">> [vm] error: "<get_string()<<'\n'; - nasal_val* ret_addr=gc.gc_alloc(vm_nil); - return ret_addr; + std::cout<<">> [vm] error: "<ptr.str<<'\n'; + return nullptr; } -nasal_val* builtin_type(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_type(nasal_val* local_scope_addr) { nasal_val* value_addr=in_builtin_find("object"); - int type=value_addr->get_type(); - nasal_val* ret_addr=gc.gc_alloc(vm_str); - switch(type) + nasal_val* ret_addr=gc_alloc(vm_str); + switch(value_addr->type) { - case vm_nil: ret_addr->set_string("nil");break; - case vm_num: ret_addr->set_string("number");break; - case vm_str: ret_addr->set_string("string");break; - case vm_vec: ret_addr->set_string("vector");break; - case vm_hash: ret_addr->set_string("hash");break; - case vm_func: ret_addr->set_string("function");break; + case vm_nil: *ret_addr->ptr.str="nil"; break; + case vm_num: *ret_addr->ptr.str="number"; break; + case vm_str: *ret_addr->ptr.str="string"; break; + case vm_vec: *ret_addr->ptr.str="vector"; break; + case vm_hash: *ret_addr->ptr.str="hash"; break; + case vm_func: *ret_addr->ptr.str="function"; break; } return ret_addr; } -nasal_val* builtin_substr(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_substr(nasal_val* local_scope_addr) { nasal_val* str_addr=in_builtin_find("str"); nasal_val* begin_addr=in_builtin_find("begin"); nasal_val* length_addr=in_builtin_find("length"); - if(str_addr->get_type()!=vm_str) + if(str_addr->type!=vm_str) { builtin_error_occurred("substr","\"str\" must be string"); - return NULL; + return nullptr; } - if(begin_addr->get_type()!=vm_num) + if(begin_addr->type!=vm_num) { builtin_error_occurred("substr","\"begin\" must be number"); - return NULL; + return nullptr; } - if(length_addr->get_type()!=vm_num) + if(length_addr->type!=vm_num) { builtin_error_occurred("substr","\"length\" must be number"); - return NULL; + return nullptr; } - std::string str=str_addr->get_string(); - int begin=(int)begin_addr->get_number(); - int len=(int)length_addr->get_number(); + std::string str=*str_addr->ptr.str; + int begin=(int)begin_addr->ptr.num; + int len=(int)length_addr->ptr.num; if(begin+len>str.length()) { builtin_error_occurred("susbtr","index out of range"); - return NULL; + return nullptr; } std::string tmp=""; for(int i=begin;iset_string(tmp); + nasal_val* ret_addr=gc_alloc(vm_str); + *ret_addr->ptr.str=tmp; return ret_addr; } -nasal_val* builtin_streq(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_streq(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); nasal_val* b_addr=in_builtin_find("b"); - nasal_val* ret_addr=gc.gc_alloc(vm_num); - if(a_addr->get_type()!=vm_str || b_addr->get_type()!=vm_str) + nasal_val* ret_addr=gc_alloc(vm_num); + if(a_addr->type!=vm_str || b_addr->type!=vm_str) { - ret_addr->set_number((double)0); + ret_addr->ptr.num=0; return ret_addr; } - int ret=(a_addr->get_string()==b_addr->get_string()); - ret_addr->set_number((double)ret); + ret_addr->ptr.num=(a_addr->ptr.str==b_addr->ptr.str); return ret_addr; } -nasal_val* builtin_left(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_left(nasal_val* local_scope_addr) { nasal_val* string_addr=in_builtin_find("string"); nasal_val* length_addr=in_builtin_find("length"); - if(string_addr->get_type()!=vm_str) + if(string_addr->type!=vm_str) { builtin_error_occurred("left","\"string\" must be string"); - return NULL; + return nullptr; } - if(length_addr->get_type()!=vm_num) + if(length_addr->type!=vm_num) { builtin_error_occurred("left","\"length\" must be number"); - return NULL; + return nullptr; } - std::string str=string_addr->get_string(); - int len=(int)length_addr->get_number(); + std::string str=*string_addr->ptr.str; + int len=(int)length_addr->ptr.num; if(len<0) len=0; std::string tmp=str.substr(0, len); - nasal_val* ret_addr=gc.gc_alloc(vm_str); - ret_addr->set_string(tmp); + nasal_val* ret_addr=gc_alloc(vm_str); + *ret_addr->ptr.str=tmp; return ret_addr; } -nasal_val* builtin_right(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_right(nasal_val* local_scope_addr) { nasal_val* string_addr=in_builtin_find("string"); nasal_val* length_addr=in_builtin_find("length"); - if(string_addr->get_type()!=vm_str) + if(string_addr->type!=vm_str) { builtin_error_occurred("right","\"string\" must be string"); - return NULL; + return nullptr; } - if(length_addr->get_type()!=vm_num) + if(length_addr->type!=vm_num) { builtin_error_occurred("right","\"length\" must be number"); - return NULL; + return nullptr; } - std::string str=string_addr->get_string(); - int len=(int)length_addr->get_number(); + std::string str=*string_addr->ptr.str; + int len=(int)length_addr->ptr.num; int srclen=str.length(); if(len>srclen) len=srclen; if(len<0) len=0; std::string tmp=str.substr(srclen-len, srclen); - nasal_val* ret_addr=gc.gc_alloc(vm_str); - ret_addr->set_string(tmp); + nasal_val* ret_addr=gc_alloc(vm_str); + *ret_addr->ptr.str=tmp; return ret_addr; } -nasal_val* builtin_cmp(nasal_val* local_scope_addr,nasal_gc& gc) +nasal_val* builtin_cmp(nasal_val* local_scope_addr) { nasal_val* a_addr=in_builtin_find("a"); nasal_val* b_addr=in_builtin_find("b"); - if(a_addr->get_type()!=vm_str) + if(a_addr->type!=vm_str) { builtin_error_occurred("cmp","\"a\" must be string"); - return NULL; + return nullptr; } - if(b_addr->get_type()!=vm_str) + if(b_addr->type!=vm_str) { builtin_error_occurred("cmp","\"b\" must be string"); - return NULL; + return nullptr; } - nasal_val* ret_addr=gc.gc_alloc(vm_num); - ret_addr->set_number(strcmp(a_addr->get_string().data(),b_addr->get_string().data())); + nasal_val* ret_addr=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_addr,nasal_gc& gc) +nasal_val* builtin_chr(nasal_val* local_scope_addr) { nasal_val* code_addr=in_builtin_find("code"); - if(code_addr->get_type()!=vm_num) + if(code_addr->type!=vm_num) { builtin_error_occurred("chr","\"code\" must be number"); - return NULL; + return nullptr; } - char chr[2]={(char)code_addr->get_number(),'\0'}; - nasal_val* ret_addr=gc.gc_alloc(vm_str); - ret_addr->set_string(chr); + nasal_val* ret_addr=gc_alloc(vm_str); + *ret_addr->ptr.str=(char)code_addr->ptr.num; return ret_addr; } + #endif \ No newline at end of file diff --git a/nasal_codegen.h b/nasal_codegen.h index 16fe22c..2cf5863 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -5,40 +5,62 @@ enum op_code { op_nop, op_load,// load value in value_stack to identifier - op_pushnum, - op_pushone, - op_pushzero, - op_pushnil, - op_pushstr, - op_newvec,op_newhash,op_newfunc, - op_vecapp,op_hashapp, - op_para,op_defpara,op_dynpara, - op_unot,op_usub, - op_add,op_sub,op_mul,op_div,op_lnk, - op_addeq,op_subeq,op_muleq,op_diveq,op_lnkeq,op_meq, - op_eq,op_neq,op_less,op_leq,op_grt,op_geq, + op_loadg, + op_loadl, + op_pnum, + op_pone, + op_pzero, + op_pnil, + op_pstr, + op_newv, + op_newh, + op_newf, + op_vapp, + op_happ, + op_para, + op_defpara, + op_dynpara, + op_unot, + op_usub, + op_add, + op_sub, + op_mul, + op_div, + op_lnk, + op_addeq, + op_subeq, + op_muleq, + op_diveq, + op_lnkeq, + op_meq, + op_eq, + op_neq, + op_less, + op_leq, + op_grt, + op_geq, op_pop, - op_jmp, // jump with no condition - op_jmptrue, // used in operator and/or,jmp when condition is true and DO NOT POP - op_jmpfalse, // used in conditional/loop,jmp when condition is false and POP STACK - op_counter, // add counter for forindex/foreach - op_cntpop, // pop counter - op_forindex, // index counter on the top of forindex_stack plus 1 - op_foreach, // index counter on the top of forindex_stack plus 1 and get the value in vector - op_call, // call identifier - op_callv, // call vec[index] - op_callvi, // call vec[immediate] (used in multi-assign/multi-define) - op_callh, // call hash.label - op_callf, // call function(parameters) - op_builtincall,// call builtin-function - op_slicebegin, // begin of slice like: vec[1,2,3:6,0,-1] - op_sliceend, // end of slice - op_slice, // slice like vec[1] - op_slice2, // slice like vec[nil:10] - op_mcall, // get memory of identifier - op_mcallv, // get memory of vec[index] - op_mcallh, // get memory of hash.label - op_return // return + op_jmp, // jump with no condition + op_jt, // used in operator and/or,jmp when condition is true and DO NOT POP + op_jf, // used in conditional/loop,jmp when condition is false and POP STACK + op_counter, // add counter for forindex/foreach + op_cntpop, // pop counter + 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_callv, // call vec[index] + op_callvi, // call vec[immediate] (used in multi-assign/multi-define) + op_callh, // call hash.label + op_callf, // call function(parameters) + op_callb, // call builtin-function + op_slcbegin, // begin of slice like: vec[1,2,3:6,0,-1] + op_slcend, // end of slice + op_slc, // slice like vec[1] + op_slc2, // slice like vec[nil:10] + op_mcall, // get memory of identifier + op_mcallv, // get memory of vec[index] + op_mcallh, // get memory of hash.label + op_ret // return }; struct @@ -47,79 +69,81 @@ struct const char* name; }code_table[]= { - {op_nop, "nop "}, - {op_load, "load "}, - {op_pushnum, "pnum "}, - {op_pushone, "pone "}, - {op_pushzero, "pzero "}, - {op_pushnil, "pnil "}, - {op_pushstr, "pstr "}, - {op_newvec, "newv "}, - {op_newhash, "newh "}, - {op_newfunc, "newf "}, - {op_vecapp, "vapp "}, - {op_hashapp, "happ "}, - {op_para, "para "}, - {op_defpara, "deflt "}, - {op_dynpara, "dyn "}, - {op_unot, "not "}, - {op_usub, "usub "}, - {op_add, "add "}, - {op_sub, "sub "}, - {op_mul, "mult "}, - {op_div, "div "}, - {op_lnk, "link "}, - {op_addeq, "addeq "}, - {op_subeq, "subeq "}, - {op_muleq, "muleq "}, - {op_diveq, "diveq "}, - {op_lnkeq, "linkeq"}, - {op_meq, "memeq "}, - {op_eq, "eq "}, - {op_neq, "neq "}, - {op_less, "less "}, - {op_leq, "leq "}, - {op_grt, "grt "}, - {op_geq, "geq "}, - {op_pop, "pop "}, - {op_jmp, "jmp "}, - {op_jmptrue, "jt "}, - {op_jmpfalse, "jf "}, - {op_counter, "cnt "}, - {op_cntpop, "cntpop"}, - {op_forindex, "findx "}, - {op_foreach, "feach "}, - {op_call, "call "}, - {op_callv, "callv "}, - {op_callvi, "callvi"}, - {op_callh, "callh "}, - {op_callf, "callf "}, - {op_builtincall, "callb "}, - {op_slicebegin, "slcbeg"}, - {op_sliceend, "slcend"}, - {op_slice, "slc "}, - {op_slice2, "slc2 "}, - {op_mcall, "mcall "}, - {op_mcallv, "mcallv"}, - {op_mcallh, "mcallh"}, - {op_return, "ret "}, - {-1, NULL }, + {op_nop, "nop "}, + {op_load, "load "}, + {op_loadg, "loadg "}, + {op_loadl, "loadl "}, + {op_pnum, "pnum "}, + {op_pone, "pone "}, + {op_pzero, "pzero "}, + {op_pnil, "pnil "}, + {op_pstr, "pstr "}, + {op_newv, "newv "}, + {op_newh, "newh "}, + {op_newf, "newf "}, + {op_vapp, "vapp "}, + {op_happ, "happ "}, + {op_para, "para "}, + {op_defpara, "def "}, + {op_dynpara, "dyn "}, + {op_unot, "not "}, + {op_usub, "usub "}, + {op_add, "add "}, + {op_sub, "sub "}, + {op_mul, "mult "}, + {op_div, "div "}, + {op_lnk, "link "}, + {op_addeq, "addeq "}, + {op_subeq, "subeq "}, + {op_muleq, "muleq "}, + {op_diveq, "diveq "}, + {op_lnkeq, "linkeq"}, + {op_meq, "meq "}, + {op_eq, "eq "}, + {op_neq, "neq "}, + {op_less, "less "}, + {op_leq, "leq "}, + {op_grt, "grt "}, + {op_geq, "geq "}, + {op_pop, "pop "}, + {op_jmp, "jmp "}, + {op_jt, "jt "}, + {op_jf, "jf "}, + {op_counter, "cnt "}, + {op_cntpop, "cntpop"}, + {op_findex, "findx "}, + {op_feach, "feach "}, + {op_call, "call "}, + {op_callv, "callv "}, + {op_callvi, "callvi"}, + {op_callh, "callh "}, + {op_callf, "callf "}, + {op_callb, "callb "}, + {op_slcbegin, "slcbeg"}, + {op_slcend, "slcend"}, + {op_slc, "slc "}, + {op_slc2, "slc2 "}, + {op_mcall, "mcall "}, + {op_mcallv, "mcallv"}, + {op_mcallh, "mcallh"}, + {op_ret, "ret "}, + {-1, NULL }, }; struct opcode { unsigned char op; - unsigned int index; - opcode(unsigned char _op=op_nop,unsigned int _index=0) + unsigned int num; + opcode(unsigned char _op=op_nop,unsigned int _num=0) { op=_op; - index=_index; + num=_num; return; } opcode& operator=(const opcode& tmp) { op=tmp.op; - index=tmp.index; + num=tmp.num; return *this; } }; @@ -127,39 +151,40 @@ struct opcode class nasal_codegen { private: - std::unordered_map number_table; - std::unordered_map string_table; - std::vector number_result_table; - std::vector string_result_table; - std::vector exec_code; - std::list > continue_ptr; - std::list > break_ptr; int error; int in_forindex; int in_foreach; + std::unordered_map number_table; + std::unordered_map string_table; + std::vector num_res_table; + std::vector str_res_table; + std::vector exec_code; + std::list > continue_ptr; + std::list > break_ptr; + void regist_number(double); void regist_string(std::string); void gen(unsigned char,unsigned int); void pop_gen(); void nil_gen(); - void number_gen(nasal_ast&); - void string_gen(nasal_ast&); - void vector_gen(nasal_ast&); + void num_gen(nasal_ast&); + void str_gen(nasal_ast&); + void vec_gen(nasal_ast&); void hash_gen(nasal_ast&); - void function_gen(nasal_ast&); + void func_gen(nasal_ast&); void call_gen(nasal_ast&); void call_id(nasal_ast&); void call_hash(nasal_ast&); void call_vec(nasal_ast&); void call_func(nasal_ast&); - void mem_call(nasal_ast&); - void mem_call_id(nasal_ast&); - void mem_call_vec(nasal_ast&); - void mem_call_hash(nasal_ast&); + void mcall(nasal_ast&); + void mcall_id(nasal_ast&); + void mcall_vec(nasal_ast&); + void mcall_hash(nasal_ast&); void multi_def(nasal_ast&); void single_def(nasal_ast&); - void definition_gen(nasal_ast&); - void multi_assignment_gen(nasal_ast&); + void def_gen(nasal_ast&); + void multi_assign_gen(nasal_ast&); void conditional_gen(nasal_ast&); void loop_gen(nasal_ast&); void load_continue_break(int,int); @@ -170,17 +195,17 @@ private: void or_gen(nasal_ast&); void and_gen(nasal_ast&); void trino_gen(nasal_ast&); - void calculation_gen(nasal_ast&); + void calc_gen(nasal_ast&); void block_gen(nasal_ast&); - void return_gen(nasal_ast&); + void ret_gen(nasal_ast&); public: nasal_codegen(); - void main_progress(nasal_ast&); - void print_op(int); - void print_byte_code(); - std::vector& get_string_table(); - std::vector& get_number_table(); - std::vector& get_exec_code(); + void main_progress(nasal_ast&); + void print_op(int); + void print_byte_code(); + std::vector& get_str_table(); + std::vector& get_num_table(); + std::vector& get_exec_code(); }; nasal_codegen::nasal_codegen() @@ -223,40 +248,40 @@ void nasal_codegen::pop_gen() void nasal_codegen::nil_gen() { - opcode op(op_pushnil,0); + opcode op(op_pnil,0); exec_code.push_back(op); return; } -void nasal_codegen::number_gen(nasal_ast& ast) +void nasal_codegen::num_gen(nasal_ast& ast) { double num=ast.get_num(); - if(num==1) gen(op_pushone,0); - else if(num==0) gen(op_pushzero,0); + if(num==1) gen(op_pone,0); + else if(num==0) gen(op_pzero,0); else { regist_number(num); - gen(op_pushnum,number_table[num]); + gen(op_pnum,number_table[num]); } return; } -void nasal_codegen::string_gen(nasal_ast& ast) +void nasal_codegen::str_gen(nasal_ast& ast) { std::string str=ast.get_str(); regist_string(str); - gen(op_pushstr,string_table[str]); + gen(op_pstr,string_table[str]); return; } -void nasal_codegen::vector_gen(nasal_ast& ast) +void nasal_codegen::vec_gen(nasal_ast& ast) { int size=ast.get_children().size(); - gen(op_newvec,0); + gen(op_newv,0); for(int i=0;i=0;--i) - calculation_gen(ast.get_children()[1].get_children()[i]); + calc_gen(ast.get_children()[1].get_children()[i]); for(int i=0;i::iterator i=jmp_label.begin();i!=jmp_label.end();++i) - exec_code[*i].index=exec_code.size(); + exec_code[*i].num=exec_code.size(); return; } @@ -564,9 +589,9 @@ void nasal_codegen::loop_gen(nasal_ast& ast) void nasal_codegen::load_continue_break(int continue_place,int break_place) { for(int i=0;isecond]=i->first; + num_res_table[i->second]=i->first; for(auto i=string_table.begin();i!=string_table.end();++i) - string_result_table[i->second]=i->first; + str_res_table[i->second]=i->first; return; } @@ -940,22 +984,22 @@ void nasal_codegen::print_op(int index) break; } // print opcode index - printf("0x%.8x ",exec_code[index].index); + printf("0x%.8x ",exec_code[index].num); // print detail info switch(exec_code[index].op) { - case op_pushnum:std::cout<<'('<& nasal_codegen::get_string_table() +std::vector& nasal_codegen::get_str_table() { - return string_result_table; + return str_res_table; } -std::vector& nasal_codegen::get_number_table() +std::vector& nasal_codegen::get_num_table() { - return number_result_table; + return num_res_table; } std::vector& nasal_codegen::get_exec_code() diff --git a/nasal_gc.h b/nasal_gc.h index cce4955..d643fc9 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -1,7 +1,7 @@ #ifndef __NASAL_GC_H__ #define __NASAL_GC_H__ -enum runtime_scalar_type +enum nasal_type { vm_nil=0, vm_num, @@ -12,184 +12,113 @@ enum runtime_scalar_type vm_hash }; -class nasal_gc; -class nasal_vec; -class nasal_hash; -class nasal_func; -class nasal_scop; -class nasal_val; +struct nasal_vec; +struct nasal_hash; +struct nasal_func; +struct nasal_scop; +struct nasal_val; -class nasal_vec +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 num_addrs; // reserved address for const vm_num +std::vector local; // local scope for function block +std::vector slice_stack; // slice stack for vec[val,val,val:val] +std::vector memory; // gc memory +std::queue 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 { -private: - nasal_gc& gc; std::vector elems; -public: - nasal_vec(nasal_gc&); - ~nasal_vec(); - int size(); - void add_elem(nasal_val*); - void print(); - nasal_val* del_elem(); - nasal_val* operator[](const int); - nasal_val* get_value_address(int); - nasal_val** get_mem_address(int); + + void print(); + nasal_val* get_val(int); + nasal_val** get_mem(int); }; -class nasal_hash +struct nasal_hash { -private: - nasal_gc& gc; std::unordered_map elems; -public: - nasal_hash(nasal_gc&); - ~nasal_hash(); - int size(); - bool check_contain(std::string); - void add_elem(std::string,nasal_val*); - void del_elem(std::string); - void print(); - nasal_val* get_special_para(std::string); - nasal_val* get_value_address(std::string); - nasal_val** get_mem_address(std::string); + + bool check_contain(std::string&); + void print(); + nasal_val* get_special_para(std::string&); + nasal_val* get_val(std::string&); + nasal_val** get_mem(std::string&); nasal_val* get_keys(); }; -class nasal_func +struct nasal_func { -private: - nasal_gc& gc; - int entry; - nasal_val* closure_addr; - std::vector para; int dynpara; - std::vector default_para_addr; -public: - nasal_func(nasal_gc&); - ~nasal_func(); - int get_entry(); - int get_dynamic_para(); - void set_entry(int); - void add_para(int,nasal_val*,bool); - void set_closure_addr(nasal_val*); - void set_new_closure(); - nasal_val* get_closure_addr(); - std::vector& get_para(); - std::vector& get_default(); + int entry; + std::vector para; + std::vector default_para; + std::unordered_map closure; + + nasal_func(); }; -class nasal_scop +struct nasal_scop { -private: - nasal_gc& gc; std::unordered_map elems; -public: - nasal_scop(nasal_gc&); - ~nasal_scop(); - void set_closure(nasal_scop&); - void add_new_value(int,nasal_val*); - nasal_val* get_value_address(int); - nasal_val** get_mem_address(int); + + nasal_val* get_val(int); + nasal_val** get_mem(int); }; -class nasal_val +struct nasal_val { -protected: + bool mark; int type; union { - double num; + double num; std::string* str; nasal_vec* vec; nasal_hash* hash; nasal_func* func; - nasal_scop* cls; + nasal_scop* scop; }ptr; -public: - int ref_cnt; - nasal_val(); - nasal_val(int,nasal_gc&); - ~nasal_val(); - void clear(); - void set_type(int,nasal_gc&); - void set_number(double); - void set_string(std::string); - int get_type(); - double to_number(); - double get_number(); - std::string to_string(); - std::string get_string(); - nasal_vec& get_vector(); - nasal_hash& get_hash(); - nasal_func& get_func(); - nasal_scop& get_closure(); -}; -class nasal_gc -{ -private: - std::queue free_space; - std::vector memory; -public: - ~nasal_gc(); - void clear(); - nasal_val* gc_alloc(int); - void add_reference(nasal_val*); - void del_reference(nasal_val*); + nasal_val(); + nasal_val(int); + ~nasal_val(); + void clear(); + void set_type(int); + double to_number(); + std::string to_string(); }; /*functions of nasal_vec*/ -nasal_vec::nasal_vec(nasal_gc& ngc):gc(ngc) -{ - return; -} -nasal_vec::~nasal_vec() -{ - int size=elems.size(); - for(int i=0;i=vec_size) { - std::cout<<">> [gc] nasal_vec::get_value_address: index out of range: "<> [gc] nasal_vec::get_val: index out of range: "<=0]]; } -nasal_val** nasal_vec::get_mem_address(int index) +nasal_val** nasal_vec::get_mem(int index) { int vec_size=elems.size(); if(index<-vec_size || index>=vec_size) { - std::cout<<">> [gc] nasal_vec::get_mem_address: index out of range: "<> [gc] nasal_vec::get_mem: index out of range: "<=0]]; @@ -203,14 +132,14 @@ void nasal_vec::print() for(int i=0;iget_type()) + switch(tmp->type) { - case vm_nil: std::cout<<"nil"; break; - case vm_num: std::cout<get_number(); break; - case vm_str: std::cout<get_string(); break; - case vm_vec: tmp->get_vector().print(); break; - case vm_hash: tmp->get_hash().print(); break; - case vm_func: std::cout<<"func(...){...}"; break; + case vm_nil: std::cout<<"nil"; break; + case vm_num: std::cout<ptr.num; break; + case vm_str: std::cout<<*tmp->ptr.str; break; + case vm_vec: tmp->ptr.vec->print(); break; + case vm_hash: tmp->ptr.hash->print(); break; + case vm_func: std::cout<<"func(...){...}"; break; } std::cout<<",]"[i==size-1]; } @@ -218,123 +147,93 @@ void nasal_vec::print() } /*functions of nasal_hash*/ -nasal_hash::nasal_hash(nasal_gc& ngc):gc(ngc) -{ - return; -} -nasal_hash::~nasal_hash() -{ - for(auto iter=elems.begin();iter!=elems.end();++iter) - gc.del_reference(iter->second); - return; -} -void nasal_hash::add_elem(std::string key,nasal_val* value_address) -{ - if(!elems.count(key)) - elems[key]=value_address; - return; -} -void nasal_hash::del_elem(std::string key) -{ - if(!elems.count(key)) - { - gc.del_reference(elems[key]); - elems.erase(key); - } - return; -} -int nasal_hash::size() -{ - return elems.size(); -} -nasal_val* nasal_hash::get_special_para(std::string key) +nasal_val* nasal_hash::get_special_para(std::string& key) { if(elems.count(key)) return elems[key]; - return NULL; + return nullptr; } -nasal_val* nasal_hash::get_value_address(std::string key) +nasal_val* nasal_hash::get_val(std::string& key) { - nasal_val* ret_value_addr=NULL; + nasal_val* ret_addr=nullptr; if(elems.count(key)) return elems[key]; else if(elems.count("parents")) { nasal_val* val_addr=elems["parents"]; - if(val_addr->get_type()==vm_vec) + if(val_addr->type==vm_vec) { - nasal_vec& vec_ref=val_addr->get_vector(); + std::vector& vec_ref=val_addr->ptr.vec->elems; int size=vec_ref.size(); for(int i=0;iget_type()==vm_hash) - ret_value_addr=tmp_val_addr->get_hash().get_value_address(key); - if(ret_value_addr) - break; + nasal_val* tmp=vec_ref[i]; + if(tmp->type==vm_hash) + ret_addr=tmp->ptr.hash->get_val(key); + if(ret_addr) + return ret_addr; } } } - return ret_value_addr; + return ret_addr; } -nasal_val** nasal_hash::get_mem_address(std::string key) +nasal_val** nasal_hash::get_mem(std::string& key) { - nasal_val** mem_addr=NULL; + nasal_val** mem_addr=nullptr; if(elems.count(key)) return &elems[key]; else if(elems.count("parents")) { nasal_val* val_addr=elems["parents"]; - if(val_addr->get_type()==vm_vec) + if(val_addr->type==vm_vec) { - nasal_vec& vec_ref=val_addr->get_vector(); + std::vector& vec_ref=val_addr->ptr.vec->elems; int size=vec_ref.size(); for(int i=0;iget_type()==vm_hash) - mem_addr=tmp_val_addr->get_hash().get_mem_address(key); + 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); if(mem_addr) - break; + return mem_addr; } } } return mem_addr; } -bool nasal_hash::check_contain(std::string key) +bool nasal_hash::check_contain(std::string& key) { if(elems.count(key)) return true; if(elems.count("parents")) { - bool result=false; nasal_val* val_addr=elems["parents"]; - if(val_addr->get_type()==vm_vec) + if(val_addr->type==vm_vec) { - nasal_vec& vec_ref=val_addr->get_vector(); + bool result=false; + std::vector& vec_ref=val_addr->ptr.vec->elems; int size=vec_ref.size(); for(int i=0;iget_type()==vm_hash) - result=tmp_val_addr->get_hash().check_contain(key); + nasal_val* tmp=vec_ref[i]; + if(tmp->type==vm_hash) + result=tmp->ptr.hash->check_contain(key); if(result) - break; + return true; } } - return result; } return false; } nasal_val* nasal_hash::get_keys() { - nasal_val* ret_addr=gc.gc_alloc(vm_vec); - nasal_vec& ref_vec=ret_addr->get_vector(); + nasal_val* ret_addr=gc_alloc(vm_vec); + std::vector& ref_vec=ret_addr->ptr.vec->elems; for(auto iter=elems.begin();iter!=elems.end();++iter) { - nasal_val* str_addr=gc.gc_alloc(vm_str); - str_addr->set_string(iter->first); - ref_vec.add_elem(str_addr); + nasal_val* str_addr=gc_alloc(vm_str); + *str_addr->ptr.str=iter->first; + ref_vec.push_back(str_addr); } return ret_addr; } @@ -350,14 +249,14 @@ void nasal_hash::print() { std::cout<first<<':'; nasal_val* tmp=i->second; - switch(tmp->get_type()) + switch(tmp->type) { - case vm_nil: std::cout<<"nil"; break; - case vm_num: std::cout<get_number(); break; - case vm_str: std::cout<get_string(); break; - case vm_vec: tmp->get_vector().print(); break; - case vm_hash: tmp->get_hash().print(); break; - case vm_func: std::cout<<"func(...){...}"; break; + case vm_nil: std::cout<<"nil"; break; + case vm_num: std::cout<ptr.num; break; + case vm_str: std::cout<<*tmp->ptr.str; break; + case vm_vec: tmp->ptr.vec->print(); break; + case vm_hash: tmp->ptr.hash->print(); break; + case vm_func: std::cout<<"func(...){...}"; break; } std::cout<<','; } @@ -366,161 +265,64 @@ void nasal_hash::print() } /*functions of nasal_func*/ -nasal_func::nasal_func(nasal_gc& ngc):gc(ngc) +nasal_func::nasal_func() { - closure_addr=NULL; dynpara=-1; return; } -nasal_func::~nasal_func() -{ - if(closure_addr) - gc.del_reference(closure_addr); - for(int i=0;i& nasal_func::get_para() -{ - return para; -} -int nasal_func::get_dynamic_para() -{ - return dynpara; -} -std::vector& nasal_func::get_default() -{ - return default_para_addr; -} -void nasal_func::set_closure_addr(nasal_val* value_address) -{ - nasal_val* new_closure=gc.gc_alloc(vm_scop); - new_closure->get_closure().set_closure(value_address->get_closure()); - closure_addr=new_closure; - return; -} -void nasal_func::set_new_closure() -{ - closure_addr=gc.gc_alloc(vm_scop); - return; -} -nasal_val* nasal_func::get_closure_addr() -{ - return closure_addr; -} /*functions of nasal_scop*/ -nasal_scop::nasal_scop(nasal_gc& ngc):gc(ngc) -{ - return; -} -nasal_scop::~nasal_scop() -{ - for(auto i=elems.begin();i!=elems.end();++i) - gc.del_reference(i->second); - return; -} -void nasal_scop::add_new_value(int key,nasal_val* value_address) -{ - if(elems.count(key)) - { - // if this value already exists,delete the old value and update a new value - gc.del_reference(elems[key]); - } - elems[key]=value_address; - return; -} -nasal_val* nasal_scop::get_value_address(int key) +nasal_val* nasal_scop::get_val(int key) { if(elems.count(key)) return elems[key]; - return NULL; + return nullptr; } -nasal_val** nasal_scop::get_mem_address(int key) +nasal_val** nasal_scop::get_mem(int key) { if(elems.count(key)) return &(elems[key]); - return NULL; -} -void nasal_scop::set_closure(nasal_scop& tmp) -{ - elems=tmp.elems; - for(auto i=elems.begin();i!=elems.end();++i) - gc.add_reference(i->second); - return; + return nullptr; } /*functions of nasal_val*/ nasal_val::nasal_val() { - ref_cnt=1; + mark=false; type=vm_nil; return; } -nasal_val::nasal_val(int nasal_val_type,nasal_gc& nvm) +nasal_val::nasal_val(int val_type) { - ref_cnt=1; - type=nasal_val_type; - switch(nasal_val_type) + mark=false; + type=val_type; + switch(type) { - case vm_nil: break; - case vm_num: ptr.num=0; break; - case vm_str: ptr.str=new std::string; break; - case vm_vec: ptr.vec=new nasal_vec(nvm); break; - case vm_hash: ptr.hash=new nasal_hash(nvm); break; - case vm_func: ptr.func=new nasal_func(nvm); break; - case vm_scop: ptr.cls=new nasal_scop(nvm); break; + case vm_num: ptr.num=0; break; + case vm_str: ptr.str=new std::string; break; + case vm_vec: ptr.vec=new nasal_vec; break; + case vm_hash: ptr.hash=new nasal_hash; break; + case vm_func: ptr.func=new nasal_func; break; + case vm_scop: ptr.scop=new nasal_scop; break; } return; } nasal_val::~nasal_val() { - // must set type and scalar_ptr to default first - // this operation will avoid SIGTRAP caused by circular reference - // circular reference will cause using destructor repeatedly - int tmp_type=type; - type=vm_nil; - switch(tmp_type) + switch(type) { - case vm_nil: break; - case vm_num: break; case vm_str: delete ptr.str; break; case vm_vec: delete ptr.vec; break; case vm_hash: delete ptr.hash; break; case vm_func: delete ptr.func; break; - case vm_scop: delete ptr.cls; break; + case vm_scop: delete ptr.scop; break; } + type=vm_nil; return; } void nasal_val::clear() { - // must set type and scalar_ptr to default first - // this operation will avoid SIGTRAP caused by circular reference - // circular reference will cause using destructor repeatedly - int tmp_type=type; - type=vm_nil; - switch(tmp_type) + switch(type) { case vm_nil: break; case vm_num: break; @@ -528,49 +330,30 @@ void nasal_val::clear() case vm_vec: delete ptr.vec; break; case vm_hash: delete ptr.hash; break; case vm_func: delete ptr.func; break; - case vm_scop: delete ptr.cls; break; + case vm_scop: delete ptr.scop; break; } + type=vm_nil; return; } -void nasal_val::set_type(int nasal_val_type,nasal_gc& nvm) +void nasal_val::set_type(int val_type) { - type=nasal_val_type; - switch(nasal_val_type) + type=val_type; + switch(type) { case vm_nil: break; - case vm_num: ptr.num=0; break; - case vm_str: ptr.str=new std::string; break; - case vm_vec: ptr.vec=new nasal_vec(nvm); break; - case vm_hash: ptr.hash=new nasal_hash(nvm); break; - case vm_func: ptr.func=new nasal_func(nvm); break; - case vm_scop: ptr.cls=new nasal_scop(nvm); break; + case vm_num: ptr.num=0; break; + case vm_str: ptr.str=new std::string; break; + case vm_vec: ptr.vec=new nasal_vec; break; + case vm_hash: ptr.hash=new nasal_hash; break; + case vm_func: ptr.func=new nasal_func; break; + case vm_scop: ptr.scop=new nasal_scop; break; } return; } -void nasal_val::set_number(double num) -{ - ptr.num=num; - return; -} -void nasal_val::set_string(std::string str) -{ - *ptr.str=str; - return; -} -int nasal_val::get_type() -{ - return type; -} double nasal_val::to_number() { - if(type==vm_num) - return ptr.num; - else if(type==vm_str) + if(type==vm_str) return trans_string_to_number(*ptr.str); - return 0; -} -double nasal_val::get_number() -{ return ptr.num; } std::string nasal_val::to_string() @@ -581,79 +364,126 @@ std::string nasal_val::to_string() return trans_number_to_string(ptr.num); return ""; } -std::string nasal_val::get_string() + +void mark() { - return *ptr.str; -} -nasal_vec& nasal_val::get_vector() -{ - return *ptr.vec; -} -nasal_hash& nasal_val::get_hash() -{ - return *ptr.hash; -} -nasal_func& nasal_val::get_func() -{ - return *ptr.func; -} -nasal_scop& nasal_val::get_closure() -{ - return *ptr.cls; + int size; + std::queue bfs; + bfs.push(zero_addr); + bfs.push(one_addr); + bfs.push(nil_addr); + bfs.push(global); + + size=num_addrs.size(); + for(int i=0;imark) continue; + tmp->mark=true; + if(tmp->type==vm_vec) + { + std::vector& vec=tmp->ptr.vec->elems; + for(auto i=vec.begin();i!=vec.end();++i) + if(!(*i)->mark) + bfs.push(*i); + } + else if(tmp->type==vm_hash) + { + std::unordered_map& hash=tmp->ptr.hash->elems; + for(auto i=hash.begin();i!=hash.end();++i) + if(!i->second->mark) + bfs.push(i->second); + } + else if(tmp->type==vm_func) + { + std::unordered_map& cls=tmp->ptr.func->closure; + std::vector& def=tmp->ptr.func->default_para; + for(auto i=cls.begin();i!=cls.end();++i) + if(!i->second->mark) + bfs.push(i->second); + for(auto i=def.begin();i!=def.end();++i) + if(*i && !(*i)->mark) + bfs.push(*i); + } + else if(tmp->type==vm_scop) + { + std::unordered_map& scop=tmp->ptr.scop->elems; + for(auto i=scop.begin();i!=scop.end();++i) + if(!i->second->mark) + bfs.push(i->second); + } + } + return; } -/*functions of nasal_gc*/ -nasal_gc::~nasal_gc() +void sweep() { - int gc_mem_size=memory.size(); - for(int i=0;iclear(); - for(int i=0;iclear(); - for(int i=0;imark) + { + memory[i]->clear(); + free_list.push(memory[i]); + } + memory[i]->mark=false; } - nasal_val* ret=free_space.front(); - free_space.pop(); - ret->ref_cnt=1; - ret->set_type(val_type,*this); + return; +} + +void gc_init() +{ + for(int i=0;i<65536;++i) + { + nasal_val* tmp=new nasal_val; + memory.push_back(tmp); + free_list.push(tmp); + } + return; +} + +void gc_clear() +{ + int size=memory.size(); + for(int i=0;iclear(); + delete memory[i]; + } + memory.clear(); + while(!free_list.empty()) + free_list.pop(); + return; +} + +nasal_val* gc_alloc(int type) +{ + if(free_list.empty()) + { + mark(); + sweep(); + } + if(free_list.empty()) + for(int i=0;i<65536;++i) + { + nasal_val* tmp=new nasal_val; + memory.push_back(tmp); + free_list.push(tmp); + } + nasal_val* ret=free_list.front(); + free_list.pop(); + ret->set_type(type); return ret; } -void nasal_gc::add_reference(nasal_val* value_address) -{ - ++value_address->ref_cnt; - return; -} -void nasal_gc::del_reference(nasal_val* value_address) -{ - --value_address->ref_cnt; - if(!value_address->ref_cnt) - { - value_address->clear(); - free_space.push(value_address); - } - return; -} - #endif \ No newline at end of file diff --git a/nasal_parse.h b/nasal_parse.h index b1acf9a..10e2910 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -77,9 +77,9 @@ private: nasal_ast unary(); nasal_ast scalar(); nasal_ast call_scalar(); - nasal_ast call_hash(); - nasal_ast call_vec(); - nasal_ast call_func(); + nasal_ast callh(); + nasal_ast callv(); + nasal_ast callf(); nasal_ast subvec(); nasal_ast definition(); nasal_ast var_incurve_def(); @@ -95,7 +95,7 @@ private: nasal_ast conditional(); nasal_ast continue_expr(); nasal_ast break_expr(); - nasal_ast return_expr(); + nasal_ast ret_expr(); public: int get_error(); void set_toklist(std::vector&); @@ -494,7 +494,7 @@ nasal_ast nasal_parse::expr() case tok_if: node=conditional(); break; case tok_continue: node=continue_expr(); break; case tok_break: node=break_expr(); break; - case tok_ret: node=return_expr(); break; + case tok_ret: node=ret_expr(); break; case tok_semi: break; default: die(error_line,"error token \""+tok_list[ptr].str+"\"");break; } @@ -714,13 +714,13 @@ nasal_ast nasal_parse::call_scalar() nasal_ast node; switch(tok_list[ptr].type) { - case tok_lcurve: node=call_func(); break; - case tok_lbracket: node=call_vec(); break; - case tok_dot: node=call_hash(); break; + case tok_lcurve: node=callf(); break; + case tok_lbracket: node=callv(); break; + case tok_dot: node=callh(); break; } return node; } -nasal_ast nasal_parse::call_hash() +nasal_ast nasal_parse::callh() { nasal_ast node(tok_list[ptr].line,ast_callh); match(tok_dot); @@ -728,7 +728,7 @@ nasal_ast nasal_parse::call_hash() match(tok_id); return node; } -nasal_ast nasal_parse::call_vec() +nasal_ast nasal_parse::callv() { nasal_ast node(tok_list[ptr].line,ast_callv); match(tok_lbracket); @@ -743,7 +743,7 @@ nasal_ast nasal_parse::call_vec() match(tok_rbracket); return node; } -nasal_ast nasal_parse::call_func() +nasal_ast nasal_parse::callf() { nasal_ast node(tok_list[ptr].line,ast_callf); bool special_call=check_special_call(); @@ -1033,7 +1033,7 @@ nasal_ast nasal_parse::break_expr() match(tok_break); return node; } -nasal_ast nasal_parse::return_expr() +nasal_ast nasal_parse::ret_expr() { nasal_ast node(tok_list[ptr].line,ast_return); match(tok_ret); diff --git a/nasal_vm.h b/nasal_vm.h index 692fe10..7bbd7b7 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -1,49 +1,35 @@ #ifndef __NASAL_VM_H__ #define __NASAL_VM_H__ -#define STACK_MAX_DEPTH 8192 +#define STACK_MAX_DEPTH (65536<<4) class nasal_vm { private: - 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 - std::vector num_addrs; // reserved address for const vm_num - bool main_loop_break_mark; // when mark is false,break the main loop - int ptr; // program counter - int me_index; // this is the index of "me" in string_table - nasal_val* global_scope_addr; // global scope address,type vm_scop - nasal_gc gc; // garbage collector and memory manager - std::vector exec_code; // byte codes store here - // main calculation stack - nasal_val** val_stack; - nasal_val** val_stack_top; - // stack for mem_call - std::stack addr_stack; - // local scope for function block - std::stack local_scope_stack; - // slice stack for vec[val,val,val:val] - std::stack slice_stack; - // ptr stack stores address for function to return - std::stack call_stack; - // iterator stack for forindex/foreach - std::stack counter_stack; - std::vector string_table; - std::vector number_table; + std::vector str_table; // symbols used in process + bool loop_mark; // when mark is false,break the main loop + int pc; // program counter + int me_index; // this is the index of "me" in str_table + std::vector exec_code; // byte codes store here + std::stack addr_stack; // stack for mem_call + std::stack call_stack; // ptr stack stores address for function to return + std::stack counter; // iterator stack for forindex/foreach + void die(std::string); bool check_condition(nasal_val*); void opr_nop(); void opr_load(); - void opr_pushnum(); - void opr_pushone(); - void opr_pushzero(); - void opr_pushnil(); - void opr_pushstr(); - void opr_newvec(); - void opr_newhash(); - void opr_newfunc(); - void opr_vecapp(); - void opr_hashapp(); + void opr_loadg(); + void opr_loadl(); + void opr_pnum(); + void opr_pone(); + void opr_pzero(); + void opr_pnil(); + void opr_pstr(); + void opr_newv(); + void opr_newh(); + void opr_newf(); + void opr_vapp(); + void opr_happ(); void opr_para(); void opr_defpara(); void opr_dynpara(); @@ -68,80 +54,112 @@ private: void opr_geq(); void opr_pop(); void opr_jmp(); - void opr_jmptrue(); - void opr_jmpfalse(); + void opr_jt(); + void opr_jf(); void opr_counter(); void opr_cntpop(); - void opr_forindex(); - void opr_foreach(); + void opr_findex(); + void opr_feach(); void opr_call(); void opr_callv(); void opr_callvi(); void opr_callh(); void opr_callf(); - void opr_builtincall(); - void opr_slicebegin(); - void opr_sliceend(); - void opr_slice(); - void opr_slice2(); + void opr_callb(); + void opr_slcbegin(); + void opr_slcend(); + void opr_slc(); + void opr_slc2(); void opr_mcall(); void opr_mcallv(); void opr_mcallh(); - void opr_return(); + void opr_ret(); public: - nasal_vm(); - ~nasal_vm(); + void init( + std::vector&, + std::vector&, + std::vector&); void clear(); - void run(std::vector&,std::vector&,std::vector&); + void run(); }; -nasal_vm::nasal_vm() +void nasal_vm::init( + std::vector& strs, + std::vector& nums, + std::vector& exec) { - val_stack=new nasal_val*[STACK_MAX_DEPTH]; - val_stack_top=val_stack; - local_scope_stack.push(NULL); - return; -} -nasal_vm::~nasal_vm() -{ - delete []val_stack; + gc_init(); + 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;iptr.num=nums[i]; + num_addrs.push_back(tmp); + } + + builtin_use_str_table.clear(); // create map that builtin functions use + for(int i=0;i> [vm] 0x%.8x: %s\n",ptr,str.data()); - main_loop_break_mark=false; + printf(">> [vm] 0x%.8x: %s\n",pc,str.data()); + loop_mark=false; return; } bool nasal_vm::check_condition(nasal_val* value_addr) { - int type=value_addr->get_type(); + int type=value_addr->type; if(type==vm_num) - return value_addr->get_number(); + return value_addr->ptr.num; else if(type==vm_str) { - std::string str=value_addr->get_string(); + std::string& str=*value_addr->ptr.str; double number=trans_string_to_number(str); if(std::isnan(number)) return str.length(); @@ -151,562 +169,449 @@ bool nasal_vm::check_condition(nasal_val* value_addr) } void nasal_vm::opr_nop() { - // nop is the end of this program - main_loop_break_mark=false; + loop_mark=false; return; } void nasal_vm::opr_load() { - nasal_val* val_addr=*val_stack_top--; - nasal_val* local_scope_top=local_scope_stack.top(); - (local_scope_top?local_scope_top:global_scope_addr)->get_closure().add_new_value(exec_code[ptr].index,val_addr); + nasal_val* val=*stack_top--; + (local.empty()?global:local.back())->ptr.scop->elems[exec_code[pc].num]=val; return; } -void nasal_vm::opr_pushnum() +void nasal_vm::opr_loadg() { - nasal_val* val_addr=num_addrs[exec_code[ptr].index]; - ++val_addr->ref_cnt; - *(++val_stack_top)=val_addr; + global->ptr.scop->elems[exec_code[pc].num]=*stack_top--; return; } -void nasal_vm::opr_pushone() +void nasal_vm::opr_loadl() { - *(++val_stack_top)=one_addr; - ++one_addr->ref_cnt; + local.back()->ptr.scop->elems[exec_code[pc].num]=*stack_top--; return; } -void nasal_vm::opr_pushzero() +void nasal_vm::opr_pnum() { - *(++val_stack_top)=zero_addr; - ++zero_addr->ref_cnt; + nasal_val* val=num_addrs[exec_code[pc].num]; + *(++stack_top)=val; return; } -void nasal_vm::opr_pushnil() +void nasal_vm::opr_pone() { - *(++val_stack_top)=nil_addr; - ++nil_addr->ref_cnt; + *(++stack_top)=one_addr; return; } -void nasal_vm::opr_pushstr() +void nasal_vm::opr_pzero() { - nasal_val* val_addr=gc.gc_alloc(vm_str); - val_addr->set_string(string_table[exec_code[ptr].index]); - *(++val_stack_top)=val_addr; + *(++stack_top)=zero_addr; return; } -void nasal_vm::opr_newvec() +void nasal_vm::opr_pnil() { - *(++val_stack_top)=gc.gc_alloc(vm_vec); + *(++stack_top)=nil_addr; return; } -void nasal_vm::opr_newhash() +void nasal_vm::opr_pstr() { - *(++val_stack_top)=gc.gc_alloc(vm_hash); + nasal_val* val=gc_alloc(vm_str); + *val->ptr.str=str_table[exec_code[pc].num]; + *(++stack_top)=val; return; } -void nasal_vm::opr_newfunc() +void nasal_vm::opr_newv() { - nasal_val* val_addr=gc.gc_alloc(vm_func); - nasal_val* local_scope_top=local_scope_stack.top(); - val_addr->get_func().set_entry(exec_code[ptr].index); - if(local_scope_top) - val_addr->get_func().set_closure_addr(local_scope_top); - else - val_addr->get_func().set_new_closure(); - *(++val_stack_top)=val_addr; + nasal_val* vec=gc_alloc(vm_vec); + *(++stack_top)=vec; return; } -void nasal_vm::opr_vecapp() +void nasal_vm::opr_newh() { - (*val_stack_top)->get_vector().add_elem(*val_stack_top--); + nasal_val* hash=gc_alloc(vm_hash); + *(++stack_top)=hash; return; } -void nasal_vm::opr_hashapp() +void nasal_vm::opr_newf() { - (*val_stack_top)->get_hash().add_elem(string_table[exec_code[ptr].index],*val_stack_top--); + nasal_val* val=gc_alloc(vm_func); + val->ptr.func->entry=exec_code[pc].num; + if(!local.empty()) + val->ptr.func->closure=local.back()->ptr.scop->elems; + *(++stack_top)=val; + return; +} +void nasal_vm::opr_vapp() +{ + nasal_val* val=*stack_top--; + (*stack_top)->ptr.vec->elems.push_back(val); + return; +} +void nasal_vm::opr_happ() +{ + nasal_val* val=*stack_top--; + (*stack_top)->ptr.hash->elems[str_table[exec_code[pc].num]]=val; return; } void nasal_vm::opr_para() { - (*val_stack_top)->get_func().add_para(exec_code[ptr].index); + (*stack_top)->ptr.func->para.push_back(exec_code[pc].num); + (*stack_top)->ptr.func->default_para.push_back(nullptr); return; } void nasal_vm::opr_defpara() { - (*val_stack_top)->get_func().add_para(exec_code[ptr].index,*val_stack_top--); + nasal_val* def_val=*stack_top--; + (*stack_top)->ptr.func->para.push_back(exec_code[pc].num); + (*stack_top)->ptr.func->default_para.push_back(def_val); return; } void nasal_vm::opr_dynpara() { - (*val_stack_top)->get_func().add_para(exec_code[ptr].index,NULL,true); + (*stack_top)->ptr.func->dynpara=exec_code[pc].num; return; } void nasal_vm::opr_unot() { - nasal_val* val_addr=*val_stack_top; - nasal_val* new_val_addr=NULL; - int type=val_addr->get_type(); + nasal_val* val=*stack_top; + nasal_val* new_val=nullptr; + int type=val->type; if(type==vm_nil) - new_val_addr=one_addr; + new_val=one_addr; else if(type==vm_num) - new_val_addr=val_addr->get_number()?zero_addr:one_addr; + new_val=val->ptr.num?zero_addr:one_addr; else if(type==vm_str) { - double number=trans_string_to_number(val_addr->get_string()); + double number=trans_string_to_number(*val->ptr.str); if(std::isnan(number)) - new_val_addr=val_addr->get_string().length()?zero_addr:one_addr; + new_val=val->ptr.str->length()?zero_addr:one_addr; else - new_val_addr=number?zero_addr:one_addr; + new_val=number?zero_addr:one_addr; } else die("unot: incorrect value type"); - ++new_val_addr->ref_cnt; - *val_stack_top=new_val_addr; - gc.del_reference(val_addr); + *stack_top=new_val; return; } void nasal_vm::opr_usub() { - nasal_val* val_addr=*val_stack_top; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(-val_addr->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr); + nasal_val* val=*stack_top; + nasal_val* new_val=gc_alloc(vm_num); + new_val->ptr.num=-val->to_number(); + *stack_top=new_val; return; } void nasal_vm::opr_add() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()+val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=gc_alloc(vm_num); + nasal_val* val2=*stack_top--; + nasal_val* val1=*stack_top; + new_val->ptr.num=val1->to_number()+val2->to_number(); + *stack_top=new_val; return; } void nasal_vm::opr_sub() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()-val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=gc_alloc(vm_num); + nasal_val* val2=*stack_top--; + nasal_val* val1=*stack_top; + new_val->ptr.num=val1->to_number()-val2->to_number(); + *stack_top=new_val; return; } void nasal_vm::opr_mul() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()*val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=gc_alloc(vm_num); + nasal_val* val2=*stack_top--; + nasal_val* val1=*stack_top; + new_val->ptr.num=val1->to_number()*val2->to_number(); + *stack_top=new_val; return; } void nasal_vm::opr_div() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()/val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=gc_alloc(vm_num); + nasal_val* val2=*stack_top--; + nasal_val* val1=*stack_top; + new_val->ptr.num=val1->to_number()/val2->to_number(); + *stack_top=new_val; return; } void nasal_vm::opr_lnk() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - nasal_val* new_val_addr=gc.gc_alloc(vm_str); - new_val_addr->set_string(val_addr1->to_string()+val_addr2->to_string()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=gc_alloc(vm_str); + nasal_val* val2=*stack_top--; + nasal_val* val1=*stack_top; + *new_val->ptr.str=val1->to_string()+val2->to_string(); + *stack_top=new_val; return; } void nasal_vm::opr_addeq() { nasal_val** mem_addr=addr_stack.top(); addr_stack.pop(); - nasal_val* val_addr2=*val_stack_top; - nasal_val* val_addr1=*mem_addr; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()+val_addr2->to_number()); - gc.add_reference(new_val_addr); - *val_stack_top=new_val_addr; - gc.del_reference(*mem_addr); - *mem_addr=new_val_addr; - gc.del_reference(val_addr2); + nasal_val* val2=*stack_top; + nasal_val* val1=*mem_addr; + nasal_val* new_val=gc_alloc(vm_num); + new_val->ptr.num=val1->to_number()+val2->to_number(); + *stack_top=new_val; + *mem_addr=new_val; return; } void nasal_vm::opr_subeq() { nasal_val** mem_addr=addr_stack.top(); addr_stack.pop(); - nasal_val* val_addr2=*val_stack_top; - nasal_val* val_addr1=*mem_addr; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()-val_addr2->to_number()); - gc.add_reference(new_val_addr); - *val_stack_top=new_val_addr; - gc.del_reference(*mem_addr); - *mem_addr=new_val_addr; - gc.del_reference(val_addr2); + nasal_val* val2=*stack_top; + nasal_val* val1=*mem_addr; + nasal_val* new_val=gc_alloc(vm_num); + new_val->ptr.num=val1->to_number()-val2->to_number(); + *stack_top=new_val; + *mem_addr=new_val; return; } void nasal_vm::opr_muleq() { nasal_val** mem_addr=addr_stack.top(); addr_stack.pop(); - nasal_val* val_addr2=*val_stack_top; - nasal_val* val_addr1=*mem_addr; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()*val_addr2->to_number()); - gc.add_reference(new_val_addr); - *val_stack_top=new_val_addr; - gc.del_reference(*mem_addr); - *mem_addr=new_val_addr; - gc.del_reference(val_addr2); + nasal_val* val2=*stack_top; + nasal_val* val1=*mem_addr; + nasal_val* new_val=gc_alloc(vm_num); + new_val->ptr.num=val1->to_number()*val2->to_number(); + *stack_top=new_val; + *mem_addr=new_val; return; } void nasal_vm::opr_diveq() { nasal_val** mem_addr=addr_stack.top(); addr_stack.pop(); - nasal_val* val_addr2=*val_stack_top; - nasal_val* val_addr1=*mem_addr; - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()/val_addr2->to_number()); - gc.add_reference(new_val_addr); - *val_stack_top=new_val_addr; - gc.del_reference(*mem_addr); - *mem_addr=new_val_addr; - gc.del_reference(val_addr2); + nasal_val* val2=*stack_top; + nasal_val* val1=*mem_addr; + nasal_val* new_val=gc_alloc(vm_num); + new_val->ptr.num=val1->to_number()/val2->to_number(); + *stack_top=new_val; + *mem_addr=new_val; return; } void nasal_vm::opr_lnkeq() { nasal_val** mem_addr=addr_stack.top(); addr_stack.pop(); - nasal_val* val_addr2=*val_stack_top; - nasal_val* val_addr1=*mem_addr; - nasal_val* new_val_addr=gc.gc_alloc(vm_str); - new_val_addr->set_string(val_addr1->to_string()+val_addr2->to_string()); - gc.add_reference(new_val_addr); - *val_stack_top=new_val_addr; - gc.del_reference(*mem_addr); - *mem_addr=new_val_addr; - gc.del_reference(val_addr2); + nasal_val* val2=*stack_top; + nasal_val* val1=*mem_addr; + nasal_val* new_val=gc_alloc(vm_str); + *new_val->ptr.str=val1->to_string()+val2->to_string(); + *stack_top=new_val; + *mem_addr=new_val; return; } void nasal_vm::opr_meq() { nasal_val** mem_addr=addr_stack.top(); addr_stack.pop(); - nasal_val* val_addr=*val_stack_top; - gc.add_reference(val_addr); - gc.del_reference(*mem_addr); - *mem_addr=val_addr; + nasal_val* val=*stack_top; + *mem_addr=val; return; } void nasal_vm::opr_eq() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - int a_ref_type=val_addr1->get_type(); - int b_ref_type=val_addr2->get_type(); - if(a_ref_type==vm_nil && b_ref_type==vm_nil) + nasal_val* new_val=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; + else if(a_type==vm_str && b_type==vm_str) { - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(1); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; + new_val->ptr.num=(*val1->ptr.str==*val2->ptr.str); + *stack_top=new_val; } - else if((a_ref_type==vm_num || a_ref_type==vm_str) && (b_ref_type==vm_num || b_ref_type==vm_str)) + else if(a_type==vm_num || b_type==vm_num) { - if(a_ref_type==vm_str && b_ref_type==vm_str) - { - std::string astr=val_addr1->get_string(); - std::string bstr=val_addr2->get_string(); - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number((double)(astr==bstr)); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; - } - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number((double)(val_addr1->to_number()==val_addr2->to_number())); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; + new_val->ptr.num=(val1->to_number()==val2->to_number()); + *stack_top=new_val; } else { - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1==val_addr2); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; + new_val->ptr.num=(val1==val2); + *stack_top=new_val; } return; } void nasal_vm::opr_neq() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - int a_ref_type=val_addr1->get_type(); - int b_ref_type=val_addr2->get_type(); - if(a_ref_type==vm_nil && b_ref_type==vm_nil) + nasal_val* new_val=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; + else if(a_type==vm_str && b_type==vm_str) { - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(0); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; + new_val->ptr.num=(*val1->ptr.str!=*val2->ptr.str); + *stack_top=new_val; } - else if((a_ref_type==vm_num || a_ref_type==vm_str) && (b_ref_type==vm_num || b_ref_type==vm_str)) + else if(a_type==vm_num || b_type==vm_num) { - if(a_ref_type==vm_str && b_ref_type==vm_str) - { - std::string astr=val_addr1->get_string(); - std::string bstr=val_addr2->get_string(); - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number((double)(astr!=bstr)); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; - } - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number((double)(val_addr1->to_number()!=val_addr2->to_number())); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; + new_val->ptr.num=(val1->to_number()!=val2->to_number()); + *stack_top=new_val; } else { - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1!=val_addr2); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; + new_val->ptr.num=(val1!=val2); + *stack_top=new_val; } return; } void nasal_vm::opr_less() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - int a_ref_type=val_addr1->get_type(); - int b_ref_type=val_addr2->get_type(); - if(a_ref_type==vm_str && b_ref_type==vm_str) - { - std::string a_str=val_addr1->get_string(); - std::string b_str=val_addr2->get_string(); - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(a_strset_number(val_addr1->to_number()to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=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_str && b_type==vm_str) + new_val->ptr.num=(*val1->ptr.str<*val2->ptr.str); + else + new_val->ptr.num=(val1->to_number()to_number()); + *stack_top=new_val; return; } void nasal_vm::opr_leq() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - int a_ref_type=val_addr1->get_type(); - int b_ref_type=val_addr2->get_type(); - if(a_ref_type==vm_str && b_ref_type==vm_str) - { - std::string a_str=val_addr1->get_string(); - std::string b_str=val_addr2->get_string(); - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(a_str<=b_str); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; - } - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()<=val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=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_str && b_type==vm_str) + new_val->ptr.num=(*val1->ptr.str<=*val2->ptr.str); + else + new_val->ptr.num=(val1->to_number()<=val2->to_number()); + *stack_top=new_val; return; } void nasal_vm::opr_grt() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - int a_ref_type=val_addr1->get_type(); - int b_ref_type=val_addr2->get_type(); - if(a_ref_type==vm_str && b_ref_type==vm_str) - { - std::string a_str=val_addr1->get_string(); - std::string b_str=val_addr2->get_string(); - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(a_str>b_str); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; - } - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()>val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=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_str && b_type==vm_str) + new_val->ptr.num=(*val1->ptr.str>*val2->ptr.str); + else + new_val->ptr.num=(val1->to_number()>val2->to_number()); + *stack_top=new_val; return; } void nasal_vm::opr_geq() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top; - int a_ref_type=val_addr1->get_type(); - int b_ref_type=val_addr2->get_type(); - if(a_ref_type==vm_str && b_ref_type==vm_str) - { - std::string a_str=val_addr1->get_string(); - std::string b_str=val_addr2->get_string(); - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(a_str>=b_str); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); - return; - } - nasal_val* new_val_addr=gc.gc_alloc(vm_num); - new_val_addr->set_number(val_addr1->to_number()>=val_addr2->to_number()); - *val_stack_top=new_val_addr; - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); + nasal_val* new_val=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_str && b_type==vm_str) + new_val->ptr.num=(*val1->ptr.str>=*val2->ptr.str); + else + new_val->ptr.num=(val1->to_number()>=val2->to_number()); + *stack_top=new_val; return; } void nasal_vm::opr_pop() { - gc.del_reference(*val_stack_top--); + --stack_top; return; } void nasal_vm::opr_jmp() { - ptr=exec_code[ptr].index-1; + pc=exec_code[pc].num-1; return; } -void nasal_vm::opr_jmptrue() +void nasal_vm::opr_jt() { - if(check_condition(*val_stack_top)) - ptr=exec_code[ptr].index-1; + if(check_condition(*stack_top)) + pc=exec_code[pc].num-1; return; } -void nasal_vm::opr_jmpfalse() +void nasal_vm::opr_jf() { - if(!check_condition(*val_stack_top)) - ptr=exec_code[ptr].index-1; - gc.del_reference(*val_stack_top--); + if(!check_condition(*stack_top)) + pc=exec_code[pc].num-1; + --stack_top; return; } void nasal_vm::opr_counter() { - if((*val_stack_top)->get_type()!=vm_vec) + if((*stack_top)->type!=vm_vec) { die("cnt: must use vector in forindex/foreach"); return; } - counter_stack.push(-1); + counter.push(-1); return; } void nasal_vm::opr_cntpop() { - counter_stack.pop(); + counter.pop(); return; } -void nasal_vm::opr_forindex() +void nasal_vm::opr_findex() { - nasal_vec& ref=(*val_stack_top)->get_vector(); - ++counter_stack.top(); - if(counter_stack.top()>=ref.size()) + if(++counter.top()>=(*stack_top)->ptr.vec->elems.size()) { - ptr=exec_code[ptr].index-1; + pc=exec_code[pc].num-1; return; } - nasal_val* res=gc.gc_alloc(vm_num); - res->set_number((double)counter_stack.top()); - *(++val_stack_top)=res; + nasal_val* res=gc_alloc(vm_num); + res->ptr.num=counter.top(); + *(++stack_top)=res; return; } -void nasal_vm::opr_foreach() +void nasal_vm::opr_feach() { - nasal_vec& ref=(*val_stack_top)->get_vector(); - ++counter_stack.top(); - if(counter_stack.top()>=ref.size()) + std::vector& ref=(*stack_top)->ptr.vec->elems; + ++counter.top(); + if(counter.top()>=ref.size()) { - ptr=exec_code[ptr].index-1; + pc=exec_code[pc].num-1; return; } - nasal_val* res=ref[counter_stack.top()]; - gc.add_reference(res); - *(++val_stack_top)=res; + nasal_val* res=ref[counter.top()]; + *(++stack_top)=res; return; } void nasal_vm::opr_call() { - nasal_val* val_addr=NULL; - nasal_val* local_scope_top=local_scope_stack.top(); - int name_index=exec_code[ptr].index; - if(local_scope_top) + nasal_val* val=nullptr; + int name_index=exec_code[pc].num; + if(!local.empty()) + val=local.back()->ptr.scop->get_val(name_index); + if(val) { - val_addr=local_scope_top->get_closure().get_value_address(name_index); - if(val_addr) - { - gc.add_reference(val_addr); - *(++val_stack_top)=val_addr; - return; - } - } - val_addr=global_scope_addr->get_closure().get_value_address(name_index); - if(val_addr) - { - gc.add_reference(val_addr); - *(++val_stack_top)=val_addr; + *(++stack_top)=val; return; } - die("call: cannot find symbol named \""+string_table[name_index]+"\""); + val=global->ptr.scop->get_val(name_index); + if(val) + { + *(++stack_top)=val; + return; + } + die("call: cannot find symbol named \""+str_table[name_index]+"\""); return; } void nasal_vm::opr_callv() { - nasal_val* val_addr=*val_stack_top--; - nasal_val* vec_addr=*val_stack_top--; - int type=vec_addr->get_type(); + nasal_val* val=*stack_top--; + nasal_val* vec_addr=*stack_top; + int type=vec_addr->type; if(type==vm_vec) { - int num=val_addr->to_number(); - nasal_val* res=vec_addr->get_vector().get_value_address(num); + int num=val->to_number(); + nasal_val* res=vec_addr->ptr.vec->get_val(num); if(res) - { - gc.add_reference(res); - *(++val_stack_top)=res; - } + *stack_top=res; else { die("callv: index out of range"); @@ -715,106 +620,95 @@ void nasal_vm::opr_callv() } else if(type==vm_hash) { - if(val_addr->get_type()!=vm_str) + if(val->type!=vm_str) { die("callv: must use string as the key"); return; } - nasal_val* res=vec_addr->get_hash().get_value_address(val_addr->get_string()); + nasal_val* res=vec_addr->ptr.hash->get_val(*val->ptr.str); if(!res) { - die("callv: cannot find member \""+val_addr->get_string()+"\" of this hash"); + die("callv: cannot find member \""+*val->ptr.str+"\" of this hash"); return; } - if(res->get_type()==vm_func) - { - (res->get_func().get_closure_addr())->get_closure().add_new_value(me_index,val_addr); - gc.add_reference(val_addr); - } - gc.add_reference(res); - *(++val_stack_top)=res; + if(res->type==vm_func) + res->ptr.func->closure[me_index]=val; + *stack_top=res; } else if(type==vm_str) { - std::string str=vec_addr->get_string(); - int num=val_addr->to_number(); + std::string& str=*vec_addr->ptr.str; + int num=val->to_number(); int str_size=str.length(); if(num<-str_size || num>=str_size) { die("callv: index out of range"); return; } - nasal_val* res=gc.gc_alloc(vm_num); - res->set_number((double)str[num>=0? num:num+str_size]); - *(++val_stack_top)=res; + nasal_val* res=gc_alloc(vm_num); + res->ptr.num=(str[num>=0? num:num+str_size]); + *stack_top=res; } else die("callv: must call a vector/hash/string"); - gc.del_reference(val_addr); - gc.del_reference(vec_addr); return; } void nasal_vm::opr_callvi() { - nasal_val* val_addr=*val_stack_top; - if(val_addr->get_type()!=vm_vec) + nasal_val* val=*stack_top; + if(val->type!=vm_vec) { die("callvi: multi-definition/multi-assignment must use a vector"); return; } // cannot use operator[],because this may cause overflow - nasal_val* res=val_addr->get_vector().get_value_address(exec_code[ptr].index); + nasal_val* res=val->ptr.vec->get_val(exec_code[pc].num); if(!res) { die("callvi: index out of range"); return; } - gc.add_reference(res); - *(++val_stack_top)=res; + *(++stack_top)=res; return; } void nasal_vm::opr_callh() { - nasal_val* val_addr=*val_stack_top; - if(val_addr->get_type()!=vm_hash) + nasal_val* val=*stack_top; + if(val->type!=vm_hash) { die("callh: must call a hash"); return; } - nasal_val* res=val_addr->get_hash().get_value_address(string_table[exec_code[ptr].index]); - if(res) - gc.add_reference(res); - else + nasal_val* res=val->ptr.hash->get_val(str_table[exec_code[pc].num]); + if(!res) { - die("callh: hash member \""+string_table[exec_code[ptr].index]+"\" does not exist"); + die("callh: hash member \""+str_table[exec_code[pc].num]+"\" does not exist"); return; } - if(res->get_type()==vm_func) - (res->get_func().get_closure_addr())->get_closure().add_new_value(me_index,val_addr); - else - gc.del_reference(val_addr); - *val_stack_top=res; + if(res->type==vm_func) + res->ptr.func->closure[me_index]=val; + *stack_top=res; return; } void nasal_vm::opr_callf() { - nasal_val* para_addr=*val_stack_top--; - nasal_val* func_addr=*val_stack_top; - if(func_addr->get_type()!=vm_func) + nasal_val* closure=gc_alloc(vm_scop); + nasal_val* para_addr=*stack_top; + nasal_val* func_addr=*(stack_top-1); + if(func_addr->type!=vm_func) { die("callf: called a value that is not a function"); return; } - nasal_func& ref_func=func_addr->get_func(); - nasal_val* closure=gc.gc_alloc(vm_scop); - nasal_scop& ref_closure=closure->get_closure(); - ref_closure.set_closure(ref_func.get_closure_addr()->get_closure()); - local_scope_stack.push(closure); - if(para_addr->get_type()==vm_vec) + nasal_func& ref_func=*func_addr->ptr.func; + nasal_scop& ref_closure=*closure->ptr.scop; + ref_closure.elems=ref_func.closure; + local.push_back(closure); + if(para_addr->type==vm_vec) { - nasal_vec& ref_vec=para_addr->get_vector(); - std::vector& ref_para=ref_func.get_para(); - std::vector& ref_default=ref_func.get_default(); + std::vector& ref_vec=para_addr->ptr.vec->elems; + std::vector& ref_para=ref_func.para; + std::vector& ref_default=ref_func.default_para; int i=0; for(;i=0) + if(ref_func.dynpara>=0) { - nasal_val* vec_addr=gc.gc_alloc(vm_vec); + nasal_val* vec_addr=gc_alloc(vm_vec); for(;iget_vector().add_elem(tmp); - gc.add_reference(tmp); + vec_addr->ptr.vec->elems.push_back(tmp); } - ref_closure.add_new_value(ref_func.get_dynamic_para(),vec_addr); + ref_closure.elems[ref_func.dynpara]=vec_addr; } } else { - nasal_hash& ref_hash=para_addr->get_hash(); - std::vector& ref_para=ref_func.get_para(); - std::vector& ref_default=ref_func.get_default(); - if(ref_func.get_dynamic_para()>=0) + nasal_hash& ref_hash=*para_addr->ptr.hash; + std::vector& ref_para=ref_func.para; + std::vector& ref_default=ref_func.default_para; + if(ref_func.dynpara>=0) { die("callf: special call cannot use dynamic parameter"); return; } for(int i=0;iget_type()!=vm_vec) + slice_stack.push_back(gc_alloc(vm_vec)); + if((*stack_top)->type!=vm_vec) die("slcbegin: must slice a vector"); return; } -void nasal_vm::opr_sliceend() +void nasal_vm::opr_slcend() { - gc.del_reference(*val_stack_top); - *val_stack_top=slice_stack.top(); - slice_stack.pop(); + *stack_top=slice_stack.back(); + slice_stack.pop_back(); return; } -void nasal_vm::opr_slice() +void nasal_vm::opr_slc() { - nasal_val* val_addr=*val_stack_top--; + nasal_val* val=*stack_top--; double num; - switch(val_addr->get_type()) + switch(val->type) { - case vm_num:num=val_addr->get_number();break; - case vm_str:num=trans_string_to_number(val_addr->get_string());break; + case vm_num:num=val->ptr.num;break; + case vm_str:num=trans_string_to_number(*val->ptr.str);break; default:die("slc: error value type");break; } - nasal_val* res=(*val_stack_top)->get_vector().get_value_address((int)num); + nasal_val* res=(*stack_top)->ptr.vec->get_val((int)num); if(res) - { - gc.add_reference(res); - (slice_stack.top())->get_vector().add_elem(res); - gc.del_reference(val_addr); - return; - } - die("slc: index out of range"); + slice_stack.back()->ptr.vec->elems.push_back(res); + else + die("slc: index out of range"); return; } -void nasal_vm::opr_slice2() +void nasal_vm::opr_slc2() { - nasal_val* val_addr2=*val_stack_top--; - nasal_val* val_addr1=*val_stack_top--; - nasal_vec& ref=(*val_stack_top)->get_vector(); - nasal_vec& aim=(slice_stack.top())->get_vector(); + nasal_val* val2=*stack_top--; + nasal_val* val1=*stack_top--; + std::vector& ref=(*stack_top)->ptr.vec->elems; + std::vector& aim=slice_stack.back()->ptr.vec->elems; - int type1=val_addr1->get_type(),type2=val_addr2->get_type(); - int num1,num2; - switch(type1) - { - case vm_nil:break; - case vm_num:num1=(int)val_addr1->get_number();break; - case vm_str:num1=(int)trans_string_to_number(val_addr1->get_string());break; - default:die("slc2: error value type");break; - } - switch(type2) - { - case vm_nil:break; - case vm_num:num2=(int)val_addr2->get_number();break; - case vm_str:num2=(int)trans_string_to_number(val_addr2->get_string());break; - default:die("slc2: error value type");break; - } + int type1=val1->type,type2=val2->type; + int num1=val1->to_number(); + int num2=val2->to_number(); int ref_size=ref.size(); if(type1==vm_nil && type2==vm_nil) { @@ -950,6 +823,7 @@ void nasal_vm::opr_slice2() num1=num2<0? -ref_size:0; else if(type1!=vm_nil && type2==vm_nil) num2=num1<0? -1:ref_size-1; + if(num1>=num2) { die("slc2: begin index must be less than end index"); @@ -962,51 +836,47 @@ void nasal_vm::opr_slice2() } for(int i=num1;i<=num2;++i) { - nasal_val* tmp=ref.get_value_address(i); - gc.add_reference(tmp); - aim.add_elem(tmp); + nasal_val* tmp=ref[i]; + aim.push_back(tmp); } - gc.del_reference(val_addr1); - gc.del_reference(val_addr2); return; } void nasal_vm::opr_mcall() { - nasal_val** mem_addr=NULL; - int name_index=exec_code[ptr].index; - nasal_val* local_scope_top=local_scope_stack.top(); - if(local_scope_top) - mem_addr=local_scope_top->get_closure().get_mem_address(name_index); + 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(mem_addr) { addr_stack.push(mem_addr); return; } - mem_addr=global_scope_addr->get_closure().get_mem_address(name_index); + mem_addr=global->ptr.scop->get_mem(name_index); if(mem_addr) { addr_stack.push(mem_addr); return; } - die("mcall: cannot find symbol named \""+string_table[name_index]+"\""); + die("mcall: cannot find symbol named \""+str_table[name_index]+"\""); return; } void nasal_vm::opr_mcallv() { - nasal_val* val_addr=*val_stack_top--; + nasal_val* val=*stack_top--; nasal_val** vec_addr=addr_stack.top(); addr_stack.pop(); - int type=(*vec_addr)->get_type(); + int type=(*vec_addr)->type; if(type==vm_vec) { int num; - switch(val_addr->get_type()) + switch(val->type) { - case vm_num:num=(int)val_addr->get_number();break; - case vm_str:num=(int)trans_string_to_number(val_addr->get_string());break; + case vm_num:num=(int)val->ptr.num;break; + case vm_str:num=(int)trans_string_to_number(*val->ptr.str);break; default:die("mcallv: error value type");break; } - nasal_val** res=(*vec_addr)->get_vector().get_mem_address(num); + nasal_val** res=(*vec_addr)->ptr.vec->get_mem(num); if(!res) { die("mcallv: index out of range"); @@ -1016,18 +886,18 @@ void nasal_vm::opr_mcallv() } else if(type==vm_hash) { - if(val_addr->get_type()!=vm_str) + if(val->type!=vm_str) { die("mcallv: must use string as the key"); return; } - nasal_hash& ref=(*vec_addr)->get_hash(); - std::string str=val_addr->get_string(); - nasal_val** res=ref.get_mem_address(str); + nasal_hash& ref=*(*vec_addr)->ptr.hash; + std::string str=*val->ptr.str; + nasal_val** res=ref.get_mem(str); if(!res) { - ref.add_elem(str,gc.gc_alloc(vm_nil)); - res=ref.get_mem_address(str); + ref.elems[str]=nil_addr; + res=ref.get_mem(str); } addr_stack.push(res); } @@ -1036,82 +906,56 @@ void nasal_vm::opr_mcallv() die("mcallv: cannot get memory space in a string"); return; } - gc.del_reference(val_addr); return; } void nasal_vm::opr_mcallh() { - nasal_val** mem_addr=NULL; + nasal_val** mem_addr=nullptr; nasal_val** hash_addr=addr_stack.top(); addr_stack.pop(); - if((*hash_addr)->get_type()!=vm_hash) + if((*hash_addr)->type!=vm_hash) { die("mcallh: must call a hash"); return; } - nasal_hash& ref=(*hash_addr)->get_hash(); - std::string str=string_table[exec_code[ptr].index]; - mem_addr=ref.get_mem_address(str); + nasal_hash& ref=*(*hash_addr)->ptr.hash; + std::string& str=str_table[exec_code[pc].num]; + mem_addr=ref.get_mem(str); if(!mem_addr) // create a new key { - ref.add_elem(str,gc.gc_alloc(vm_nil)); - mem_addr=ref.get_mem_address(str); + ref.elems[str]=nil_addr; + mem_addr=ref.get_mem(str); } addr_stack.push(mem_addr); return; } -void nasal_vm::opr_return() +void nasal_vm::opr_ret() { - gc.del_reference(local_scope_stack.top()); - local_scope_stack.pop(); - ptr=call_stack.top(); + local.pop_back(); + pc=call_stack.top(); call_stack.pop(); - nasal_val* tmp=*val_stack_top--; - // delete function - gc.del_reference(*val_stack_top); - *val_stack_top=tmp; + nasal_val* ret_val=*stack_top--; + *stack_top=ret_val; return; } -void nasal_vm::run(std::vector& strs,std::vector& nums,std::vector& exec) +void nasal_vm::run() { - me_index=-1; - string_table=strs; - number_table=nums; - exec_code=exec; - zero_addr=gc.gc_alloc(vm_num); - zero_addr->set_number(0); - one_addr=gc.gc_alloc(vm_num); - one_addr->set_number(1); - nil_addr=gc.gc_alloc(vm_nil); - num_addrs.clear(); - for(int i=0;iset_number(number_table[i]); - } - - builtin_use_string_table.clear(); - for(int i=0;i& strs,std::vector& nums,std: &nasal_vm::opr_geq, &nasal_vm::opr_pop, &nasal_vm::opr_jmp, - &nasal_vm::opr_jmptrue, - &nasal_vm::opr_jmpfalse, + &nasal_vm::opr_jt, + &nasal_vm::opr_jf, &nasal_vm::opr_counter, &nasal_vm::opr_cntpop, - &nasal_vm::opr_forindex, - &nasal_vm::opr_foreach, + &nasal_vm::opr_findex, + &nasal_vm::opr_feach, &nasal_vm::opr_call, &nasal_vm::opr_callv, &nasal_vm::opr_callvi, &nasal_vm::opr_callh, &nasal_vm::opr_callf, - &nasal_vm::opr_builtincall, - &nasal_vm::opr_slicebegin, - &nasal_vm::opr_sliceend, - &nasal_vm::opr_slice, - &nasal_vm::opr_slice2, + &nasal_vm::opr_callb, + &nasal_vm::opr_slcbegin, + &nasal_vm::opr_slcend, + &nasal_vm::opr_slc, + &nasal_vm::opr_slc2, &nasal_vm::opr_mcall, &nasal_vm::opr_mcallv, &nasal_vm::opr_mcallh, - &nasal_vm::opr_return + &nasal_vm::opr_ret }; - - main_loop_break_mark=true; - builtin_die_state=false; - - global_scope_addr=gc.gc_alloc(vm_scop); clock_t begin_time=clock(); - // main loop - for(ptr=0;main_loop_break_mark;++ptr) - (this->*opr_table[exec_code[ptr].op])(); + for(pc=0;loop_mark;++pc) + (this->*opr_table[exec_code[pc].op])(); - float total_run_time=((double)(clock()-begin_time))/CLOCKS_PER_SEC; - std::cout<<">> [vm] process exited after "<> [vm] process exited after "<0.001) { error=0; @@ -138,20 +137,14 @@ while(error>0.001) } cnt+=1; show+=1; - if(show==200) + if(show==150) { show=0; print('epoch ',cnt,':',error,'\r'); } } print('finished after ',cnt,' epoch.\n'); -var vec=[ - [0,0], - [0,1], - [1,0], - [1,1] -]; -foreach(var v;vec) +foreach(var v;training_set) { run(v); print(v,': ',output[0].out,'\n'); diff --git a/test/class.nas b/test/class.nas index eacba91..1f5e262 100644 --- a/test/class.nas +++ b/test/class.nas @@ -1,19 +1,23 @@ import("lib.nas"); -var student= +var student=func(name,age) { - new:func(name,age) - { - return { - parents:[student], - name:name, - age:age - }; - }, - print_info:func(){println(me.name,' ',me.age);}, - get_age:func(){return me.age;}, - get_name:func(){return me.name;} + var val={ + name:name, + age:age + }; + return { + print_info:func(){println(val.name,' ',val.age);}, + set_age: func(age){val.age=age;}, + get_age: func(){return val.age;}, + set_name: func(name){val.name=name;}, + get_name: func(){return val.name;} + } }; -var s=student.new('tiansuohaoer',24); +var s=student('valk',24); +s.print_info(); +println(s.get_age(),' ',s.get_name()); +s.set_age(18); +s.set_name('aluo'); s.print_info(); println(s.get_age(),' ',s.get_name()); \ No newline at end of file diff --git a/test/fib.nas b/test/fib.nas index e29e6a4..55ae771 100644 --- a/test/fib.nas +++ b/test/fib.nas @@ -1,27 +1,19 @@ -var print=func(elements...) -{ - nasal_call_builtin_std_cout(elements); - return nil; -}; -var setsize=func(vector,size) -{ - nasal_call_builtin_set_size(vector,size); - return nil; -} +import("lib.nas"); var fib=func(x) { if(x<2) return x; return fib(x-1)+fib(x-2); } -print(fib(30),'\n'); +for(var i=0;i<31;i+=1) + print(fib(i),'\n'); -var m=[0,1,1,2,3,5,8]; -setsize(m,101); -var fib=func(n) -{ - if(m[n]!=nil) return m[n]; - var t=fib(n-1)+fib(n-2); - m[n]=t; - return t; -} -print(fib(100),'\n'); \ No newline at end of file +# var m=[0,1,1,2,3,5,8]; +# setsize(m,101); +# var fib=func(n) +# { +# if(m[n]!=nil) return m[n]; +# var t=fib(n-1)+fib(n-2); +# m[n]=t; +# return t; +# } +# print(fib(100),'\n'); \ No newline at end of file diff --git a/test/lexer.nas b/test/lexer.nas index 31cd157..a33aab7 100644 --- a/test/lexer.nas +++ b/test/lexer.nas @@ -1,60 +1,60 @@ import("lib.nas"); -var s=split('',io.fin(input())); +var s=io.fin(input()); var len=size(s); var ptr=0; +var cnt=0; +var token=[]; var jump_note=func() { - while(ptr=len) @@ -62,80 +62,77 @@ var generate_str=func() ptr+=1; return tok_str; } - var generate_number=func() { - var number=s[ptr]; + var number=chr(s[ptr]); ptr+=1; - if(s[ptr]=='x') + if(chr(s[ptr])=='x') { ptr+=1; - while(ptr' or s[ptr]=='<' or s[ptr]=='!' or s[ptr]=='=') + if(chr(s[ptr])=='+' or chr(s[ptr])=='-' or chr(s[ptr])=='~' or chr(s[ptr])=='/' or chr(s[ptr])=='*' or chr(s[ptr])=='>' or chr(s[ptr])=='<' or chr(s[ptr])=='!' or chr(s[ptr])=='=') { - tmp=s[ptr]; + tmp=chr(s[ptr]); ptr+=1; - if(ptr0) - tmp=s[ptr]; + elsif(chr(s[ptr])!=' ' and chr(s[ptr])!='\t' and chr(s[ptr])!='\n' and chr(s[ptr])!='\r' and chr(s[ptr])[0]>0) + tmp=chr(s[ptr]); ptr+=1; return tmp; } -var cnt=0; -var token=[]; + while(ptr=len) break; } + foreach(var i;token) { print("(",cnt," | ",i,")\n"); cnt+=1; -} \ No newline at end of file +} diff --git a/test/lib.nas b/test/lib.nas index 3a0029d..2974927 100644 --- a/test/lib.nas +++ b/test/lib.nas @@ -1,157 +1,157 @@ var import=func(filename) { - nasal_call_import(filename); + __builtin_import(filename); return nil; } var print=func(elements...) { - nasal_call_builtin_std_cout(elements); + __builtin_std_cout(elements); return nil; }; var println=func(elements...) { - nasal_call_builtin_std_cout(elements); + __builtin_std_cout(elements); print('\n'); return nil; } var append=func(vector,elements...) { - nasal_call_builtin_push_back(vector,elements); + __builtin_push_back(vector,elements); return nil; } var setsize=func(vector,size) { - nasal_call_builtin_set_size(vector,size); + __builtin_set_size(vector,size); return nil; } var system=func(str) { - nasal_call_builtin_system(str); + __builtin_system(str); return; } var input=func() { - return nasal_call_builtin_input(); + return __builtin_input(); } var sleep=func(duration) { - nasal_call_builtin_sleep(duration); + __builtin_sleep(duration); return; } var split=func(delimeter,string) { - return nasal_call_builtin_split(delimeter,string); + return __builtin_split(delimeter,string); } var rand=func(seed=nil) { - return nasal_call_builtin_rand(seed); + return __builtin_rand(seed); } var id=func(thing) { - return nasal_call_builtin_get_id(thing); + return __builtin_get_id(thing); } var int=func(value) { - return nasal_call_builtin_trans_int(value); + return __builtin_int(value); } var num=func(value) { - return nasal_call_builtin_trans_num(value); + return __builtin_num(value); } var pop=func(vector) { - return nasal_call_builtin_pop_back(vector); + return __builtin_pop_back(vector); } var str=func(number) { - return nasal_call_builtin_trans_str(number); + return __builtin_str(number); } var size=func(object) { - return nasal_call_builtin_size(object); + return __builtin_size(object); } var contains=func(hash,key) { - return nasal_call_builtin_contains(hash,key); + return __builtin_contains(hash,key); } var delete=func(hash,key) { - nasal_call_builtin_delete(hash,key); + __builtin_delete(hash,key); return; } var keys=func(hash) { - return nasal_call_builtin_get_keys(hash); + return __builtin_get_keys(hash); } var time=func(begin_time) { - return nasal_call_builtin_time(begin_time); + return __builtin_time(begin_time); } var die=func(str) { - nasal_call_builtin_die(str); + __builtin_die(str); return nil; } var typeof=func(object) { - return nasal_call_builtin_type(object); + return __builtin_type(object); } var substr=func(str,begin,length) { - return nasal_call_builtin_substr(str,begin,length); + return __builtin_substr(str,begin,length); } var streq=func(a,b) { - return nasal_call_builtin_streq(a,b); + return __builtin_streq(a,b); } var left=func(string,length) { - return nasal_call_builtin_left(string,length); + return __builtin_left(string,length); } var right=func(string,length) { - return nasal_call_builtin_right(string,length); + return __builtin_right(string,length); } var cmp=func(a,b) { - return nasal_call_builtin_cmp(a,b); + return __builtin_cmp(a,b); } var chr=func(code) #//Unlike in FG, this chr does not support Extended ASCII { - return nasal_call_builtin_chr(code); + return __builtin_chr(code); } var io= { fin:func(filename) { - return nasal_call_builtin_finput(filename); + return __builtin_fin(filename); }, fout:func(filename,str) { - nasal_call_builtin_foutput(filename,str); + __builtin_fout(filename,str); return; } }; var bits= { - bitxor: func(a,b){return nasal_call_builtin_xor(a,b); }, - bitand: func(a,b){return nasal_call_builtin_and(a,b); }, - bitor: func(a,b){return nasal_call_builtin_or(a,b); }, - bitnand: func(a,b){return nasal_call_builtin_nand(a,b);}, - bitnot: func(a) {return nasal_call_builtin_not(a); } + bitxor: func(a,b){return __builtin_xor(a,b); }, + bitand: func(a,b){return __builtin_and(a,b); }, + bitor: func(a,b){return __builtin_or(a,b); }, + bitnand: func(a,b){return __builtin_nand(a,b);}, + bitnot: func(a) {return __builtin_not(a); } }; var math= { e: 2.7182818284590452354, pi: 3.14159265358979323846264338327950288, - sin: func(x) {return nasal_call_builtin_sin(x); }, - cos: func(x) {return nasal_call_builtin_cos(x); }, - tan: func(x) {return nasal_call_builtin_tan(x); }, - exp: func(x) {return nasal_call_builtin_exp(x); }, - ln: func(x) {return nasal_call_builtin_cpp_math_ln(x); }, - sqrt: func(x) {return nasal_call_builtin_cpp_math_sqrt(x);}, - atan2: func(x,y){return nasal_call_builtin_cpp_atan2(x,y); } + sin: func(x) {return __builtin_sin(x); }, + cos: func(x) {return __builtin_cos(x); }, + tan: func(x) {return __builtin_tan(x); }, + exp: func(x) {return __builtin_exp(x); }, + ln: func(x) {return __builtin_ln(x); }, + sqrt: func(x) {return __builtin_sqrt(x); }, + atan2: func(x,y){return __builtin_atan2(x,y);} };