diff --git a/main.cpp b/main.cpp index 1a586bf..d4f10c1 100644 --- a/main.cpp +++ b/main.cpp @@ -132,10 +132,11 @@ void execute() } code_generator.main_progress(import.get_root()); code_generator.print_byte_code(); - bytevm.set_string_table(code_generator.get_string_table()); - bytevm.set_number_table(code_generator.get_number_table()); - bytevm.set_exec_code(code_generator.get_exec_code()); - //bytevm.run(); + bytevm.run( + code_generator.get_string_table(), + code_generator.get_number_table(), + code_generator.get_exec_code() + ); return; } diff --git a/nasal_bytecode_vm.h b/nasal_bytecode_vm.h index c0be748..9ff7484 100644 --- a/nasal_bytecode_vm.h +++ b/nasal_bytecode_vm.h @@ -80,10 +80,7 @@ public: nasal_bytecode_vm(); ~nasal_bytecode_vm(); void clear(); - void set_string_table(std::vector&); - void set_number_table(std::vector&); - void set_exec_code(std::vector&); - void run(); + void run(std::vector&,std::vector&,std::vector&); }; nasal_bytecode_vm::nasal_bytecode_vm() @@ -172,10 +169,14 @@ void nasal_bytecode_vm::clear() vm.clear(); global_scope_addr=-1; while(!value_stack.empty())value_stack.pop(); - while(local_scope_stack.top()!=-1)local_scope_stack.pop(); + while(!local_scope_stack.empty())local_scope_stack.pop(); + local_scope_stack.push(-1); while(!slice_stack.empty())slice_stack.pop(); while(!call_stack.empty())call_stack.pop(); while(!counter_stack.empty())counter_stack.pop(); + string_table.clear(); + number_table.clear(); + exec_code.clear(); return; } void nasal_bytecode_vm::die(std::string str) @@ -211,7 +212,10 @@ void nasal_bytecode_vm::opr_load() { int val_addr=value_stack.top(); value_stack.pop(); - vm.gc_get(global_scope_addr).get_closure().add_new_value(string_table[exec_code[ptr].index],val_addr); + if(local_scope_stack.top()>=0) + vm.gc_get(local_scope_stack.top()).get_closure().add_new_value(string_table[exec_code[ptr].index],val_addr); + else + vm.gc_get(global_scope_addr).get_closure().add_new_value(string_table[exec_code[ptr].index],val_addr); return; } void nasal_bytecode_vm::opr_pushnum() @@ -285,38 +289,27 @@ void nasal_bytecode_vm::opr_hashapp() { int val_addr=value_stack.top(); value_stack.pop(); - int str_addr=value_stack.top(); - value_stack.pop(); int hash_addr=value_stack.top(); - vm.gc_get(hash_addr).get_hash().add_elem(vm.gc_get(str_addr).get_string(),val_addr); - vm.del_reference(str_addr); + vm.gc_get(hash_addr).get_hash().add_elem(string_table[exec_code[ptr].index],val_addr); return; } void nasal_bytecode_vm::opr_para() { - int str_addr=value_stack.top(); - value_stack.pop(); - std::string str=vm.gc_get(str_addr).get_string(); - vm.del_reference(str_addr); - vm.gc_get(value_stack.top()).get_func().add_para(str,-1); + std::string str=string_table[exec_code[ptr].index]; + vm.gc_get(value_stack.top()).get_func().add_para(str); return; } void nasal_bytecode_vm::opr_defpara() { - int str_addr=value_stack.top(); - value_stack.pop(); - std::string str=vm.gc_get(str_addr).get_string(); - vm.del_reference(str_addr); - vm.gc_get(value_stack.top()).get_func().add_para(str,value_stack.top()); + int val_addr=value_stack.top(); value_stack.pop(); + std::string str=string_table[exec_code[ptr].index]; + vm.gc_get(value_stack.top()).get_func().add_para(str,val_addr); return; } void nasal_bytecode_vm::opr_dynpara() { - int str_addr=value_stack.top(); - value_stack.pop(); - std::string str=vm.gc_get(str_addr).get_string(); - vm.del_reference(str_addr); + std::string str=string_table[exec_code[ptr].index]; vm.gc_get(value_stack.top()).get_func().add_para(str,-1,true); return; } @@ -1039,9 +1032,9 @@ void nasal_bytecode_vm::opr_call() { int val_addr=-1; if(local_scope_stack.top()>=0) - vm.gc_get(local_scope_stack.top()).get_closure().get_value_address(string_table[exec_code[ptr].index]); + val_addr=vm.gc_get(local_scope_stack.top()).get_closure().get_value_address(string_table[exec_code[ptr].index]); else - vm.gc_get(global_scope_addr).get_closure().get_value_address(string_table[exec_code[ptr].index]); + val_addr=vm.gc_get(global_scope_addr).get_closure().get_value_address(string_table[exec_code[ptr].index]); if(val_addr<0) die("call: cannot find symbol named \""+string_table[exec_code[ptr].index]+"\""); value_stack.push(val_addr); @@ -1157,10 +1150,73 @@ void nasal_bytecode_vm::opr_callf() } nasal_function& ref=vm.gc_get(func_addr).get_func(); int closure=ref.get_closure_addr(); - vm.gc_get(closure).get_closure().add_scope(); + nasal_closure& ref_closure=vm.gc_get(closure).get_closure(); + ref_closure.add_scope(); local_scope_stack.push(closure); vm.add_reference(closure); // unfinished + if(vm.gc_get(para_addr).get_type()==vm_vector) + { + nasal_vector& ref_vec=vm.gc_get(para_addr).get_vector(); + std::vector& ref_para=ref.get_para(); + std::vector& ref_default=ref.get_default(); + int i=0; + for(;i=ref_vec.size()) + { + if(ref_default[i]<0) + { + die("callf: lack argument(s)"); + return; + } + ref_closure.add_new_value(ref_para[i],ref_default[i]); + vm.add_reference(ref_default[i]); + } + else + { + int tmp=ref_vec.get_value_address(i); + ref_closure.add_new_value(ref_para[i],tmp); + vm.add_reference(tmp); + } + } + if(ref.get_dynamic_para().length()) + { + int vec_addr=vm.gc_alloc(vm_vector); + for(;i& ref_para=ref.get_para(); + std::vector& ref_default=ref.get_default(); + if(ref.get_dynamic_para().length()) + { + die("callf: special call cannot use dynamic parameter"); + return; + } + for(int i=0;i& table) -{ - string_table=table; - return; -} -void nasal_bytecode_vm::set_number_table(std::vector& table) -{ - number_table=table; - return; -} -void nasal_bytecode_vm::set_exec_code(std::vector& exec) +void nasal_bytecode_vm::run(std::vector& strs,std::vector& nums,std::vector& exec) { + string_table=strs; + number_table=nums; int size=exec.size(); for(int i=0;i& exec) tmp=exec[i]; exec_code.push_back(tmp); } - return; -} -void nasal_bytecode_vm::run() -{ + error=0; global_scope_addr=vm.gc_alloc(vm_closure); - int size=exec_code.size(); + size=exec_code.size(); for(ptr=0;ptr*opr_table[exec_code[ptr].op])(); if(error) break; diff --git a/nasal_codegen.h b/nasal_codegen.h index e757855..2497262 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -277,10 +277,11 @@ void nasal_codegen::hash_gen(nasal_ast& ast) exec_code.push_back(op); for(int i=0;i para; + std::vector para_name; + std::string dynamic_para_name; + std::vector default_para_addr; public: nasal_function(nasal_virtual_machine&); ~nasal_function(); void set_entry(int); int get_entry(); void add_para(std::string,int,bool); + std::vector& get_para(); + std::string get_dynamic_para(); + std::vector& get_default(); void set_closure_addr(int); int get_closure_addr(); void set_arguments(nasal_ast&); @@ -272,6 +278,12 @@ int nasal_hash::size() { return elems.size(); } +int nasal_hash::get_special_para(std::string key) +{ + if(elems.find(key)!=elems.end()) + return vm.mem_get(elems[key]); + return -1; +} int nasal_hash::get_value_address(std::string key) { int ret_value_addr=-1; @@ -388,6 +400,7 @@ void nasal_hash::print() nasal_function::nasal_function(nasal_virtual_machine& nvm):vm(nvm) { closure_addr=-1; + dynamic_para_name=""; argument_list.clear(); function_expr.clear(); return; @@ -396,10 +409,9 @@ nasal_function::~nasal_function() { if(closure_addr>=0) vm.del_reference(closure_addr); - for(std::map::iterator i=para.begin();i!=para.end();++i) - if(i->second>=0) - vm.del_reference(i->second); - para.clear(); + for(int i=0;i=0) + vm.del_reference(default_para_addr[i]); argument_list.clear(); function_expr.clear(); return; @@ -413,15 +425,29 @@ int nasal_function::get_entry() { return entry; } -void nasal_function::add_para(std::string key,int init_value_addr,bool is_dynamic=false) +void nasal_function::add_para(std::string name,int val_addr=-1,bool is_dynamic=false) { - if(para.find(key)!=para.end()) - vm.del_reference(para[key]); - para[key]=init_value_addr; if(is_dynamic) - para[key]=vm.gc_alloc(vm_vector); + { + dynamic_para_name=name; + return; + } + para_name.push_back(name); + default_para_addr.push_back(val_addr); return; } +std::vector& nasal_function::get_para() +{ + return para_name; +} +std::string nasal_function::get_dynamic_para() +{ + return dynamic_para_name; +} +std::vector& nasal_function::get_default() +{ + return default_para_addr; +} void nasal_function::set_closure_addr(int value_address) { if(closure_addr>=0) diff --git a/nasal_runtime.h b/nasal_runtime.h index 08da867..1d03bb3 100644 --- a/nasal_runtime.h +++ b/nasal_runtime.h @@ -53,7 +53,7 @@ private: int call_scalar(nasal_ast&,int); int call_vector(nasal_ast&,int,int); int call_hash(nasal_ast&,int,int); - int call_function(nasal_ast&,std::string,int,int,int); + int call_function(nasal_ast&,int,int,int); int call_builtin_function(std::string,int); // get scalars' memory place in complex data structure like vector/hash/function/closure(scope) int call_scalar_mem(nasal_ast&,int); @@ -505,7 +505,7 @@ int nasal_runtime::call_scalar(nasal_ast& node,int local_scope_addr) val_name=call_expr.get_str(); break; case ast_call_func: - tmp_value_addr=call_function(call_expr,val_name,value_address,last_call_hash_addr,local_scope_addr); + tmp_value_addr=call_function(call_expr,value_address,last_call_hash_addr,local_scope_addr); last_call_hash_addr=-1; val_name=""; break; @@ -734,7 +734,7 @@ int nasal_runtime::call_hash(nasal_ast& node,int base_value_addr,int local_scope nasal_vm.add_reference(ret_value_addr); return ret_value_addr; } -int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_value_addr,int last_call_hash_addr,int local_scope_addr) +int nasal_runtime::call_function(nasal_ast& node,int base_value_addr,int last_call_hash_addr,int local_scope_addr) { int ret_value_addr=-1; int value_type=nasal_vm.gc_get(base_value_addr).get_type(); @@ -753,12 +753,6 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_ nasal_vm.add_reference(last_call_hash_addr); run_closure.add_new_value("me",last_call_hash_addr); } - else if(func_name.length()) - { - // when hash.me does not exist,set self - nasal_vm.add_reference(base_value_addr); - run_closure.add_new_value(func_name,base_value_addr); - } nasal_ast& argument_format=reference_of_func.get_arguments(); if(!node.get_children().size()) {