update
This commit is contained in:
parent
b0bc5a33a9
commit
afd26d5957
|
@ -127,6 +127,7 @@ enum parse_error
|
||||||
lack_args,
|
lack_args,
|
||||||
default_arg_not_end,
|
default_arg_not_end,
|
||||||
dynamic_id_not_end,
|
dynamic_id_not_end,
|
||||||
|
name_repetition,
|
||||||
definition_use_call,
|
definition_use_call,
|
||||||
multi_id_use_call,
|
multi_id_use_call,
|
||||||
multi_assign_lack_val,
|
multi_assign_lack_val,
|
||||||
|
@ -137,9 +138,9 @@ enum parse_error
|
||||||
|
|
||||||
void error_info(int line,int error_type,std::string error_str="")
|
void error_info(int line,int error_type,std::string error_str="")
|
||||||
{
|
{
|
||||||
std::string info=">> [parse] error: line ";
|
std::string info=">> [parse] error_info: [line ";
|
||||||
std::string detail;
|
std::string detail;
|
||||||
std::cout<<info<<line<<": ";
|
std::cout<<info<<line<<"] ";
|
||||||
switch(error_type)
|
switch(error_type)
|
||||||
{
|
{
|
||||||
case unknown: detail="unknown error."; break;
|
case unknown: detail="unknown error."; break;
|
||||||
|
@ -163,6 +164,7 @@ void error_info(int line,int error_type,std::string error_str="")
|
||||||
case lack_args: detail="expected arguments here."; break;
|
case lack_args: detail="expected arguments here."; break;
|
||||||
case default_arg_not_end: detail="default argument missing for parameter of "+error_str+".";break;
|
case default_arg_not_end: detail="default argument missing for parameter of "+error_str+".";break;
|
||||||
case dynamic_id_not_end: detail="dynamic id must be the end of "+error_str+".";break;
|
case dynamic_id_not_end: detail="dynamic id must be the end of "+error_str+".";break;
|
||||||
|
case name_repetition: detail="this identifier name has existed.";break;
|
||||||
case definition_use_call: detail="should not use call_scalar in definition progress";break;
|
case definition_use_call: detail="should not use call_scalar in definition progress";break;
|
||||||
case multi_id_use_call: detail="should not use call_scalar in multi_id progress";break;
|
case multi_id_use_call: detail="should not use call_scalar in multi_id progress";break;
|
||||||
case multi_assign_lack_val:detail="multi-assignment lacks value list.";break;
|
case multi_assign_lack_val:detail="multi-assignment lacks value list.";break;
|
||||||
|
|
|
@ -495,6 +495,25 @@ nasal_ast nasal_parse::args_list_gen()
|
||||||
error_info(node.get_children()[i].get_line(),dynamic_id_not_end,args_format);
|
error_info(node.get_children()[i].get_line(),dynamic_id_not_end,args_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::map<std::string,bool> argname_table;
|
||||||
|
for(int i=0;i<node_child_size;++i)
|
||||||
|
{
|
||||||
|
int tmp_type=node.get_children()[i].get_type();
|
||||||
|
std::string new_name;
|
||||||
|
switch(tmp_type)
|
||||||
|
{
|
||||||
|
case ast_dynamic_id:
|
||||||
|
case ast_identifier:new_name=node.get_children()[i].get_str();break;
|
||||||
|
case ast_default_arg:new_name=node.get_children()[i].get_children()[0].get_str();break;
|
||||||
|
}
|
||||||
|
if(argname_table.find(new_name)!=argname_table.end())
|
||||||
|
{
|
||||||
|
error_info(node.get_children()[i].get_line(),name_repetition);
|
||||||
|
++error;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
argname_table[new_name]=true;
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
nasal_ast nasal_parse::expr()
|
nasal_ast nasal_parse::expr()
|
||||||
|
|
|
@ -40,13 +40,11 @@ private:
|
||||||
// main expression block running process
|
// main expression block running process
|
||||||
int main_progress();
|
int main_progress();
|
||||||
// function/loop/conditional expression block running process
|
// function/loop/conditional expression block running process
|
||||||
int block_progress(nasal_ast&,int);
|
int block_progress(nasal_ast&,int,bool);
|
||||||
// run loop
|
// run loop
|
||||||
int loop_progress(nasal_ast&,int);
|
int loop_progress(nasal_ast&,int,bool);
|
||||||
// run conditional
|
// run conditional
|
||||||
int conditional_progress(nasal_ast&,int);
|
int conditional_progress(nasal_ast&,int,bool);
|
||||||
// run function
|
|
||||||
int function_progress(nasal_ast&,int);
|
|
||||||
// get scalars in complex data structure like vector/hash/function/closure(scope)
|
// get scalars in complex data structure like vector/hash/function/closure(scope)
|
||||||
int call_scalar(nasal_ast&,int);
|
int call_scalar(nasal_ast&,int);
|
||||||
int call_vector(nasal_ast&,int,int);
|
int call_vector(nasal_ast&,int,int);
|
||||||
|
@ -202,13 +200,13 @@ int nasal_runtime::main_progress()
|
||||||
multi_assignment(root.get_children()[i],-1);
|
multi_assignment(root.get_children()[i],-1);
|
||||||
break;
|
break;
|
||||||
case ast_conditional:
|
case ast_conditional:
|
||||||
ret_state=conditional_progress(root.get_children()[i],-1);
|
ret_state=conditional_progress(root.get_children()[i],-1,false);
|
||||||
break;
|
break;
|
||||||
case ast_while:
|
case ast_while:
|
||||||
case ast_for:
|
case ast_for:
|
||||||
case ast_forindex:
|
case ast_forindex:
|
||||||
case ast_foreach:
|
case ast_foreach:
|
||||||
ret_state=loop_progress(root.get_children()[i],-1);
|
ret_state=loop_progress(root.get_children()[i],-1,false);
|
||||||
break;
|
break;
|
||||||
case ast_number:break;
|
case ast_number:break;
|
||||||
case ast_string:break;
|
case ast_string:break;
|
||||||
|
@ -267,7 +265,7 @@ int nasal_runtime::main_progress()
|
||||||
}
|
}
|
||||||
return ret_state;
|
return ret_state;
|
||||||
}
|
}
|
||||||
int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr)
|
int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allow_return)
|
||||||
{
|
{
|
||||||
int ret_state=rt_exit_without_error;
|
int ret_state=rt_exit_without_error;
|
||||||
if(local_scope_addr<0)
|
if(local_scope_addr<0)
|
||||||
|
@ -292,13 +290,13 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr)
|
||||||
multi_assignment(node.get_children()[i],local_scope_addr);
|
multi_assignment(node.get_children()[i],local_scope_addr);
|
||||||
break;
|
break;
|
||||||
case ast_conditional:
|
case ast_conditional:
|
||||||
ret_state=conditional_progress(node.get_children()[i],local_scope_addr);
|
ret_state=conditional_progress(node.get_children()[i],local_scope_addr,allow_return);
|
||||||
break;
|
break;
|
||||||
case ast_while:
|
case ast_while:
|
||||||
case ast_for:
|
case ast_for:
|
||||||
case ast_forindex:
|
case ast_forindex:
|
||||||
case ast_foreach:
|
case ast_foreach:
|
||||||
ret_state=loop_progress(node.get_children()[i],local_scope_addr);
|
ret_state=loop_progress(node.get_children()[i],local_scope_addr,allow_return);
|
||||||
break;
|
break;
|
||||||
case ast_number:break;
|
case ast_number:break;
|
||||||
case ast_string:break;
|
case ast_string:break;
|
||||||
|
@ -328,7 +326,13 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr)
|
||||||
break;
|
break;
|
||||||
case ast_return:
|
case ast_return:
|
||||||
ret_state=rt_return;
|
ret_state=rt_return;
|
||||||
|
if(allow_return)
|
||||||
function_returned_address=calculation(root.get_children()[i].get_children()[0],local_scope_addr);
|
function_returned_address=calculation(root.get_children()[i].get_children()[0],local_scope_addr);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout<<">> [runtime] return expression is not allowed here."<<std::endl;
|
||||||
|
++error;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(ret_state==rt_error)
|
if(ret_state==rt_error)
|
||||||
|
@ -342,19 +346,16 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr)
|
||||||
nasal_vm.del_reference(local_scope_addr);
|
nasal_vm.del_reference(local_scope_addr);
|
||||||
return ret_state;
|
return ret_state;
|
||||||
}
|
}
|
||||||
int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr)
|
int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow_return)
|
||||||
{
|
{
|
||||||
int ret_state=rt_exit_without_error;
|
int ret_state=rt_exit_without_error;
|
||||||
|
// unfinished
|
||||||
return ret_state;
|
return ret_state;
|
||||||
}
|
}
|
||||||
int nasal_runtime::conditional_progress(nasal_ast& node,int local_scope_addr)
|
int nasal_runtime::conditional_progress(nasal_ast& node,int local_scope_addr,bool allow_return)
|
||||||
{
|
|
||||||
int ret_state=rt_exit_without_error;
|
|
||||||
return ret_state;
|
|
||||||
}
|
|
||||||
int nasal_runtime::function_progress(nasal_ast& node,int local_scope_addr)
|
|
||||||
{
|
{
|
||||||
int ret_state=rt_exit_without_error;
|
int ret_state=rt_exit_without_error;
|
||||||
|
// unfinished
|
||||||
return ret_state;
|
return ret_state;
|
||||||
}
|
}
|
||||||
int nasal_runtime::call_scalar(nasal_ast& node,int local_scope_addr)
|
int nasal_runtime::call_scalar(nasal_ast& node,int local_scope_addr)
|
||||||
|
@ -366,6 +367,8 @@ int nasal_runtime::call_scalar(nasal_ast& node,int local_scope_addr)
|
||||||
value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(node.get_children()[0].get_str());
|
value_address=nasal_vm.gc_get(global_scope_address).get_closure().get_value_address(node.get_children()[0].get_str());
|
||||||
if(value_address<0)
|
if(value_address<0)
|
||||||
{
|
{
|
||||||
|
// unfinished
|
||||||
|
// builtin-function call will be set here
|
||||||
std::cout<<">> [runtime] call_nasal_scalar: cannot find value named \'"<<node.get_children()[0].get_str()<<"\'."<<std::endl;
|
std::cout<<">> [runtime] call_nasal_scalar: cannot find value named \'"<<node.get_children()[0].get_str()<<"\'."<<std::endl;
|
||||||
++error;
|
++error;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -679,25 +682,188 @@ int nasal_runtime::call_function(nasal_ast& node,int base_value_addr,int last_ca
|
||||||
run_closure.add_scope();
|
run_closure.add_scope();
|
||||||
nasal_vm.add_reference(last_call_hash_addr);
|
nasal_vm.add_reference(last_call_hash_addr);
|
||||||
run_closure.add_new_value("me",last_call_hash_addr);
|
run_closure.add_new_value("me",last_call_hash_addr);
|
||||||
// unfinished
|
|
||||||
nasal_ast& argument_format=reference_of_func.get_arguments();
|
nasal_ast& argument_format=reference_of_func.get_arguments();
|
||||||
if(!node.get_children().size())
|
if(!node.get_children().size())
|
||||||
{
|
{
|
||||||
;
|
if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()!=ast_default_arg && argument_format.get_children()[0].get_type()!=ast_dynamic_id)
|
||||||
|
{
|
||||||
|
int size=argument_format.get_children().size();
|
||||||
|
int sum=0;
|
||||||
|
for(int i=0;i<size;++i)
|
||||||
|
sum+=(argument_format.get_children()[i].get_type()!=ast_default_arg);
|
||||||
|
std::cout<<">> [runtime] call_function: lack at least "<<sum<<" argument(s) but get 0."<<std::endl;
|
||||||
|
++error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()==ast_dynamic_id)
|
||||||
|
{
|
||||||
|
// load null dynamic-id
|
||||||
|
int vector_value_addr=nasal_vm.gc_alloc();
|
||||||
|
nasal_vm.gc_get(vector_value_addr).set_type(vm_vector);
|
||||||
|
run_closure.add_new_value(argument_format.get_children()[0].get_str(),vector_value_addr);
|
||||||
|
}
|
||||||
|
else if(argument_format.get_children().size() && argument_format.get_children()[0].get_type()==ast_default_arg)
|
||||||
|
{
|
||||||
|
// load default values
|
||||||
|
int size=argument_format.get_children().size();
|
||||||
|
for(int i=0;i<size;++i)
|
||||||
|
{
|
||||||
|
int tmp_value_addr=calculation(argument_format.get_children()[i].get_children()[1],local_scope_addr);
|
||||||
|
if(tmp_value_addr<0)
|
||||||
|
return -1;
|
||||||
|
run_closure.add_new_value(argument_format.get_children()[i].get_children()[0].get_str(),tmp_value_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if(node.get_children()[0].get_type()==ast_hashmember)
|
else if(node.get_children()[0].get_type()==ast_hashmember)
|
||||||
{
|
{
|
||||||
;
|
std::map<std::string,bool> args_usage_table; // check arguments in argument_format is correctly used
|
||||||
|
std::map<std::string,bool> default_args_table; // check default arguments
|
||||||
|
std::map<std::string,nasal_ast*> default_args_node; // if one of default arguments is not in use,use default value
|
||||||
|
// load arguments' name.
|
||||||
|
int arg_format_size=argument_format.get_children().size();
|
||||||
|
for(int i=0;i<arg_format_size;++i)
|
||||||
|
{
|
||||||
|
nasal_ast& tmp_node=argument_format.get_children()[i];
|
||||||
|
std::string id_name=(tmp_node.get_type()==ast_default_arg? tmp_node.get_children()[0].get_str():tmp_node.get_str());
|
||||||
|
args_usage_table[id_name]=false;
|
||||||
|
if(tmp_node.get_type()==ast_default_arg)
|
||||||
|
{
|
||||||
|
default_args_table[id_name]=false;
|
||||||
|
default_args_node[id_name]=&tmp_node.get_children()[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// initialize normal arguments.
|
||||||
|
int args_size=node.get_children().size();
|
||||||
|
for(int i=0;i<args_size;++i)
|
||||||
|
{
|
||||||
|
nasal_ast& tmp_node=node.get_children()[i];
|
||||||
|
std::string id_name=tmp_node.get_children()[0].get_str();
|
||||||
|
if(args_usage_table.find(id_name)==args_usage_table.end())
|
||||||
|
{
|
||||||
|
std::cout<<">> [runtime] call_function: identifier named \'"<<id_name<<"\' does not exist."<<std::endl;
|
||||||
|
++error;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
;
|
args_usage_table[id_name]=true;
|
||||||
|
if(default_args_table.find(id_name)!=default_args_table.end())
|
||||||
|
default_args_table[id_name]=true;
|
||||||
}
|
}
|
||||||
int ret_state=block_progress(reference_of_func.get_run_block(),run_closure_addr); //?
|
int value_addr=calculation(tmp_node.get_children()[1],local_scope_addr);
|
||||||
|
if(value_addr<0)
|
||||||
|
return -1;
|
||||||
|
run_closure.add_new_value(id_name,value_addr);
|
||||||
|
}
|
||||||
|
// use default value if a default-argument haven't been initialized.
|
||||||
|
for(std::map<std::string,bool>::iterator i=default_args_table.begin();i!=default_args_table.end();++i)
|
||||||
|
if(!i->second)
|
||||||
|
{
|
||||||
|
int value_addr=calculation(*default_args_node[i->first],local_scope_addr);
|
||||||
|
if(value_addr<0)
|
||||||
|
return -1;
|
||||||
|
run_closure.add_new_value(i->first,value_addr);
|
||||||
|
args_usage_table[i->first]=true;
|
||||||
|
}
|
||||||
|
// use null vector if dynamic-identifier haven't been initialized.
|
||||||
|
if(argument_format.get_children().back().get_type()==ast_dynamic_id)
|
||||||
|
{
|
||||||
|
std::string dyn_str=argument_format.get_children().back().get_str();
|
||||||
|
if(!args_usage_table[dyn_str])
|
||||||
|
{
|
||||||
|
args_usage_table[dyn_str]=true;
|
||||||
|
int vector_value_addr=nasal_vm.gc_alloc();
|
||||||
|
nasal_vm.gc_get(vector_value_addr).set_type(vm_vector);
|
||||||
|
run_closure.add_new_value(dyn_str,vector_value_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check if each argument is initialized.
|
||||||
|
for(std::map<std::string,bool>::iterator i=args_usage_table.begin();i!=args_usage_table.end();++i)
|
||||||
|
if(!i->second)
|
||||||
|
{
|
||||||
|
std::cout<<">> [runtime] call_function: argument named \'"<<i->first<<"\' is not in use."<<std::endl;
|
||||||
|
++error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<int> args; // store value address of input arguments
|
||||||
|
int size=node.get_children().size();
|
||||||
|
for(int i=0;i<size;++i)
|
||||||
|
{
|
||||||
|
int tmp_val_addr=calculation(node.get_children()[i],local_scope_addr);
|
||||||
|
if(tmp_val_addr<0)
|
||||||
|
{
|
||||||
|
std::cout<<">> [runtime] call_function: error value address when generating argument list."<<std::endl;
|
||||||
|
++error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
args.push_back(tmp_val_addr);
|
||||||
|
}
|
||||||
|
int arg_format_size=argument_format.get_children().size();
|
||||||
|
if(size>arg_format_size && argument_format.get_children().back().get_type()!=ast_dynamic_id)
|
||||||
|
{
|
||||||
|
std::cout<<">> [runtime] call_function: too much arguments."<<std::endl;
|
||||||
|
++error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
for(int i=0;i<arg_format_size;++i)
|
||||||
|
{
|
||||||
|
nasal_ast& tmp_node=argument_format.get_children()[i];
|
||||||
|
if(tmp_node.get_type()==ast_identifier || tmp_node.get_type()==ast_dynamic_id)
|
||||||
|
{
|
||||||
|
if(tmp_node.get_type()==ast_dynamic_id)
|
||||||
|
{
|
||||||
|
int vector_value_addr=nasal_vm.gc_alloc();
|
||||||
|
nasal_vm.gc_get(vector_value_addr).set_type(vm_vector);
|
||||||
|
nasal_vector& ref_vec=nasal_vm.gc_get(vector_value_addr).get_vector();
|
||||||
|
for(int j=i;j<size;++j)
|
||||||
|
{
|
||||||
|
int new_mem=nasal_vm.mem_alloc();
|
||||||
|
nasal_vm.mem_init(new_mem,args[j]);
|
||||||
|
ref_vec.add_elem(new_mem);
|
||||||
|
}
|
||||||
|
run_closure.add_new_value(tmp_node.get_str(),vector_value_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(i<size)
|
||||||
|
run_closure.add_new_value(tmp_node.get_str(),args[i]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout<<">> [runtime] call_function: lack argument(s).stop."<<std::endl;
|
||||||
|
++error;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // default_args
|
||||||
|
{
|
||||||
|
if(i<size)
|
||||||
|
run_closure.add_new_value(tmp_node.get_children()[0].get_str(),args[i]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tmp_val_addr=calculation(tmp_node.get_children()[1],local_scope_addr);
|
||||||
|
if(tmp_val_addr<0)
|
||||||
|
return -1;
|
||||||
|
run_closure.add_new_value(tmp_node.get_children()[0].get_str(),tmp_val_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block_progress(reference_of_func.get_run_block(),run_closure_addr,true);
|
||||||
|
|
||||||
run_closure.del_scope();
|
run_closure.del_scope();
|
||||||
|
if(function_returned_address>=0)
|
||||||
|
{
|
||||||
ret_value_addr=function_returned_address;
|
ret_value_addr=function_returned_address;
|
||||||
function_returned_address=-1;
|
function_returned_address=-1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret_value_addr=nasal_vm.gc_alloc();
|
||||||
|
nasal_vm.gc_get(ret_value_addr).set_type(vm_nil);
|
||||||
|
}
|
||||||
return ret_value_addr;
|
return ret_value_addr;
|
||||||
}
|
}
|
||||||
int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr)
|
int nasal_runtime::call_scalar_mem(nasal_ast& node,int local_scope_addr)
|
||||||
|
@ -1061,10 +1227,12 @@ int nasal_runtime::calculation(nasal_ast& node,int local_scope_addr)
|
||||||
}
|
}
|
||||||
void nasal_runtime::definition(nasal_ast& node,int local_scope_addr)
|
void nasal_runtime::definition(nasal_ast& node,int local_scope_addr)
|
||||||
{
|
{
|
||||||
|
// unfinished
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
void nasal_runtime::multi_assignment(nasal_ast& node,int local_scope_addr)
|
void nasal_runtime::multi_assignment(nasal_ast& node,int local_scope_addr)
|
||||||
{
|
{
|
||||||
|
//unfinished
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue