From 540aeb73f48d5688a153cd28c5dcbeebae560f15 Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Wed, 20 Oct 2021 20:54:23 +0800 Subject: [PATCH] optimize nasal_ast and fix bug in opr_slc2 --- makefile | 25 ++- nasal_ast.h | 51 +++-- nasal_builtin.h | 4 +- nasal_codegen.h | 575 +++++++++++++++++++++++------------------------- nasal_gc.h | 8 +- nasal_import.h | 11 +- nasal_parse.h | 125 ++++++----- nasal_vm.h | 23 +- 8 files changed, 418 insertions(+), 404 deletions(-) diff --git a/makefile b/makefile index 50e26e6..cdfa961 100644 --- a/makefile +++ b/makefile @@ -1,14 +1,31 @@ .PHONY=test nasal:main.cpp 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.h - clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions + clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -Wshadow test:nasal ./nasal test/ascii-art.nas - ./nasal test/bp.nas + ./nasal -c test/bf.nas + ./nasal -c test/bfconvertor.nas + ./nasal test/bfs.nas ./nasal -t test/bigloop.nas - ./nasal -t test/fib.nas + ./nasal test/bp.nas + ./nasal test/calc.nas + ./nasal test/choice.nas ./nasal test/class.nas + # ./nasal test/exception.nas + ./nasal -t test/fib.nas + ./nasal test/hexdump.nas + ./nasal test/json.nas + ./nasal test/leetcode1319.nas ./nasal test/lexer.nas + ./nasal -c test/life.nas + ./nasal -t test/loop.nas + ./nasal -c test/mandel.nas ./nasal -t test/mandelbrot.nas + ./nasal test/nasal_test.nas ./nasal -t test/pi.nas + ./nasal -t test/prime.nas + ./nasal -t test/quick_sort.nas + ./nasal test/scalar.nas + ./nasal test/trait.nas ./nasal -t test/ycombinator.nas - ./nasal test/exception.nas \ No newline at end of file + \ No newline at end of file diff --git a/nasal_ast.h b/nasal_ast.h index d7c2041..1a29727 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -4,17 +4,25 @@ enum ast_node { ast_null=0, - ast_root,ast_block, + ast_root, + ast_block, ast_file, // ast_file is only used to store which file the subtree is on,codegen will generate nothing ast_nil,ast_num,ast_str,ast_id,ast_func,ast_hash,ast_vec, - ast_hashmember,ast_call,ast_callh,ast_callv,ast_callf,ast_subvec, - ast_args,ast_default_arg,ast_dynamic_id, + ast_hashmember, + ast_call,ast_callh,ast_callv,ast_callf, + ast_subvec, + ast_args,ast_default,ast_dynamic, ast_and,ast_or, - ast_equal,ast_addeq,ast_subeq,ast_multeq,ast_diveq,ast_lnkeq, + 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_add,ast_sub, + ast_mult,ast_div, + ast_link, ast_neg,ast_not, ast_trino, ast_for,ast_forindex,ast_foreach,ast_while,ast_new_iter, @@ -27,17 +35,25 @@ enum ast_node const char* ast_name[]= { "null", - "root","block", + "root", + "block", "file", - "nil","node_num","node_str","id","func","hash","vec", - "hashmember","call","callh","callv","callf","subvec", - "args","deflt_arg","dyn_id", + "nil","num","str","id","func","hash","vec", + "hashmember", + "call","callh","callv","callf", + "subvec", + "args","default","dynamic", "and","or", - "=","+=","-=","*=","/=","~=", + "=", + "+=","-=", + "*=","/=", + "~=", "==","!=", "<","<=", ">",">=", - "+","-","*","/","~", + "+","-", + "*","/", + "~", "unary-","unary!", "trino", "for","forindex","foreach","while","iter", @@ -59,10 +75,15 @@ public: nasal_ast(const uint32_t l=0,const uint32_t t=ast_null):text_line(l),node_type(t){} nasal_ast(const nasal_ast&); nasal_ast(nasal_ast&&); - nasal_ast& operator=(const nasal_ast&); - nasal_ast& operator=(nasal_ast&&); void print(const int); void clear(); + + nasal_ast& operator=(const nasal_ast&); + nasal_ast& operator=(nasal_ast&&); + nasal_ast& operator[](const int index){return node_child[index];} + const nasal_ast& operator[](const int index) const {return node_child[index];} + size_t size() const {return node_child.size();} + void add(nasal_ast&& ast){node_child.push_back(std::move(ast));} void add(const nasal_ast& ast){node_child.push_back(ast);} void set_line(const uint32_t l){text_line=l;} @@ -133,8 +154,8 @@ void nasal_ast::print(const int depth) if( node_type==ast_str || node_type==ast_id || - node_type==ast_default_arg || - node_type==ast_dynamic_id || + node_type==ast_default || + node_type==ast_dynamic || node_type==ast_callh) std::cout<<":"<&,nasal_gc&); -} builtin_func[]= +} builtin[]= { {"__builtin_print", builtin_print }, {"__builtin_append", builtin_append }, diff --git a/nasal_codegen.h b/nasal_codegen.h index e947ec9..461681d 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -178,14 +178,8 @@ struct opcode uint16_t fidx;// source code file index uint32_t num; // imm num uint32_t line;// line of source code - opcode(uint8_t _op=op_nop,uint16_t _fidx=0,uint32_t _num=0,uint32_t _line=0) - { - op=_op; - fidx=_fidx; - num=_num; - line=_line; - return; - } + opcode(uint8_t o=op_nop,uint16_t f=0,uint32_t n=0,uint32_t l=0): + op(o),fidx(f),num(n),line(l){} opcode& operator=(const opcode& tmp) { op=tmp.op; @@ -205,10 +199,10 @@ private: uint32_t in_foreach; std::unordered_map num_table; std::unordered_map str_table; - std::vector num_res_table; - std::vector str_res_table; - std::vector file_name; - std::vector exec_code; + std::vector num_res; + std::vector str_res; + std::vector file; + std::vector code; std::list> continue_ptr; std::list> break_ptr; std::vector global; @@ -259,15 +253,15 @@ public: void compile(const nasal_parse&,const nasal_import&); void print_op(uint32_t); void print(); - const std::vector& get_strs() const {return str_res_table;} - const std::vector& get_nums() const {return num_res_table;} - const std::vector& get_code() const {return exec_code;} + const std::vector& get_strs() const {return str_res;} + const std::vector& get_nums() const {return num_res;} + const std::vector& get_code() const {return code;} }; void nasal_codegen::die(const std::string info,const int line) { ++error; - std::cout<<"[code] <"< line "< line "<65536) die("too many local variants: "+std::to_string(local.back().size())+".",block.line()); local.pop_back(); - if(!block.child().size() || block.child().back().type()!=ast_ret) + if(!block.size() || block.child().back().type()!=ast_ret) { gen(op_pnil,0,block.line()); gen(op_ret,0,block.line()); } - exec_code[jmp_ptr].num=exec_code.size(); + code[jmp_ptr].num=code.size(); return; } void nasal_codegen::call_gen(const nasal_ast& ast) { - calc_gen(ast.child()[0]); - if(exec_code.empty()) + calc_gen(ast[0]); + if(code.empty()) std::cout<<"warning\n"; - if(exec_code.back().op==op_callb) + if(code.back().op==op_callb) return; - int child_size=ast.child().size(); + int child_size=ast.size(); for(int i=1;i=0) + int index; + if((index=local_find(str))>=0) { gen(op_calll,index,ast.line()); return; } - index=upvalue_find(str); - if(index>=0) + if((index=upvalue_find(str))>=0) { gen(op_upval,index,ast.line()); return; } - index=global_find(str); - if(index>=0) + if((index=global_find(str))>=0) { gen(op_callg,index,ast.line()); return; @@ -549,19 +522,18 @@ void nasal_codegen::call_id(const nasal_ast& ast) void nasal_codegen::call_hash(const nasal_ast& ast) { - const std::string& str=ast.str(); - regist_string(str); - gen(op_callh,str_table[str],ast.line()); + regist_string(ast.str()); + gen(op_callh,str_table[ast.str()],ast.line()); return; } void nasal_codegen::call_vec(const nasal_ast& ast) { // maybe this place can use callv-const if ast's first child is ast_num - if(ast.child().size()==1 && ast.child()[0].type()!=ast_subvec) + if(ast.size()==1 && ast[0].type()!=ast_subvec) { - calc_gen(ast.child()[0]); - gen(op_callv,0,ast.child()[0].line()); + calc_gen(ast[0]); + gen(op_callv,0,ast[0].line()); return; } gen(op_slcbegin,0,ast.line()); @@ -574,8 +546,8 @@ void nasal_codegen::call_vec(const nasal_ast& ast) } else { - calc_gen(tmp.child()[0]); - calc_gen(tmp.child()[1]); + calc_gen(tmp[0]); + calc_gen(tmp[1]); gen(op_slc2,0,tmp.line()); } } @@ -585,9 +557,9 @@ void nasal_codegen::call_vec(const nasal_ast& ast) void nasal_codegen::call_func(const nasal_ast& ast) { - if(!ast.child().size()) + if(!ast.size()) gen(op_callfv,0,ast.line()); - else if(ast.child()[0].type()==ast_hashmember) + else if(ast[0].type()==ast_hashmember) { hash_gen(ast); gen(op_callfh,0,ast.line()); @@ -596,7 +568,7 @@ void nasal_codegen::call_func(const nasal_ast& ast) { for(auto& node:ast.child()) calc_gen(node); - gen(op_callfv,ast.child().size(),ast.line()); + gen(op_callfv,ast.size(),ast.line()); } return; } @@ -608,10 +580,10 @@ void nasal_codegen::mcall(const nasal_ast& ast) mcall_id(ast); return; } - calc_gen(ast.child()[0]); - for(int i=1;i=0) + int index; + if((index=local_find(str))>=0) { gen(op_mcalll,index,ast.line()); return; } - index=upvalue_find(str); - if(index>=0) + if((index=upvalue_find(str))>=0) { gen(op_mupval,index,ast.line()); return; } - index=global_find(str); - if(index>=0) + if((index=global_find(str))>=0) { gen(op_mcallg,index,ast.line()); return; @@ -660,23 +630,22 @@ void nasal_codegen::mcall_id(const nasal_ast& ast) void nasal_codegen::mcall_vec(const nasal_ast& ast) { - calc_gen(ast.child()[0]); + calc_gen(ast[0]); gen(op_mcallv,0,ast.line()); return; } void nasal_codegen::mcall_hash(const nasal_ast& ast) { - const std::string& str=ast.str(); - regist_string(str); - gen(op_mcallh,str_table[str],ast.line()); + regist_string(ast.str()); + gen(op_mcallh,str_table[ast.str()],ast.line()); return; } void nasal_codegen::single_def(const nasal_ast& ast) { - const std::string& str=ast.child()[0].str(); - calc_gen(ast.child()[1]); + const std::string& str=ast[0].str(); + calc_gen(ast[1]); local.empty()? gen(op_loadg,global_find(str),ast.line()): gen(op_loadl,local_find(str),ast.line()); @@ -684,11 +653,11 @@ void nasal_codegen::single_def(const nasal_ast& ast) } void nasal_codegen::multi_def(const nasal_ast& ast) { - auto& ids=ast.child()[0].child(); + auto& ids=ast[0].child(); int size=ids.size(); - if(ast.child()[1].type()==ast_multi_scalar) + if(ast[1].type()==ast_multi_scalar) { - auto& vals=ast.child()[1].child(); + auto& vals=ast[1].child(); for(int i=0;i=0;--i) - calc_gen(ast.child()[1].child()[i]); + calc_gen(ast[1][i]); for(int i=0;i()); switch(ast.type()) { - case ast_while: while_gen(ast); break; - case ast_for: for_gen(ast); break; + case ast_while: while_gen(ast); break; + case ast_for: for_gen(ast); break; case ast_forindex: ++in_forindex;forindex_gen(ast);--in_forindex; break; case ast_foreach: ++in_foreach; foreach_gen(ast); --in_foreach; break; } @@ -820,9 +789,9 @@ void nasal_codegen::loop_gen(const nasal_ast& ast) void nasal_codegen::load_continue_break(int continue_place,int break_place) { for(auto i:continue_ptr.front()) - exec_code[i].num=continue_place; + code[i].num=continue_place; for(auto i:break_ptr.front()) - exec_code[i].num=break_place; + code[i].num=break_place; continue_ptr.pop_front(); break_ptr.pop_front(); return; @@ -830,25 +799,25 @@ void nasal_codegen::load_continue_break(int continue_place,int break_place) void nasal_codegen::while_gen(const nasal_ast& ast) { - int loop_ptr=exec_code.size(); - calc_gen(ast.child()[0]); - int condition_ptr=exec_code.size(); + int loop_ptr=code.size(); + calc_gen(ast[0]); + int condition_ptr=code.size(); gen(op_jf,0,0); - block_gen(ast.child()[1]); + block_gen(ast[1]); gen(op_jmp,loop_ptr,0); - exec_code[condition_ptr].num=exec_code.size(); - load_continue_break(exec_code.size()-1,exec_code.size()); + code[condition_ptr].num=code.size(); + load_continue_break(code.size()-1,code.size()); return; } void nasal_codegen::for_gen(const nasal_ast& ast) { - switch(ast.child()[0].type()) + switch(ast[0].type()) { case ast_null:break; - case ast_def:def_gen(ast.child()[0]);break; - case ast_multi_assign:multi_assign_gen(ast.child()[0]);break; + case ast_def:def_gen(ast[0]);break; + case ast_multi_assign:multi_assign_gen(ast[0]);break; case ast_nil: case ast_num: case ast_str: @@ -876,25 +845,25 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_geq: case ast_grt: case ast_trino: - calc_gen(ast.child()[0]); + calc_gen(ast[0]); gen(op_pop,0,0); break; } - int jmp_place=exec_code.size(); - if(ast.child()[1].type()==ast_null) - gen(op_pone,0,ast.child()[1].line()); + int jmp_place=code.size(); + if(ast[1].type()==ast_null) + gen(op_pone,0,ast[1].line()); else - calc_gen(ast.child()[1]); - int label_exit=exec_code.size(); + calc_gen(ast[1]); + int label_exit=code.size(); gen(op_jf,0,0); - block_gen(ast.child()[3]); - int continue_place=exec_code.size(); - switch(ast.child()[2].type()) + block_gen(ast[3]); + int continue_place=code.size(); + switch(ast[2].type()) { case ast_null:break; - case ast_def:def_gen(ast.child()[2]);break; - case ast_multi_assign:multi_assign_gen(ast.child()[2]);break; + case ast_def:def_gen(ast[2]);break; + case ast_multi_assign:multi_assign_gen(ast[2]);break; case ast_nil:case ast_num:case ast_str:case ast_func:break; case ast_vec:case ast_hash: case ast_call: @@ -907,68 +876,68 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_cmpeq:case ast_neq:case ast_leq: case ast_less:case ast_geq:case ast_grt: case ast_trino: - calc_gen(ast.child()[2]); + calc_gen(ast[2]); gen(op_pop,0,0); break; } gen(op_jmp,jmp_place,0); - exec_code[label_exit].num=exec_code.size(); + code[label_exit].num=code.size(); - load_continue_break(continue_place,exec_code.size()); + load_continue_break(continue_place,code.size()); return; } void nasal_codegen::forindex_gen(const nasal_ast& ast) { - calc_gen(ast.child()[1]); - gen(op_cnt,0,ast.child()[1].line()); - int ptr=exec_code.size(); + calc_gen(ast[1]); + gen(op_cnt,0,ast[1].line()); + int ptr=code.size(); gen(op_findex,0,ast.line()); - if(ast.child()[0].type()==ast_new_iter) + if(ast[0].type()==ast_new_iter) { - const std::string& str=ast.child()[0].child()[0].str(); + const std::string& str=ast[0][0].str(); local.empty()? - gen(op_loadg,global_find(str),ast.child()[0].child()[0].line()) - :gen(op_loadl,local_find(str),ast.child()[0].child()[0].line()); + gen(op_loadg,global_find(str),ast[0][0].line()): + gen(op_loadl,local_find(str),ast[0][0].line()); } else { - mcall(ast.child()[0]); - gen(op_meq,0,ast.child()[0].line()); + mcall(ast[0]); + gen(op_meq,0,ast[0].line()); gen(op_pop,0,0); } - block_gen(ast.child()[2]); + block_gen(ast[2]); gen(op_jmp,ptr,0); - exec_code[ptr].num=exec_code.size(); - load_continue_break(exec_code.size()-1,exec_code.size()); + code[ptr].num=code.size(); + load_continue_break(code.size()-1,code.size()); gen(op_pop,0,0);// pop vector gen(op_cntpop,0,0); return; } void nasal_codegen::foreach_gen(const nasal_ast& ast) { - calc_gen(ast.child()[1]); + calc_gen(ast[1]); gen(op_cnt,0,ast.line()); - int ptr=exec_code.size(); + int ptr=code.size(); gen(op_feach,0,ast.line()); - if(ast.child()[0].type()==ast_new_iter) + if(ast[0].type()==ast_new_iter) { - const std::string& str=ast.child()[0].child()[0].str(); + const std::string& str=ast[0][0].str(); local.empty()? - gen(op_loadg,global_find(str),ast.child()[0].child()[0].line()) - :gen(op_loadl,local_find(str),ast.child()[0].child()[0].line()); + gen(op_loadg,global_find(str),ast[0][0].line()): + gen(op_loadl,local_find(str),ast[0][0].line()); } else { - mcall(ast.child()[0]); - gen(op_meq,0,ast.child()[0].line()); + mcall(ast[0]); + gen(op_meq,0,ast[0].line()); gen(op_pop,0,0); } - block_gen(ast.child()[2]); + block_gen(ast[2]); gen(op_jmp,ptr,0); - exec_code[ptr].num=exec_code.size(); - load_continue_break(exec_code.size()-1,exec_code.size()); + code[ptr].num=code.size(); + load_continue_break(code.size()-1,code.size()); gen(op_pop,0,0);// pop vector gen(op_cntpop,0,0); return; @@ -976,35 +945,35 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast) void nasal_codegen::or_gen(const nasal_ast& ast) { - calc_gen(ast.child()[0]); - int l1=exec_code.size(); + calc_gen(ast[0]); + int l1=code.size(); gen(op_jt,0,0); gen(op_pop,0,0); - calc_gen(ast.child()[1]); - int l2=exec_code.size(); + calc_gen(ast[1]); + int l2=code.size(); gen(op_jt,0,0); gen(op_pop,0,0); gen(op_pnil,0,0); - exec_code[l1].num=exec_code[l2].num=exec_code.size(); + code[l1].num=code[l2].num=code.size(); return; } void nasal_codegen::and_gen(const nasal_ast& ast) { - calc_gen(ast.child()[0]); - gen(op_jt,exec_code.size()+2,0); + calc_gen(ast[0]); + gen(op_jt,code.size()+2,0); - int lfalse=exec_code.size(); + int lfalse=code.size(); gen(op_jmp,0,0); gen(op_pop,0,0);// jt jumps here - calc_gen(ast.child()[1]); - gen(op_jt,exec_code.size()+3,0); + calc_gen(ast[1]); + gen(op_jt,code.size()+3,0); - exec_code[lfalse].num=exec_code.size(); + code[lfalse].num=code.size(); gen(op_pop,0,0); gen(op_pnil,0,0); //jt jumps here @@ -1013,15 +982,15 @@ void nasal_codegen::and_gen(const nasal_ast& ast) void nasal_codegen::trino_gen(const nasal_ast& ast) { - calc_gen(ast.child()[0]); - int lfalse=exec_code.size(); + calc_gen(ast[0]); + int lfalse=code.size(); gen(op_jf,0,0); - calc_gen(ast.child()[1]); - int lexit=exec_code.size(); + calc_gen(ast[1]); + int lexit=code.size(); gen(op_jmp,0,0); - exec_code[lfalse].num=exec_code.size(); - calc_gen(ast.child()[2]); - exec_code[lexit].num=exec_code.size(); + code[lfalse].num=code.size(); + calc_gen(ast[2]); + code[lexit].num=code.size(); return; } @@ -1030,102 +999,102 @@ void nasal_codegen::calc_gen(const nasal_ast& ast) switch(ast.type()) { case ast_nil: gen(op_pnil,0,ast.line());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_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.child()[1]); - mcall(ast.child()[0]); + calc_gen(ast[1]); + mcall(ast[0]); gen(op_meq,0,ast.line()); break; // ast_addeq(22)~ast_lnkeq(26) op_addeq(23)~op_lnkeq(27) case ast_addeq:case ast_subeq:case ast_multeq:case ast_diveq: - if(ast.child()[1].type()!=ast_num) - calc_gen(ast.child()[1]); - mcall(ast.child()[0]); - if(ast.child()[1].type()!=ast_num) + if(ast[1].type()!=ast_num) + calc_gen(ast[1]); + mcall(ast[0]); + if(ast[1].type()!=ast_num) gen(ast.type()-ast_addeq+op_addeq,0,ast.line()); else { - regist_number(ast.child()[1].num()); - gen(ast.type()-ast_addeq+op_addeqc,num_table[ast.child()[1].num()],ast.line()); + regist_number(ast[1].num()); + gen(ast.type()-ast_addeq+op_addeqc,num_table[ast[1].num()],ast.line()); } break; case ast_lnkeq: - if(ast.child()[1].type()!=ast_str) - calc_gen(ast.child()[1]); + if(ast[1].type()!=ast_str) + calc_gen(ast[1]); else - regist_string(ast.child()[1].str()); - mcall(ast.child()[0]); - if(ast.child()[1].type()!=ast_str) + regist_string(ast[1].str()); + mcall(ast[0]); + if(ast[1].type()!=ast_str) gen(op_lnkeq,0,ast.line()); else - gen(op_lnkeqc,str_table[ast.child()[1].str()],ast.line()); + gen(op_lnkeqc,str_table[ast[1].str()],ast.line()); break; case ast_or:or_gen(ast);break; case ast_and:and_gen(ast);break; // ast_add(33)~ast_link(37) op_add(18)~op_lnk(22) case ast_add:case ast_sub:case ast_mult:case ast_div: - calc_gen(ast.child()[0]); - if(ast.child()[1].type()!=ast_num) + calc_gen(ast[0]); + if(ast[1].type()!=ast_num) { - calc_gen(ast.child()[1]); + calc_gen(ast[1]); gen(ast.type()-ast_add+op_add,0,ast.line()); } else { - regist_number(ast.child()[1].num()); - gen(ast.type()-ast_add+op_addc,num_table[ast.child()[1].num()],ast.line()); + regist_number(ast[1].num()); + gen(ast.type()-ast_add+op_addc,num_table[ast[1].num()],ast.line()); } break; case ast_link: - calc_gen(ast.child()[0]); - if(ast.child()[1].type()!=ast_str) + calc_gen(ast[0]); + if(ast[1].type()!=ast_str) { - calc_gen(ast.child()[1]); + calc_gen(ast[1]); gen(op_lnk,0,ast.line()); } else { - regist_string(ast.child()[1].str()); - gen(op_lnkc,str_table[ast.child()[1].str()],ast.line()); + regist_string(ast[1].str()); + gen(op_lnkc,str_table[ast[1].str()],ast.line()); } break; // ast_cmpeq(27)~ast_geq(32) op_eq(29)~op_geq(34) case ast_cmpeq:case ast_neq: - calc_gen(ast.child()[0]); - calc_gen(ast.child()[1]); + calc_gen(ast[0]); + calc_gen(ast[1]); gen(ast.type()-ast_cmpeq+op_eq,0,ast.line()); break; case ast_less:case ast_leq:case ast_grt:case ast_geq: - calc_gen(ast.child()[0]); - if(ast.child()[1].type()!=ast_num) + calc_gen(ast[0]); + if(ast[1].type()!=ast_num) { - calc_gen(ast.child()[1]); + calc_gen(ast[1]); gen(ast.type()-ast_less+op_less,0,ast.line()); } else { - regist_number(ast.child()[1].num()); - gen(ast.type()-ast_less+op_lessc,num_table[ast.child()[1].num()],ast.line()); + regist_number(ast[1].num()); + gen(ast.type()-ast_less+op_lessc,num_table[ast[1].num()],ast.line()); } break; case ast_trino:trino_gen(ast);break; case ast_neg: - calc_gen(ast.child()[0]); + calc_gen(ast[0]); gen(op_usub,0,ast.line()); break; case ast_not: - calc_gen(ast.child()[0]); + calc_gen(ast[0]); gen(op_unot,0,ast.line()); break; case ast_def: single_def(ast); - call_id(ast.child()[0]); + call_id(ast[0]); break; } return; @@ -1141,11 +1110,11 @@ void nasal_codegen::block_gen(const nasal_ast& ast) case ast_multi_assign:multi_assign_gen(tmp);break; case ast_conditional:conditional_gen(tmp);break; case ast_continue: - continue_ptr.front().push_back(exec_code.size()); + continue_ptr.front().push_back(code.size()); gen(op_jmp,0,0); break; case ast_break: - break_ptr.front().push_back(exec_code.size()); + break_ptr.front().push_back(code.size()); gen(op_jmp,0,0); break; case ast_while: @@ -1153,17 +1122,17 @@ void nasal_codegen::block_gen(const nasal_ast& ast) case ast_forindex: case ast_foreach:loop_gen(tmp);break; case ast_equal: - if(tmp.child()[0].type()==ast_id) + if(tmp[0].type()==ast_id) { - calc_gen(tmp.child()[1]); - mcall_id(tmp.child()[0]); + calc_gen(tmp[1]); + mcall_id(tmp[0]); // only the first mcall_id can use load - if(exec_code.back().op==op_mcalll) - exec_code.back().op=op_loadl; - else if(exec_code.back().op==op_mupval) - exec_code.back().op=op_loadu; + if(code.back().op==op_mcalll) + code.back().op=op_loadl; + else if(code.back().op==op_mupval) + code.back().op=op_loadu; else - exec_code.back().op=op_loadg; + code.back().op=op_loadg; } else { @@ -1213,8 +1182,8 @@ void nasal_codegen::ret_gen(const nasal_ast& ast) gen(op_pop,0,0); gen(op_cntpop,0,0); } - if(ast.child().size()) - calc_gen(ast.child()[0]); + if(ast.size()) + calc_gen(ast[0]); else gen(op_pnil,0,ast.line()); gen(op_ret,0,ast.line()); @@ -1230,10 +1199,10 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import) num_table.clear(); str_table.clear(); - num_res_table.clear(); - str_res_table.clear(); - file_name=import.get_file(); - exec_code.clear(); + num_res.clear(); + str_res.clear(); + file=import.get_file(); + code.clear(); global.clear(); local.clear(); @@ -1255,17 +1224,17 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import) case ast_forindex: case ast_foreach:loop_gen(tmp);break; case ast_equal: - if(tmp.child()[0].type()==ast_id) + if(tmp[0].type()==ast_id) { - calc_gen(tmp.child()[1]); - mcall_id(tmp.child()[0]); + calc_gen(tmp[1]); + mcall_id(tmp[0]); // only the first mcall_id can use load - if(exec_code.back().op==op_mcalll) - exec_code.back().op=op_loadl; - else if(exec_code.back().op==op_mupval) - exec_code.back().op=op_loadu; + if(code.back().op==op_mcalll) + code.back().op=op_loadl; + else if(code.back().op==op_mupval) + code.back().op=op_loadu; else - exec_code.back().op=op_loadg; + code.back().op=op_loadg; } else { @@ -1309,32 +1278,32 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import) void nasal_codegen::print_op(uint32_t index) { // print opcode index,opcode name,opcode immediate number - const opcode& code=exec_code[index]; - printf("0x%.8x: %s ",index,code_table[code.op].name); + const opcode& c=code[index]; + printf("0x%.8x: %s ",index,code_table[c.op].name); // print detail info - switch(code.op) + switch(c.op) { - case op_addc:case op_subc:case op_mulc:case op_divc: - case op_addeqc:case op_subeqc:case op_muleqc:case op_diveqc: - case op_lessc:case op_leqc:case op_grtc:case op_geqc: + case op_addc: case op_subc: case op_mulc: case op_divc: + case op_addeqc:case op_subeqc: case op_muleqc:case op_diveqc: + case op_lessc: case op_leqc: case op_grtc: case op_geqc: case op_pnum: - printf("0x%x (%lf)\n",code.num,num_res_table[code.num]);break; - case op_callvi:case op_newv:case op_callfv: - case op_intg:case op_intl: - case op_newf:case op_jmp:case op_jt:case op_jf: - printf("0x%x\n",code.num);break; + printf("0x%x (%lf)\n",c.num,num_res[c.num]);break; + case op_callvi:case op_newv: case op_callfv: + case op_intg: case op_intl: + case op_newf: case op_jmp: case op_jt: case op_jf: + printf("0x%x\n",c.num);break; case op_callb: - printf("0x%x <%s>\n",code.num,builtin_func[code.num].name);break; - case op_callg:case op_mcallg:case op_loadg: - case op_calll:case op_mcalll:case op_loadl: - printf("0x%x\n",code.num);break; - case op_upval:case op_mupval:case op_loadu: - printf("0x%x[0x%x]\n",(code.num>>16)&0xffff,code.num&0xffff);break; - case op_happ:case op_pstr: - case op_lnkc:case op_lnkeqc: - case op_callh:case op_mcallh: - case op_para:case op_defpara:case op_dynpara: - printf("0x%x (\"%s\")\n",code.num,raw_string(str_res_table[code.num]).c_str()); + printf("0x%x <%s>\n",c.num,builtin[c.num].name);break; + case op_callg: case op_mcallg: case op_loadg: + case op_calll: case op_mcalll: case op_loadl: + printf("0x%x\n",c.num);break; + case op_upval:case op_mupval: case op_loadu: + printf("0x%x[0x%x]\n",(c.num>>16)&0xffff,c.num&0xffff);break; + case op_happ: case op_pstr: + case op_lnkc: case op_lnkeqc: + case op_callh: case op_mcallh: + case op_para: case op_defpara:case op_dynpara: + printf("0x%x (\"%s\")\n",c.num,raw_string(str_res[c.num]).c_str()); break; default:printf("\n");break; } @@ -1343,11 +1312,11 @@ void nasal_codegen::print_op(uint32_t index) void nasal_codegen::print() { - for(auto num:num_res_table) + for(auto num:num_res) std::cout<<".number "< local; // local scope with default value(nasal_ref) std::vector upvalue; // closure @@ -116,11 +116,11 @@ struct nasal_func// 112 bytes void clear(); }; +constexpr uint8_t GC_UNCOLLECTED=0; +constexpr uint8_t GC_COLLECTED =1; +constexpr uint8_t GC_FOUND =2; struct nasal_val// 16 bytes { -#define GC_UNCOLLECTED 0 -#define GC_COLLECTED 1 -#define GC_FOUND 2 uint8_t mark; uint8_t type; union diff --git a/nasal_import.h b/nasal_import.h index 5b0078d..5210e64 100644 --- a/nasal_import.h +++ b/nasal_import.h @@ -37,14 +37,13 @@ only this kind of node can be recognized as 'import': */ if(node.type()!=ast_call) return false; - const std::vector& vec=node.child(); - if(vec.size()!=2) + if(node.size()!=2) return false; - if(vec[0].str()!="import") + if(node[0].str()!="import") return false; - if(vec[1].type()!=ast_callf) + if(node[1].type()!=ast_callf) return false; - if(vec[1].child().size()!=1 || vec[1].child()[0].type()!=ast_str) + if(node[1].size()!=1 || node[1][0].type()!=ast_str) return false; return true; } @@ -69,7 +68,7 @@ void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root) nasal_ast nasal_import::file_import(nasal_ast& node) { // get filename and set node to ast_null - std::string filename=node.child()[1].child()[0].str(); + std::string filename=node[1][0].str(); node.clear(); // avoid infinite loading loop diff --git a/nasal_parse.h b/nasal_parse.h index 834507b..654375f 100644 --- a/nasal_parse.h +++ b/nasal_parse.h @@ -43,8 +43,8 @@ class nasal_parse private: uint32_t ptr; uint32_t error; - uint32_t in_func; // count when generating function block,used to check return-expression - uint32_t in_loop; // count when generating loop block,used to check break/continue-expression + uint32_t in_func; // count when generating function block + uint32_t in_loop; // count when generating loop block nasal_ast root; std::vector tokens; std::vector error_token; @@ -53,7 +53,7 @@ private: void match(uint32_t type,const char* info=nullptr); bool check_comma(const uint32_t*); bool check_multi_scalar(); - bool check_function_end(const nasal_ast&); + bool check_func_end(const nasal_ast&); bool check_special_call(); bool need_semi_check(const nasal_ast&); void check_memory_reachable(const nasal_ast&); @@ -93,7 +93,7 @@ private: nasal_ast while_loop(); nasal_ast for_loop(); nasal_ast forei_loop(); - nasal_ast new_iter_gen(); + nasal_ast iter_gen(); nasal_ast conditional(); nasal_ast continue_expr(); nasal_ast break_expr(); @@ -197,7 +197,7 @@ bool nasal_parse::check_multi_scalar() } return false; } -bool nasal_parse::check_function_end(const nasal_ast& node) +bool nasal_parse::check_func_end(const nasal_ast& node) { uint32_t type=node.type(); if(type==ast_func) @@ -218,7 +218,7 @@ bool nasal_parse::check_function_end(const nasal_ast& node) ) return false; else - return check_function_end(node.child().back()); + return check_func_end(node.child().back()); return false; } bool nasal_parse::check_special_call() @@ -250,7 +250,7 @@ bool nasal_parse::need_semi_check(const nasal_ast& node) uint32_t type=node.type(); if(type==ast_for || type==ast_foreach || type==ast_forindex || type==ast_while || type==ast_conditional) return false; - return !check_function_end(node); + return !check_func_end(node); } void nasal_parse::check_memory_reachable(const nasal_ast& node) { @@ -259,7 +259,7 @@ void nasal_parse::check_memory_reachable(const nasal_ast& node) const nasal_ast& tmp=node.child().back(); if(tmp.type()==ast_callf) die(tmp.line(),"bad left-value"); - if(tmp.type()==ast_callv && (tmp.child().size()>1 || tmp.child()[0].type()==ast_subvec)) + if(tmp.type()==ast_callv && (tmp.size()>1 || tmp[0].type()==ast_subvec)) die(tmp.line(),"bad left-value"); } else if(node.type()!=ast_id) @@ -380,14 +380,14 @@ nasal_ast nasal_parse::args() { match(tok_eq); special_arg=std::move(tmp); - special_arg.set_type(ast_default_arg); + special_arg.set_type(ast_default); special_arg.add(calc()); } else { match(tok_ellipsis); special_arg=std::move(tmp); - special_arg.set_type(ast_dynamic_id); + special_arg.set_type(ast_dynamic); } node.add(std::move(special_arg)); } @@ -405,40 +405,41 @@ nasal_ast nasal_parse::args() std::string format="func("; for(auto& tmp:node.child()) { + format+=tmp.str(); switch(tmp.type()) { - case ast_id: format+=tmp.str();break; - case ast_default_arg: format+=tmp.str()+"=val";break; - case ast_dynamic_id: format+=tmp.str()+"...";break; + case ast_id: break; + case ast_default: format+="=val";break; + case ast_dynamic: format+="..."; break; } format+=",)"[&tmp==&node.child().back()]; } - bool checked_default_val=false,checked_dynamic_ids=false; + bool checked_default=false,checked_dynamic=false; for(auto& tmp:node.child()) { - if(tmp.type()==ast_default_arg) - checked_default_val=true; - else if(tmp.type()==ast_dynamic_id) - checked_dynamic_ids=true; - if(checked_default_val && tmp.type()!=ast_default_arg) - die(tmp.line(),"must use default paras after using it once: "+format); - if(checked_dynamic_ids && &tmp!=&node.child().back()) + if(tmp.type()==ast_default) + checked_default=true; + else if(tmp.type()==ast_dynamic) + checked_dynamic=true; + if(checked_default && tmp.type()!=ast_default) + die(tmp.line(),"must use default paras after using once: "+format); + if(checked_dynamic && &tmp!=&node.child().back()) die(tmp.line(),"dynamic para must be the end: "+format); } - std::unordered_map argname_table; + std::unordered_map argname; for(auto& tmp:node.child()) { - std::string new_name; + std::string name; switch(tmp.type()) { - case ast_dynamic_id: - case ast_id: new_name=tmp.str();break; - case ast_default_arg:new_name=tmp.str();break; + case ast_dynamic: + case ast_id: name=tmp.str();break; + case ast_default:name=tmp.str();break; } - if(argname_table.count(new_name)) - die(tmp.line(),"parameter's name repeats: "+new_name); + if(argname.count(name)) + die(tmp.line(),"parameter's name repeats: "+name); else - argname_table[new_name]=true; + argname[name]=true; } return node; } @@ -766,9 +767,9 @@ nasal_ast nasal_parse::definition() match(tok_var); switch(tokens[ptr].type) { - case tok_id: node.add(id());match(tok_id); break; - case tok_lcurve: node.add(var_outcurve_def()); break; - default: die(error_line,"expected identifier"); break; + case tok_id: node.add(id());match(tok_id);break; + case tok_lcurve: node.add(var_outcurve_def());break; + default: die(error_line,"expected identifier");break; } } else if(tokens[ptr].type==tok_lcurve) @@ -778,11 +779,11 @@ nasal_ast nasal_parse::definition() node.add(check_multi_scalar()?multi_scalar(false):calc()); else node.add(calc()); - if(node.child()[0].type()==ast_id && node.child()[1].type()==ast_multi_scalar) - die(node.child()[1].line(),"one identifier cannot accept too many values"); - else if(node.child()[0].type()==ast_multi_id && node.child()[1].type()==ast_multi_scalar) - if(node.child()[0].child().size()!=node.child()[1].child().size()) - die(node.child()[0].line(),"too much or lack values in multi-definition"); + if(node[0].type()==ast_id && node[1].type()==ast_multi_scalar) + die(node[1].line(),"one identifier cannot accept too many values"); + else if(node[0].type()==ast_multi_id && node[1].type()==ast_multi_scalar) + if(node[0].size()!=node[1].size()) + die(node[0].line(),"too much or lack values in multi-definition"); return node; } nasal_ast nasal_parse::var_incurve_def() @@ -861,9 +862,9 @@ nasal_ast nasal_parse::multi_assgin() node.add(check_multi_scalar()?multi_scalar(false):calc()); else node.add(calc()); - if(node.child()[1].type()==ast_multi_scalar - && node.child()[0].child().size()!=node.child()[1].child().size()) - die(node.child()[0].line(),"too much or lack values in multi-assignment"); + if(node[1].type()==ast_multi_scalar + && node[0].size()!=node[1].size()) + die(node[0].line(),"too much or lack values in multi-assignment"); return node; } nasal_ast nasal_parse::loop() @@ -933,15 +934,15 @@ nasal_ast nasal_parse::forei_loop() nasal_ast node(tokens[ptr].line,ast_null); switch(tokens[ptr].type) { - case tok_forindex: node.set_type(ast_forindex);match(tok_forindex); break; - case tok_foreach: node.set_type(ast_foreach); match(tok_foreach); break; + case tok_forindex:node.set_type(ast_forindex);match(tok_forindex);break; + case tok_foreach: node.set_type(ast_foreach); match(tok_foreach); break; } match(tok_lcurve); // first expression // foreach/forindex must have an iterator to loop through if(tokens[ptr].type!=tok_var && tokens[ptr].type!=tok_id) die(error_line,"expected iterator"); - node.add(new_iter_gen()); + node.add(iter_gen()); // check semi match(tok_semi,"expected \';\' in foreach/forindex(iter;vector)"); // check vector @@ -952,7 +953,7 @@ nasal_ast nasal_parse::forei_loop() node.add(exprs()); return node; } -nasal_ast nasal_parse::new_iter_gen() +nasal_ast nasal_parse::iter_gen() { nasal_ast node(tokens[ptr].line,ast_null); if(tokens[ptr].type==tok_var) @@ -975,30 +976,29 @@ nasal_ast nasal_parse::new_iter_gen() nasal_ast nasal_parse::conditional() { nasal_ast node(tokens[ptr].line,ast_conditional); - nasal_ast tmp(tokens[ptr].line,ast_if); + nasal_ast ifnode(tokens[ptr].line,ast_if); match(tok_if); match(tok_lcurve); - tmp.add(calc()); + ifnode.add(calc()); match(tok_rcurve); - tmp.add(exprs()); - node.add(std::move(tmp)); - // end of if-expression + ifnode.add(exprs()); + node.add(std::move(ifnode)); while(tokens[ptr].type==tok_elsif) { - nasal_ast tmp(tokens[ptr].line,ast_elsif); + nasal_ast elsifnode(tokens[ptr].line,ast_elsif); match(tok_elsif); match(tok_lcurve); - tmp.add(calc()); + elsifnode.add(calc()); match(tok_rcurve); - tmp.add(exprs()); - node.add(std::move(tmp)); + elsifnode.add(exprs()); + node.add(std::move(elsifnode)); } if(tokens[ptr].type==tok_else) { - nasal_ast tmp(tokens[ptr].line,ast_else); + nasal_ast elsenode(tokens[ptr].line,ast_else); match(tok_else); - tmp.add(exprs()); - node.add(std::move(tmp)); + elsenode.add(exprs()); + node.add(std::move(elsenode)); } return node; } @@ -1019,8 +1019,17 @@ nasal_ast nasal_parse::ret_expr() nasal_ast node(tokens[ptr].line,ast_ret); match(tok_ret); uint32_t type=tokens[ptr].type; - if(type==tok_nil || type==tok_num || type==tok_str || type==tok_id || type==tok_func || - type==tok_sub || type==tok_not || type==tok_lcurve || type==tok_lbracket || type==tok_lbrace) + if( + type==tok_nil || + type==tok_num || + type==tok_str || + type==tok_id || + type==tok_func || + type==tok_sub || + type==tok_not || + type==tok_lcurve || + type==tok_lbracket || + type==tok_lbrace) node.add(calc()); return node; } diff --git a/nasal_vm.h b/nasal_vm.h index d96c1d4..c00c31e 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -165,7 +165,7 @@ void nasal_vm::bytecodeinfo(const uint32_t p) const opcode& code=bytecode[p]; printf("\t0x%.8x: %s 0x%x",p,code_table[code.op].name,code.num); if(code.op==op_callb) - printf(" <%s>",builtin_func[code.num].name); + printf(" <%s>",builtin[code.num].name); printf(" (<%s> line %d)\n",files[code.fidx].c_str(),code.line); } void nasal_vm::traceback() @@ -286,10 +286,9 @@ inline bool nasal_vm::condition(nasal_ref val) return val.value.num; else if(val.type==vm_str) { - const std::string& str=*val.str(); - double num=str2num(str.c_str()); + double num=str2num(val.str()->c_str()); if(std::isnan(num)) - return str.empty(); + return val.str()->empty(); return num; } return false; @@ -560,7 +559,7 @@ inline void nasal_vm::opr_findex() pc=imm[pc]-1; return; } - (++top)[0]={vm_num,static_cast(counter.top())}; + (++top)[0]={vm_num,(double)counter.top()}; } inline void nasal_vm::opr_feach() { @@ -642,7 +641,7 @@ inline void nasal_vm::opr_callh() } inline void nasal_vm::opr_callfv() { - size_t args_size=imm[pc]; + uint32_t args_size=imm[pc]; nasal_ref* args=top-args_size+1; if(args[-1].type!=vm_func) die("callfv: must call a function"); @@ -655,13 +654,13 @@ inline void nasal_vm::opr_callfv() // load parameters auto& closure=gc.local.back().vec()->elems; - size_t para_size=func.keys.size(); + uint32_t para_size=func.keys.size(); // load arguments // if the first default value is not vm_none,then values after it are not nullptr if(args_sizepara_size,for 0 to args_size will cause corruption - size_t min_size=std::min(para_size,args_size); + uint32_t min_size=std::min(para_size,args_size); for(uint32_t i=0;i=para_size @@ -707,7 +706,7 @@ inline void nasal_vm::opr_callfh() } inline void nasal_vm::opr_callb() { - (++top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back().vec()->elems,gc); + (++top)[0]=(*builtin[imm[pc]].func)(gc.local.back().vec()->elems,gc); if(top[0].type==vm_none) die("native function error."); } @@ -744,7 +743,7 @@ inline void nasal_vm::opr_slc2() uint8_t type1=val1.type,type2=val2.type; int num1=val1.to_number(); int num2=val2.to_number(); - size_t size=ref.size(); + int size=ref.size(); if(type1==vm_nil && type2==vm_nil) { num1=0; @@ -799,7 +798,7 @@ inline void nasal_vm::opr_mcallv() mem_addr=ref.get_mem(str); if(!mem_addr) { - ref.elems[str]=gc.nil; + ref.elems[str]={vm_nil}; mem_addr=ref.get_mem(str); } } @@ -816,7 +815,7 @@ inline void nasal_vm::opr_mcallh() mem_addr=ref.get_mem(str); if(!mem_addr) // create a new key { - ref.elems[str]=gc.nil; + ref.elems[str]={vm_nil}; mem_addr=ref.get_mem(str); } }