This commit is contained in:
Valk Richard Li 2020-03-24 22:09:03 +08:00 committed by GitHub
parent 682e2b3701
commit a55c6aae1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 795 additions and 77 deletions

View File

@ -370,15 +370,9 @@ int nasal_vector::get_elem(int addr)
// 0 ~ size-1 -size ~ -1 // 0 ~ size-1 -size ~ -1
int bound=nas_array.size(); int bound=nas_array.size();
if(-bound<=addr && addr<0) if(-bound<=addr && addr<0)
{
nasal_gc.reference_add(nas_array[bound+addr]);
return nas_array[bound+addr]; return nas_array[bound+addr];
}
else if(0<=addr && addr<bound) else if(0<=addr && addr<bound)
{
nasal_gc.reference_add(nas_array[addr]);
return nas_array[addr]; return nas_array[addr];
}
return -1; return -1;
} }
int nasal_vector::vec_pop() int nasal_vector::vec_pop()
@ -446,10 +440,7 @@ int* nasal_hash::get_hash_member_addr(std::string member_name)
int nasal_hash::get_hash_member(std::string member_name) int nasal_hash::get_hash_member(std::string member_name)
{ {
if(nas_hash.find(member_name)!=nas_hash.end()) if(nas_hash.find(member_name)!=nas_hash.end())
{
nasal_gc.reference_add(nas_hash[member_name]);
return nas_hash[member_name]; return nas_hash[member_name];
}
return -1; return -1;
} }
void nasal_hash::hash_push(std::string member_name,int addr) void nasal_hash::hash_push(std::string member_name,int addr)

View File

@ -31,12 +31,14 @@ class nasal_parse
error_begin_token_of_scalar, // in scalar_generate() error_begin_token_of_scalar, // in scalar_generate()
need_default_parameter, // parameters must have a default value if detected there is a default parameter before.
default_dynamic_parameter, // default parameter should not be dynamic default_dynamic_parameter, // default parameter should not be dynamic
parameter_lack_part, // parameter lack a ')' or identifier parameter_lack_part, // parameter lack a ')' or identifier
parameter_lack_curve, // parameter lack a ',' or ')' parameter_lack_curve, // parameter lack a ',' or ')'
special_call_func_lack_id, special_call_func_lack_id,
special_call_func_lack_colon, special_call_func_lack_colon,
normal_call_func_has_colon, // when calling a function,normal way and special way cannot be used together
call_func_lack_comma, // lack comma when giving parameters to a function call_func_lack_comma, // lack comma when giving parameters to a function
call_hash_lack_id, // lack identifier when calling a hash call_hash_lack_id, // lack identifier when calling a hash
call_vector_wrong_comma, // wrong use of comma like this: id[0,4:6,7,] (the last comma is incorrect here) call_vector_wrong_comma, // wrong use of comma like this: id[0,4:6,7,] (the last comma is incorrect here)
@ -181,124 +183,128 @@ void nasal_parse::get_token_list(std::list<token>& detail_token_stream)
void nasal_parse::print_parse_error(int error_type,int line,int error_token_type=__stack_end) void nasal_parse::print_parse_error(int error_type,int line,int error_token_type=__stack_end)
{ {
std::string error_info_head=">> [Parse] line "; std::cout<<">> [Parse] line "<<line<<": ";
switch(error_type) switch(error_type)
{ {
case parse_unknown_error: case parse_unknown_error:
std::cout<<error_info_head<<line<<": unknown parse error.(token id: "<<error_token_type<<")."<<std::endl;break; std::cout<<"unknown parse error.(token id: "<<error_token_type<<")."<<std::endl;break;
case error_token_in_main: case error_token_in_main:
std::cout<<error_info_head<<line<<": statements should not begin with \'"; std::cout<<"statements should not begin with \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' in main scope."<<std::endl; std::cout<<"\' in main scope."<<std::endl;
break; break;
case error_token_in_block: case error_token_in_block:
std::cout<<error_info_head<<line<<": statements should not begin with \'"; std::cout<<"statements should not begin with \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' in block scope."<<std::endl; std::cout<<"\' in block scope."<<std::endl;
break; break;
case lack_semi: case lack_semi:
std::cout<<error_info_head<<line<<": expect a \';\' at the end of the statement."<<std::endl;break; std::cout<<"expect a \';\' at the end of the statement."<<std::endl;break;
case lack_id: case lack_id:
std::cout<<error_info_head<<line<<": expect an identifier here."<<std::endl;break; std::cout<<"expect an identifier here."<<std::endl;break;
case lack_left_curve: case lack_left_curve:
std::cout<<error_info_head<<line<<": expect a \'(\' here."<<std::endl;break; std::cout<<"expect a \'(\' here."<<std::endl;break;
case lack_right_curve: case lack_right_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here."<<std::endl;break; std::cout<<"expect a \')\' here."<<std::endl;break;
case lack_right_brace: case lack_right_brace:
std::cout<<error_info_head<<line<<": expect a \'}\' here."<<std::endl;break; std::cout<<"expect a \'}\' here."<<std::endl;break;
case definition_lack_id: case definition_lack_id:
std::cout<<error_info_head<<line<<": expect identifier(s) after \'var\'."<<std::endl;break; std::cout<<"expect identifier(s) after \'var\'."<<std::endl;break;
case definition_lack_equal: case definition_lack_equal:
std::cout<<error_info_head<<line<<": expect a \'=\' here but get \'"; std::cout<<"expect a \'=\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' when generating definition."<<std::endl; std::cout<<"\' when generating definition."<<std::endl;
break; break;
case assignment_begin_error: case assignment_begin_error:
std::cout<<error_info_head<<line<<": assignment should begin with one identifier_call."<<std::endl; std::cout<<"assignment should begin with one identifier_call."<<std::endl;
break; break;
case multi_definition_need_curve: case multi_definition_need_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here but get \'"; std::cout<<"expect a \')\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case multi_assignment_need_curve: case multi_assignment_need_curve:
std::cout<<error_info_head<<line<<": expect a \')\' here but get \'"; std::cout<<"expect a \')\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case multi_assignment_need_equal: case multi_assignment_need_equal:
std::cout<<error_info_head<<line<<": expect a \'=\' here but get \'"; std::cout<<"expect a \'=\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case error_begin_token_of_scalar: case error_begin_token_of_scalar:
std::cout<<error_info_head<<line<<": expect a scalar here but get \'"; std::cout<<"expect a scalar here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case need_default_parameter:
std::cout<<"parameters after a default parameter must have their own default values."<<std::endl;break;
case default_dynamic_parameter: case default_dynamic_parameter:
std::cout<<error_info_head<<line<<": dynamic parameter should not have a default value."<<std::endl;break; std::cout<<"dynamic parameter should not have a default value."<<std::endl;break;
case parameter_lack_part: case parameter_lack_part:
std::cout<<error_info_head<<line<<": expect a \')\' or identifier here when generating parameter_list."<<std::endl;break; std::cout<<"expect a \')\' or identifier here when generating parameter_list."<<std::endl;break;
case parameter_lack_curve: case parameter_lack_curve:
std::cout<<error_info_head<<line<<": expect a \')\' or \',\' here when generating parameter_list."<<std::endl;break; std::cout<<"expect a \')\' or \',\' here when generating parameter_list."<<std::endl;break;
case special_call_func_lack_id: case special_call_func_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier here but get \'"; std::cout<<"expect an identifier here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' when calling functions."<<std::endl; std::cout<<"\' when calling functions."<<std::endl;
break; break;
case special_call_func_lack_colon: case special_call_func_lack_colon:
std::cout<<error_info_head<<line<<": expect an \':\' here but get \'"; std::cout<<"expect an \':\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' when calling functions."<<std::endl; std::cout<<"\' when calling functions."<<std::endl;
break; break;
case normal_call_func_has_colon:
std::cout<<"normal and special ways of calling a function are not allowed to be used together."<<std::endl;break;
case call_func_lack_comma: case call_func_lack_comma:
std::cout<<error_info_head<<line<<": expect a \',\' when calling a function but get \'"; std::cout<<"expect a \',\' when calling a function but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case call_hash_lack_id: case call_hash_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier after \'.\' ."<<std::endl;break; std::cout<<"expect an identifier after \'.\' ."<<std::endl;break;
case call_vector_wrong_comma: case call_vector_wrong_comma:
std::cout<<error_info_head<<line<<": expect a scalar after \',\' but get \']\' ."<<std::endl; std::cout<<"expect a scalar after \',\' but get \']\' ."<<std::endl;
break; break;
case call_vector_lack_bracket: case call_vector_lack_bracket:
std::cout<<error_info_head<<line<<": expect a \']\' here but get \'"; std::cout<<"expect a \']\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case call_vector_wrong_token: case call_vector_wrong_token:
std::cout<<error_info_head<<line<<": expect \':\' or ',' or ']' here but get \'"; std::cout<<"expect \':\' or ',' or ']' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case vector_gen_lack_end: case vector_gen_lack_end:
std::cout<<error_info_head<<line<<": expect a \',\' or \')\' here but get \'"; std::cout<<"expect a \',\' or \')\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case hash_gen_lack_id: case hash_gen_lack_id:
std::cout<<error_info_head<<line<<": expect an identifier or string here but get \'"; std::cout<<"expect an identifier or string here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case hash_gen_lack_colon: case hash_gen_lack_colon:
std::cout<<error_info_head<<line<<": expect a \':\' here but get \'"; std::cout<<"expect a \':\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case hash_gen_lack_end: case hash_gen_lack_end:
std::cout<<error_info_head<<line<<": expect a \',\' or \'}\' here but get \'"; std::cout<<"expect a \',\' or \'}\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
case ternary_operator_lack_colon: case ternary_operator_lack_colon:
std::cout<<error_info_head<<line<<": expect a \':\' here but get \'"; std::cout<<"expect a \':\' here but get \'";
print_parse_token(error_token_type); print_parse_token(error_token_type);
std::cout<<"\' ."<<std::endl; std::cout<<"\' ."<<std::endl;
break; break;
default: default:
std::cout<<error_info_head<<line<<": unknown parse error.(token id: "<<error_token_type<<")."<<std::endl;break; std::cout<<"unknown parse error.(token id: "<<error_token_type<<")."<<std::endl;break;
} }
return; return;
} }
@ -1052,6 +1058,8 @@ abstract_syntax_tree nasal_parse::scalar_generate()
if(this_token.type!=__right_curve) if(this_token.type!=__right_curve)
{ {
bool scalar_para=true; bool scalar_para=true;
// scalar_para is used to record that parameters is in normal format like f(1,2,3,4)
// if scalar_para is false ,this means parameters is in special format like f(a:1,b:2)
if(this_token.type==__id) if(this_token.type==__id)
{ {
this->get_token(); this->get_token();
@ -1117,7 +1125,10 @@ abstract_syntax_tree nasal_parse::scalar_generate()
if((this_token.type!=__comma) && (this_token.type!=__right_curve)) if((this_token.type!=__comma) && (this_token.type!=__right_curve))
{ {
++error; ++error;
print_parse_error(call_func_lack_comma,this_token.line,this_token.type); if(this_token.type==__colon)
print_parse_error(normal_call_func_has_colon,this_token.line,this_token.type);
else
print_parse_error(call_func_lack_comma,this_token.line,this_token.type);
break; break;
} }
if(this_token.type==__comma) if(this_token.type==__comma)
@ -1316,6 +1327,7 @@ abstract_syntax_tree nasal_parse::function_generate()
this->get_token(); this->get_token();
if(this_token.type==__left_curve) if(this_token.type==__left_curve)
{ {
bool has_default_para=false;
while(this_token.type!=__right_curve) while(this_token.type!=__right_curve)
{ {
// check identifier // check identifier
@ -1348,8 +1360,15 @@ abstract_syntax_tree nasal_parse::function_generate()
// check equal operator // check equal operator
this->get_token(); this->get_token();
if(has_default_para && this_token.type!=__equal)
{
++error;
print_parse_error(need_default_parameter,this_token.line,this_token.type);
break;
}
if(this_token.type==__equal) if(this_token.type==__equal)
{ {
has_default_para=true;
if(parameter_type==__id) if(parameter_type==__id)
{ {
abstract_syntax_tree default_parameter; abstract_syntax_tree default_parameter;
@ -1692,10 +1711,8 @@ abstract_syntax_tree nasal_parse::loop_expr()
print_parse_error(lack_right_curve,this_token.line,this_token.type); print_parse_error(lack_right_curve,this_token.line,this_token.type);
} }
} }
else else if(this_token.type==__forindex || this_token.type==__foreach)
{ {
// forindex
// foreach
this->get_token();// '(' this->get_token();// '('
if(this_token.type!=__left_curve) if(this_token.type!=__left_curve)
{ {
@ -1704,20 +1721,39 @@ abstract_syntax_tree nasal_parse::loop_expr()
} }
this->get_token();// 'var' this->get_token();// 'var'
if(this_token.type!=__var) if(this_token.type!=__var)
this->push_token();
this->get_token();// id
if(this_token.type!=__id)
{ {
++error; // if checked not the 'var' then checking if this token is an identifier
print_parse_error(lack_id,this_token.line); if(this_token.type!=__id)
{
++error;
print_parse_error(lack_id,this_token.line);
}
else
{
this->push_token();
loop_main_node.add_children(scalar_generate());
}
} }
else else
{ {
abstract_syntax_tree id_node; abstract_syntax_tree new_definition_node;
id_node.set_node_line(this_token.line); new_definition_node.set_node_line(this_token.line);
id_node.set_node_type(__id); new_definition_node.set_node_type(__definition);
id_node.set_var_name(this_token.str); this->get_token();
loop_main_node.add_children(id_node); if(this_token.type!=__id)
{
++error;
print_parse_error(lack_id,this_token.line);
}
else
{
abstract_syntax_tree new_id_node;
new_id_node.set_node_line(this_token.line);
new_id_node.set_node_type(__id);
new_id_node.set_var_name(this_token.str);
new_definition_node.add_children(new_id_node);
}
loop_main_node.add_children(new_definition_node);
} }
this->get_token();// ';' this->get_token();// ';'
if(this_token.type!=__semi) if(this_token.type!=__semi)

View File

@ -42,6 +42,7 @@ class nasal_runtime
__special_call_vector_too_large_value, __special_call_vector_too_large_value,
__normal_call_vector_too_large_value, __normal_call_vector_too_large_value,
__error_call_type_when_getting_address, __error_call_type_when_getting_address,
__call_function_lack_para,
__forindex_foreach_not_vector, __forindex_foreach_not_vector,
__break_not_used_in_loop, __break_not_used_in_loop,
__continue_not_used_in_loop, __continue_not_used_in_loop,
@ -58,12 +59,13 @@ class nasal_runtime
bool check_condition (std::list<std::map<std::string,int> >&,abstract_syntax_tree&); bool check_condition (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int calculation (std::list<std::map<std::string,int> >&,abstract_syntax_tree&); 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* get_identifier_addr(std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int call_scalar (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int call_identifier (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::list<std::map<std::string,int> >&,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&);
int loop_expr (std::list<std::map<std::string,int> >&,abstract_syntax_tree&); int loop_expr (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int conditional (std::list<std::map<std::string,int> >&,abstract_syntax_tree&); int conditional (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int block_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&); int block_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&);
int func_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&,abstract_syntax_tree&,int); int func_proc (std::list<std::map<std::string,int> >&,abstract_syntax_tree&,abstract_syntax_tree&,abstract_syntax_tree&,int);
public: public:
nasal_runtime() nasal_runtime()
{ {
@ -121,6 +123,8 @@ void nasal_runtime::error_interrupt(const int type,const int line)
std::cout<<"the number used to call the vector is too large(over 0x7fffffff)."<<std::endl;break; std::cout<<"the number used to call the vector is too large(over 0x7fffffff)."<<std::endl;break;
case __error_call_type_when_getting_address: case __error_call_type_when_getting_address:
std::cout<<"this type of calling identifier is not allowed here."<<std::endl;break; std::cout<<"this type of calling identifier is not allowed here."<<std::endl;break;
case __call_function_lack_para:
std::cout<<"lack parameter(s) when calling a function."<<std::endl;break;
case __forindex_foreach_not_vector: case __forindex_foreach_not_vector:
std::cout<<"forindex and foreach need vector here."<<std::endl;break; std::cout<<"forindex and foreach need vector here."<<std::endl;break;
case __break_not_used_in_loop: case __break_not_used_in_loop:
@ -183,13 +187,261 @@ int nasal_runtime::vector_generation(std::list<std::map<std::string,int> >& loca
break; break;
} }
} }
int last_hash_addr=-1;
for(;call_node!=node.get_children().end();++call_node) for(;call_node!=node.get_children().end();++call_node)
{ {
switch(call_node->get_node_type()) if(nasal_gc.get_scalar(addr).get_type()==scalar_hash)
last_hash_addr=addr;
// call vector/special call hash/subvec
// the special type of calling hash like a["name"] is also generated as calling vector
if(call_node->get_node_type()==__call_vector)
{ {
case __call_vector:break; // check the scalar type of called identifier here
case __call_hash:break; int called_type=nasal_gc.get_scalar(addr).get_type();
case __call_function:break; if(called_type!=scalar_vector && called_type!=scalar_hash)
{
error_interrupt(__error_value_type,call_node->get_node_line());
return -1;
}
if(call_node->get_children().front().get_node_type()==__sub_vector)
{
if(called_type==scalar_hash)
{
error_interrupt(__not_callable_vector,call_node->get_node_line());
return -1;
}
int num1_addr=-1;
int num2_addr=-1;
// identifier[num1:];
if(call_node->get_children().front().get_children().size()==1)
{
num1_addr=calculation(local_scope,call_node->get_children().front().get_children().front());
if(num1_addr<0)
return -1;
}
// identifier[num1:num2];
else
{
num1_addr=calculation(local_scope,call_node->get_children().front().get_children().front());
num2_addr=calculation(local_scope,call_node->get_children().front().get_children().back());
if(num1_addr<0 || num2_addr<0)
return -1;
}
if(nasal_gc.get_scalar(num1_addr).get_type()!=scalar_number
&& nasal_gc.get_scalar(num1_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
if(num2_addr>=0
&& (nasal_gc.get_scalar(num2_addr).get_type()!=scalar_number
&& nasal_gc.get_scalar(num2_addr).get_type()!=scalar_string
&& nasal_gc.get_scalar(num2_addr).get_type()!=scalar_nil))
{
error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
if(nasal_gc.get_scalar(num1_addr).get_type()==scalar_string)
{
if(check_numerable_string(nasal_gc.get_scalar(num1_addr).get_string().get_string()))
{
double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num1_addr).get_string().get_string());
if(tmp_num<0)
{
error_interrupt(__special_call_vector_negative_value,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
nasal_gc.reference_delete(num1_addr);
num1_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(num1_addr).set_type(scalar_number);
nasal_gc.get_scalar(num1_addr).get_number().set_number(tmp_num);
}
else
{
error_interrupt(__not_numerable_str,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
}
if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_type()==scalar_string)
{
if(check_numerable_string(nasal_gc.get_scalar(num2_addr).get_string().get_string()))
{
double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num2_addr).get_string().get_string());
if(tmp_num<0)
{
error_interrupt(__special_call_vector_negative_value,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
nasal_gc.reference_delete(num2_addr);
num2_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(num2_addr).set_type(scalar_number);
nasal_gc.get_scalar(num2_addr).get_number().set_number(tmp_num);
}
else
{
error_interrupt(__not_numerable_str,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
}
if(nasal_gc.get_scalar(num1_addr).get_number().get_number()>2147483647)
{
error_interrupt(__special_call_vector_too_large_value,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_number().get_number()>2147483647)
{
error_interrupt(__special_call_vector_too_large_value,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number();
int end_num=0;
if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil)
end_num=nasal_gc.get_scalar(addr).get_vector().get_size();
else
end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number();
if(num1_addr>=0)
nasal_gc.reference_delete(num1_addr);
if(num2_addr>=0)
nasal_gc.reference_delete(num2_addr);
std::vector<int> subvec_result;
for(int i=begin_num;i<end_num;++i)
{
// addr used here
int tmp_data_addr=nasal_gc.get_scalar(addr).get_vector().get_elem(i);
int new_addr=-1;
if(tmp_data_addr<0)
{
error_interrupt(__invalid_vector_member,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
switch(nasal_gc.get_scalar(tmp_data_addr).get_type())
{
case scalar_nil:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_nil);
break;
case scalar_number:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_number);
nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number());
break;
case scalar_string:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_string);
nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string());
break;
case scalar_function:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_function);
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function());
break;
case scalar_vector:
case scalar_hash:
new_addr=tmp_data_addr;
nasal_gc.reference_add(new_addr);
break;
}
nasal_gc.reference_delete(tmp_data_addr);
subvec_result.push_back(new_addr);
}
int tmp_addr=addr;
addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(addr).set_type(scalar_vector);
for(int i=0;i<subvec_result.size();++i)
nasal_gc.get_scalar(addr).get_vector().vec_push(subvec_result[i]);
nasal_gc.reference_delete(tmp_addr);
}// end sub-vector
else
{
// normal vector/hash calling
int data_addr=calculation(local_scope,call_node->get_children().front());
if(data_addr<0)
return -1;
if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_number && nasal_gc.get_scalar(data_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_node_line());
return -1;
}
if(called_type==scalar_vector)
{
double place_num=0;
if(nasal_gc.get_scalar(data_addr).get_type()==scalar_string)
{
if(check_numerable_string(nasal_gc.get_scalar(data_addr).get_string().get_string()))
place_num=(int)trans_string_to_number(nasal_gc.get_scalar(data_addr).get_string().get_string());
else
{
error_interrupt(__not_numerable_str,call_node->get_children().front().get_node_line());
return -1;
}
}
if(place_num>2147483647 || place_num<-2147483648)
{
error_interrupt(__normal_call_vector_too_large_value,call_node->get_children().front().get_node_line());
return -1;
}
int tmp_addr=addr;
addr=nasal_gc.get_scalar(addr).get_vector().get_elem((int)place_num);
if(addr<0)
{
error_interrupt(__invalid_vector_member,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
nasal_gc.reference_add(addr);
nasal_gc.reference_delete(tmp_addr);
}
else if(called_type==scalar_hash)
{
if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type_when_calling_hash,call_node->get_children().front().get_node_line());
return -1;
}
int tmp_addr=addr;
addr=nasal_gc.get_scalar(addr).get_hash().get_hash_member(nasal_gc.get_scalar(data_addr).get_string().get_string());
if(addr<0)
{
error_interrupt(__invalid_hash_member,call_node->get_children().front().get_node_line());
return -1;
}
nasal_gc.reference_add(addr);
nasal_gc.reference_delete(tmp_addr);
}
nasal_gc.reference_delete(data_addr);
}
}// end call vector
// call hash identifier.identifier
else if(call_node->get_node_type()==__call_hash)
{
if(nasal_gc.get_scalar(addr).get_type()!=scalar_hash)
{
error_interrupt(__not_callable_hash,call_node->get_node_line());
return -1;
}
addr=nasal_gc.get_scalar(addr).get_hash().get_hash_member(call_node->get_var_name());
if(addr<0)
{
error_interrupt(__invalid_hash_member,call_node->get_node_line());
return -1;
}
}// end call hash
// call function identifier(...)
else if(call_node->get_node_type()==__call_function)
{
if(nasal_gc.get_scalar(addr).get_type()!=scalar_function)
{
error_interrupt(__not_callable_function,call_node->get_node_line());
return -1;
}
int tmp_addr=addr;
addr=func_proc(
nasal_gc.get_scalar(addr).get_function().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,
last_hash_addr);
if(addr<0)
return -1;
} }
} }
return addr; return addr;
@ -233,9 +485,262 @@ int nasal_runtime::hash_generation(std::list<std::map<std::string,int> >& local_
nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,calculation(local_scope,*i)); nasal_gc.get_scalar(addr).get_hash().hash_push(member_name,calculation(local_scope,*i));
} }
} }
int last_hash_addr=-1;
for(;call_node!=node.get_children().end();++call_node) for(;call_node!=node.get_children().end();++call_node)
{ {
; if(nasal_gc.get_scalar(addr).get_type()==scalar_hash)
last_hash_addr=addr;
// call vector/special call hash/subvec
// the special type of calling hash like a["name"] is also generated as calling vector
if(call_node->get_node_type()==__call_vector)
{
// check the scalar type of called identifier here
int called_type=nasal_gc.get_scalar(addr).get_type();
if(called_type!=scalar_vector && called_type!=scalar_hash)
{
error_interrupt(__error_value_type,call_node->get_node_line());
return -1;
}
if(call_node->get_children().front().get_node_type()==__sub_vector)
{
if(called_type==scalar_hash)
{
error_interrupt(__not_callable_vector,call_node->get_node_line());
return -1;
}
int num1_addr=-1;
int num2_addr=-1;
// identifier[num1:];
if(call_node->get_children().front().get_children().size()==1)
{
num1_addr=calculation(local_scope,call_node->get_children().front().get_children().front());
if(num1_addr<0)
return -1;
}
// identifier[num1:num2];
else
{
num1_addr=calculation(local_scope,call_node->get_children().front().get_children().front());
num2_addr=calculation(local_scope,call_node->get_children().front().get_children().back());
if(num1_addr<0 || num2_addr<0)
return -1;
}
if(nasal_gc.get_scalar(num1_addr).get_type()!=scalar_number
&& nasal_gc.get_scalar(num1_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
if(num2_addr>=0
&& (nasal_gc.get_scalar(num2_addr).get_type()!=scalar_number
&& nasal_gc.get_scalar(num2_addr).get_type()!=scalar_string
&& nasal_gc.get_scalar(num2_addr).get_type()!=scalar_nil))
{
error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
if(nasal_gc.get_scalar(num1_addr).get_type()==scalar_string)
{
if(check_numerable_string(nasal_gc.get_scalar(num1_addr).get_string().get_string()))
{
double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num1_addr).get_string().get_string());
if(tmp_num<0)
{
error_interrupt(__special_call_vector_negative_value,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
nasal_gc.reference_delete(num1_addr);
num1_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(num1_addr).set_type(scalar_number);
nasal_gc.get_scalar(num1_addr).get_number().set_number(tmp_num);
}
else
{
error_interrupt(__not_numerable_str,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
}
if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_type()==scalar_string)
{
if(check_numerable_string(nasal_gc.get_scalar(num2_addr).get_string().get_string()))
{
double tmp_num=trans_string_to_number(nasal_gc.get_scalar(num2_addr).get_string().get_string());
if(tmp_num<0)
{
error_interrupt(__special_call_vector_negative_value,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
nasal_gc.reference_delete(num2_addr);
num2_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(num2_addr).set_type(scalar_number);
nasal_gc.get_scalar(num2_addr).get_number().set_number(tmp_num);
}
else
{
error_interrupt(__not_numerable_str,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
}
if(nasal_gc.get_scalar(num1_addr).get_number().get_number()>2147483647)
{
error_interrupt(__special_call_vector_too_large_value,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
if(num2_addr>=0 && nasal_gc.get_scalar(num2_addr).get_number().get_number()>2147483647)
{
error_interrupt(__special_call_vector_too_large_value,call_node->get_children().front().get_children().back().get_node_line());
return -1;
}
int begin_num=(int)nasal_gc.get_scalar(num1_addr).get_number().get_number();
int end_num=0;
if(num2_addr<0 || nasal_gc.get_scalar(num2_addr).get_type()==scalar_nil)
end_num=nasal_gc.get_scalar(addr).get_vector().get_size();
else
end_num=(int)nasal_gc.get_scalar(num2_addr).get_number().get_number();
if(num1_addr>=0)
nasal_gc.reference_delete(num1_addr);
if(num2_addr>=0)
nasal_gc.reference_delete(num2_addr);
std::vector<int> subvec_result;
for(int i=begin_num;i<end_num;++i)
{
// addr used here
int tmp_data_addr=nasal_gc.get_scalar(addr).get_vector().get_elem(i);
int new_addr=-1;
if(tmp_data_addr<0)
{
error_interrupt(__invalid_vector_member,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
switch(nasal_gc.get_scalar(tmp_data_addr).get_type())
{
case scalar_nil:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_nil);
break;
case scalar_number:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_number);
nasal_gc.get_scalar(new_addr).get_number().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_number());
break;
case scalar_string:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_string);
nasal_gc.get_scalar(new_addr).get_string().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_string());
break;
case scalar_function:
new_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(new_addr).set_type(scalar_function);
nasal_gc.get_scalar(new_addr).get_function().deep_copy(nasal_gc.get_scalar(tmp_data_addr).get_function());
break;
case scalar_vector:
case scalar_hash:
new_addr=tmp_data_addr;
nasal_gc.reference_add(new_addr);
break;
}
nasal_gc.reference_delete(tmp_data_addr);
subvec_result.push_back(new_addr);
}
int tmp_addr=addr;
addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(addr).set_type(scalar_vector);
for(int i=0;i<subvec_result.size();++i)
nasal_gc.get_scalar(addr).get_vector().vec_push(subvec_result[i]);
nasal_gc.reference_delete(tmp_addr);
}// end sub-vector
else
{
// normal vector/hash calling
int data_addr=calculation(local_scope,call_node->get_children().front());
if(data_addr<0)
return -1;
if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_number && nasal_gc.get_scalar(data_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type_when_calling_vector,call_node->get_children().front().get_node_line());
return -1;
}
if(called_type==scalar_vector)
{
double place_num=0;
if(nasal_gc.get_scalar(data_addr).get_type()==scalar_string)
{
if(check_numerable_string(nasal_gc.get_scalar(data_addr).get_string().get_string()))
place_num=(int)trans_string_to_number(nasal_gc.get_scalar(data_addr).get_string().get_string());
else
{
error_interrupt(__not_numerable_str,call_node->get_children().front().get_node_line());
return -1;
}
}
if(place_num>2147483647 || place_num<-2147483648)
{
error_interrupt(__normal_call_vector_too_large_value,call_node->get_children().front().get_node_line());
return -1;
}
int tmp_addr=addr;
addr=nasal_gc.get_scalar(addr).get_vector().get_elem((int)place_num);
if(addr<0)
{
error_interrupt(__invalid_vector_member,call_node->get_children().front().get_children().front().get_node_line());
return -1;
}
nasal_gc.reference_add(addr);
nasal_gc.reference_delete(tmp_addr);
}
else if(called_type==scalar_hash)
{
if(nasal_gc.get_scalar(data_addr).get_type()!=scalar_string)
{
error_interrupt(__error_value_type_when_calling_hash,call_node->get_children().front().get_node_line());
return -1;
}
int tmp_addr=addr;
addr=nasal_gc.get_scalar(addr).get_hash().get_hash_member(nasal_gc.get_scalar(data_addr).get_string().get_string());
if(addr<0)
{
error_interrupt(__invalid_hash_member,call_node->get_children().front().get_node_line());
return -1;
}
nasal_gc.reference_add(addr);
nasal_gc.reference_delete(tmp_addr);
}
nasal_gc.reference_delete(data_addr);
}
}// end call vector
// call hash identifier.identifier
else if(call_node->get_node_type()==__call_hash)
{
if(nasal_gc.get_scalar(addr).get_type()!=scalar_hash)
{
error_interrupt(__not_callable_hash,call_node->get_node_line());
return -1;
}
addr=nasal_gc.get_scalar(addr).get_hash().get_hash_member(call_node->get_var_name());
if(addr<0)
{
error_interrupt(__invalid_hash_member,call_node->get_node_line());
return -1;
}
}// end call hash
// call function identifier(...)
else if(call_node->get_node_type()==__call_function)
{
if(nasal_gc.get_scalar(addr).get_type()!=scalar_function)
{
error_interrupt(__not_callable_function,call_node->get_node_line());
return -1;
}
int tmp_addr=addr;
addr=func_proc(
nasal_gc.get_scalar(addr).get_function().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,
last_hash_addr);
if(addr<0)
return -1;
}
} }
return addr; return addr;
} }
@ -1224,6 +1729,12 @@ int* nasal_runtime::get_identifier_addr(std::list<std::map<std::string,int> >& l
} }
return ret_addr; return ret_addr;
} }
int nasal_runtime::call_scalar(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
{
int addr=-1;
return addr;
}
int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node) int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& node)
{ {
int addr=-1; int addr=-1;
@ -1491,6 +2002,7 @@ int nasal_runtime::call_identifier(std::list<std::map<std::string,int> >& local_
nasal_gc.get_scalar(addr).get_function().get_local_scope(), nasal_gc.get_scalar(addr).get_function().get_local_scope(),
nasal_gc.get_scalar(addr).get_function().get_parameter_list(), nasal_gc.get_scalar(addr).get_function().get_parameter_list(),
nasal_gc.get_scalar(addr).get_function().get_statement_block(), nasal_gc.get_scalar(addr).get_function().get_statement_block(),
*iter,
last_hash_addr); last_hash_addr);
if(addr<0) if(addr<0)
return -1; return -1;
@ -1680,8 +2192,30 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
} }
else if(loop_type==__foreach) else if(loop_type==__foreach)
{ {
// foreach(i;vector)
// foreach gives elements in the vector to the identifier 'i' and the 'i' will take part in calculation
std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin(); std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin();
int* addr=NULL;// definition int* addr=NULL;// definition/assignment
if(iter->get_node_type()==__definition)
{
std::string identifier_name=iter->get_children().front().get_var_name();
int new_identifier_addr=nasal_gc.gc_alloc();
local_scope.back()[identifier_name]=new_identifier_addr;
nasal_gc.get_scalar(new_identifier_addr).set_type(scalar_nil);
addr=&(local_scope.back()[identifier_name]);
}
else
{
addr=get_identifier_addr(local_scope,*iter);
if(addr && *addr>=0)
{
nasal_gc.reference_delete(*addr);
*addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(*addr).set_type(scalar_nil);
}
}
if(!addr)
return __state_error;
++iter; ++iter;
int vec_addr=calculation(local_scope,*iter); int vec_addr=calculation(local_scope,*iter);
if(vec_addr<0) if(vec_addr<0)
@ -1694,7 +2228,35 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
++iter; ++iter;
for(int i=0;i<nasal_gc.get_scalar(vec_addr).get_vector().get_size();++i) for(int i=0;i<nasal_gc.get_scalar(vec_addr).get_vector().get_size();++i)
{ {
; int now_step_elem_addr=nasal_gc.get_scalar(vec_addr).get_vector().get_elem(i);
nasal_gc.reference_delete(*addr);
switch(nasal_gc.get_scalar(now_step_elem_addr).get_type())
{
case scalar_nil:
*addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(*addr).set_type(scalar_nil);
break;
case scalar_number:
*addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(*addr).set_type(scalar_number);
nasal_gc.get_scalar(*addr).get_number().deep_copy(nasal_gc.get_scalar(now_step_elem_addr).get_number());
break;
case scalar_string:
*addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(*addr).set_type(scalar_string);
nasal_gc.get_scalar(*addr).get_string().deep_copy(nasal_gc.get_scalar(now_step_elem_addr).get_string());
break;
case scalar_function:
*addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(*addr).set_type(scalar_function);
nasal_gc.get_scalar(*addr).get_function().deep_copy(nasal_gc.get_scalar(now_step_elem_addr).get_function());
break;
case scalar_vector:
case scalar_hash:
*addr=now_step_elem_addr;
nasal_gc.reference_add(*addr);
break;
}
int state=block_proc(local_scope,*iter); int state=block_proc(local_scope,*iter);
if(state==__state_break) if(state==__state_break)
break; break;
@ -1707,12 +2269,36 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
else if(state==__state_no_operation) else if(state==__state_no_operation)
; ;
} }
// run block
} }
else if(loop_type==__forindex) else if(loop_type==__forindex)
{ {
// forindex(i;vector)
// forindex gives the index of elements in the vector to identifier 'i'
// and the 'i' will take part in the calculation
std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin(); std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin();
int* addr=NULL;// definition int* addr=NULL;// definition/assignment
if(iter->get_node_type()==__definition)
{
std::string identifier_name=iter->get_children().front().get_var_name();
int new_identifier_addr=nasal_gc.gc_alloc();
local_scope.back()[identifier_name]=new_identifier_addr;
nasal_gc.get_scalar(new_identifier_addr).set_type(scalar_number);
nasal_gc.get_scalar(new_identifier_addr).get_number().set_number(0);
addr=&(local_scope.back()[identifier_name]);
}
else
{
addr=get_identifier_addr(local_scope,*iter);
if(addr && *addr>=0)
{
nasal_gc.reference_delete(*addr);
*addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(*addr).set_type(scalar_number);
nasal_gc.get_scalar(*addr).get_number().set_number(0);
}
}
if(!addr)
return __state_error;
++iter; ++iter;
int vec_addr=calculation(local_scope,*iter); int vec_addr=calculation(local_scope,*iter);
if(vec_addr<0) if(vec_addr<0)
@ -1725,7 +2311,7 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
++iter; ++iter;
for(int i=0;i<nasal_gc.get_scalar(vec_addr).get_vector().get_size();++i) for(int i=0;i<nasal_gc.get_scalar(vec_addr).get_vector().get_size();++i)
{ {
; nasal_gc.get_scalar(*addr).get_number().set_number((double)i);
int state=block_proc(local_scope,*iter); int state=block_proc(local_scope,*iter);
if(state==__state_break) if(state==__state_break)
break; break;
@ -1738,24 +2324,21 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
else if(state==__state_no_operation) else if(state==__state_no_operation)
; ;
} }
// run block
} }
else if(loop_type==__for) else if(loop_type==__for)
{ {
std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin(); std::list<abstract_syntax_tree>::iterator iter=node.get_children().begin();
if(iter->get_node_type()!=__null_type)
definition(local_scope,local_scope.back(),*iter);
// definition before loop // definition before loop
++iter; ++iter; std::list<abstract_syntax_tree>::iterator condition_iterator=iter;
std::list<abstract_syntax_tree>::iterator condition_iterator=iter;
// conditional // conditional
++iter; ++iter; std::list<abstract_syntax_tree>::iterator step_iterator=iter;
std::list<abstract_syntax_tree>::iterator step_iterator=iter;
// step length // step length
++iter; ++iter; std::list<abstract_syntax_tree>::iterator block_proc_iterator=iter;
std::list<abstract_syntax_tree>::iterator block_proc_iterator=iter;
// run block // run block
while(check_condition(local_scope,*condition_iterator)) while(check_condition(local_scope,*condition_iterator))
{ {
;
int state=block_proc(local_scope,*block_proc_iterator); int state=block_proc(local_scope,*block_proc_iterator);
if(state==__state_break) if(state==__state_break)
break; break;
@ -1768,6 +2351,13 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
else if(state==__state_no_operation) else if(state==__state_no_operation)
; ;
// step update here // step update here
if(step_iterator->get_node_type()!=__null_type)
{
int assign_addr=calculation(local_scope,*step_iterator);
if(assign_addr<0)
return __state_error;
nasal_gc.reference_delete(assign_addr);
}
} }
} }
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)
@ -1875,21 +2465,111 @@ int nasal_runtime::block_proc(std::list<std::map<std::string,int> >& local_scope
state=__state_error; state=__state_error;
break; break;
} }
if(state==__state_break || state==__state_continue || state==__state_return || state==__state_error)
break;
} }
return state; return state;
} }
int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,abstract_syntax_tree& parameter_list,abstract_syntax_tree& func_root,int called_hash_addr) int nasal_runtime::func_proc(
std::list<std::map<std::string,int> >& local_scope,// running scope,often gets the scope that has been recorded in 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& input_parameters, // input parameters when calling this nasal function
int called_hash_addr // if called a hash before calling this nasal function,this address will be given to 'me'
)
{ {
std::map<std::string,int> new_scope; std::map<std::string,int> new_scope;
local_scope.push_back(new_scope); local_scope.push_back(new_scope);
if(called_hash_addr>=0) if(called_hash_addr>=0)
local_scope.back()["me"]=called_hash_addr; local_scope.back()["me"]=called_hash_addr;
// loading parameters // loading parameters
std::vector<std::string> para_name_list;
bool has_dynamic_id=false;
int dynamic_args=nasal_gc.gc_alloc();
nasal_gc.get_scalar(dynamic_args).set_type(scalar_vector);
for(std::list<abstract_syntax_tree>::iterator iter=parameter_list.get_children().begin();iter!=parameter_list.get_children().end();++iter) for(std::list<abstract_syntax_tree>::iterator iter=parameter_list.get_children().begin();iter!=parameter_list.get_children().end();++iter)
{ {
if(iter->get_node_type()==__id)
{
para_name_list.push_back(iter->get_var_name());
local_scope.back()[para_name_list.back()]=-1;
}
else if(iter->get_node_type()==__default_parameter)
{
para_name_list.push_back(iter->get_children().front().get_var_name());
int default_val_addr=calculation(local_scope,iter->get_children().back());
if(default_val_addr<0)
return -1;
local_scope.back()[para_name_list.back()]=default_val_addr;
}
else if(iter->get_node_type()==__dynamic_id)
{
has_dynamic_id=true;
local_scope.back()[iter->get_var_name()]=dynamic_args;
break;
}
} }
if(input_parameters.get_children().front().get_node_type()!=__special_parameter)
{
int tmp_ptr=0;
for(std::list<abstract_syntax_tree>::iterator iter=input_parameters.get_children().begin();iter!=input_parameters.get_children().end();++iter)
{
if(tmp_ptr>=para_name_list.size())
{
if(has_dynamic_id)
{
int val_addr=calculation(local_scope,*iter);
if(val_addr<0)
return -1;
nasal_gc.get_scalar(dynamic_args).get_vector().vec_push(val_addr);
}
else
break;
}
else
{
int val_addr=calculation(local_scope,*iter);
if(val_addr<0)
return -1;
if(local_scope.back()[para_name_list[tmp_ptr]]<0)
local_scope.back()[para_name_list[tmp_ptr]]=val_addr;
else
{
nasal_gc.reference_delete(local_scope.back()[para_name_list[tmp_ptr]]);
local_scope.back()[para_name_list[tmp_ptr]]=val_addr;
}
}
++tmp_ptr;
}
}
else// special parameter f(a:1,b:2)
{
for(std::list<abstract_syntax_tree>::iterator iter=input_parameters.get_children().begin();iter!=input_parameters.get_children().end();++iter)
{
std::string tmp_para_name=iter->get_children().front().get_var_name();
if(local_scope.back().find(tmp_para_name)!=local_scope.back().end())
{
int val_addr=calculation(local_scope,iter->get_children().back());
if(val_addr<0)
return -1;
if(local_scope.back()[tmp_para_name]<0)
local_scope.back()[tmp_para_name]=val_addr;
else
{
nasal_gc.reference_delete(local_scope.back()[tmp_para_name]);
local_scope.back()[tmp_para_name]=val_addr;
}
}
}
}
for(int i=0;i<para_name_list.size();++i)
if(local_scope.back()[para_name_list[i]]<0)
{
error_interrupt(__call_function_lack_para,input_parameters.get_node_line());
return -1;
}
// process // process
int ret_addr=-1;
int state=__state_no_operation; int state=__state_no_operation;
for(std::list<abstract_syntax_tree>::iterator iter=func_root.get_children().begin();iter!=func_root.get_children().end();++iter) for(std::list<abstract_syntax_tree>::iterator iter=func_root.get_children().begin();iter!=func_root.get_children().end();++iter)
{ {
@ -1936,6 +2616,17 @@ int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,
state=this->conditional(local_scope,*iter); state=this->conditional(local_scope,*iter);
else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex)) else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex))
state=this->loop_expr(local_scope,*iter); state=this->loop_expr(local_scope,*iter);
else if(node_type==__return)
{
if(!iter->get_children().size())
{
ret_addr=nasal_gc.gc_alloc();
nasal_gc.get_scalar(ret_addr).set_type(scalar_nil);
}
else
ret_addr=calculation(local_scope,iter->get_children().front());
break;
}
if(runtime_error_exit_mark>=0) if(runtime_error_exit_mark>=0)
break; break;
if(state==__state_return) if(state==__state_return)
@ -1955,7 +2646,7 @@ int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,
else if(state==__state_no_operation) else if(state==__state_no_operation)
; ;
} }
return -1; return ret_addr;
} }
void nasal_runtime::main_proc(abstract_syntax_tree& root) void nasal_runtime::main_proc(abstract_syntax_tree& root)