optimize codes
This commit is contained in:
parent
46716620e3
commit
630c99c39a
118
nasal_ast.h
118
nasal_ast.h
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
17
nasal_err.h
17
nasal_err.h
|
@ -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
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]~'>');
|
||||
|
|
Loading…
Reference in New Issue