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
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
LL(k) parser.

View File

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

View File

@ -181,8 +181,6 @@ private:
int local_find(std::string&);
int global_find(std::string&);
void gen(unsigned char,unsigned int);
void pop_gen();
void nil_gen();
void num_gen(nasal_ast&);
void str_gen(nasal_ast&);
void vec_gen(nasal_ast&);
@ -304,20 +302,6 @@ void nasal_codegen::gen(unsigned char op,unsigned int index)
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)
{
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)
{
nil_gen();
gen(op_pnil,0);
gen(op_ret,0);
}
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)
{
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)
{
auto& vals=ast.get_children()[1].get_children();
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);
calc_gen(ast.get_children()[1].get_children()[i]);
if(local.empty())
gen(op_loadg,global_find(str));
else
@ -611,14 +597,14 @@ void nasal_codegen::multi_def(nasal_ast& ast)
for(int i=0;i<size;++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);
if(local.empty())
gen(op_loadg,global_find(str));
else
gen(op_loadl,local_find(str));
}
pop_gen();
gen(op_pop,0);
}
return;
}
@ -643,7 +629,7 @@ void nasal_codegen::multi_assign_gen(nasal_ast& ast)
{
mcall(ast.get_children()[0].get_children()[i]);
gen(op_meq,0);
pop_gen();
gen(op_pop,0);
}
}
else
@ -654,20 +640,18 @@ void nasal_codegen::multi_assign_gen(nasal_ast& ast)
gen(op_callvi,i);
mcall(ast.get_children()[0].get_children()[i]);
gen(op_meq,0);
pop_gen();
gen(op_pop,0);
}
pop_gen();
gen(op_pop,0);
}
return;
}
void nasal_codegen::conditional_gen(nasal_ast& ast)
{
int size=ast.get_children().size();
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)
{
calc_gen(tmp.get_children()[0]);
@ -676,7 +660,7 @@ void nasal_codegen::conditional_gen(nasal_ast& ast)
block_gen(tmp.get_children()[1]);
jmp_label.push_back(exec_code.size());
// without 'else' the last condition doesn't need to jmp
if(i!=size-1)
if(&tmp!=&ast.get_children().back())
gen(op_jmp,0);
exec_code[ptr].num=exec_code.size();
}
@ -686,8 +670,8 @@ void nasal_codegen::conditional_gen(nasal_ast& ast)
break;
}
}
for(std::vector<int>::iterator i=jmp_label.begin();i!=jmp_label.end();++i)
exec_code[*i].num=exec_code.size();
for(auto i:jmp_label)
exec_code[i].num=exec_code.size();
return;
}
@ -765,7 +749,7 @@ void nasal_codegen::for_gen(nasal_ast& ast)
case ast_less:
case ast_geq:
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();
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_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_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);
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]);
gen(op_meq,0);
pop_gen();
gen(op_pop,0);
}
block_gen(ast.get_children()[2]);
gen(op_jmp,ptr);
exec_code[ptr].num=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);
return;
}
@ -846,14 +830,14 @@ void nasal_codegen::foreach_gen(nasal_ast& ast)
{
mcall(ast.get_children()[0]);
gen(op_meq,0);
pop_gen();
gen(op_pop,0);
}
block_gen(ast.get_children()[2]);
gen(op_jmp,ptr);
exec_code[ptr].num=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);
return;
}
@ -864,13 +848,13 @@ void nasal_codegen::or_gen(nasal_ast& ast)
int l1=exec_code.size();
gen(op_jt,0);
pop_gen();
gen(op_pop,0);
calc_gen(ast.get_children()[1]);
int l2=exec_code.size();
gen(op_jt,0);
pop_gen();
nil_gen();
gen(op_pop,0);
gen(op_pnil,0);
exec_code[l1].num=exec_code[l2].num=exec_code.size();
return;
@ -883,14 +867,14 @@ void nasal_codegen::and_gen(nasal_ast& ast)
int lfalse=exec_code.size();
gen(op_jmp,0);
pop_gen();// jt jumps here
gen(op_pop,0);// jt jumps here
calc_gen(ast.get_children()[1]);
gen(op_jt,exec_code.size()+3);
exec_code[lfalse].num=exec_code.size();
pop_gen();
nil_gen();
gen(op_pop,0);
gen(op_pnil,0);
//jt jumps here
return;
}
@ -913,14 +897,14 @@ void nasal_codegen::calc_gen(nasal_ast& ast)
{
switch(ast.get_type())
{
case ast_nil: nil_gen(); break;
case ast_num: num_gen(ast); break;
case ast_str: str_gen(ast); break;
case ast_id: call_id(ast); break;
case ast_vec: vec_gen(ast); break;
case ast_hash: hash_gen(ast);break;
case ast_func: func_gen(ast);break;
case ast_call: call_gen(ast);break;
case ast_nil: gen(op_pnil,0); break;
case ast_num: num_gen(ast); break;
case ast_str: str_gen(ast); break;
case ast_id: call_id(ast); break;
case ast_vec: vec_gen(ast); break;
case ast_hash: hash_gen(ast); break;
case ast_func: func_gen(ast); break;
case ast_call: call_gen(ast); break;
case ast_equal:
calc_gen(ast.get_children()[1]);
mcall(ast.get_children()[0]);
@ -1009,7 +993,7 @@ void nasal_codegen::block_gen(nasal_ast& ast)
case ast_grt:
case ast_or:
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;
}
return;
@ -1030,7 +1014,7 @@ void nasal_codegen::ret_gen(nasal_ast& ast)
if(ast.get_children().size())
calc_gen(ast.get_children()[0]);
else
nil_gen();
gen(op_pnil,0);
gen(op_ret,0);
return;
}
@ -1082,7 +1066,7 @@ void nasal_codegen::main_progress(nasal_ast& ast)
case ast_grt:
case ast_or:
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);

View File

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