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
int bound=nas_array.size();
if(-bound<=addr && addr<0)
{
nasal_gc.reference_add(nas_array[bound+addr]);
return nas_array[bound+addr];
}
else if(0<=addr && addr<bound)
{
nasal_gc.reference_add(nas_array[addr]);
return nas_array[addr];
}
return -1;
}
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)
{
if(nas_hash.find(member_name)!=nas_hash.end())
{
nasal_gc.reference_add(nas_hash[member_name]);
return nas_hash[member_name];
}
return -1;
}
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()
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
parameter_lack_part, // parameter lack a ')' or identifier
parameter_lack_curve, // parameter lack a ',' or ')'
special_call_func_lack_id,
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_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)
@ -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)
{
std::string error_info_head=">> [Parse] line ";
std::cout<<">> [Parse] line "<<line<<": ";
switch(error_type)
{
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:
std::cout<<error_info_head<<line<<": statements should not begin with \'";
std::cout<<"statements should not begin with \'";
print_parse_token(error_token_type);
std::cout<<"\' in main scope."<<std::endl;
break;
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);
std::cout<<"\' in block scope."<<std::endl;
break;
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:
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:
std::cout<<error_info_head<<line<<": expect a \'(\' here."<<std::endl;break;
std::cout<<"expect a \'(\' here."<<std::endl;break;
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:
std::cout<<error_info_head<<line<<": expect a \'}\' here."<<std::endl;break;
std::cout<<"expect a \'}\' here."<<std::endl;break;
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:
std::cout<<error_info_head<<line<<": expect a \'=\' here but get \'";
std::cout<<"expect a \'=\' here but get \'";
print_parse_token(error_token_type);
std::cout<<"\' when generating definition."<<std::endl;
break;
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;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
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:
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:
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:
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:
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);
std::cout<<"\' when calling functions."<<std::endl;
break;
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);
std::cout<<"\' when calling functions."<<std::endl;
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:
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);
std::cout<<"\' ."<<std::endl;
break;
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:
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;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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);
std::cout<<"\' ."<<std::endl;
break;
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;
}
@ -1052,6 +1058,8 @@ abstract_syntax_tree nasal_parse::scalar_generate()
if(this_token.type!=__right_curve)
{
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)
{
this->get_token();
@ -1117,7 +1125,10 @@ abstract_syntax_tree nasal_parse::scalar_generate()
if((this_token.type!=__comma) && (this_token.type!=__right_curve))
{
++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;
}
if(this_token.type==__comma)
@ -1316,6 +1327,7 @@ abstract_syntax_tree nasal_parse::function_generate()
this->get_token();
if(this_token.type==__left_curve)
{
bool has_default_para=false;
while(this_token.type!=__right_curve)
{
// check identifier
@ -1348,8 +1360,15 @@ abstract_syntax_tree nasal_parse::function_generate()
// check equal operator
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)
{
has_default_para=true;
if(parameter_type==__id)
{
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);
}
}
else
else if(this_token.type==__forindex || this_token.type==__foreach)
{
// forindex
// foreach
this->get_token();// '('
if(this_token.type!=__left_curve)
{
@ -1704,20 +1721,39 @@ abstract_syntax_tree nasal_parse::loop_expr()
}
this->get_token();// 'var'
if(this_token.type!=__var)
this->push_token();
this->get_token();// id
if(this_token.type!=__id)
{
++error;
print_parse_error(lack_id,this_token.line);
// if checked not the 'var' then checking if this token is an identifier
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
{
abstract_syntax_tree id_node;
id_node.set_node_line(this_token.line);
id_node.set_node_type(__id);
id_node.set_var_name(this_token.str);
loop_main_node.add_children(id_node);
abstract_syntax_tree new_definition_node;
new_definition_node.set_node_line(this_token.line);
new_definition_node.set_node_type(__definition);
this->get_token();
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();// ';'
if(this_token.type!=__semi)

View File

@ -42,6 +42,7 @@ class nasal_runtime
__special_call_vector_too_large_value,
__normal_call_vector_too_large_value,
__error_call_type_when_getting_address,
__call_function_lack_para,
__forindex_foreach_not_vector,
__break_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&);
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_scalar (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&);
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 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:
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;
case __error_call_type_when_getting_address:
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:
std::cout<<"forindex and foreach need vector here."<<std::endl;break;
case __break_not_used_in_loop:
@ -183,13 +187,261 @@ int nasal_runtime::vector_generation(std::list<std::map<std::string,int> >& loca
break;
}
}
int last_hash_addr=-1;
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;
case __call_hash:break;
case __call_function:break;
// 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;
@ -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));
}
}
int last_hash_addr=-1;
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;
}
@ -1224,6 +1729,12 @@ int* nasal_runtime::get_identifier_addr(std::list<std::map<std::string,int> >& l
}
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 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_parameter_list(),
nasal_gc.get_scalar(addr).get_function().get_statement_block(),
*iter,
last_hash_addr);
if(addr<0)
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)
{
// 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();
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;
int vec_addr=calculation(local_scope,*iter);
if(vec_addr<0)
@ -1694,7 +2228,35 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
++iter;
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);
if(state==__state_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)
;
}
// run block
}
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();
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;
int vec_addr=calculation(local_scope,*iter);
if(vec_addr<0)
@ -1725,7 +2311,7 @@ int nasal_runtime::loop_expr(std::list<std::map<std::string,int> >& local_scope,
++iter;
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);
if(state==__state_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)
;
}
// run block
}
else if(loop_type==__for)
{
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
++iter;
std::list<abstract_syntax_tree>::iterator condition_iterator=iter;
++iter; std::list<abstract_syntax_tree>::iterator condition_iterator=iter;
// conditional
++iter;
std::list<abstract_syntax_tree>::iterator step_iterator=iter;
++iter; std::list<abstract_syntax_tree>::iterator step_iterator=iter;
// step length
++iter;
std::list<abstract_syntax_tree>::iterator block_proc_iterator=iter;
++iter; std::list<abstract_syntax_tree>::iterator block_proc_iterator=iter;
// run block
while(check_condition(local_scope,*condition_iterator))
{
;
int state=block_proc(local_scope,*block_proc_iterator);
if(state==__state_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)
;
// 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)
@ -1875,21 +2465,111 @@ int nasal_runtime::block_proc(std::list<std::map<std::string,int> >& local_scope
state=__state_error;
break;
}
if(state==__state_break || state==__state_continue || state==__state_return || state==__state_error)
break;
}
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;
local_scope.push_back(new_scope);
if(called_hash_addr>=0)
local_scope.back()["me"]=called_hash_addr;
// 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)
{
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
int ret_addr=-1;
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)
{
@ -1936,6 +2616,17 @@ int nasal_runtime::func_proc(std::list<std::map<std::string,int> >& local_scope,
state=this->conditional(local_scope,*iter);
else if((node_type==__while) || (node_type==__for) || (node_type==__foreach) || (node_type==__forindex))
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)
break;
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)
;
}
return -1;
return ret_addr;
}
void nasal_runtime::main_proc(abstract_syntax_tree& root)