optimize codes

This commit is contained in:
ValKmjolnir 2022-01-16 22:48:00 +08:00
parent 46716620e3
commit 630c99c39a
10 changed files with 128 additions and 168 deletions

View File

@ -4,63 +4,63 @@
enum ast_node
{
ast_null=0,
ast_root, // mark the root node of ast
ast_block, // expression block
ast_file, // used to store which file the sub-tree is on
ast_nil, // nil keyword
ast_num, // number, basic value type
ast_str, // string, basic value type
ast_id, // identifier
ast_func, // func keyword
ast_hash, // hash, basic value type
ast_vec, // vector, basic value type
ast_hashmember,// elements in hashmap
ast_call, // mark a sub-tree of calling an identifier
ast_callh, // id.name
ast_callv, // id[index]
ast_callf, // id()
ast_subvec, // id[index:index]
ast_args, // mark a sub-tree of function parameters
ast_default, // default parameter
ast_dynamic, // dynamic parameter
ast_and, // and keyword
ast_or, // or keyword
ast_equal, // =
ast_addeq, // +=
ast_subeq, // -=
ast_multeq, // *=
ast_diveq, // /=
ast_lnkeq, // ~=
ast_cmpeq, // ==
ast_neq, // !=
ast_less, // <
ast_leq, // <=
ast_grt, // >
ast_geq, // >=
ast_add, // +
ast_sub, // -
ast_mult, // *
ast_div, // /
ast_link, // ~
ast_neg, // -
ast_not, // ~
ast_trino, // ?:
ast_for, // for keyword
ast_forindex,// forindex keyword
ast_foreach, // foreach keyword
ast_while, // while
ast_new_iter,// iterator, used in forindex/foreach
ast_conditional,// mark a sub-tree of conditional expression
ast_if, // if keyword
ast_elsif, // elsif keyword
ast_else, // else keyword
ast_multi_id,// multi identifiers sub-tree
ast_root, // mark the root node of ast
ast_block, // expression block
ast_file, // used to store which file the sub-tree is on, only used in main block
ast_nil, // nil keyword
ast_num, // number, basic value type
ast_str, // string, basic value type
ast_id, // identifier
ast_func, // func keyword
ast_hash, // hash, basic value type
ast_vec, // vector, basic value type
ast_hashmember, // elements in hashmap
ast_call, // mark a sub-tree of calling an identifier
ast_callh, // id.name
ast_callv, // id[index]
ast_callf, // id()
ast_subvec, // id[index:index]
ast_args, // mark a sub-tree of function parameters
ast_default, // default parameter
ast_dynamic, // dynamic parameter
ast_and, // and keyword
ast_or, // or keyword
ast_equal, // =
ast_addeq, // +=
ast_subeq, // -=
ast_multeq, // *=
ast_diveq, // /=
ast_lnkeq, // ~=
ast_cmpeq, // ==
ast_neq, // !=
ast_less, // <
ast_leq, // <=
ast_grt, // >
ast_geq, // >=
ast_add, // +
ast_sub, // -
ast_mult, // *
ast_div, // /
ast_link, // ~
ast_neg, // -
ast_not, // ~
ast_trino, // ?:
ast_for, // for keyword
ast_forindex, // forindex keyword
ast_foreach, // foreach keyword
ast_while, // while
ast_new_iter, // iterator, used in forindex/foreach
ast_conditional, // mark a sub-tree of conditional expression
ast_if, // if keyword
ast_elsif, // elsif keyword
ast_else, // else keyword
ast_multi_id, // multi identifiers sub-tree
ast_multi_scalar,// multi value sub-tree
ast_def, // definition
ast_def, // definition
ast_multi_assign,// multi assignment sub-tree
ast_continue,// continue keyword
ast_break, // break keyword
ast_ret // return keyword
ast_continue, // continue keyword, only used in loop
ast_break, // break keyword, only used in loop
ast_ret // return keyword, only used in function block
};
const char* ast_name[]=
@ -228,10 +228,18 @@ void nasal_ast::print(int depth,bool last=false)
if(last && depth)
intentation.back()=" ";
else if(!last && depth)
#ifdef _WIN32
intentation.back()="| ";
#else
intentation.back()="";
#endif
for(uint32_t i=0;i<_child.size();++i)
{
#ifdef _WIN32
intentation.push_back(i==_child.size()-1?"`-":"|-");
#else
intentation.push_back(i==_child.size()-1?"└─":"├─");
#endif
_child[i].print(depth+1,i==_child.size()-1);
intentation.pop_back();
}

View File

@ -87,7 +87,7 @@ nas_native(builtin_platform);
nasal_ref builtin_err(const char* func_name,std::string info)
{
std::cout<<"[vm] "<<func_name<<": "<<info<<".\n";
std::cerr<<"[vm] "<<func_name<<": "<<info<<".\n";
return {vm_none,nullptr};
}
@ -574,7 +574,7 @@ nasal_ref builtin_die(std::vector<nasal_ref>& local,nasal_gc& gc)
nasal_ref str=local[1];
if(str.type!=vm_str)
return builtin_err("die","\"str\" must be string");
std::cout<<"[vm] error: "<<*str.str()<<'\n';
std::cerr<<"[vm] error: "<<*str.str()<<'\n';
return nasal_ref(vm_none);
}
nasal_ref builtin_type(std::vector<nasal_ref>& local,nasal_gc& gc)

View File

@ -205,7 +205,7 @@ private:
std::vector<std::string> global; // global : max 4095 values
std::list<std::vector<std::string>> local; // local : max 32768 upvalues 65536 values
void die(const std::string&,const uint32_t);
void die(std::string,const uint32_t);
void regist_number(const double);
void regist_string(const std::string&);
void find_symbol(const nasal_ast&);
@ -255,10 +255,10 @@ public:
const std::vector<opcode>& get_code() const {return code;}
};
void nasal_codegen::die(const std::string& info,const uint32_t line)
void nasal_codegen::die(std::string info,const uint32_t line)
{
nerr.load(file[fileindex]);
nerr.err("code",line,info.c_str());
nerr.err("code",line,info);
}
void nasal_codegen::regist_number(const double num)
@ -455,8 +455,6 @@ void nasal_codegen::func_gen(const nasal_ast& ast)
void nasal_codegen::call_gen(const nasal_ast& ast)
{
calc_gen(ast[0]);
if(code.empty())
std::cout<<"warning\n";
if(code.back().op==op_callb)
return;
int child_size=ast.size();
@ -1068,6 +1066,7 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
switch(tmp.type())
{
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_file:fileindex=tmp.num();break; // special node type in main block
case ast_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break;
case ast_conditional:conditional_gen(tmp);break;
@ -1151,68 +1150,9 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import)
file=import.get_file().data();
in_iterloop.push(0);
// search symbols first
find_symbol(parse.ast());
find_symbol(parse.ast()); // search symbols first
gen(op_intg,global.size(),0);
for(auto& tmp:parse.ast().child())
{
switch(tmp.type())
{
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break;
case ast_file:fileindex=tmp.num();break;
case ast_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break;
case ast_conditional:conditional_gen(tmp);break;
case ast_while:
case ast_for:
case ast_forindex:
case ast_foreach:loop_gen(tmp);break;
case ast_equal:
if(tmp[0].type()==ast_id)
{
calc_gen(tmp[1]);
mcall_id(tmp[0]);
// only the first mcall_id can use load
if(code.back().op==op_mcalll)
code.back().op=op_loadl;
else if(code.back().op==op_mupval)
code.back().op=op_loadu;
else
code.back().op=op_loadg;
}
else
{
calc_gen(tmp);
gen(op_pop,0,tmp.line());
}
break;
case ast_id:
case ast_vec:
case ast_hash:
case ast_call:
case ast_addeq:
case ast_subeq:
case ast_multeq:
case ast_diveq:
case ast_lnkeq:
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_or:
case ast_and:
case ast_trino:calc_gen(tmp);gen(op_pop,0,tmp.line());break;
}
}
block_gen(parse.ast()); // generate main block
gen(op_exit,0,0);
if(global.size()>=STACK_MAX_DEPTH)
die("too many global variants: "+std::to_string(global.size())+".",0);

View File

@ -56,7 +56,7 @@ uint16_t nasal_dbg::get_fileindex(const std::string& filename)
void nasal_dbg::err()
{
std::cout
std::cerr
<<"incorrect command\n"
<<"input \'h\' to get help\n";
}

View File

@ -13,7 +13,7 @@ protected:
public:
void load(const std::string& f)
{
if(file==f)
if(file==f) // don't need to load a loaded file
return;
file=f;
res.clear();
@ -48,33 +48,32 @@ public:
void err(const char* stage,const std::string& info)
{
++error;
std::cout<<"["<<stage<<"] "<<info<<'\n';
std::cerr<<"["<<stage<<"] "<<info<<'\n';
}
void err(const char* stage,uint32_t line,uint32_t column,const std::string& info)
{
++error;
if(!line)
{
std::cout<<"["<<stage<<"] "<<file<<": "<<info<<'\n';
std::cerr<<"["<<stage<<"] "<<file<<": "<<info<<'\n';
return;
}
std::cout<<"["<<stage<<"] "<<file<<":"<<line<<":"<<column<<" "<<info<<"\n"<<res[line-1]<<'\n';
std::cerr<<"["<<stage<<"] "<<file<<":"<<line<<":"<<column<<" "<<info<<"\n"<<res[line-1]<<'\n';
for(int i=0;i<(int)column-1;++i)
std::cout<<char(" \t"[res[line-1][i]=='\t']);
std::cout<<"^\n";
std::cerr<<char(" \t"[res[line-1][i]=='\t']);
std::cerr<<"^\n";
}
void err(const char* stage,uint32_t line,const std::string& info)
{
++error;
if(!line)
{
std::cout<<"["<<stage<<"] "<<file<<": "<<info<<'\n';
std::cerr<<"["<<stage<<"] "<<file<<": "<<info<<'\n';
return;
}
std::cout<<"["<<stage<<"] "<<file<<":"<<line<<" "<<info<<"\n"<<res[line-1]<<'\n';
std::cerr<<"["<<stage<<"] "<<file<<":"<<line<<" "<<info<<"\n"<<res[line-1]<<'\n';
}
void chkerr(){if(error)std::exit(1);}
};
#endif

View File

@ -295,12 +295,9 @@ nasal_val::~nasal_val()
}
type=vm_nil;
}
double nasal_ref::to_number()
{
if(type==vm_str)
return str2num(str()->c_str());
return value.num;
return type!=vm_str?value.num:str2num(str()->c_str());
}
std::string nasal_ref::to_string()
{

View File

@ -113,7 +113,7 @@ private:
std::vector<token> tokens;
uint32_t get_type(const std::string&);
void die(const char* info){nerr.err("lexer",line,column,info);};
void die(std::string info){nerr.err("lexer",line,column,info);};
void open(const std::string&);
std::string id_gen();
std::string num_gen();
@ -165,7 +165,7 @@ std::string nasal_lexer::num_gen()
str+=res[ptr++];
column+=str.length();
if(str.length()<3)// "0x"
die("invalid number.");
die("invalid number:"+str);
return str;
}
// generate oct number
@ -177,7 +177,7 @@ std::string nasal_lexer::num_gen()
str+=res[ptr++];
column+=str.length();
if(str.length()<3)// "0o"
die("invalid number.");
die("invalid number:"+str);
return str;
}
// generate dec number
@ -194,7 +194,7 @@ std::string nasal_lexer::num_gen()
if(str.back()=='.')
{
column+=str.length();
die("invalid number.");
die("invalid number:"+str);
return "0";
}
}
@ -209,7 +209,7 @@ std::string nasal_lexer::num_gen()
if(str.back()=='e' || str.back()=='E' || str.back()=='-' || str.back()=='+')
{
column+=str.length();
die("invalid number.");
die("invalid number:"+str);
return "0";
}
}
@ -309,7 +309,7 @@ void nasal_lexer::scan(const std::string& file)
++column;
uint32_t type=get_type(str);
if(!type)
die("invalid operator.");
die("invalid operator:"+str);
tokens.push_back({line,column,type,str});
++ptr;
}

View File

@ -48,7 +48,7 @@ private:
nasal_ast root;
nasal_err& nerr;
void die(uint32_t,const std::string&);
void die(uint32_t,std::string);
void match(uint32_t type,const char* info=nullptr);
bool check_comma(const uint32_t*);
bool check_multi_scalar();
@ -121,7 +121,7 @@ void nasal_parse::compile(const nasal_lexer& lexer)
}
nerr.chkerr();
}
void nasal_parse::die(uint32_t line,const std::string& info)
void nasal_parse::die(uint32_t line,std::string info)
{
int col=(int)tokens[ptr].column-(int)tokens[ptr].str.length();
if(tokens[ptr].type==tok_str)
@ -434,9 +434,9 @@ nasal_ast nasal_parse::expr()
{
uint32_t tok_type=tokens[ptr].type;
if((tok_type==tok_break || tok_type==tok_continue) && !in_loop)
die(error_line,"use break/continue in the loop");
die(error_line,"should use break/continue in loops");
if(tok_type==tok_ret && !in_func)
die(error_line,"use return in the function");
die(error_line,"should use return in functions");
switch(tok_type)
{
case tok_nil:

View File

@ -1,29 +1,45 @@
import("lib.nas");
var filename=["main.cpp","nasal_err.h","nasal_ast.h","nasal_builtin.h","nasal_codegen.h","nasal_gc.h","nasal_import.h","nasal_lexer.h","nasal_parse.h","nasal_vm.h","nasal_dbg.h","nasal.h"];
var space=[" "," "," ","",""," "," "," "," "," "," "," "];
var enter_cnt=func(s)
{
var (cnt,len,enter)=(0,size(s),'\n'[0]);
var filename=[
"main.cpp",
"nasal_err.h",
"nasal_ast.h",
"nasal_builtin.h",
"nasal_codegen.h",
"nasal_gc.h",
"nasal_import.h",
"nasal_lexer.h",
"nasal_parse.h",
"nasal_vm.h",
"nasal_dbg.h",
"nasal.h"
];
var space=[
" ",
" ",
" ",
"",
"",
" ",
" ",
" ",
" ",
" ",
" ",
" "
];
var count=func(s,c){
var (cnt,len,ch)=(0,size(s),c[0]);
for(var i=0;i<len;i+=1)
cnt+=(s[i]==enter);
return cnt;
}
var semic_cnt=func(s)
{
var (cnt,len,semi)=(0,size(s),';'[0]);
for(var i=0;i<len;i+=1)
cnt+=(s[i]==semi);
cnt+=(s[i]==ch);
return cnt;
}
func(){
var (bytes,line,semi)=(0,0,0);
forindex(var i;filename)
{
forindex(var i;filename){
var s=io.fin(filename[i]);
bytes+=size(s);
var line_cnt=enter_cnt(s);
var semi_cnt=semic_cnt(s);
var (line_cnt,semi_cnt)=(count(s,'\n'),count(s,';'));
println(filename[i],space[i],'| ',line_cnt,' \tline | ',semi_cnt,' \tsemi');
bytes+=size(s);
line+=line_cnt;
semi+=semi_cnt;
}

View File

@ -5,7 +5,7 @@ var table=[
['q1','1','1','R','q1'],
['q1','0','0','S','q2'],
['q2','0','1','R','q3'],
['q3',' ',' ','S','q3']
['q3',nil,nil,'S','q3']
];
var prt=func(state,pointer,paper,act=nil){
print(state,':',pointer,':',act!=nil?act:'','\n\t');
@ -19,7 +19,7 @@ var prt=func(state,pointer,paper,act=nil){
print(s,'^\n');
}
var run=func(table,node,start,stop){
var paper=['0','1','0','1','0','a'];
var paper=['0','1','1','1','0','1','0','a'];
var pointer=0;
foreach(var action;table){
if(!contains(node,action[0]))
@ -37,7 +37,7 @@ var run=func(table,node,start,stop){
while(state!=stop){
foreach(var action;table)
if(action[0]==state and (action[1]==paper[pointer] or action[1]==' ')){
paper[pointer]=action[2]==' '?paper[pointer]:action[2];
paper[pointer]=action[2]==nil?paper[pointer]:action[2];
if(action[3]=='L') pointer-=1;
elsif(action[3]=='R') pointer+=1;
elsif(action[3]!='S') die("invalid action <"~action[3]~'>');