This commit is contained in:
Valk Richard Li 2020-03-18 01:40:19 +08:00 committed by GitHub
parent ed35e9a5f3
commit 6abca8c12f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 58 deletions

View File

@ -16,13 +16,10 @@ class nasal_function
// parent_hash_addr is used to store the address of the hash which has this nasal_function
// because nasal_function needs this address to adjust the identifier called 'me' in local_scope
// 'me' is the identifier which points to the hash which has this nasal_function
int parent_hash_addr;
public:
nasal_function();
void set_clear();
void set_local_scope(std::list<std::map<std::string,int> >&);
void set_statement_block(abstract_syntax_tree&);
void set_parent_hash_addr(int);
std::list<std::map<std::string,int> >& get_local_scope();
abstract_syntax_tree& get_statement_block();
void deep_copy(nasal_function&);
@ -240,11 +237,7 @@ 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)
nasal_function::nasal_function()
{
parent_hash_addr=-1;
return;
}
void nasal_function::set_clear()
{
for(std::list<std::map<std::string,int> >::iterator iter=local_scope.begin();iter!=local_scope.end();++iter)
@ -252,7 +245,6 @@ void nasal_function::set_clear()
nasal_gc.reference_delete(i->second);
local_scope.clear();
function_root.set_clear();
parent_hash_addr=-1;
return;
}
void nasal_function::set_local_scope(std::list<std::map<std::string,int> >& tmp_scope)
@ -268,35 +260,6 @@ void nasal_function::set_statement_block(abstract_syntax_tree& func_block)
function_root=func_block;
return;
}
void nasal_function::set_parent_hash_addr(int addr)
{
// in normal cases this function is often called after this->set_local_scope(...)
// because creating a new nasal function needs local_scope(closure) and abstract syntax tree.
// then the nasal function will be given to an identifier.
// after checking the identifier and making sure it is a hash,
// call this function and set 'me' to this addr if exists.
// if 'me' does not exist,then add a new identifeir named 'me' and give it the addr.
// also 'me' can be changed in hash function by ways like "var me=1;"
parent_hash_addr=addr;
bool has_identifier_me=false;
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)
if(i->first=="me")
{
has_identifier_me=true;
i->second=parent_hash_addr;
}
if(!has_identifier_me)
{
if(local_scope.empty())
{
std::map<std::string,int> new_scope;
local_scope.push_back(new_scope);
}
local_scope.back()["me"]=parent_hash_addr;
}
return;
}
std::list<std::map<std::string,int> >& nasal_function::get_local_scope()
{
return local_scope;
@ -448,11 +411,7 @@ int nasal_hash::get_hash_member(std::string member_name)
void nasal_hash::hash_push(std::string member_name,int addr)
{
if(nas_hash.find(member_name)==nas_hash.end())
{
nas_hash[member_name]=addr;
if(nasal_gc.place_check(addr) && nasal_gc.get_scalar(addr).get_type()==scalar_function)
nasal_gc.get_scalar(addr).get_function().set_parent_hash_addr(this->get_self_addr());
}
return;
}
void nasal_hash::hash_pop(std::string member_name)
@ -489,10 +448,7 @@ void nasal_hash::deep_copy(nasal_hash& tmp)
nasal_gc.get_scalar(new_addr).get_hash().deep_copy(nasal_gc.get_scalar(i->second).get_hash());
}
else if(tmp_type==scalar_function)
{
nasal_gc.get_scalar(new_addr).get_function().set_parent_hash_addr(this->self_addr);
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(i->second).get_function());
}
nas_hash[i->first]=new_addr;
}
return;

View File

@ -18,6 +18,8 @@ class nasal_runtime
__incorrect_head_of_func,
__undefined_identifier,
__multi_assign_incorrect_value_number,
__invalid_vector_member,
__invalid_hash_member,
__memory_overflow,
__not_callable_vector,
__not_callable_hash,
@ -35,7 +37,7 @@ class nasal_runtime
int calculation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int* get_identifier_addr(std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int call_identifier (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
void definition (std::map<std::string,int>&,abstract_syntax_tree&);
void definition (std::list<std::map<std::string,int> >&,std::map<std::string,int>&,abstract_syntax_tree&);
void loop_expr (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
void conditional (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int func_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
@ -68,6 +70,10 @@ void nasal_runtime::error_interrupt(const int type,const int line)
std::cout<<"undefined identifier."<<std::endl;break;
case __multi_assign_incorrect_value_number:
std::cout<<"numbers of assigned identifiers and values are not the same."<<std::endl;break;
case __invalid_vector_member:
std::cout<<"this member of vector does not exist."<<std::endl;break;
case __invalid_hash_member:
std::cout<<"this member of hash does not exist."<<std::endl;break;
case __memory_overflow:
std::cout<<"memory overflow occurred when calling vector or hash."<<std::endl;break;
case __not_callable_vector:
@ -142,6 +148,8 @@ int nasal_runtime::hash_generation(std::list<std::map<std::string,int> >& local_
{
int addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(addr).set_type(scalar_hash);
// self address must be set here
// if not,then 'me' in function-type member will not get a correct address
nasal_gc.get_scalar(addr).get_hash().set_self_addr(addr);
std::list<abstract_syntax_tree>::iterator call_node=node.get_children().end();
for(std::list<abstract_syntax_tree>::iterator i=node.get_children().begin();i!=node.get_children().end();++i)
@ -153,6 +161,9 @@ int nasal_runtime::hash_generation(std::list<std::map<std::string,int> >& local_
}
else
{
// note:how does nasal_function change the address of me when a hash calls it?
// because before calling this function,hash gives the address if itself as a parameter to the function,
// and this parameter's name is 'me'
std::string member_name=i->get_children().front().get_var_string();
int var_type=i->get_children().back().get_node_type();
if(var_type==__number)
@ -164,12 +175,7 @@ int nasal_runtime::hash_generation(std::list<std::map<std::string,int> >& local_
else if(var_type==__hash)
nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,hash_generation(local_scope,*i));
else if(var_type==__function)
{
// hash's function must get a parent_hash_addr
// this address will be given to identifier 'me'
nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,function_generation(local_scope,i->get_children().back()));
nasal_gc.get_scalar(nasal_gc.get_scalar(addr).get_hash().get_hash_member(member_name)).get_function().set_parent_hash_addr(addr);
}
else if(var_type==__add_operator || var_type==__sub_operator || var_type==__mul_operator || var_type==__div_operator || var_type==__link_operator ||
var_type==__cmp_equal || var_type==__cmp_less || var_type==__cmp_more || var_type==__cmp_not_equal || var_type==__cmp_less_or_equal || var_type==__cmp_more_or_equal ||
var_type==__and_operator || var_type==__or_operator || var_type==__ques_mark ||
@ -188,7 +194,11 @@ int nasal_runtime::function_generation(std::list<std::map<std::string,int> >& lo
int addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(addr).set_type(scalar_function);
nasal_gc.get_scalar(addr).get_function().set_local_scope(local_scope);
// set
// function
// parameters
// block
// calls...
std::list<abstract_syntax_tree>::iterator i=node.get_children().begin();
return addr;
}
@ -529,7 +539,12 @@ int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scop
{
std::vector<int> data_addrs;
for(std::list<abstract_syntax_tree>::iterator i=node.get_children().back().get_children().begin();i!=node.get_children().back().get_children().end();++i)
data_addrs.push_back(calculation(local_scope,*i));
{
int new_addr=calculation(local_scope,*i);
if(new_addr<0)
return -1;
data_addrs.push_back(new_addr);
}
if(data_addrs.size()!=assigned_addrs.size())
{
error_interrupt(__multi_assign_incorrect_value_number,node.get_children().back().get_node_line());
@ -576,6 +591,8 @@ int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scop
else
{
int data_addr=calculation(local_scope,node.get_children().back());
if(data_addr<0)
return -1;
if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_vector)
{
error_interrupt(__error_value_type,node.get_children().back().get_node_line());
@ -592,7 +609,7 @@ int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scop
int vector_member_addr=nasal_gc.get_scalar(data_addr).get_vector().get_elem(i);
if(vector_member_addr<0)
{
error_interrupt(__memory_overflow,node.get_children().back().get_node_line());
error_interrupt(__invalid_vector_member,node.get_children().back().get_node_line());
return -1;
}
switch(nasal_gc.get_scalar(vector_member_addr).get_type())
@ -636,6 +653,8 @@ int nasal_runtime::calculation(std::list<std::map<std::string,int> >& local_scop
if(!assigned_addr)
return -1;
int data_addr=calculation(local_scope,node.get_children().back());
if(data_addr<0)
return -1;
int new_data_addr=-1;
nasal_gc.reference_delete(*assigned_addr);
switch(nasal_gc.get_scalar(data_addr).get_type())
@ -1083,7 +1102,7 @@ int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_
}
return addr;
}
void nasal_runtime::definition(std::map<std::string,int>& local_scope,abstract_syntax_tree& node)
void nasal_runtime::definition(std::list<std::map<std::string,int> >&local_scope,std::map<std::string,int>& now_scope,abstract_syntax_tree& node)
{
if(node.get_children().front().get_node_type()==__multi_id)
{
@ -1091,7 +1110,42 @@ void nasal_runtime::definition(std::map<std::string,int>& local_scope,abstract_s
}
else
{
;
std::string id_name=node.get_children().front().get_var_name();
if(now_scope.find(id_name)!=now_scope.end())
nasal_gc.reference_delete(now_scope[id_name]);
int data_addr=calculation(local_scope,node.get_children().back());
if(data_addr<0)
return;
int new_data_addr=-1;
switch(nasal_gc.get_scalar(data_addr).get_type())
{
case scalar_nil:
new_data_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_data_addr).set_type(scalar_nil);
break;
case scalar_number:
new_data_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_data_addr).set_type(scalar_number);
nasal_gc.get_scalar(new_data_addr).get_number().deep_copy(nasal_gc.get_scalar(data_addr).get_number());
break;
case scalar_string:
new_data_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_data_addr).set_type(scalar_string);
nasal_gc.get_scalar(new_data_addr).get_string().deep_copy(nasal_gc.get_scalar(data_addr).get_string());
break;
case scalar_function:
new_data_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_data_addr).set_type(scalar_function);
nasal_gc.get_scalar(new_data_addr).get_function().deep_copy(nasal_gc.get_scalar(data_addr).get_function());
break;
case scalar_vector:
case scalar_hash:
new_data_addr=data_addr;
nasal_gc.reference_add(new_data_addr);
break;
}
nasal_gc.reference_delete(data_addr);
now_scope[id_name]=new_data_addr;
}
return;
}
@ -1116,6 +1170,9 @@ void nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope
{
;
}
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();
return;
}
void nasal_runtime::conditional(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
@ -1132,6 +1189,9 @@ void nasal_runtime::conditional(std::list<std::map<std::string,int> >& local_sco
else
;
}
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();
return;
}
@ -1170,7 +1230,7 @@ int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,
node_type==__equal || node_type==__add_equal || node_type==__sub_equal || node_type==__div_equal || node_type==__mul_equal || node_type==__link_equal)
this->calculation(local_scope,*iter);
else if(node_type==__definition)
this->definition(local_scope.back(),*iter);
this->definition(local_scope,local_scope.back(),*iter);
else if(node_type==__conditional)
this->conditional(local_scope,*iter);
else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex))
@ -1217,7 +1277,7 @@ void nasal_runtime::main_proc(abstract_syntax_tree& root)
node_type==__equal || node_type==__add_equal || node_type==__sub_equal || node_type==__div_equal || node_type==__mul_equal || node_type==__link_equal)
this->calculation(main_local_scope,*iter);
else if(node_type==__definition)
this->definition(global_scope,*iter);
this->definition(main_local_scope,global_scope,*iter);
else if(node_type==__conditional)
this->conditional(main_local_scope,*iter);
else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex))