This commit is contained in:
Valk Richard Li 2021-06-13 01:01:32 +08:00
parent de305d26ad
commit 4f3ddf803a
4 changed files with 67 additions and 77 deletions

View File

@ -58,6 +58,12 @@ Use these commands to get help:
> ./nasal -h | -help > ./nasal -h | -help
If your system is Windows and you want to output unicode,please use this command before running nasal interpreter:
> chcp 65001
The interpreter's interactive mode will do this automatically,so you don't need to run this command if you use the interactive interpreter.
## Parser ## Parser
LL(k) parser. LL(k) parser.

View File

@ -19,6 +19,9 @@ void help_interact()
void help_cmd() void help_cmd()
{ {
std::cout std::cout
#ifdef _WIN32
<<"use command \'chcp 65001\' if want to use unicode.\n"
#endif
<<"nasal | use interactive interpreter.\n" <<"nasal | use interactive interpreter.\n"
<<"nasal -h -help | get help.\n" <<"nasal -h -help | get help.\n"
<<"nasal -v -version | get version of nasal interpreter.\n" <<"nasal -v -version | get version of nasal interpreter.\n"

View File

@ -181,8 +181,6 @@ private:
int local_find(std::string&); int local_find(std::string&);
int global_find(std::string&); int global_find(std::string&);
void gen(unsigned char,unsigned int); void gen(unsigned char,unsigned int);
void pop_gen();
void nil_gen();
void num_gen(nasal_ast&); void num_gen(nasal_ast&);
void str_gen(nasal_ast&); void str_gen(nasal_ast&);
void vec_gen(nasal_ast&); void vec_gen(nasal_ast&);
@ -304,20 +302,6 @@ void nasal_codegen::gen(unsigned char op,unsigned int index)
return; return;
} }
void nasal_codegen::pop_gen()
{
opcode op(op_pop,0);
exec_code.push_back(op);
return;
}
void nasal_codegen::nil_gen()
{
opcode op(op_pnil,0);
exec_code.push_back(op);
return;
}
void nasal_codegen::num_gen(nasal_ast& ast) void nasal_codegen::num_gen(nasal_ast& ast)
{ {
double num=ast.get_num(); double num=ast.get_num();
@ -422,7 +406,7 @@ void nasal_codegen::func_gen(nasal_ast& ast)
if(!block.get_children().size() || block.get_children().back().get_type()!=ast_ret) if(!block.get_children().size() || block.get_children().back().get_type()!=ast_ret)
{ {
nil_gen(); gen(op_pnil,0);
gen(op_ret,0); gen(op_ret,0);
} }
exec_code[jmp_ptr].num=exec_code.size(); exec_code[jmp_ptr].num=exec_code.size();
@ -591,14 +575,16 @@ void nasal_codegen::single_def(nasal_ast& ast)
} }
void nasal_codegen::multi_def(nasal_ast& ast) void nasal_codegen::multi_def(nasal_ast& ast)
{ {
int size=ast.get_children()[0].get_children().size(); auto& ids=ast.get_children()[0].get_children();
int size=ids.size();
if(ast.get_children()[1].get_type()==ast_multi_scalar) if(ast.get_children()[1].get_type()==ast_multi_scalar)
{ {
auto& vals=ast.get_children()[1].get_children();
for(int i=0;i<size;++i) for(int i=0;i<size;++i)
{ {
std::string& str=ast.get_children()[0].get_children()[i].get_str(); calc_gen(vals[i]);
std::string& str=ids[i].get_str();
add_sym(str); add_sym(str);
calc_gen(ast.get_children()[1].get_children()[i]);
if(local.empty()) if(local.empty())
gen(op_loadg,global_find(str)); gen(op_loadg,global_find(str));
else else
@ -611,14 +597,14 @@ void nasal_codegen::multi_def(nasal_ast& ast)
for(int i=0;i<size;++i) for(int i=0;i<size;++i)
{ {
gen(op_callvi,i); gen(op_callvi,i);
std::string& str=ast.get_children()[0].get_children()[i].get_str(); std::string& str=ids[i].get_str();
add_sym(str); add_sym(str);
if(local.empty()) if(local.empty())
gen(op_loadg,global_find(str)); gen(op_loadg,global_find(str));
else else
gen(op_loadl,local_find(str)); gen(op_loadl,local_find(str));
} }
pop_gen(); gen(op_pop,0);
} }
return; return;
} }
@ -643,7 +629,7 @@ void nasal_codegen::multi_assign_gen(nasal_ast& ast)
{ {
mcall(ast.get_children()[0].get_children()[i]); mcall(ast.get_children()[0].get_children()[i]);
gen(op_meq,0); gen(op_meq,0);
pop_gen(); gen(op_pop,0);
} }
} }
else else
@ -654,20 +640,18 @@ void nasal_codegen::multi_assign_gen(nasal_ast& ast)
gen(op_callvi,i); gen(op_callvi,i);
mcall(ast.get_children()[0].get_children()[i]); mcall(ast.get_children()[0].get_children()[i]);
gen(op_meq,0); gen(op_meq,0);
pop_gen(); gen(op_pop,0);
} }
pop_gen(); gen(op_pop,0);
} }
return; return;
} }
void nasal_codegen::conditional_gen(nasal_ast& ast) void nasal_codegen::conditional_gen(nasal_ast& ast)
{ {
int size=ast.get_children().size();
std::vector<int> jmp_label; std::vector<int> jmp_label;
for(int i=0;i<size;++i) for(auto& tmp:ast.get_children())
{ {
nasal_ast& tmp=ast.get_children()[i];
if(tmp.get_type()==ast_if || tmp.get_type()==ast_elsif) if(tmp.get_type()==ast_if || tmp.get_type()==ast_elsif)
{ {
calc_gen(tmp.get_children()[0]); calc_gen(tmp.get_children()[0]);
@ -676,7 +660,7 @@ void nasal_codegen::conditional_gen(nasal_ast& ast)
block_gen(tmp.get_children()[1]); block_gen(tmp.get_children()[1]);
jmp_label.push_back(exec_code.size()); jmp_label.push_back(exec_code.size());
// without 'else' the last condition doesn't need to jmp // without 'else' the last condition doesn't need to jmp
if(i!=size-1) if(&tmp!=&ast.get_children().back())
gen(op_jmp,0); gen(op_jmp,0);
exec_code[ptr].num=exec_code.size(); exec_code[ptr].num=exec_code.size();
} }
@ -686,8 +670,8 @@ void nasal_codegen::conditional_gen(nasal_ast& ast)
break; break;
} }
} }
for(std::vector<int>::iterator i=jmp_label.begin();i!=jmp_label.end();++i) for(auto i:jmp_label)
exec_code[*i].num=exec_code.size(); exec_code[i].num=exec_code.size();
return; return;
} }
@ -765,7 +749,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
case ast_less: case ast_less:
case ast_geq: case ast_geq:
case ast_grt: case ast_grt:
case ast_trino:calc_gen(ast.get_children()[0]);pop_gen();break; case ast_trino:calc_gen(ast.get_children()[0]);gen(op_pop,0);break;
} }
int jmp_place=exec_code.size(); int jmp_place=exec_code.size();
if(ast.get_children()[1].get_type()==ast_null) if(ast.get_children()[1].get_type()==ast_null)
@ -789,7 +773,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
case ast_neg:case ast_not: case ast_neg:case ast_not:
case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link: case ast_add:case ast_sub:case ast_mult:case ast_div:case ast_link:
case ast_cmpeq:case ast_neq:case ast_leq:case ast_less:case ast_geq:case ast_grt: case ast_cmpeq:case ast_neq:case ast_leq:case ast_less:case ast_geq:case ast_grt:
case ast_trino:calc_gen(ast.get_children()[2]);pop_gen();break; case ast_trino:calc_gen(ast.get_children()[2]);gen(op_pop,0);break;
} }
gen(op_jmp,jmp_place); gen(op_jmp,jmp_place);
exec_code[label_exit].num=exec_code.size(); exec_code[label_exit].num=exec_code.size();
@ -816,14 +800,14 @@ void nasal_codegen::forindex_gen(nasal_ast& ast)
{ {
mcall(ast.get_children()[0]); mcall(ast.get_children()[0]);
gen(op_meq,0); gen(op_meq,0);
pop_gen(); gen(op_pop,0);
} }
block_gen(ast.get_children()[2]); block_gen(ast.get_children()[2]);
gen(op_jmp,ptr); gen(op_jmp,ptr);
exec_code[ptr].num=exec_code.size(); exec_code[ptr].num=exec_code.size();
load_continue_break(exec_code.size()-1,exec_code.size()); load_continue_break(exec_code.size()-1,exec_code.size());
pop_gen();// pop vector gen(op_pop,0);// pop vector
gen(op_cntpop,0); gen(op_cntpop,0);
return; return;
} }
@ -846,14 +830,14 @@ void nasal_codegen::foreach_gen(nasal_ast& ast)
{ {
mcall(ast.get_children()[0]); mcall(ast.get_children()[0]);
gen(op_meq,0); gen(op_meq,0);
pop_gen(); gen(op_pop,0);
} }
block_gen(ast.get_children()[2]); block_gen(ast.get_children()[2]);
gen(op_jmp,ptr); gen(op_jmp,ptr);
exec_code[ptr].num=exec_code.size(); exec_code[ptr].num=exec_code.size();
load_continue_break(exec_code.size()-1,exec_code.size()); load_continue_break(exec_code.size()-1,exec_code.size());
pop_gen();// pop vector gen(op_pop,0);// pop vector
gen(op_cntpop,0); gen(op_cntpop,0);
return; return;
} }
@ -864,13 +848,13 @@ void nasal_codegen::or_gen(nasal_ast& ast)
int l1=exec_code.size(); int l1=exec_code.size();
gen(op_jt,0); gen(op_jt,0);
pop_gen(); gen(op_pop,0);
calc_gen(ast.get_children()[1]); calc_gen(ast.get_children()[1]);
int l2=exec_code.size(); int l2=exec_code.size();
gen(op_jt,0); gen(op_jt,0);
pop_gen(); gen(op_pop,0);
nil_gen(); gen(op_pnil,0);
exec_code[l1].num=exec_code[l2].num=exec_code.size(); exec_code[l1].num=exec_code[l2].num=exec_code.size();
return; return;
@ -883,14 +867,14 @@ void nasal_codegen::and_gen(nasal_ast& ast)
int lfalse=exec_code.size(); int lfalse=exec_code.size();
gen(op_jmp,0); gen(op_jmp,0);
pop_gen();// jt jumps here gen(op_pop,0);// jt jumps here
calc_gen(ast.get_children()[1]); calc_gen(ast.get_children()[1]);
gen(op_jt,exec_code.size()+3); gen(op_jt,exec_code.size()+3);
exec_code[lfalse].num=exec_code.size(); exec_code[lfalse].num=exec_code.size();
pop_gen(); gen(op_pop,0);
nil_gen(); gen(op_pnil,0);
//jt jumps here //jt jumps here
return; return;
} }
@ -913,7 +897,7 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
{ {
switch(ast.get_type()) switch(ast.get_type())
{ {
case ast_nil: nil_gen(); break; case ast_nil: gen(op_pnil,0); break;
case ast_num: num_gen(ast); break; case ast_num: num_gen(ast); break;
case ast_str: str_gen(ast); break; case ast_str: str_gen(ast); break;
case ast_id: call_id(ast); break; case ast_id: call_id(ast); break;
@ -1009,7 +993,7 @@ void nasal_codegen::block_gen(nasal_ast& ast)
case ast_grt: case ast_grt:
case ast_or: case ast_or:
case ast_and: case ast_and:
case ast_trino:calc_gen(tmp);pop_gen();break; case ast_trino:calc_gen(tmp);gen(op_pop,0);break;
case ast_ret:ret_gen(tmp);break; case ast_ret:ret_gen(tmp);break;
} }
return; return;
@ -1030,7 +1014,7 @@ void nasal_codegen::ret_gen(nasal_ast& ast)
if(ast.get_children().size()) if(ast.get_children().size())
calc_gen(ast.get_children()[0]); calc_gen(ast.get_children()[0]);
else else
nil_gen(); gen(op_pnil,0);
gen(op_ret,0); gen(op_ret,0);
return; return;
} }
@ -1082,7 +1066,7 @@ void nasal_codegen::main_progress(nasal_ast& ast)
case ast_grt: case ast_grt:
case ast_or: case ast_or:
case ast_and: case ast_and:
case ast_trino:calc_gen(tmp);pop_gen();break; case ast_trino:calc_gen(tmp);gen(op_pop,0);break;
} }
} }
gen(op_nop,0); gen(op_nop,0);

View File

@ -271,10 +271,8 @@ void nasal_parse::check_memory_reachable(nasal_ast& node)
{ {
if(node.get_children()[0].get_type()!=ast_id) if(node.get_children()[0].get_type()!=ast_id)
die(node.get_line(),"cannot get the memory of a temporary data"); die(node.get_line(),"cannot get the memory of a temporary data");
int size=node.get_children().size(); for(auto& tmp:node.get_children())
for(int i=0;i<size;++i)
{ {
nasal_ast& tmp=node.get_children()[i];
if(tmp.get_type()==ast_callf) if(tmp.get_type()==ast_callf)
die(tmp.get_line(),"cannot get the memory of function-returned value"); die(tmp.get_line(),"cannot get the memory of function-returned value");
if(tmp.get_type()==ast_callv && (tmp.get_children().size()>1 || tmp.get_children()[0].get_type()==ast_subvec)) if(tmp.get_type()==ast_callv && (tmp.get_children().size()>1 || tmp.get_children()[0].get_type()==ast_subvec))
@ -419,41 +417,40 @@ nasal_ast nasal_parse::args_gen()
match(tok_rcurve,"expected \')\' after parameter list"); match(tok_rcurve,"expected \')\' after parameter list");
std::string args_format="func("; std::string args_format="func(";
int node_child_size=node.get_children().size(); for(auto& tmp:node.get_children())
for(int i=0;i<node_child_size;++i)
{ {
switch(node.get_children()[i].get_type()) switch(tmp.get_type())
{ {
case ast_id: args_format+="val";break; case ast_id: args_format+="val";break;
case ast_default_arg: args_format+="val=scalar";break; case ast_default_arg: args_format+="val=scalar";break;
case ast_dynamic_id: args_format+="val...";break; case ast_dynamic_id: args_format+="val...";break;
} }
args_format+=",)"[i==node_child_size-1]; args_format+=",)"[&tmp==&node.get_children().back()];
} }
bool checked_default_val=false,checked_dynamic_ids=false; bool checked_default_val=false,checked_dynamic_ids=false;
for(int i=0;i<node_child_size;++i) for(auto& tmp:node.get_children())
{ {
if(node.get_children()[i].get_type()==ast_default_arg) if(tmp.get_type()==ast_default_arg)
checked_default_val=true; checked_default_val=true;
else if(node.get_children()[i].get_type()==ast_dynamic_id) else if(tmp.get_type()==ast_dynamic_id)
checked_dynamic_ids=true; checked_dynamic_ids=true;
if(checked_default_val && node.get_children()[i].get_type()!=ast_default_arg) if(checked_default_val && tmp.get_type()!=ast_default_arg)
die(node.get_children()[i].get_line(),"must use default arguments until the end of argument list: "+args_format); die(tmp.get_line(),"must use default parameters after using it once: "+args_format);
if(checked_dynamic_ids && i!=node_child_size-1) if(checked_dynamic_ids && &tmp!=&node.get_children().back())
die(node.get_children()[i].get_line(),"dynamic identifier must be the end of argument list: "+args_format); die(tmp.get_line(),"dynamic parameter must be the end: "+args_format);
} }
std::unordered_map<std::string,bool> argname_table; std::unordered_map<std::string,bool> argname_table;
for(int i=0;i<node_child_size;++i) for(auto& tmp:node.get_children())
{ {
std::string new_name; std::string new_name;
switch(node.get_children()[i].get_type()) switch(tmp.get_type())
{ {
case ast_dynamic_id: case ast_dynamic_id:
case ast_id:new_name=node.get_children()[i].get_str();break; case ast_id:new_name=tmp.get_str();break;
case ast_default_arg:new_name=node.get_children()[i].get_children()[0].get_str();break; case ast_default_arg:tmp.get_children()[0].get_str();break;
} }
if(argname_table.find(new_name)!=argname_table.end()) if(argname_table.count(new_name))
die(node.get_children()[i].get_line(),"argument name should not repeat"); die(tmp.get_line(),"parameter's name repeats: "+new_name);
else else
argname_table[new_name]=true; argname_table[new_name]=true;
} }
@ -464,9 +461,9 @@ nasal_ast nasal_parse::expr()
nasal_ast node(tok_list[ptr].line,ast_null); nasal_ast node(tok_list[ptr].line,ast_null);
int tok_type=tok_list[ptr].type; int tok_type=tok_list[ptr].type;
if((tok_type==tok_break || tok_type==tok_continue) && !in_loop) if((tok_type==tok_break || tok_type==tok_continue) && !in_loop)
die(error_line,"cannot use break/continue outside loop"); die(error_line,"use break/continue in the loop");
if(tok_type==tok_ret && !in_function) if(tok_type==tok_ret && !in_function)
die(error_line,"cannot use return outside function"); die(error_line,"use return in the function");
switch(tok_type) switch(tok_type)
{ {
case tok_nil: case tok_nil: