This commit is contained in:
Valk Richard Li 2020-11-19 23:42:51 +08:00
parent 1625f241fa
commit 4a5083f5cf
3 changed files with 63 additions and 61 deletions

View File

@ -48,6 +48,8 @@ private:
int error; int error;
nasal_ast root; nasal_ast root;
std::vector<token> tok_list; std::vector<token> tok_list;
int in_function; // count when generating function block,used to check return-expression
int in_loop; // count when generating loop block,used to check break/continue-expression
void reset(); void reset();
void die(int,std::string); void die(int,std::string);
bool check_multi_definition(); bool check_multi_definition();
@ -114,6 +116,8 @@ void nasal_parse::clear()
this->tok_list_size=0; this->tok_list_size=0;
this->ptr=0; this->ptr=0;
this->error=0; this->error=0;
this->in_function=0;
this->in_loop=0;
this->tok_list.clear(); this->tok_list.clear();
this->root.clear(); this->root.clear();
return; return;
@ -166,6 +170,8 @@ nasal_ast& nasal_parse::get_root()
void nasal_parse::reset() void nasal_parse::reset()
{ {
this->ptr=0; this->ptr=0;
this->in_function=0;
this->in_loop=0;
this->error=0; this->error=0;
this->root.clear(); this->root.clear();
return; return;
@ -521,7 +527,18 @@ nasal_ast nasal_parse::expr()
{ {
nasal_ast node; nasal_ast node;
node.set_line(tok_list[ptr].line); node.set_line(tok_list[ptr].line);
switch(tok_list[ptr].type) int tok_type=tok_list[ptr].type;
if((tok_type==tok_break || tok_type==tok_continue) && !in_loop)
{
die(error_line,"cannot use break/continue outside loop");
return node;
}
if(tok_type==tok_return && !in_function)
{
die(error_line,"cannot use return outside function");
return node;
}
switch(tok_type)
{ {
case tok_nil: case tok_nil:
case tok_number: case tok_number:
@ -916,7 +933,11 @@ nasal_ast nasal_parse::scalar()
node=id_gen(); node=id_gen();
} }
else else
{
++in_function;
node=func_gen(); node=func_gen();
--in_function;
}
} }
else if(tok_list[ptr].type==tok_left_bracket) else if(tok_list[ptr].type==tok_left_bracket)
node=vector_gen(); node=vector_gen();
@ -1204,6 +1225,7 @@ nasal_ast nasal_parse::multi_assgin()
} }
nasal_ast nasal_parse::loop() nasal_ast nasal_parse::loop()
{ {
++in_loop;
nasal_ast node; nasal_ast node;
switch(tok_list[ptr].type) switch(tok_list[ptr].type)
{ {
@ -1212,6 +1234,7 @@ nasal_ast nasal_parse::loop()
case tok_forindex: case tok_forindex:
case tok_foreach: node=forei_loop(); break; case tok_foreach: node=forei_loop(); break;
} }
--in_loop;
return node; return node;
} }
nasal_ast nasal_parse::while_loop() nasal_ast nasal_parse::while_loop()

View File

@ -4,9 +4,9 @@
enum runtime_returned_state enum runtime_returned_state
{ {
rt_return=1, rt_return=1,
rt_error,
rt_break, rt_break,
rt_continue, rt_continue,
rt_error,
rt_exit_without_error rt_exit_without_error
}; };
@ -38,16 +38,16 @@ private:
*/ */
// main expression block running process // main expression block running process
int main_progress(); void main_progress();
// function/loop/conditional expression block running process // function/loop/conditional expression block running process
int block_progress(nasal_ast&,int,bool); int block_progress(nasal_ast&,int);
// run loop // run loop
int before_for_loop(nasal_ast&,int); void before_for_loop(nasal_ast&,int);
int after_each_for_loop(nasal_ast&,int); void after_each_for_loop(nasal_ast&,int);
int loop_progress(nasal_ast&,int,bool); int loop_progress(nasal_ast&,int);
// run conditional // run conditional
bool check_condition(int); bool check_condition(int);
int conditional_progress(nasal_ast&,int,bool); int conditional_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);
@ -194,7 +194,7 @@ void nasal_runtime::run()
nasal_vm.gc_get(global_scope_address).get_closure().add_scope(); nasal_vm.gc_get(global_scope_address).get_closure().add_scope();
time_t begin_time=std::time(NULL); time_t begin_time=std::time(NULL);
int returned_statement=main_progress(); main_progress();
time_t end_time=std::time(NULL); time_t end_time=std::time(NULL);
nasal_vm.gc_get(global_scope_address).get_closure().del_scope(); nasal_vm.gc_get(global_scope_address).get_closure().del_scope();
@ -249,9 +249,8 @@ int nasal_runtime::function_generation(nasal_ast& node,int local_scope_addr)
} }
return new_addr; return new_addr;
} }
int nasal_runtime::main_progress() void nasal_runtime::main_progress()
{ {
int ret_state=rt_exit_without_error;
int expr_number=root.get_children().size(); int expr_number=root.get_children().size();
int process_returned_value_addr=-1; int process_returned_value_addr=-1;
for(int i=0;i<expr_number;++i) for(int i=0;i<expr_number;++i)
@ -262,9 +261,9 @@ int nasal_runtime::main_progress()
{ {
case ast_definition:definition(node,-1);break; case ast_definition:definition(node,-1);break;
case ast_multi_assign:multi_assignment(node,-1);break; case ast_multi_assign:multi_assignment(node,-1);break;
case ast_conditional:ret_state=conditional_progress(node,-1,false);break; case ast_conditional:conditional_progress(node,-1);break;
case ast_while:case ast_for:case ast_forindex:case ast_foreach: case ast_while:case ast_for:case ast_forindex:case ast_foreach:
ret_state=loop_progress(node,-1,false);break; loop_progress(node,-1);break;
case ast_nil:case ast_number:case ast_string:case ast_function:break; case ast_nil:case ast_number:case ast_string:case ast_function:break;
case ast_identifier: case ast_identifier:
case ast_vector:case ast_hash: case ast_vector:case ast_hash:
@ -275,14 +274,11 @@ int nasal_runtime::main_progress()
case ast_trinocular:nasal_vm.del_reference(calculation(node,-1));break; case ast_trinocular:nasal_vm.del_reference(calculation(node,-1));break;
} }
if(error) if(error)
{
ret_state=rt_error;
break; break;
}
} }
return ret_state; return;
} }
int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allow_return) int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr)
{ {
int ret_state=rt_exit_without_error; int ret_state=rt_exit_without_error;
// if local_scope does not exist,create a new one. // if local_scope does not exist,create a new one.
@ -306,9 +302,9 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allo
{ {
case ast_definition:definition(tmp_node,local_scope_addr);break; case ast_definition:definition(tmp_node,local_scope_addr);break;
case ast_multi_assign:multi_assignment(tmp_node,local_scope_addr);break; case ast_multi_assign:multi_assignment(tmp_node,local_scope_addr);break;
case ast_conditional:ret_state=conditional_progress(tmp_node,local_scope_addr,allow_return);break; case ast_conditional:ret_state=conditional_progress(tmp_node,local_scope_addr);break;
case ast_while:case ast_for:case ast_forindex:case ast_foreach: case ast_while:case ast_for:case ast_forindex:case ast_foreach:
ret_state=loop_progress(tmp_node,local_scope_addr,allow_return);break; ret_state=loop_progress(tmp_node,local_scope_addr);break;
case ast_nil:case ast_number:case ast_string:case ast_function:break; case ast_nil:case ast_number:case ast_string:case ast_function:break;
case ast_identifier: case ast_identifier:
case ast_vector:case ast_hash: case ast_vector:case ast_hash:
@ -321,15 +317,10 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allo
case ast_continue:ret_state=rt_continue;break; case ast_continue:ret_state=rt_continue;break;
case ast_return: case ast_return:
ret_state=rt_return; ret_state=rt_return;
if(allow_return) if(tmp_node.get_children().size())
{ function_returned_address=calculation(tmp_node.get_children()[0],local_scope_addr);
if(tmp_node.get_children().size())
function_returned_address=calculation(tmp_node.get_children()[0],local_scope_addr);
else
function_returned_address=nasal_vm.gc_alloc(vm_nil);
}
else else
die(tmp_node.get_line(),"cannot use return here"); function_returned_address=nasal_vm.gc_alloc(vm_nil);
break; break;
} }
if(error || ret_state==rt_break || ret_state==rt_continue || ret_state==rt_return) if(error || ret_state==rt_break || ret_state==rt_continue || ret_state==rt_return)
@ -339,7 +330,7 @@ int nasal_runtime::block_progress(nasal_ast& node,int local_scope_addr,bool allo
nasal_vm.del_reference(local_scope_addr); nasal_vm.del_reference(local_scope_addr);
return ret_state; return ret_state;
} }
int nasal_runtime::before_for_loop(nasal_ast& node,int local_scope_addr) void nasal_runtime::before_for_loop(nasal_ast& node,int local_scope_addr)
{ {
int before_loop_node_type=node.get_type(); int before_loop_node_type=node.get_type();
switch(before_loop_node_type) switch(before_loop_node_type)
@ -356,11 +347,9 @@ int nasal_runtime::before_for_loop(nasal_ast& node,int local_scope_addr)
case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break; case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break;
default:die(node.get_line(),"cannot use this expression before for-loop");break; default:die(node.get_line(),"cannot use this expression before for-loop");break;
} }
if(error) return;
return rt_error;
return rt_exit_without_error;
} }
int nasal_runtime::after_each_for_loop(nasal_ast& node,int local_scope_addr) void nasal_runtime::after_each_for_loop(nasal_ast& node,int local_scope_addr)
{ {
int node_type=node.get_type(); int node_type=node.get_type();
switch(node_type) switch(node_type)
@ -377,11 +366,9 @@ int nasal_runtime::after_each_for_loop(nasal_ast& node,int local_scope_addr)
case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break; case ast_trinocular:nasal_vm.del_reference(calculation(node,local_scope_addr));break;
default:die(node.get_line(),"cannot use this expression after each for-loop");break; default:die(node.get_line(),"cannot use this expression after each for-loop");break;
} }
if(error) return;
return rt_error;
return rt_exit_without_error;
} }
int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow_return) int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr)
{ {
int ret_state=rt_exit_without_error; int ret_state=rt_exit_without_error;
int loop_type=node.get_type(); int loop_type=node.get_type();
@ -408,8 +395,8 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
while(result) while(result)
{ {
// return expression will be checked in block_progress // return expression will be checked in block_progress
ret_state=block_progress(run_block_node,local_scope_addr,allow_return); ret_state=block_progress(run_block_node,local_scope_addr);
if(ret_state==rt_break || ret_state==rt_error || ret_state==rt_return || error) if(ret_state==rt_break || ret_state==rt_return || error)
break; break;
condition_value_addr=calculation(condition_node,while_local_scope_addr); condition_value_addr=calculation(condition_node,while_local_scope_addr);
result=check_condition(condition_value_addr); result=check_condition(condition_value_addr);
@ -475,8 +462,8 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
nasal_vm.add_reference(value_addr); nasal_vm.add_reference(value_addr);
nasal_vm.mem_change(mem_addr,value_addr); nasal_vm.mem_change(mem_addr,value_addr);
} }
ret_state=block_progress(run_block_node,forei_local_scope_addr,allow_return); ret_state=block_progress(run_block_node,forei_local_scope_addr);
if(ret_state==rt_break || ret_state==rt_return || ret_state==rt_error || error) if(ret_state==rt_break || ret_state==rt_return || error)
break; break;
} }
nasal_vm.del_reference(vector_value_addr); nasal_vm.del_reference(vector_value_addr);
@ -503,18 +490,18 @@ int nasal_runtime::loop_progress(nasal_ast& node,int local_scope_addr,bool allow
nasal_vm.gc_get(for_local_scope_addr).get_closure().add_scope(); nasal_vm.gc_get(for_local_scope_addr).get_closure().add_scope();
} }
// for progress // for progress
ret_state=before_for_loop(before_loop_node,for_local_scope_addr); before_for_loop(before_loop_node,for_local_scope_addr);
int condition_value_addr=calculation(condition_node,for_local_scope_addr); int condition_value_addr=calculation(condition_node,for_local_scope_addr);
bool result=check_condition(condition_value_addr); bool result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr); nasal_vm.del_reference(condition_value_addr);
while(result) while(result)
{ {
if(ret_state==rt_error) if(error)
break; break;
ret_state=block_progress(run_block_node,for_local_scope_addr,allow_return); ret_state=block_progress(run_block_node,for_local_scope_addr);
if(ret_state==rt_error || ret_state==rt_return || ret_state==rt_break || error) if(ret_state==rt_return || ret_state==rt_break || error)
break; break;
ret_state=after_each_for_loop(each_loop_do_node,for_local_scope_addr); after_each_for_loop(each_loop_do_node,for_local_scope_addr);
condition_value_addr=calculation(condition_node,for_local_scope_addr); condition_value_addr=calculation(condition_node,for_local_scope_addr);
result=check_condition(condition_value_addr); result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr); nasal_vm.del_reference(condition_value_addr);
@ -545,7 +532,7 @@ bool nasal_runtime::check_condition(int value_addr)
return (nasal_vm.gc_get(value_addr).get_number()!=0); return (nasal_vm.gc_get(value_addr).get_number()!=0);
return false; return false;
} }
int nasal_runtime::conditional_progress(nasal_ast& node,int local_scope_addr,bool allow_return) int nasal_runtime::conditional_progress(nasal_ast& node,int local_scope_addr)
{ {
int ret_state=rt_exit_without_error; int ret_state=rt_exit_without_error;
int size=node.get_children().size(); int size=node.get_children().size();
@ -557,18 +544,21 @@ int nasal_runtime::conditional_progress(nasal_ast& node,int local_scope_addr,boo
{ {
int condition_value_addr=calculation(tmp_node.get_children()[0],local_scope_addr); int condition_value_addr=calculation(tmp_node.get_children()[0],local_scope_addr);
if(condition_value_addr<0) if(condition_value_addr<0)
{
die(tmp_node.get_children()[0].get_line(),"cannot check condition of this value");
return rt_error; return rt_error;
}
bool result=check_condition(condition_value_addr); bool result=check_condition(condition_value_addr);
nasal_vm.del_reference(condition_value_addr); nasal_vm.del_reference(condition_value_addr);
if(result) if(result)
{ {
ret_state=block_progress(tmp_node.get_children()[1],local_scope_addr,allow_return); ret_state=block_progress(tmp_node.get_children()[1],local_scope_addr);
break; break;
} }
} }
else else
{ {
ret_state=block_progress(tmp_node.get_children()[0],local_scope_addr,allow_return); ret_state=block_progress(tmp_node.get_children()[0],local_scope_addr);
break; break;
} }
if(error) if(error)
@ -1035,17 +1025,9 @@ int nasal_runtime::call_function(nasal_ast& node,std::string func_name,int base_
} }
} }
} }
int ret_state=block_progress(reference_of_func.get_run_block(),run_closure_addr,true); block_progress(reference_of_func.get_run_block(),run_closure_addr);
run_closure.del_scope(); run_closure.del_scope();
if(ret_state==rt_break || ret_state==rt_continue)
{
die(node.get_line(),"cannot use break/continue in function main block");
return -1;
}
else if(ret_state==rt_error)
return -1;
if(function_returned_address>=0) if(function_returned_address>=0)
{ {
ret_value_addr=function_returned_address; ret_value_addr=function_returned_address;

View File

@ -59,10 +59,7 @@ var generate_str=func()
ptr+=1; ptr+=1;
} }
if(ptr>=len) if(ptr>=len)
{
print("read eof when generating string."); print("read eof when generating string.");
break;
}
ptr+=1; ptr+=1;
return tok_str; return tok_str;
} }