This commit is contained in:
Valk Richard Li 2020-04-12 01:58:30 -07:00 committed by GitHub
parent c186d3b030
commit 5899c6e378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 284 additions and 250 deletions

View File

@ -49,7 +49,6 @@ int main()
std::cin>>command; std::cin>>command;
if(command=="help") if(command=="help")
{ {
std::cout<<">> Be careful that this program does not support unicode(unicode will be set to \'?\')"<<std::endl;
std::cout<<">> [\'file\'] input a file."<<std::endl; std::cout<<">> [\'file\'] input a file."<<std::endl;
std::cout<<">> [cls ] clear the screen."<<std::endl; std::cout<<">> [cls ] clear the screen."<<std::endl;
std::cout<<">> [del ] clear the resource code."<<std::endl; std::cout<<">> [del ] clear the resource code."<<std::endl;

View File

@ -10,94 +10,96 @@
class nasal_function class nasal_function
{ {
private: private:
std::list<std::map<std::string,int> > local_scope; // closure_updated flag is used to mark if this function's closure is updated.
abstract_syntax_tree parameter_list; // to avoid some unexpected errors,closure of each function must be updated before blocks popping back the last scope
abstract_syntax_tree function_root; bool closure_updated;
// parent_hash_addr is used to store the address of the hash which has this nasal_function std::list<std::map<std::string,int> > local_scope;
// because nasal_function needs this address to adjust the identifier called 'me' in local_scope abstract_syntax_tree parameter_list;
// 'me' is the identifier which points to the hash which has this nasal_function abstract_syntax_tree function_root;
public: public:
void set_clear(); void set_clear();
void set_local_scope(std::list<std::map<std::string,int> >&); void set_local_scope(std::list<std::map<std::string,int> >&);
void set_paramemter_list(abstract_syntax_tree&); bool get_closure_update_state();
void set_statement_block(abstract_syntax_tree&); void set_closure_update_state(bool);
std::list<std::map<std::string,int> >& get_local_scope(); void set_paramemter_list(abstract_syntax_tree&);
abstract_syntax_tree& get_parameter_list(); void set_statement_block(abstract_syntax_tree&);
abstract_syntax_tree& get_statement_block(); std::list<std::map<std::string,int> >& get_local_scope();
void deep_copy(nasal_function&); abstract_syntax_tree& get_parameter_list();
abstract_syntax_tree& get_statement_block();
void deep_copy(nasal_function&);
}; };
class nasal_number class nasal_number
{ {
private: private:
double nas_number; double nas_number;
public: public:
void set_clear(); void set_clear();
void set_number(double); void set_number(double);
double get_number(); double get_number();
void deep_copy(nasal_number&); void deep_copy(nasal_number&);
}; };
class nasal_string class nasal_string
{ {
private: private:
std::string nas_string; std::string nas_string;
public: public:
void set_clear(); void set_clear();
void set_string(std::string); void set_string(std::string);
std::string get_string(); std::string get_string();
void deep_copy(nasal_string&); void deep_copy(nasal_string&);
}; };
class nasal_vector class nasal_vector
{ {
private: private:
std::vector<int> nas_array; std::vector<int> nas_array;
public: public:
void set_clear(); void set_clear();
void vec_push(int); void vec_push(int);
int* get_elem_addr(int); int* get_elem_addr(int);
int get_elem(int); int get_elem(int);
int vec_pop(); int vec_pop();
int get_size(); int get_size();
int* get_parent_hash_member_addr(std::string); int* get_parent_hash_member_addr(std::string);
int get_parent_hash_member(std::string); int get_parent_hash_member(std::string);
void generate_new_hash(); void generate_new_hash();
void deep_copy(nasal_vector&); void deep_copy(nasal_vector&);
}; };
class nasal_hash class nasal_hash
{ {
private: private:
std::map<std::string,int> nas_hash; std::map<std::string,int> nas_hash;
public: public:
void set_clear(); void set_clear();
int* get_hash_member_addr(std::string); int* get_hash_member_addr(std::string);
int get_hash_member(std::string); int get_hash_member(std::string);
void hash_push(std::string,int); void hash_push(std::string,int);
void hash_pop(std::string); void hash_pop(std::string);
void deep_copy(nasal_hash&); void deep_copy(nasal_hash&);
}; };
class nasal_scalar class nasal_scalar
{ {
private: private:
int type; int type;
nasal_string var_string; nasal_string var_string;
nasal_number var_number; nasal_number var_number;
nasal_vector var_vector; nasal_vector var_vector;
nasal_hash var_hash; nasal_hash var_hash;
nasal_function var_func; nasal_function var_func;
public: public:
nasal_scalar(); nasal_scalar();
void set_type(int); void set_type(int);
int get_type(); int get_type();
nasal_number& get_number(); nasal_number& get_number();
nasal_string& get_string(); nasal_string& get_string();
nasal_vector& get_vector(); nasal_vector& get_vector();
nasal_hash& get_hash(); nasal_hash& get_hash();
nasal_function& get_function(); nasal_function& get_function();
}; };
struct gc_unit struct gc_unit
@ -126,208 +128,208 @@ struct memory_block
class memory_block_list class memory_block_list
{ {
private: private:
memory_block* head; memory_block* head;
int mem_size; int mem_size;
int blk_size; int blk_size;
public: public:
memory_block_list() memory_block_list()
{
mem_size=0;
blk_size=1;
head=new memory_block;
head->next=NULL;
return;
}
~memory_block_list()
{
mem_size=0;
blk_size=0;
memory_block* ptr=head;
while(ptr)
{ {
mem_size=0; memory_block* tmp_ptr=ptr;
blk_size=1; ptr=ptr->next;
head=new memory_block; delete tmp_ptr;
head->next=NULL;
return;
} }
~memory_block_list() return;
}
void clear()
{
memory_block* ptr=head;
while(ptr)
{ {
mem_size=0; memory_block* tmp_ptr=ptr;
blk_size=0; ptr=ptr->next;
memory_block* ptr=head; delete tmp_ptr;
while(ptr)
{
memory_block* tmp_ptr=ptr;
ptr=ptr->next;
delete tmp_ptr;
}
return;
} }
void clear() mem_size=0;
blk_size=1;
head=new memory_block;
head->next=NULL;
return;
}
gc_unit& operator[](int address)
{
int block_num=address/NAS_POOL_SIZE;
int block_plc=address%NAS_POOL_SIZE;
memory_block* ptr=head;
for(int i=0;i<block_num;++i)
ptr=ptr->next;
return ptr->space[block_plc];
}
void push_back()
{
++mem_size;
if(mem_size>blk_size*NAS_POOL_SIZE)
{ {
memory_block* ptr=head; memory_block* ptr=head;
while(ptr) while(ptr->next)
{
memory_block* tmp_ptr=ptr;
ptr=ptr->next; ptr=ptr->next;
delete tmp_ptr; ptr->next=new memory_block;
} ptr->next->next=NULL;
mem_size=0; ++blk_size;
blk_size=1;
head=new memory_block;
head->next=NULL;
return;
}
gc_unit& operator[](int address)
{
int block_num=address/NAS_POOL_SIZE;
int block_plc=address%NAS_POOL_SIZE;
memory_block* ptr=head;
for(int i=0;i<block_num;++i)
ptr=ptr->next;
return ptr->space[block_plc];
}
void push_back()
{
++mem_size;
if(mem_size>blk_size*NAS_POOL_SIZE)
{
memory_block* ptr=head;
while(ptr->next)
ptr=ptr->next;
ptr->next=new memory_block;
ptr->next->next=NULL;
++blk_size;
}
return;
}
int size()
{
return mem_size;
}
int capacity()
{
return NAS_POOL_SIZE*blk_size;
} }
return;
}
int size()
{
return mem_size;
}
int capacity()
{
return NAS_POOL_SIZE*blk_size;
}
}; };
#endif #endif
class gc_manager class gc_manager
{ {
private: private:
// free_space list is used to store space that is not in use. // free_space list is used to store space that is not in use.
std::list<int> free_space; std::list<int> free_space;
/* /*
cannot use std::vector to simulate memory cannot use std::vector to simulate memory
because if vector memory is not enough,vector will use another larger memory as it's main memory because if vector memory is not enough,vector will use another larger memory as it's main memory
then all the things will be moved to a new space, then all the things will be moved to a new space,
at this time if you reference a member in it,this will cause segmentation error. at this time if you reference a member in it,this will cause segmentation error.
*/ */
memory_block_list memory; memory_block_list memory;
bool error_occurred; bool error_occurred;
public: public:
void gc_init() void gc_init()
{
// this function must be called in class nasal_runtime before running any codes
memory.clear();
free_space.clear();
error_occurred=false;
return;
}
int gc_alloc()
{
// add a new space for a new value
// if list free_space is not empty,it will get the address at the front and give it to the new value
// if list free_space is empty,it will add new space in memory vector and give it to the new value
// by this way it can manage memory efficiently.
if(free_space.empty())
{ {
// this function must be called in class nasal_runtime before running any codes memory.push_back();
memory.clear(); free_space.push_back(memory.size()-1);
free_space.clear();
error_occurred=false;
return;
} }
int gc_alloc() int alloc_plc=free_space.front();
free_space.pop_front();
memory[alloc_plc].collected=false;
memory[alloc_plc].refcnt=1;
return alloc_plc;
}
int get_reference(int addr)
{
// get the reference counts of the scalar
return memory[addr].refcnt;
}
nasal_scalar& get_scalar(int addr)
{
// get the reference of the scalar
return memory[addr].elem;
}
bool place_check(const int addr)
{
// check if this place is in memory
// and this place is uncollected
// this function is often used when an identifier is calling a space in memory
return (0<=addr) && (addr<memory.size()) && (!memory[addr].collected);
}
bool reference_add(const int addr)
{
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
++memory[addr].refcnt;
else
{ {
// add a new space for a new value std::cout<<">> [Gc] fatal error: reference unexpected memory place ";
// if list free_space is not empty,it will get the address at the front and give it to the new value prt_hex(addr);
// if list free_space is empty,it will add new space in memory vector and give it to the new value std::cout<<" ."<<std::endl;
// by this way it can manage memory efficiently. return false;
if(free_space.empty()) }
return true;
}
bool reference_delete(const int addr)
{
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
{
--memory[addr].refcnt;
if(!memory[addr].refcnt)
{ {
memory.push_back(); // if refcnt is 0,then starting the destructor
free_space.push_back(memory.size()-1); // std::cout<<">> [Gc] collected ";prt_hex(addr);std::cout<<std::endl;
} memory[addr].collected=true;
int alloc_plc=free_space.front(); switch(memory[addr].elem.get_type())
free_space.pop_front();
memory[alloc_plc].collected=false;
memory[alloc_plc].refcnt=1;
return alloc_plc;
}
int get_reference(int addr)
{
// get the reference counts of the scalar
return memory[addr].refcnt;
}
nasal_scalar& get_scalar(int addr)
{
// get the reference of the scalar
return memory[addr].elem;
}
bool place_check(const int addr)
{
// check if this place is in memory
// and this place is uncollected
// this function is often used when an identifier is calling a space in memory
return (0<=addr) && (addr<memory.size()) && (!memory[addr].collected);
}
bool reference_add(const int addr)
{
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
++memory[addr].refcnt;
else
{
std::cout<<">> [Gc] fatal error: reference unexpected memory place ";
prt_hex(addr);
std::cout<<" ."<<std::endl;
return false;
}
return true;
}
bool reference_delete(const int addr)
{
if((0<=addr) && (addr<memory.size()) && (!memory[addr].collected))
{
--memory[addr].refcnt;
if(!memory[addr].refcnt)
{ {
// if refcnt is 0,then starting the destructor case scalar_number: memory[addr].elem.get_number().set_clear(); break;
// std::cout<<">> [Gc] collected ";prt_hex(addr);std::cout<<std::endl; case scalar_string: memory[addr].elem.get_string().set_clear(); break;
memory[addr].collected=true; case scalar_vector: memory[addr].elem.get_vector().set_clear(); break;
switch(memory[addr].elem.get_type()) case scalar_hash: memory[addr].elem.get_hash().set_clear(); break;
{ case scalar_function:memory[addr].elem.get_function().set_clear();break;
case scalar_number: memory[addr].elem.get_number().set_clear(); break; default:break;
case scalar_string: memory[addr].elem.get_string().set_clear(); break;
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;
default:break;
}
memory[addr].elem.set_type(scalar_nil);
free_space.push_back(addr);
} }
memory[addr].elem.set_type(scalar_nil);
free_space.push_back(addr);
} }
else }
else
{
std::cout<<">> [Gc] fatal error: delete unexpected memory address: ";
prt_hex(addr);
std::cout<<" ."<<std::endl;
return false;
}
return true;
}
void info_print()
{
std::cout<<">> [Gc] memory size:"<<memory.size()*sizeof(gc_unit)<<" byte."<<std::endl;
std::cout<<">> [Gc] memory capacity:"<<memory.capacity()*sizeof(gc_unit)<<" byte."<<std::endl;
std::cout<<">> [Gc] memory usage: "<<std::endl;
int cnt=0;
for(int i=0;i<memory.size();++i)
if(!memory[i].collected)
{ {
std::cout<<">> [Gc] fatal error: delete unexpected memory address: "; prt_hex(i);
prt_hex(addr); std::cout<<"["<<memory[i].refcnt<<"]";
std::cout<<" ."<<std::endl; // cnt is used to check if it is the right time to output in the next line
return false; ++cnt;
if(!(cnt%8))
std::cout<<std::endl;
else
std::cout<<" ";
} }
return true; if(cnt%8)
} std::cout<<std::endl;
void info_print() return;
{ }
std::cout<<">> [Gc] memory size:"<<memory.size()*sizeof(gc_unit)<<" byte."<<std::endl; bool check_error()
std::cout<<">> [Gc] memory capacity:"<<memory.capacity()*sizeof(gc_unit)<<" byte."<<std::endl; {
std::cout<<">> [Gc] memory usage: "<<std::endl; return error_occurred;
int cnt=0; }
for(int i=0;i<memory.size();++i)
if(!memory[i].collected)
{
prt_hex(i);
std::cout<<"["<<memory[i].refcnt<<"]";
// cnt is used to check if it is the right time to output in the next line
++cnt;
if(!(cnt%8))
std::cout<<std::endl;
else
std::cout<<" ";
}
if(cnt%8)
std::cout<<std::endl;
return;
}
bool check_error()
{
return error_occurred;
}
}; };
gc_manager nasal_gc; gc_manager nasal_gc;
// this object is used in "nasal_runtime.h" // this object is used in "nasal_runtime.h"
@ -339,18 +341,31 @@ void nasal_function::set_clear()
for(std::list<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) 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) for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
nasal_gc.reference_delete(i->second); nasal_gc.reference_delete(i->second);
closure_updated=false;
local_scope.clear(); local_scope.clear();
function_root.set_clear(); function_root.set_clear();
return; return;
} }
void nasal_function::set_local_scope(std::list<std::map<std::string,int> >& tmp_scope) void nasal_function::set_local_scope(std::list<std::map<std::string,int> >& 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_delete(i->second);
local_scope=tmp_scope; local_scope=tmp_scope;
for(std::list<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter) 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) for(std::map<std::string,int>::iterator i=iter->begin();i!=iter->end();++i)
nasal_gc.reference_add(i->second); nasal_gc.reference_add(i->second);
return; return;
} }
bool nasal_function::get_closure_update_state()
{
return closure_updated;
}
void nasal_function::set_closure_update_state(bool _state)
{
closure_updated=_state;
return;
}
void nasal_function::set_paramemter_list(abstract_syntax_tree& para_list) void nasal_function::set_paramemter_list(abstract_syntax_tree& para_list)
{ {
parameter_list=para_list; parameter_list=para_list;

View File

@ -100,6 +100,7 @@ class nasal_runtime
int vector_generation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);//checked 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 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 int function_generation(std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked
void update_closure (std::list<std::map<std::string,int> >&);
bool check_condition (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);// checked 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 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); int assignment (std::list<std::map<std::string,int> >&,abstract_syntax_tree&,int);
@ -1463,6 +1464,7 @@ int nasal_runtime::function_generation(std::list<std::map<std::string,int> >& lo
int addr=nasal_gc.gc_alloc(); int addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(addr).set_type(scalar_function); 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(local_scope);
nasal_gc.get_scalar(addr).get_function().set_closure_update_state(false);
std::list<abstract_syntax_tree>::iterator i=node.get_children().begin(); std::list<abstract_syntax_tree>::iterator i=node.get_children().begin();
nasal_gc.get_scalar(addr).get_function().set_paramemter_list(*i); nasal_gc.get_scalar(addr).get_function().set_paramemter_list(*i);
@ -2054,6 +2056,20 @@ int nasal_runtime::function_generation(std::list<std::map<std::string,int> >& lo
} }
return addr; return addr;
} }
void nasal_runtime::update_closure(std::list<std::map<std::string,int> >& local_scope)
{
// update_closure
if(!local_scope.size())
return;
for(std::map<std::string,int>::iterator i=local_scope.back().begin();i!=local_scope.back().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);
nasal_gc.get_scalar(i->second).get_function().set_closure_update_state(true);
}
return;
}
bool nasal_runtime::check_condition(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node) bool nasal_runtime::check_condition(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
{ {
bool ret=false; bool ret=false;
@ -4403,11 +4419,13 @@ int nasal_runtime::block_proc(std::list<std::map<std::string,int> >& local_scope
if(state==__state_break || state==__state_continue || state==__state_return || state==__state_error) if(state==__state_break || state==__state_continue || state==__state_return || state==__state_error)
break; break;
} }
// update_closure
update_closure(local_scope);
return state; return state;
} }
int nasal_runtime::func_proc( 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> >& 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& parameter_list, // parameter list format of nasal function
abstract_syntax_tree& func_root, // main runnning block 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 abstract_syntax_tree& input_parameters, // input parameters when calling this nasal function
@ -4596,6 +4614,8 @@ int nasal_runtime::func_proc(
function_returned_addr=nasal_gc.gc_alloc(); function_returned_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(function_returned_addr).set_type(scalar_nil); nasal_gc.get_scalar(function_returned_addr).set_type(scalar_nil);
} }
// update closure
update_closure(local_scope);
for(std::map<std::string,int>::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i) for(std::map<std::string,int>::iterator i=local_scope.back().begin();i!=local_scope.back().end();++i)
nasal_gc.reference_delete(i->second); nasal_gc.reference_delete(i->second);
local_scope.pop_back(); local_scope.pop_back();