diff --git a/version2.0/nasal_enum.h b/version2.0/nasal_enum.h index 2d1094e..ca26832 100644 --- a/version2.0/nasal_enum.h +++ b/version2.0/nasal_enum.h @@ -229,7 +229,8 @@ enum scalar_type scalar_string, scalar_vector, scalar_hash, - scalar_function + scalar_function, + scalar_closure }; // print types that used in nasal_runtime and nasal_gc void print_scalar_type(const int type) @@ -242,6 +243,7 @@ void print_scalar_type(const int type) case scalar_vector: std::cout<<"vector";break; case scalar_hash: std::cout<<"hash";break; case scalar_function: std::cout<<"function";break; + case scalar_closure: std::cout<<"closure";break; default: std::cout<<"nil";break; } return; diff --git a/version2.0/nasal_gc.h b/version2.0/nasal_gc.h index 3b515db..8caeb28 100644 --- a/version2.0/nasal_gc.h +++ b/version2.0/nasal_gc.h @@ -8,23 +8,35 @@ // the identifier will get a new memory space in nasal_gc and do deep_copy() // and the memory space that is not used ,its ref_cnt-=1. +class nasal_closure +{ +private: + std::list > closure; +public: + void set_clear(); + void set_local_scope(std::list >&); + std::list >& get_local_scope(); + void print_closure_ids(); +}; + class nasal_function { private: // closure_updated flag is used to mark if this function's closure is updated. // to avoid some unexpected errors,closure of each function must be updated before blocks popping back the last scope bool closure_updated; - std::list > local_scope; + int closure_addr; abstract_syntax_tree parameter_list; abstract_syntax_tree function_root; public: + nasal_function(); void set_clear(); - void set_local_scope(std::list >&); + void set_local_scope(int); bool get_closure_update_state(); void set_closure_update_state(bool); void set_paramemter_list(abstract_syntax_tree&); void set_statement_block(abstract_syntax_tree&); - std::list >& get_local_scope(); + int get_local_scope(); abstract_syntax_tree& get_parameter_list(); abstract_syntax_tree& get_statement_block(); void deep_copy(nasal_function&); @@ -91,6 +103,7 @@ private: nasal_vector var_vector; nasal_hash var_hash; nasal_function var_func; + nasal_closure var_cls; public: nasal_scalar(); void set_type(int); @@ -100,6 +113,7 @@ public: nasal_vector& get_vector(); nasal_hash& get_hash(); nasal_function& get_function(); + nasal_closure& get_closure(); }; struct gc_unit @@ -245,6 +259,8 @@ public: int get_reference(int addr) { // get the reference counts of the scalar + if(addr>=memory.size()) + return -1; return memory[addr].refcnt; } nasal_scalar& get_scalar(int addr) @@ -289,6 +305,7 @@ public: case scalar_vector: memory[addr].elem.get_vector().set_clear(); break; case scalar_hash: memory[addr].elem.get_hash().set_clear(); break; case scalar_function:memory[addr].elem.get_function().set_clear();break; + case scalar_closure: memory[addr].elem.get_closure().set_clear(); break; default:break; } memory[addr].elem.set_type(scalar_nil); @@ -335,26 +352,65 @@ gc_manager nasal_gc; // this object is used in "nasal_runtime.h" // because there must be only one gc when running a program(one process) - -void nasal_function::set_clear() +void nasal_closure::set_clear() { - for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) + if(!closure.size()) + return; + for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) for(std::map::iterator i=iter->begin();i!=iter->end();++i) nasal_gc.reference_delete(i->second); + closure.clear(); + return; +} +void nasal_closure::set_local_scope(std::list >& tmp_scope) +{ + if(closure.size()) + for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) + for(std::map::iterator i=iter->begin();i!=iter->end();++i) + nasal_gc.reference_delete(i->second); + closure.clear(); + closure=tmp_scope; + for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) + for(std::map::iterator i=iter->begin();i!=iter->end();++i) + nasal_gc.reference_add(i->second); + return; +} +std::list >& nasal_closure::get_local_scope() +{ + return closure; +} +void nasal_closure::print_closure_ids() +{ + for(std::list >::iterator iter=closure.begin();iter!=closure.end();++iter) + for(std::map::iterator i=iter->begin();i!=iter->end();++i) + { + std::cout<first<<": "; + prt_hex(i->second); + std::cout<=0) + nasal_gc.reference_delete(closure_addr); + closure_addr=-1; function_root.set_clear(); return; } -void nasal_function::set_local_scope(std::list >& tmp_scope) +void nasal_function::set_local_scope(int tmp_addr) { - for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) - for(std::map::iterator i=iter->begin();i!=iter->end();++i) - nasal_gc.reference_delete(i->second); - local_scope=tmp_scope; - for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) - for(std::map::iterator i=iter->begin();i!=iter->end();++i) - nasal_gc.reference_add(i->second); + if(closure_addr>=0) + nasal_gc.reference_delete(closure_addr); + closure_addr=tmp_addr; return; } bool nasal_function::get_closure_update_state() @@ -376,9 +432,9 @@ void nasal_function::set_statement_block(abstract_syntax_tree& func_block) function_root=func_block; return; } -std::list >& nasal_function::get_local_scope() +int nasal_function::get_local_scope() { - return local_scope; + return closure_addr; } abstract_syntax_tree& nasal_function::get_parameter_list() { @@ -390,17 +446,10 @@ abstract_syntax_tree& nasal_function::get_statement_block() } void nasal_function::deep_copy(nasal_function& tmp) { - // before deep copy nasal_functions needs to delete all values in its scope - for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) - for(std::map::iterator i=iter->begin();i!=iter->end();++i) - nasal_gc.reference_delete(i->second); - // when copying a local scope,one thing that must be noticed is that - // each identifier in local_scope shares the same address with tmp.local_scope - // copy all the values in tmp's scope - local_scope=tmp.local_scope; - for(std::list >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) - for(std::map::iterator i=iter->begin();i!=iter->end();++i) - nasal_gc.reference_add(i->second); + if(closure_addr>=0) + nasal_gc.reference_delete(closure_addr); + closure_addr=tmp.closure_addr; + nasal_gc.reference_add(closure_addr); // copy abstract_syntax_tree parameter_list=tmp.parameter_list; function_root=tmp.function_root; @@ -624,7 +673,7 @@ nasal_scalar::nasal_scalar() void nasal_scalar::set_type(int tmp_type) { // scalar_function is the last enum in enum::scalar_type - type=tmp_type>scalar_function? scalar_nil:tmp_type; + type=tmp_type>scalar_closure? scalar_nil:tmp_type; return; } int nasal_scalar::get_type() @@ -657,6 +706,11 @@ nasal_function& nasal_scalar::get_function() // get nasal_function return var_func; } +nasal_closure& nasal_scalar::get_closure() +{ + // get nasal_closure + return var_cls; +} #endif diff --git a/version2.0/nasal_runtime.h b/version2.0/nasal_runtime.h index 6861a09..81662ab 100644 --- a/version2.0/nasal_runtime.h +++ b/version2.0/nasal_runtime.h @@ -100,7 +100,7 @@ class nasal_runtime int vector_generation (std::list >&,abstract_syntax_tree&);//checked int hash_generation (std::list >&,abstract_syntax_tree&);// checked int function_generation(std::list >&,abstract_syntax_tree&);// checked - void update_closure (std::list >&); + void update_closure (std::list >&,int); bool check_condition (std::list >&,abstract_syntax_tree&);// checked int calculation (std::list >&,abstract_syntax_tree&);// checked int assignment (std::list >&,abstract_syntax_tree&,int); @@ -109,7 +109,7 @@ class nasal_runtime int loop_expr (std::list >&,abstract_syntax_tree&);// checked int conditional (std::list >&,abstract_syntax_tree&);// checked int block_proc (std::list >&,abstract_syntax_tree&);// checked - int func_proc (std::list >&,std::list >,abstract_syntax_tree&,abstract_syntax_tree&,abstract_syntax_tree&,int);// checked + int func_proc (std::list >&,std::list >&,abstract_syntax_tree&,abstract_syntax_tree&,abstract_syntax_tree&,int);// checked int inline_function (std::list >&,std::string); public: nasal_runtime() @@ -802,7 +802,7 @@ int nasal_runtime::vector_generation(std::list >& loca int tmp_addr=addr; addr=func_proc( local_scope, - nasal_gc.get_scalar(addr).get_function().get_local_scope(), + nasal_gc.get_scalar(nasal_gc.get_scalar(addr).get_function().get_local_scope()).get_closure().get_local_scope(), nasal_gc.get_scalar(addr).get_function().get_parameter_list(), nasal_gc.get_scalar(addr).get_function().get_statement_block(), *call_node, @@ -1443,7 +1443,7 @@ int nasal_runtime::hash_generation(std::list >& local_ int tmp_addr=addr; addr=func_proc( local_scope, - nasal_gc.get_scalar(addr).get_function().get_local_scope(), + nasal_gc.get_scalar(nasal_gc.get_scalar(addr).get_function().get_local_scope()).get_closure().get_local_scope(), nasal_gc.get_scalar(addr).get_function().get_parameter_list(), nasal_gc.get_scalar(addr).get_function().get_statement_block(), *call_node, @@ -1462,8 +1462,11 @@ int nasal_runtime::function_generation(std::list >& lo // block // calls... int addr=nasal_gc.gc_alloc(); + int scope_addr=nasal_gc.gc_alloc(); + nasal_gc.get_scalar(scope_addr).set_type(scalar_closure); + nasal_gc.get_scalar(scope_addr).get_closure().set_local_scope(local_scope); nasal_gc.get_scalar(addr).set_type(scalar_function); - nasal_gc.get_scalar(addr).get_function().set_local_scope(local_scope); + nasal_gc.get_scalar(addr).get_function().set_local_scope(scope_addr); nasal_gc.get_scalar(addr).get_function().set_closure_update_state(false); std::list::iterator i=node.get_children().begin(); @@ -2044,7 +2047,7 @@ int nasal_runtime::function_generation(std::list >& lo int tmp_addr=addr; addr=func_proc( local_scope, - nasal_gc.get_scalar(addr).get_function().get_local_scope(), + nasal_gc.get_scalar(nasal_gc.get_scalar(addr).get_function().get_local_scope()).get_closure().get_local_scope(), nasal_gc.get_scalar(addr).get_function().get_parameter_list(), nasal_gc.get_scalar(addr).get_function().get_statement_block(), *call_node, @@ -2056,7 +2059,7 @@ int nasal_runtime::function_generation(std::list >& lo } return addr; } -void nasal_runtime::update_closure(std::list >& local_scope) +void nasal_runtime::update_closure(std::list >& local_scope,int local_scope_addr) { // update_closure if(!local_scope.size()) @@ -2065,7 +2068,16 @@ void nasal_runtime::update_closure(std::list >& local_ if(nasal_gc.get_scalar(i->second).get_type()==scalar_function && !nasal_gc.get_scalar(i->second).get_function().get_closure_update_state()) { - nasal_gc.get_scalar(i->second).get_function().set_local_scope(local_scope); + nasal_gc.get_scalar(i->second).get_function().set_local_scope(local_scope_addr); + nasal_gc.reference_add(local_scope_addr); + nasal_gc.get_scalar(i->second).get_function().set_closure_update_state(true); + } + for(std::map::iterator i=global_scope.begin();i!=global_scope.end();++i) + if(nasal_gc.get_scalar(i->second).get_type()==scalar_function && + !nasal_gc.get_scalar(i->second).get_function().get_closure_update_state()) + { + nasal_gc.get_scalar(i->second).get_function().set_local_scope(local_scope_addr); + nasal_gc.reference_add(local_scope_addr); nasal_gc.get_scalar(i->second).get_function().set_closure_update_state(true); } return; @@ -3975,7 +3987,7 @@ int nasal_runtime::call_identifier(std::list >& local_ int tmp_addr=addr; addr=func_proc( local_scope, - nasal_gc.get_scalar(addr).get_function().get_local_scope(), + nasal_gc.get_scalar(nasal_gc.get_scalar(addr).get_function().get_local_scope()).get_closure().get_local_scope(), nasal_gc.get_scalar(addr).get_function().get_parameter_list(), nasal_gc.get_scalar(addr).get_function().get_statement_block(), *iter, @@ -4420,12 +4432,16 @@ int nasal_runtime::block_proc(std::list >& local_scope break; } // update_closure - update_closure(local_scope); + int closure_addr=nasal_gc.gc_alloc(); + nasal_gc.get_scalar(closure_addr).set_type(scalar_closure); + nasal_gc.get_scalar(closure_addr).get_closure().set_local_scope(local_scope); + update_closure(local_scope,closure_addr); + nasal_gc.reference_delete(closure_addr); return state; } int nasal_runtime::func_proc( std::list >& parameters_assist_scope,// scope that used to generate parameters - std::list > local_scope, // running scope,often gets the scope that calls it + std::list >& local_scope,// running scope,often gets the scope that calls it abstract_syntax_tree& parameter_list, // parameter list format of nasal function abstract_syntax_tree& func_root, // main runnning block of nasal function abstract_syntax_tree& input_parameters, // input parameters when calling this nasal function @@ -4615,7 +4631,11 @@ int nasal_runtime::func_proc( nasal_gc.get_scalar(function_returned_addr).set_type(scalar_nil); } // update closure - update_closure(local_scope); + int closure_addr=nasal_gc.gc_alloc(); + nasal_gc.get_scalar(closure_addr).set_type(scalar_closure); + nasal_gc.get_scalar(closure_addr).get_closure().set_local_scope(local_scope); + update_closure(local_scope,closure_addr); + nasal_gc.reference_delete(closure_addr); for(std::map::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i) nasal_gc.reference_delete(i->second); local_scope.pop_back(); @@ -4776,9 +4796,23 @@ void nasal_runtime::main_proc(abstract_syntax_tree& root) int addr=this->calculation(main_local_scope,*iter); if(addr>=0) nasal_gc.reference_delete(addr); + // new functions in global scope must set its closure_update_state to true + // or its local scope maybe changed after running other expressions + for(std::map::iterator i=global_scope.begin();i!=global_scope.end();++i) + if(nasal_gc.get_scalar(i->second).get_type()==scalar_function && + !nasal_gc.get_scalar(i->second).get_function().get_closure_update_state()) + nasal_gc.get_scalar(i->second).get_function().set_closure_update_state(true); } else if(node_type==__definition) + { this->definition(main_local_scope,global_scope,*iter); + // new functions in global scope must set its closure_update_state to true + // or its local scope maybe changed after running other expressions + for(std::map::iterator i=global_scope.begin();i!=global_scope.end();++i) + if(nasal_gc.get_scalar(i->second).get_type()==scalar_function && + !nasal_gc.get_scalar(i->second).get_function().get_closure_update_state()) + nasal_gc.get_scalar(i->second).get_function().set_closure_update_state(true); + } else if(node_type==__conditional) state=this->conditional(main_local_scope,*iter); else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex))