This commit is contained in:
Valk Richard Li 2020-04-12 04:43:09 -07:00 committed by GitHub
parent 5899c6e378
commit a245a8503e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 42 deletions

View File

@ -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;

View File

@ -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<std::map<std::string,int> > closure;
public:
void set_clear();
void set_local_scope(std::list<std::map<std::string,int> >&);
std::list<std::map<std::string,int> >& 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<std::map<std::string,int> > 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<std::map<std::string,int> >&);
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<std::map<std::string,int> >& 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<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
if(!closure.size())
return;
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
for(std::map<std::string,int>::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<std::map<std::string,int> >& tmp_scope)
{
if(closure.size())
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
nasal_gc.reference_delete(i->second);
closure.clear();
closure=tmp_scope;
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
nasal_gc.reference_add(i->second);
return;
}
std::list<std::map<std::string,int> >& nasal_closure::get_local_scope()
{
return closure;
}
void nasal_closure::print_closure_ids()
{
for(std::list<std::map<std::string,int> >::iterator iter=closure.begin();iter!=closure.end();++iter)
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
{
std::cout<<i->first<<": ";
prt_hex(i->second);
std::cout<<std::endl;
}
return;
}
nasal_function::nasal_function()
{
closure_updated=false;
local_scope.clear();
closure_addr=-1;
return;
}
void nasal_function::set_clear()
{
closure_updated=false;
if(closure_addr>=0)
nasal_gc.reference_delete(closure_addr);
closure_addr=-1;
function_root.set_clear();
return;
}
void nasal_function::set_local_scope(std::list<std::map<std::string,int> >& tmp_scope)
void nasal_function::set_local_scope(int tmp_addr)
{
for(std::list<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
nasal_gc.reference_delete(i->second);
local_scope=tmp_scope;
for(std::list<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
for(std::map<std::string,int>::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<std::map<std::string,int> >& 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<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
for(std::map<std::string,int>::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<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
for(std::map<std::string,int>::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

View File

@ -100,7 +100,7 @@ class nasal_runtime
int vector_generation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);//checked
int hash_generation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
int function_generation(std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
void update_closure (std::list<std::map<std::string,int> >&);
void update_closure (std::list<std::map<std::string,int> >&,int);
bool check_condition (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
int calculation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
int assignment (std::list<std::map<std::string,int> >&,abstract_syntax_tree&,int);
@ -109,7 +109,7 @@ class nasal_runtime
int loop_expr (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
int conditional (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
int block_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
int func_proc (std::list<std::map<std::string,int> >&,std::list<std::map<std::string,int> >,abstract_syntax_tree&,abstract_syntax_tree&,abstract_syntax_tree&,int);// checked
int func_proc (std::list<std::map<std::string,int> >&,std::list<std::map<std::string,int> >&,abstract_syntax_tree&,abstract_syntax_tree&,abstract_syntax_tree&,int);// checked
int inline_function (std::list<std::map<std::string,int> >&,std::string);
public:
nasal_runtime()
@ -802,7 +802,7 @@ int nasal_runtime::vector_generation(std::list<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<abstract_syntax_tree>::iterator i=node.get_children().begin();
@ -2044,7 +2047,7 @@ int nasal_runtime::function_generation(std::list<std::map<std::string,int> >& 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<std::map<std::string,int> >& lo
}
return addr;
}
void nasal_runtime::update_closure(std::list<std::map<std::string,int> >& local_scope)
void nasal_runtime::update_closure(std::list<std::map<std::string,int> >& local_scope,int local_scope_addr)
{
// update_closure
if(!local_scope.size())
@ -2065,7 +2068,16 @@ void nasal_runtime::update_closure(std::list<std::map<std::string,int> >& 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<std::string,int>::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<std::map<std::string,int> >& 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<std::map<std::string,int> >& 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<std::map<std::string,int> >& parameters_assist_scope,// scope that used to generate parameters
std::list<std::map<std::string,int> > local_scope, // running scope,often gets the scope that calls it
std::list<std::map<std::string,int> >& 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<std::string,int>::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<std::string,int>::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<std::string,int>::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))