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

View File

@ -87,7 +87,7 @@ nas_native(builtin_platform);
nasal_ref builtin_err(const char* func_name,std::string info) 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}; 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]; nasal_ref str=local[1];
if(str.type!=vm_str) if(str.type!=vm_str)
return builtin_err("die","\"str\" must be string"); 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); return nasal_ref(vm_none);
} }
nasal_ref builtin_type(std::vector<nasal_ref>& local,nasal_gc& gc) 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::vector<std::string> global; // global : max 4095 values
std::list<std::vector<std::string>> local; // local : max 32768 upvalues 65536 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_number(const double);
void regist_string(const std::string&); void regist_string(const std::string&);
void find_symbol(const nasal_ast&); void find_symbol(const nasal_ast&);
@ -255,10 +255,10 @@ public:
const std::vector<opcode>& get_code() const {return code;} 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.load(file[fileindex]);
nerr.err("code",line,info.c_str()); nerr.err("code",line,info);
} }
void nasal_codegen::regist_number(const double num) 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) void nasal_codegen::call_gen(const nasal_ast& ast)
{ {
calc_gen(ast[0]); calc_gen(ast[0]);
if(code.empty())
std::cout<<"warning\n";
if(code.back().op==op_callb) if(code.back().op==op_callb)
return; return;
int child_size=ast.size(); int child_size=ast.size();
@ -1068,6 +1066,7 @@ void nasal_codegen::block_gen(const nasal_ast& ast)
switch(tmp.type()) switch(tmp.type())
{ {
case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break; 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_def:def_gen(tmp);break;
case ast_multi_assign:multi_assign_gen(tmp);break; case ast_multi_assign:multi_assign_gen(tmp);break;
case ast_conditional:conditional_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(); file=import.get_file().data();
in_iterloop.push(0); in_iterloop.push(0);
// search symbols first find_symbol(parse.ast()); // search symbols first
find_symbol(parse.ast());
gen(op_intg,global.size(),0); gen(op_intg,global.size(),0);
for(auto& tmp:parse.ast().child()) block_gen(parse.ast()); // generate main block
{
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;
}
}
gen(op_exit,0,0); gen(op_exit,0,0);
if(global.size()>=STACK_MAX_DEPTH) if(global.size()>=STACK_MAX_DEPTH)
die("too many global variants: "+std::to_string(global.size())+".",0); 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() void nasal_dbg::err()
{ {
std::cout std::cerr
<<"incorrect command\n" <<"incorrect command\n"
<<"input \'h\' to get help\n"; <<"input \'h\' to get help\n";
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -1,29 +1,45 @@
import("lib.nas"); 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 filename=[
var space=[" "," "," ","",""," "," "," "," "," "," "," "]; "main.cpp",
var enter_cnt=func(s) "nasal_err.h",
{ "nasal_ast.h",
var (cnt,len,enter)=(0,size(s),'\n'[0]); "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) for(var i=0;i<len;i+=1)
cnt+=(s[i]==enter); cnt+=(s[i]==ch);
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);
return cnt; return cnt;
} }
func(){ func(){
var (bytes,line,semi)=(0,0,0); var (bytes,line,semi)=(0,0,0);
forindex(var i;filename) forindex(var i;filename){
{
var s=io.fin(filename[i]); var s=io.fin(filename[i]);
bytes+=size(s); var (line_cnt,semi_cnt)=(count(s,'\n'),count(s,';'));
var line_cnt=enter_cnt(s);
var semi_cnt=semic_cnt(s);
println(filename[i],space[i],'| ',line_cnt,' \tline | ',semi_cnt,' \tsemi'); println(filename[i],space[i],'| ',line_cnt,' \tline | ',semi_cnt,' \tsemi');
bytes+=size(s);
line+=line_cnt; line+=line_cnt;
semi+=semi_cnt; semi+=semi_cnt;
} }

View File

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