diff --git a/README.md b/README.md index f517ab4..a2e8f69 100644 --- a/README.md +++ b/README.md @@ -465,7 +465,7 @@ a=b=0; 2021/10/8 update: In this version vm_nil and vm_num now is not managed by nasal_gc, -this will decrease the usage of gc_alloc and increase the efficiency of execution. +this will decrease the usage of gc::alloc and increase the efficiency of execution. New value type is added: vm_obj. This type is reserved for user to define their own value types. @@ -897,7 +897,7 @@ nasal_ref builtin_print(std::vector& local,nasal_gc& gc) case vm_obj: std::cout<<""; break; } std::cout<& local,nasal_gc& gc) } // push vector into local scope to avoid being sweeped - local.push_back(gc.gc_alloc(vm_vec)); + local.push_back(gc.alloc(vm_vec)); std::vector& vec=local.back().vec()->elems; for(auto& iter:hash.hash()->elems) { diff --git a/main.cpp b/main.cpp index d39dcfb..160f9e1 100644 --- a/main.cpp +++ b/main.cpp @@ -1,11 +1,11 @@ #include "nasal.h" -#define VM_LEXINFO 1 -#define VM_ASTINFO 2 -#define VM_CODEINFO 4 -#define VM_EXECTIME 8 -#define VM_OPCALLNUM 16 -#define VM_EXEC 32 -void help_cmd() +constexpr uint32_t VM_LEXINFO =1; +constexpr uint32_t VM_ASTINFO =2; +constexpr uint32_t VM_CODEINFO =4; +constexpr uint32_t VM_EXECTIME =8; +constexpr uint32_t VM_OPCALLNUM=16; +constexpr uint32_t VM_EXEC =32; +void help() { std::cout #ifdef _WIN32 @@ -27,7 +27,6 @@ void help_cmd() <<" -o, --opcnt | count operands while running.\n" <<"file:\n" <<" input file name to execute script file.\n"; - return; } void logo() @@ -43,8 +42,7 @@ void logo() <<"code repo : https://github.com/ValKmjolnir/Nasal-Interpreter\n" <<"code repo : https://gitee.com/valkmjolnir/Nasal-Interpreter\n" <<"lang info : http://wiki.flightgear.org/Nasal_scripting_language\n" - <<"input \"nasal -h\" to get help .\n"; - return; + <<"input to get help .\n"; } void die(const char* stage,const std::string& filename) @@ -53,11 +51,11 @@ void die(const char* stage,const std::string& filename) std::exit(1); } -void cmderr() +void err() { std::cout <<"invalid argument(s).\n" - <<"use nasal -h to get help.\n"; + <<"use to get help.\n"; std::exit(1); } @@ -65,44 +63,44 @@ void execute(const std::string& file,const uint16_t cmd) { nasal_lexer lexer; nasal_parse parse; - nasal_import import; - nasal_codegen codegen; + nasal_import linker; + nasal_codegen gen; nasal_vm vm; - lexer.open(file); - lexer.scan(); + + // lexer scans file to get tokens + lexer.scan(file); if(lexer.err()) die("lexer",file); - if(cmd&VM_LEXINFO) - lexer.print(); - parse.compile(lexer.get_tokens()); + + // parser gets lexer's token list to compile + parse.compile(lexer); if(parse.err()) die("parse",file); + + // linker gets parser's ast and load import files to this ast + linker.link(parse,file); + if(linker.err()) + die("import",file); + + // code generator gets parser's ast and linker's import file list to generate code + gen.compile(parse,linker); + if(gen.err()) + die("code",file); + + if(cmd&VM_LEXINFO) + lexer.print(); if(cmd&VM_ASTINFO) parse.ast().print(0); - // first used file is itself - import.link(parse.ast(),file); - if(import.err()) - die("import",file); - codegen.compile(import.ast(),import.get_file()); - if(codegen.err()) - die("code",file); if(cmd&VM_CODEINFO) - codegen.print(); - vm.init( - codegen.get_strs(), - codegen.get_nums(), - import.get_file() - ); + gen.print(); if(cmd&VM_EXECTIME) { clock_t t=clock(); - vm.run(codegen.get_code(),cmd&VM_OPCALLNUM); + vm.run(gen,linker,cmd&VM_OPCALLNUM); std::cout<<"process exited after "<<((double)(clock()-t))/CLOCKS_PER_SEC<<"s.\n"; } else if(cmd&VM_EXEC) - vm.run(codegen.get_code(),cmd&VM_OPCALLNUM); - vm.clear(); - return; + vm.run(gen,linker,cmd&VM_OPCALLNUM); } int main(int argc,const char* argv[]) @@ -110,7 +108,7 @@ int main(int argc,const char* argv[]) if(argc==2 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) logo(); else if(argc==2 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) - help_cmd(); + help(); else if(argc==2 && argv[1][0]!='-') execute(argv[1],VM_EXEC); else if(argc>=3) @@ -130,11 +128,11 @@ int main(int argc,const char* argv[]) else if(s=="--time" || s=="-t") cmd|=VM_EXECTIME; else - cmderr(); + err(); } execute(argv[argc-1],cmd); } else - cmderr(); + err(); return 0; } \ No newline at end of file diff --git a/nasal.h b/nasal.h index ddfffb1..4b2890f 100644 --- a/nasal.h +++ b/nasal.h @@ -20,6 +20,25 @@ #include #include +class nasal_err +{ +private: + uint32_t error; + std::string stage; +public: + nasal_err( + const uint32_t _error, + const std::string _stage + ):error(_error),stage(_stage){} + void unwarp(const std::string& error_file) + { + if(!error) + return; + std::cout<<"["<: error(s) occurred,stop.\n"; + std::exit(1); + } +}; + /* check if a string can be converted to a number if this string cannot be converted to a number,it will return nan diff --git a/nasal_ast.h b/nasal_ast.h index 1b2077b..d7c2041 100644 --- a/nasal_ast.h +++ b/nasal_ast.h @@ -29,7 +29,7 @@ const char* ast_name[]= "null", "root","block", "file", - "nil","num","str","id","func","hash","vec", + "nil","node_num","node_str","id","func","hash","vec", "hashmember","call","callh","callv","callf","subvec", "args","deflt_arg","dyn_id", "and","or", @@ -50,103 +50,98 @@ const char* ast_name[]= class nasal_ast { private: - uint32_t line; - uint32_t type; - double num; - std::string str; - std::vector children; + uint32_t text_line; + uint32_t node_type; + double node_num; + std::string node_str; + std::vector node_child; public: - nasal_ast(){line=0;type=ast_null;} - nasal_ast(const uint32_t l,const uint32_t t){line=l;type=t;} + 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(); - void add_child(nasal_ast&& ast){children.push_back(std::move(ast));} - void add_child(const nasal_ast& ast){children.push_back(ast);} - void set_line(const uint32_t l){line=l;} - void set_type(const uint32_t t){type=t;} - void set_str(const std::string& s){str=s;} - void set_num(const double n){num=n;} + void print(const int); + void clear(); + 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;} + void set_type(const uint32_t t){node_type=t;} + void set_str(const std::string& s){node_str=s;} + void set_num(const double n){node_num=n;} - uint32_t get_line(){return line;} - uint32_t get_type(){return type;} - double get_num() {return num;} - std::string& get_str() {return str;} - std::vector& get_children(){return children;} - - uint32_t get_line() const {return line;} - uint32_t get_type() const {return type;} - double get_num() const {return num;} - const std::string& get_str() const {return str;} - const std::vector& get_children() const {return children;} + inline const uint32_t line() const {return text_line;} + inline const uint32_t type() const {return node_type;} + inline const double num() const {return node_num;} + inline const std::string& str() const {return node_str;} + inline const std::vector& child() const {return node_child;} + inline std::vector& child(){return node_child;} }; nasal_ast::nasal_ast(const nasal_ast& tmp) { - line=tmp.line; - type=tmp.type; - num =tmp.num; - str =tmp.str; - children=tmp.children; - return; + text_line=tmp.text_line; + node_type=tmp.node_type; + node_num =tmp.node_num; + node_str =tmp.node_str; + node_child=tmp.node_child; } nasal_ast::nasal_ast(nasal_ast&& tmp) { - line=tmp.line; - type=tmp.type; - num =tmp.num; - str.swap(tmp.str); - children.swap(tmp.children); - return; + text_line=tmp.text_line; + node_type=tmp.node_type; + node_num =tmp.node_num; + node_str.swap(tmp.node_str); + node_child.swap(tmp.node_child); } nasal_ast& nasal_ast::operator=(const nasal_ast& tmp) { - line=tmp.line; - type=tmp.type; - num=tmp.num; - str=tmp.str; - children=tmp.children; + text_line=tmp.text_line; + node_type=tmp.node_type; + node_num=tmp.node_num; + node_str=tmp.node_str; + node_child=tmp.node_child; return *this; } nasal_ast& nasal_ast::operator=(nasal_ast&& tmp) { - line=tmp.line; - type=tmp.type; - num=tmp.num; - str.swap(tmp.str); - children.swap(tmp.children); + text_line=tmp.text_line; + node_type=tmp.node_type; + node_num=tmp.node_num; + node_str.swap(tmp.node_str); + node_child.swap(tmp.node_child); return *this; } void nasal_ast::clear() { - line=0; - num=0; - str=""; - type=ast_null; - children.clear(); - return; + text_line=0; + node_num=0; + node_str=""; + node_type=ast_null; + node_child.clear(); } void nasal_ast::print(const int depth) { for(int i=0;i& local,nasal_gc& gc) // local[0] is reserved for 'me' nasal_ref vec=local[1]; // main process - for(auto i:vec.vec()->elems) + for(auto& i:vec.vec()->elems) switch(i.type) { case vm_none: std::cout<<"null"; break; @@ -143,7 +143,7 @@ nasal_ref builtin_append(std::vector& local,nasal_gc& gc) if(vec.type!=vm_vec) return builtin_err("append","\"vector\" must be vector"); auto& ref_vec=vec.vec()->elems; - for(auto i:elem.vec()->elems) + for(auto& i:elem.vec()->elems) ref_vec.push_back(i); return gc.nil; } @@ -170,7 +170,7 @@ nasal_ref builtin_system(std::vector& local,nasal_gc& gc) } nasal_ref builtin_input(std::vector& local,nasal_gc& gc) { - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); std::cin>>*ret.str(); return ret; } @@ -192,7 +192,7 @@ nasal_ref builtin_fin(std::vector& local,nasal_gc& gc) std::ifstream fin(filename); if(!fin.fail()) { - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); std::stringstream rd; rd<& local,nasal_gc& gc) size_t source_len=source.length(); // push it to local scope to avoid being sweeped - local.push_back(gc.gc_alloc(vm_vec)); + local.push_back(gc.alloc(vm_vec)); std::vector& vec=local.back().vec()->elems; if(!delimeter_len) { for(int i=0;i& local,nasal_gc& gc) { if(tmp.length()) { - vec.push_back(gc.gc_alloc(vm_str)); + vec.push_back(gc.alloc(vm_str)); *vec.back().str()=tmp; tmp=""; } @@ -268,7 +268,7 @@ nasal_ref builtin_split(std::vector& local,nasal_gc& gc) } if(tmp.length()) { - vec.push_back(gc.gc_alloc(vm_str)); + vec.push_back(gc.alloc(vm_str)); *vec.back().str()=tmp; tmp=""; } @@ -292,7 +292,7 @@ nasal_ref builtin_rand(std::vector& local,nasal_gc& gc) nasal_ref builtin_id(std::vector& local,nasal_gc& gc) { nasal_ref val=local[1]; - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); char buf[32]; if(val.type>vm_num) sprintf(buf,"%p",val.value.gcobj); @@ -334,7 +334,7 @@ nasal_ref builtin_str(std::vector& local,nasal_gc& gc) nasal_ref val=local[1]; if(val.type!=vm_num) return builtin_err("str","\"number\" must be number"); - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); *ret.str()=std::to_string(val.num()); return ret; } @@ -500,11 +500,11 @@ nasal_ref builtin_keys(std::vector& local,nasal_gc& gc) if(hash.type!=vm_hash) return builtin_err("keys","\"hash\" must be hash"); // push vector into local scope to avoid being sweeped - local.push_back(gc.gc_alloc(vm_vec)); + local.push_back(gc.alloc(vm_vec)); auto& vec=local.back().vec()->elems; for(auto& iter:hash.hash()->elems) { - nasal_ref str=gc.gc_alloc(vm_str); + nasal_ref str=gc.alloc(vm_str); *str.str()=iter.first; vec.push_back(str); } @@ -527,7 +527,7 @@ nasal_ref builtin_die(std::vector& local,nasal_gc& gc) nasal_ref builtin_type(std::vector& local,nasal_gc& gc) { nasal_ref val=local[1]; - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); switch(val.type) { case vm_none: *ret.str()="undefined";break; @@ -558,7 +558,7 @@ nasal_ref builtin_substr(std::vector& local,nasal_gc& gc) return builtin_err("susbtr","index out of range"); if(length<0) length=0; - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); *ret.str()=str.str()->substr(begin,length); return ret; } @@ -579,7 +579,7 @@ nasal_ref builtin_left(std::vector& local,nasal_gc& gc) int length=(int)len.num(); if(length<0) length=0; - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); *ret.str()=str.str()->substr(0,length); return ret; } @@ -597,7 +597,7 @@ nasal_ref builtin_right(std::vector& local,nasal_gc& gc) length=srclen; if(length<0) length=0; - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); *ret.str()=str.str()->substr(srclen-length, srclen); return ret; } @@ -634,7 +634,7 @@ nasal_ref builtin_chr(std::vector& local,nasal_gc& gc) nasal_ref code=local[1]; if(code.type!=vm_num) return builtin_err("chr","\"code\" must be number"); - nasal_ref ret=gc.gc_alloc(vm_str); + nasal_ref ret=gc.alloc(vm_str); int num=code.num(); if(0<=num && num<128) *ret.str()=(char)num; diff --git a/nasal_codegen.h b/nasal_codegen.h index 7d6ee9d..e947ec9 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -203,8 +203,8 @@ private: uint16_t fileindex; uint32_t in_forindex; uint32_t in_foreach; - std::unordered_map number_table; - std::unordered_map string_table; + std::unordered_map num_table; + std::unordered_map str_table; std::vector num_res_table; std::vector str_res_table; std::vector file_name; @@ -256,27 +256,26 @@ private: void ret_gen(const nasal_ast&); public: uint32_t err(){return error;} - void compile(const nasal_ast&,const std::vector&); + void compile(const nasal_parse&,const nasal_import&); void print_op(uint32_t); void print(); - std::vector& get_strs(){return str_res_table;} - std::vector& get_nums(){return num_res_table;} - std::vector& get_code(){return exec_code;} + 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;} }; void nasal_codegen::die(const std::string info,const int line) { ++error; std::cout<<"[code] <"< line "<65536) - die("too many local variants: "+std::to_string(local.back().size())+".",block.get_line()); + die("too many local variants: "+std::to_string(local.back().size())+".",block.line()); local.pop_back(); - if(!block.get_children().size() || block.get_children().back().get_type()!=ast_ret) + if(!block.child().size() || block.child().back().type()!=ast_ret) { - gen(op_pnil,0,block.get_line()); - gen(op_ret,0,block.get_line()); + gen(op_pnil,0,block.line()); + gen(op_ret,0,block.line()); } exec_code[jmp_ptr].num=exec_code.size(); return; @@ -496,16 +495,16 @@ void nasal_codegen::func_gen(const nasal_ast& ast) void nasal_codegen::call_gen(const nasal_ast& ast) { - calc_gen(ast.get_children()[0]); + calc_gen(ast.child()[0]); if(exec_code.empty()) std::cout<<"warning\n"; if(exec_code.back().op==op_callb) return; - int child_size=ast.get_children().size(); + int child_size=ast.child().size(); for(int i=1;i=0) { - gen(op_calll,index,ast.get_line()); + gen(op_calll,index,ast.line()); return; } index=upvalue_find(str); if(index>=0) { - gen(op_upval,index,ast.get_line()); + gen(op_upval,index,ast.line()); return; } index=global_find(str); if(index>=0) { - gen(op_callg,index,ast.get_line()); + gen(op_callg,index,ast.line()); return; } - die("undefined symbol \""+str+"\".",ast.get_line()); + die("undefined symbol \""+str+"\".",ast.line()); return; } void nasal_codegen::call_hash(const nasal_ast& ast) { - const std::string& str=ast.get_str(); + const std::string& str=ast.str(); regist_string(str); - gen(op_callh,string_table[str],ast.get_line()); + gen(op_callh,str_table[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.get_children().size()==1 && ast.get_children()[0].get_type()!=ast_subvec) + if(ast.child().size()==1 && ast.child()[0].type()!=ast_subvec) { - calc_gen(ast.get_children()[0]); - gen(op_callv,0,ast.get_children()[0].get_line()); + calc_gen(ast.child()[0]); + gen(op_callv,0,ast.child()[0].line()); return; } - gen(op_slcbegin,0,ast.get_line()); - for(auto& tmp:ast.get_children()) + gen(op_slcbegin,0,ast.line()); + for(auto& tmp:ast.child()) { - if(tmp.get_type()!=ast_subvec) + if(tmp.type()!=ast_subvec) { calc_gen(tmp); - gen(op_slc,0,tmp.get_line()); + gen(op_slc,0,tmp.line()); } else { - calc_gen(tmp.get_children()[0]); - calc_gen(tmp.get_children()[1]); - gen(op_slc2,0,tmp.get_line()); + calc_gen(tmp.child()[0]); + calc_gen(tmp.child()[1]); + gen(op_slc2,0,tmp.line()); } } - gen(op_slcend,0,ast.get_line()); + gen(op_slcend,0,ast.line()); return; } void nasal_codegen::call_func(const nasal_ast& ast) { - if(!ast.get_children().size()) - gen(op_callfv,0,ast.get_line()); - else if(ast.get_children()[0].get_type()==ast_hashmember) + if(!ast.child().size()) + gen(op_callfv,0,ast.line()); + else if(ast.child()[0].type()==ast_hashmember) { hash_gen(ast); - gen(op_callfh,0,ast.get_line()); + gen(op_callfh,0,ast.line()); } else { - for(auto& node:ast.get_children()) + for(auto& node:ast.child()) calc_gen(node); - gen(op_callfv,ast.get_children().size(),ast.get_line()); + gen(op_callfv,ast.child().size(),ast.line()); } return; } void nasal_codegen::mcall(const nasal_ast& ast) { - if(ast.get_type()==ast_id) + if(ast.type()==ast_id) { mcall_id(ast); return; } - calc_gen(ast.get_children()[0]); - for(int i=1;i=0) { - gen(op_mcalll,index,ast.get_line()); + gen(op_mcalll,index,ast.line()); return; } index=upvalue_find(str); if(index>=0) { - gen(op_mupval,index,ast.get_line()); + gen(op_mupval,index,ast.line()); return; } index=global_find(str); if(index>=0) { - gen(op_mcallg,index,ast.get_line()); + gen(op_mcallg,index,ast.line()); return; } - die("undefined symbol \""+str+"\".",ast.get_line()); + die("undefined symbol \""+str+"\".",ast.line()); return; } void nasal_codegen::mcall_vec(const nasal_ast& ast) { - calc_gen(ast.get_children()[0]); - gen(op_mcallv,0,ast.get_line()); + calc_gen(ast.child()[0]); + gen(op_mcallv,0,ast.line()); return; } void nasal_codegen::mcall_hash(const nasal_ast& ast) { - const std::string& str=ast.get_str(); + const std::string& str=ast.str(); regist_string(str); - gen(op_mcallh,string_table[str],ast.get_line()); + gen(op_mcallh,str_table[str],ast.line()); return; } void nasal_codegen::single_def(const nasal_ast& ast) { - const std::string& str=ast.get_children()[0].get_str(); - calc_gen(ast.get_children()[1]); - local.empty()?gen(op_loadg,global_find(str),ast.get_line()):gen(op_loadl,local_find(str),ast.get_line()); + const std::string& str=ast.child()[0].str(); + calc_gen(ast.child()[1]); + local.empty()? + gen(op_loadg,global_find(str),ast.line()): + gen(op_loadl,local_find(str),ast.line()); return; } void nasal_codegen::multi_def(const nasal_ast& ast) { - auto& ids=ast.get_children()[0].get_children(); + auto& ids=ast.child()[0].child(); int size=ids.size(); - if(ast.get_children()[1].get_type()==ast_multi_scalar) + if(ast.child()[1].type()==ast_multi_scalar) { - auto& vals=ast.get_children()[1].get_children(); + auto& vals=ast.child()[1].child(); for(int i=0;i=0;--i) - calc_gen(ast.get_children()[1].get_children()[i]); + calc_gen(ast.child()[1].child()[i]); for(int i=0;i jmp_label; - for(auto& tmp:ast.get_children()) + for(auto& tmp:ast.child()) { - if(tmp.get_type()==ast_if || tmp.get_type()==ast_elsif) + if(tmp.type()==ast_if || tmp.type()==ast_elsif) { - calc_gen(tmp.get_children()[0]); + calc_gen(tmp.child()[0]); int ptr=exec_code.size(); gen(op_jf,0,0); - block_gen(tmp.get_children()[1]); + block_gen(tmp.child()[1]); // without 'else' the last condition doesn't need to jmp - if(&tmp!=&ast.get_children().back()) + if(&tmp!=&ast.child().back()) { jmp_label.push_back(exec_code.size()); gen(op_jmp,0,0); @@ -790,7 +794,7 @@ void nasal_codegen::conditional_gen(const nasal_ast& ast) } else { - block_gen(tmp.get_children()[0]); + block_gen(tmp.child()[0]); break; } } @@ -803,7 +807,7 @@ void nasal_codegen::loop_gen(const nasal_ast& ast) { continue_ptr.push_front(std::vector()); break_ptr.push_front(std::vector()); - switch(ast.get_type()) + switch(ast.type()) { case ast_while: while_gen(ast); break; case ast_for: for_gen(ast); break; @@ -827,11 +831,11 @@ 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.get_children()[0]); + calc_gen(ast.child()[0]); int condition_ptr=exec_code.size(); gen(op_jf,0,0); - block_gen(ast.get_children()[1]); + block_gen(ast.child()[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()); @@ -840,11 +844,11 @@ void nasal_codegen::while_gen(const nasal_ast& ast) void nasal_codegen::for_gen(const nasal_ast& ast) { - switch(ast.get_children()[0].get_type()) + switch(ast.child()[0].type()) { case ast_null:break; - case ast_def:def_gen(ast.get_children()[0]);break; - case ast_multi_assign:multi_assign_gen(ast.get_children()[0]);break; + case ast_def:def_gen(ast.child()[0]);break; + case ast_multi_assign:multi_assign_gen(ast.child()[0]);break; case ast_nil: case ast_num: case ast_str: @@ -872,34 +876,38 @@ void nasal_codegen::for_gen(const nasal_ast& ast) case ast_geq: case ast_grt: case ast_trino: - calc_gen(ast.get_children()[0]); + calc_gen(ast.child()[0]); gen(op_pop,0,0); break; } int jmp_place=exec_code.size(); - if(ast.get_children()[1].get_type()==ast_null) - gen(op_pone,0,ast.get_children()[1].get_line()); + if(ast.child()[1].type()==ast_null) + gen(op_pone,0,ast.child()[1].line()); else - calc_gen(ast.get_children()[1]); + calc_gen(ast.child()[1]); int label_exit=exec_code.size(); gen(op_jf,0,0); - block_gen(ast.get_children()[3]); + block_gen(ast.child()[3]); int continue_place=exec_code.size(); - switch(ast.get_children()[2].get_type()) + switch(ast.child()[2].type()) { case ast_null:break; - case ast_def:def_gen(ast.get_children()[2]);break; - case ast_multi_assign:multi_assign_gen(ast.get_children()[2]);break; + case ast_def:def_gen(ast.child()[2]);break; + case ast_multi_assign:multi_assign_gen(ast.child()[2]);break; case ast_nil:case ast_num:case ast_str:case ast_func:break; case ast_vec:case ast_hash: case ast_call: - case ast_equal:case ast_addeq:case ast_subeq:case ast_multeq:case ast_diveq:case ast_lnkeq: + case ast_equal: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_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]); + calc_gen(ast.child()[2]); gen(op_pop,0,0); break; } @@ -911,25 +919,25 @@ void nasal_codegen::for_gen(const nasal_ast& ast) } void nasal_codegen::forindex_gen(const nasal_ast& ast) { - calc_gen(ast.get_children()[1]); - gen(op_cnt,0,ast.get_children()[1].get_line()); + calc_gen(ast.child()[1]); + gen(op_cnt,0,ast.child()[1].line()); int ptr=exec_code.size(); - gen(op_findex,0,ast.get_line()); - if(ast.get_children()[0].get_type()==ast_new_iter) + gen(op_findex,0,ast.line()); + if(ast.child()[0].type()==ast_new_iter) { - const std::string& str=ast.get_children()[0].get_children()[0].get_str(); + const std::string& str=ast.child()[0].child()[0].str(); local.empty()? - gen(op_loadg,global_find(str),ast.get_children()[0].get_children()[0].get_line()) - :gen(op_loadl,local_find(str),ast.get_children()[0].get_children()[0].get_line()); + gen(op_loadg,global_find(str),ast.child()[0].child()[0].line()) + :gen(op_loadl,local_find(str),ast.child()[0].child()[0].line()); } else { - mcall(ast.get_children()[0]); - gen(op_meq,0,ast.get_children()[0].get_line()); + mcall(ast.child()[0]); + gen(op_meq,0,ast.child()[0].line()); gen(op_pop,0,0); } - block_gen(ast.get_children()[2]); + block_gen(ast.child()[2]); gen(op_jmp,ptr,0); exec_code[ptr].num=exec_code.size(); load_continue_break(exec_code.size()-1,exec_code.size()); @@ -939,25 +947,25 @@ void nasal_codegen::forindex_gen(const nasal_ast& ast) } void nasal_codegen::foreach_gen(const nasal_ast& ast) { - calc_gen(ast.get_children()[1]); - gen(op_cnt,0,ast.get_line()); + calc_gen(ast.child()[1]); + gen(op_cnt,0,ast.line()); int ptr=exec_code.size(); - gen(op_feach,0,ast.get_line()); - if(ast.get_children()[0].get_type()==ast_new_iter) + gen(op_feach,0,ast.line()); + if(ast.child()[0].type()==ast_new_iter) { - const std::string& str=ast.get_children()[0].get_children()[0].get_str(); + const std::string& str=ast.child()[0].child()[0].str(); local.empty()? - gen(op_loadg,global_find(str),ast.get_children()[0].get_children()[0].get_line()) - :gen(op_loadl,local_find(str),ast.get_children()[0].get_children()[0].get_line()); + gen(op_loadg,global_find(str),ast.child()[0].child()[0].line()) + :gen(op_loadl,local_find(str),ast.child()[0].child()[0].line()); } else { - mcall(ast.get_children()[0]); - gen(op_meq,0,ast.get_children()[0].get_line()); + mcall(ast.child()[0]); + gen(op_meq,0,ast.child()[0].line()); gen(op_pop,0,0); } - block_gen(ast.get_children()[2]); + block_gen(ast.child()[2]); gen(op_jmp,ptr,0); exec_code[ptr].num=exec_code.size(); load_continue_break(exec_code.size()-1,exec_code.size()); @@ -968,12 +976,12 @@ void nasal_codegen::foreach_gen(const nasal_ast& ast) void nasal_codegen::or_gen(const nasal_ast& ast) { - calc_gen(ast.get_children()[0]); + calc_gen(ast.child()[0]); int l1=exec_code.size(); gen(op_jt,0,0); gen(op_pop,0,0); - calc_gen(ast.get_children()[1]); + calc_gen(ast.child()[1]); int l2=exec_code.size(); gen(op_jt,0,0); @@ -986,14 +994,14 @@ void nasal_codegen::or_gen(const nasal_ast& ast) void nasal_codegen::and_gen(const nasal_ast& ast) { - calc_gen(ast.get_children()[0]); + calc_gen(ast.child()[0]); gen(op_jt,exec_code.size()+2,0); int lfalse=exec_code.size(); gen(op_jmp,0,0); gen(op_pop,0,0);// jt jumps here - calc_gen(ast.get_children()[1]); + calc_gen(ast.child()[1]); gen(op_jt,exec_code.size()+3,0); exec_code[lfalse].num=exec_code.size(); @@ -1005,23 +1013,23 @@ void nasal_codegen::and_gen(const nasal_ast& ast) void nasal_codegen::trino_gen(const nasal_ast& ast) { - calc_gen(ast.get_children()[0]); + calc_gen(ast.child()[0]); int lfalse=exec_code.size(); gen(op_jf,0,0); - calc_gen(ast.get_children()[1]); + calc_gen(ast.child()[1]); int lexit=exec_code.size(); gen(op_jmp,0,0); exec_code[lfalse].num=exec_code.size(); - calc_gen(ast.get_children()[2]); + calc_gen(ast.child()[2]); exec_code[lexit].num=exec_code.size(); return; } void nasal_codegen::calc_gen(const nasal_ast& ast) { - switch(ast.get_type()) + switch(ast.type()) { - case ast_nil: gen(op_pnil,0,ast.get_line());break; + 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; @@ -1030,94 +1038,94 @@ void nasal_codegen::calc_gen(const nasal_ast& ast) 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]); - gen(op_meq,0,ast.get_line()); + calc_gen(ast.child()[1]); + mcall(ast.child()[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.get_children()[1].get_type()!=ast_num) - calc_gen(ast.get_children()[1]); - mcall(ast.get_children()[0]); - if(ast.get_children()[1].get_type()!=ast_num) - gen(ast.get_type()-ast_addeq+op_addeq,0,ast.get_line()); + if(ast.child()[1].type()!=ast_num) + calc_gen(ast.child()[1]); + mcall(ast.child()[0]); + if(ast.child()[1].type()!=ast_num) + gen(ast.type()-ast_addeq+op_addeq,0,ast.line()); else { - regist_number(ast.get_children()[1].get_num()); - gen(ast.get_type()-ast_addeq+op_addeqc,number_table[ast.get_children()[1].get_num()],ast.get_line()); + regist_number(ast.child()[1].num()); + gen(ast.type()-ast_addeq+op_addeqc,num_table[ast.child()[1].num()],ast.line()); } break; case ast_lnkeq: - if(ast.get_children()[1].get_type()!=ast_str) - calc_gen(ast.get_children()[1]); + if(ast.child()[1].type()!=ast_str) + calc_gen(ast.child()[1]); else - regist_string(ast.get_children()[1].get_str()); - mcall(ast.get_children()[0]); - if(ast.get_children()[1].get_type()!=ast_str) - gen(op_lnkeq,0,ast.get_line()); + regist_string(ast.child()[1].str()); + mcall(ast.child()[0]); + if(ast.child()[1].type()!=ast_str) + gen(op_lnkeq,0,ast.line()); else - gen(op_lnkeqc,string_table[ast.get_children()[1].get_str()],ast.get_line()); + gen(op_lnkeqc,str_table[ast.child()[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.get_children()[0]); - if(ast.get_children()[1].get_type()!=ast_num) + calc_gen(ast.child()[0]); + if(ast.child()[1].type()!=ast_num) { - calc_gen(ast.get_children()[1]); - gen(ast.get_type()-ast_add+op_add,0,ast.get_line()); + calc_gen(ast.child()[1]); + gen(ast.type()-ast_add+op_add,0,ast.line()); } else { - regist_number(ast.get_children()[1].get_num()); - gen(ast.get_type()-ast_add+op_addc,number_table[ast.get_children()[1].get_num()],ast.get_line()); + regist_number(ast.child()[1].num()); + gen(ast.type()-ast_add+op_addc,num_table[ast.child()[1].num()],ast.line()); } break; case ast_link: - calc_gen(ast.get_children()[0]); - if(ast.get_children()[1].get_type()!=ast_str) + calc_gen(ast.child()[0]); + if(ast.child()[1].type()!=ast_str) { - calc_gen(ast.get_children()[1]); - gen(op_lnk,0,ast.get_line()); + calc_gen(ast.child()[1]); + gen(op_lnk,0,ast.line()); } else { - regist_string(ast.get_children()[1].get_str()); - gen(op_lnkc,string_table[ast.get_children()[1].get_str()],ast.get_line()); + regist_string(ast.child()[1].str()); + gen(op_lnkc,str_table[ast.child()[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.get_children()[0]); - calc_gen(ast.get_children()[1]); - gen(ast.get_type()-ast_cmpeq+op_eq,0,ast.get_line()); + calc_gen(ast.child()[0]); + calc_gen(ast.child()[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.get_children()[0]); - if(ast.get_children()[1].get_type()!=ast_num) + calc_gen(ast.child()[0]); + if(ast.child()[1].type()!=ast_num) { - calc_gen(ast.get_children()[1]); - gen(ast.get_type()-ast_less+op_less,0,ast.get_line()); + calc_gen(ast.child()[1]); + gen(ast.type()-ast_less+op_less,0,ast.line()); } else { - regist_number(ast.get_children()[1].get_num()); - gen(ast.get_type()-ast_less+op_lessc,number_table[ast.get_children()[1].get_num()],ast.get_line()); + regist_number(ast.child()[1].num()); + gen(ast.type()-ast_less+op_lessc,num_table[ast.child()[1].num()],ast.line()); } break; case ast_trino:trino_gen(ast);break; case ast_neg: - calc_gen(ast.get_children()[0]); - gen(op_usub,0,ast.get_line()); + calc_gen(ast.child()[0]); + gen(op_usub,0,ast.line()); break; case ast_not: - calc_gen(ast.get_children()[0]); - gen(op_unot,0,ast.get_line()); + calc_gen(ast.child()[0]); + gen(op_unot,0,ast.line()); break; case ast_def: single_def(ast); - call_id(ast.get_children()[0]); + call_id(ast.child()[0]); break; } return; @@ -1125,8 +1133,8 @@ void nasal_codegen::calc_gen(const nasal_ast& ast) void nasal_codegen::block_gen(const nasal_ast& ast) { - for(auto& tmp:ast.get_children()) - switch(tmp.get_type()) + for(auto& tmp:ast.child()) + switch(tmp.type()) { case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break; case ast_def:def_gen(tmp);break; @@ -1145,10 +1153,10 @@ void nasal_codegen::block_gen(const nasal_ast& ast) case ast_forindex: case ast_foreach:loop_gen(tmp);break; case ast_equal: - if(tmp.get_children()[0].get_type()==ast_id) + if(tmp.child()[0].type()==ast_id) { - calc_gen(tmp.get_children()[1]); - mcall_id(tmp.get_children()[0]); + calc_gen(tmp.child()[1]); + mcall_id(tmp.child()[0]); // only the first mcall_id can use load if(exec_code.back().op==op_mcalll) exec_code.back().op=op_loadl; @@ -1160,7 +1168,7 @@ void nasal_codegen::block_gen(const nasal_ast& ast) else { calc_gen(tmp); - gen(op_pop,0,tmp.get_line()); + gen(op_pop,0,tmp.line()); } break; case ast_id: @@ -1205,40 +1213,40 @@ void nasal_codegen::ret_gen(const nasal_ast& ast) gen(op_pop,0,0); gen(op_cntpop,0,0); } - if(ast.get_children().size()) - calc_gen(ast.get_children()[0]); + if(ast.child().size()) + calc_gen(ast.child()[0]); else - gen(op_pnil,0,ast.get_line()); - gen(op_ret,0,ast.get_line()); + gen(op_pnil,0,ast.line()); + gen(op_ret,0,ast.line()); return; } -void nasal_codegen::compile(const nasal_ast& ast,const std::vector& files) +void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import) { error=0; in_foreach=0; in_forindex=0; fileindex=0; - number_table.clear(); - string_table.clear(); + num_table.clear(); + str_table.clear(); num_res_table.clear(); str_res_table.clear(); - file_name=files; + file_name=import.get_file(); exec_code.clear(); global.clear(); local.clear(); // search symbols first - find_symbol(ast); + find_symbol(parse.ast()); gen(op_intg,global.size(),0); - for(auto& tmp:ast.get_children()) + for(auto& tmp:parse.ast().child()) { - switch(tmp.get_type()) + switch(tmp.type()) { case ast_null:case ast_nil:case ast_num:case ast_str:case ast_func:break; - case ast_file:fileindex=tmp.get_num();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; @@ -1247,10 +1255,10 @@ void nasal_codegen::compile(const nasal_ast& ast,const std::vector& case ast_forindex: case ast_foreach:loop_gen(tmp);break; case ast_equal: - if(tmp.get_children()[0].get_type()==ast_id) + if(tmp.child()[0].type()==ast_id) { - calc_gen(tmp.get_children()[1]); - mcall_id(tmp.get_children()[0]); + calc_gen(tmp.child()[1]); + mcall_id(tmp.child()[0]); // only the first mcall_id can use load if(exec_code.back().op==op_mcalll) exec_code.back().op=op_loadl; @@ -1262,7 +1270,7 @@ void nasal_codegen::compile(const nasal_ast& ast,const std::vector& else { calc_gen(tmp); - gen(op_pop,0,tmp.get_line()); + gen(op_pop,0,tmp.line()); } break; case ast_id: @@ -1289,7 +1297,7 @@ void nasal_codegen::compile(const nasal_ast& ast,const std::vector& case ast_grt: case ast_or: case ast_and: - case ast_trino:calc_gen(tmp);gen(op_pop,0,tmp.get_line());break; + case ast_trino:calc_gen(tmp);gen(op_pop,0,tmp.line());break; } } gen(op_exit,0,0); @@ -1341,7 +1349,6 @@ void nasal_codegen::print() std::cout<<".symbol \""< local; void mark(); void sweep(); - void gc_init(const std::vector&); - void gc_clear(); - nasal_ref gc_alloc(const uint8_t); + void init(const std::vector&); + void clear(); + nasal_ref alloc(const uint8_t); nasal_ref builtin_alloc(const uint8_t); }; @@ -350,7 +350,7 @@ struct nasal_gc void nasal_gc::mark() { std::queue bfs; - for(auto i:local) + for(auto& i:local) bfs.push(i); for(nasal_ref* i=val_stack;i<=stack_top;++i) bfs.push(*i); @@ -406,7 +406,7 @@ void nasal_gc::sweep() } return; } -void nasal_gc::gc_init(const std::vector& strs) +void nasal_gc::init(const std::vector& strs) { for(uint8_t i=vm_str;i& strs) } return; } -void nasal_gc::gc_clear() +void nasal_gc::clear() { for(auto i:memory) delete i; @@ -445,7 +445,7 @@ void nasal_gc::gc_clear() str_addrs.clear(); return; } -nasal_ref nasal_gc::gc_alloc(uint8_t type) +nasal_ref nasal_gc::alloc(uint8_t type) { if(free_list[type].empty()) { @@ -467,7 +467,7 @@ nasal_ref nasal_gc::gc_alloc(uint8_t type) nasal_ref nasal_gc::builtin_alloc(uint8_t type) { // when running a builtin function,alloc will run more than one time - // this may cause mark-sweep in gc_alloc + // this may cause mark-sweep in gc::alloc // and the value got before will be collected,this is a fatal error // so use builtin_alloc in builtin functions if this function uses alloc more then one time if(free_list[type].empty()) diff --git a/nasal_import.h b/nasal_import.h index 008992b..23a653a 100644 --- a/nasal_import.h +++ b/nasal_import.h @@ -8,7 +8,7 @@ private: nasal_lexer import_lex; nasal_parse import_par; nasal_ast import_ast; - std::vector filename_table; + std::vector file_table; void die(const std::string&,const char*); bool check_import(const nasal_ast&); bool check_exist(const std::string&); @@ -17,9 +17,8 @@ private: nasal_ast load(nasal_ast&,uint16_t); public: uint32_t err(){return error;} - void link(nasal_ast&,const std::string&); - const nasal_ast& ast(){return import_ast;} - const std::vector& get_file(){return filename_table;} + void link(nasal_parse&,const std::string&); + const std::vector& get_file() const {return file_table;} }; void nasal_import::die(const std::string& file,const char* stage) @@ -37,16 +36,16 @@ only this kind of node can be recognized as 'import': call_func string:'filename' */ - if(node.get_type()!=ast_call) + if(node.type()!=ast_call) return false; - const std::vector& ref_vec=node.get_children(); + const std::vector& ref_vec=node.child(); if(ref_vec.size()!=2) return false; - if(ref_vec[0].get_str()!="import") + if(ref_vec[0].str()!="import") return false; - if(ref_vec[1].get_type()!=ast_callf) + if(ref_vec[1].type()!=ast_callf) return false; - if(ref_vec[1].get_children().size()!=1 || ref_vec[1].get_children()[0].get_type()!=ast_str) + if(ref_vec[1].child().size()!=1 || ref_vec[1].child()[0].type()!=ast_str) return false; return true; } @@ -54,76 +53,70 @@ only this kind of node can be recognized as 'import': bool nasal_import::check_exist(const std::string& file) { // avoid importing the same file - for(auto& fname:filename_table) + for(auto& fname:file_table) if(file==fname) return true; - filename_table.push_back(file); + file_table.push_back(file); return false; } void nasal_import::linker(nasal_ast& root,nasal_ast&& add_root) { // add children of add_root to the back of root - for(auto& i:add_root.get_children()) - root.add_child(std::move(i)); + for(auto& i:add_root.child()) + root.add(std::move(i)); } nasal_ast nasal_import::file_import(nasal_ast& node) { - // initializing - nasal_ast tmp(0,ast_root); - // get filename and set node to ast_null - std::string filename=node.get_children()[1].get_children()[0].get_str(); + std::string filename=node.child()[1].child()[0].str(); node.clear(); // avoid infinite loading loop if(check_exist(filename)) - return tmp; + return {0,ast_root}; // start importing... - import_lex.open(filename); - import_lex.scan(); + import_lex.scan(filename); if(import_lex.err()) { die(filename,"lexer"); - return tmp; + return {0,ast_root}; } - import_par.compile(import_lex.get_tokens()); + import_par.compile(import_lex); if(import_par.err()) { die(filename,"parser"); - return tmp; + return {0,ast_root}; } - tmp=std::move(import_par.ast()); + nasal_ast tmp=std::move(import_par.ast()); // check if tmp has 'import' - return load(tmp,filename_table.size()-1); + return load(tmp,file_table.size()-1); } nasal_ast nasal_import::load(nasal_ast& root,uint16_t fileindex) { nasal_ast new_root(0,ast_root); - for(auto& i:root.get_children()) + for(auto& i:root.child()) if(check_import(i)) linker(new_root,file_import(i)); // add root to the back of new_root nasal_ast file_head(0,ast_file); file_head.set_num(fileindex); - new_root.add_child(std::move(file_head)); + new_root.add(std::move(file_head)); linker(new_root,std::move(root)); return new_root; } -void nasal_import::link(nasal_ast& root,const std::string& self) +void nasal_import::link(nasal_parse& parse,const std::string& self) { // initializing error=0; - filename_table.clear(); - filename_table.push_back(self); - import_ast.clear(); + file_table={self}; // scan root and import files,then generate a new ast and return to import_ast // the main file's index is 0 - import_ast=load(root,0); + parse.ast()=load(parse.ast(),0); } #endif \ No newline at end of file diff --git a/nasal_lexer.h b/nasal_lexer.h index 9508fae..7d598b8 100644 --- a/nasal_lexer.h +++ b/nasal_lexer.h @@ -1,22 +1,24 @@ #ifndef __NASAL_LEXER_H__ #define __NASAL_LEXER_H__ -#define IS_ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')) -#define IS_HEX(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F')) -#define IS_OCT(c) ('0'<=c&&c<='7') -#define IS_DIGIT(c) ('0'<=c&&c<='9') -#define IS_STR(c) (c=='\''||c=='\"'||c=='`') +#define ID(c) ((c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')) +#define HEX(c) (('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F')) +#define OCT(c) ('0'<=c&&c<='7') +#define DIGIT(c) ('0'<=c&&c<='9') +#define STR(c) (c=='\''||c=='\"'||c=='`') // single operators have only one character -#define IS_SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\ +#define SINGLE_OPERATOR(c) (c=='('||c==')'||c=='['||c==']'||c=='{'||c=='}'||c==','||c==';'||c=='|'||c==':'||\ c=='?'||c=='`'||c=='&'||c=='@'||c=='%'||c=='$'||c=='^'||c=='\\') // calculation operators may have two chars, for example: += -= *= /= ~= != == >= <= -#define IS_CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~') -#define IS_NOTE(c) (c=='#') +#define CALC_OPERATOR(c) (c=='='||c=='+'||c=='-'||c=='*'||c=='!'||c=='/'||c=='<'||c=='>'||c=='~') +#define NOTE(c) (c=='#') enum token_type { - tok_null=0, - tok_num,tok_str,tok_id, + tok_null=0,// null token default token type + tok_num, // number basic token type + tok_str, // string basic token type + tok_id, // identifier basic token type tok_for,tok_forindex,tok_foreach,tok_while, tok_var,tok_func,tok_break,tok_continue, tok_ret,tok_if,tok_elsif,tok_else,tok_nil, @@ -28,7 +30,7 @@ enum token_type tok_eq, tok_addeq,tok_subeq,tok_multeq,tok_diveq,tok_lnkeq, tok_cmpeq,tok_neq,tok_less,tok_leq,tok_grt,tok_geq, - tok_eof + tok_eof // end of token list }; struct @@ -105,26 +107,25 @@ private: std::vector tokens; uint32_t get_type(const std::string&); void die(const char*); + void open(const std::string&); std::string id_gen(); std::string num_gen(); std::string str_gen(); public: - void open(const std::string&); - void scan(); - void print(); uint32_t err(){return error;} - const std::vector& get_tokens(){return tokens;} + void scan(const std::string&); + void print(); + const std::vector& get_tokens() const {return tokens;} }; -void nasal_lexer::open(const std::string& filename) +void nasal_lexer::open(const std::string& file) { error=0; - res.clear(); - std::ifstream fin(filename,std::ios::binary); + std::ifstream fin(file,std::ios::binary); if(fin.fail()) { ++error; - std::cout<<"[lexer] cannot open file <"<.\n"; + std::cout<<"[lexer] cannot open file <"<.\n"; } std::stringstream ss; ss< [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*) std::string str=""; - while(ptr=size) break; - if(IS_ID(res[ptr])) + if(ID(res[ptr])) { str=id_gen(); - tokens.push_back({line,get_type(str),str}); - if(!tokens.back().type) - tokens.back().type=tok_id; + uint32_t type=get_type(str); + tokens.push_back({line,type?type:tok_id,str}); } - else if(IS_DIGIT(res[ptr])) + else if(DIGIT(res[ptr])) tokens.push_back({line,tok_num,num_gen()}); - else if(IS_STR(res[ptr])) + else if(STR(res[ptr])) tokens.push_back({line,tok_str,str_gen()}); - else if(IS_SINGLE_OPERATOR(res[ptr])) + else if(SINGLE_OPERATOR(res[ptr])) { str=res[ptr]; code+=res[ptr]; @@ -311,20 +311,14 @@ void nasal_lexer::scan() } else if(res[ptr]=='.') { + str="."; if(ptr+2 tok_list; + std::vector tokens; std::vector error_token; - int in_function; // count when generating function block,used to check return-expression - int in_loop; // count when generating loop block,used to check break/continue-expression - void die(int,const std::string&&); - void die(int,const char*); - void match(int type,const char* err_info=""); - bool check_comma(const int*); + + void die(uint32_t,const std::string&); + 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_special_call(); bool need_semi_check(const nasal_ast&); void check_memory_reachable(const nasal_ast&); - nasal_ast null_node_gen(); - nasal_ast nil_gen(); - nasal_ast num_gen(); - nasal_ast str_gen(); - nasal_ast id_gen(); - nasal_ast vec_gen(); - nasal_ast hash_gen(); - nasal_ast hmem_gen(); - nasal_ast func_gen(); - nasal_ast args_gen(); + nasal_ast null(); + nasal_ast nil(); + nasal_ast num(); + nasal_ast str(); + nasal_ast id(); + nasal_ast vec(); + nasal_ast hash(); + nasal_ast hmem(); + nasal_ast func(); + nasal_ast args(); nasal_ast lcurve_expr(); nasal_ast expr(); nasal_ast exprs(); @@ -100,36 +100,35 @@ private: nasal_ast ret_expr(); public: uint32_t err(){return error;} - void compile(const std::vector&); + void compile(const nasal_lexer&); nasal_ast& ast(){return root;} + const nasal_ast& ast() const {return root;} }; -void nasal_parse::compile(const std::vector& toks) +void nasal_parse::compile(const nasal_lexer& lexer) { - tok_list=toks; - ptr=in_function=in_loop=error=0; - root.clear(); + tokens=lexer.get_tokens(); + ptr=in_func=in_loop=error=0; error_token.clear(); - root.set_line(1); - root.set_type(ast_root); - while(tok_list[ptr].type!=tok_eof) + root={1,ast_root}; + while(tokens[ptr].type!=tok_eof) { - int err_tok_size=error_token.size(); - root.add_child(expr()); - if(tok_list[ptr].type==tok_semi) + uint32_t err_tok_size=error_token.size(); + root.add(expr()); + if(tokens[ptr].type==tok_semi) match(tok_semi); // if detect error token, avoid checking semicolon else if(error_token.size()>err_tok_size) continue; // the last expression can be recognized without semi - else if(need_semi_check(root.get_children().back()) && tok_list[ptr].type!=tok_eof) + else if(need_semi_check(root.child().back()) && tokens[ptr].type!=tok_eof) die(error_line,"expected \";\""); } if(!error_token.size()) return; ++error; std::cout<<"[parse] line"; - int err_line=0; + uint32_t err_line=0; for(auto& tok:error_token) if(err_line!=tok.line) { @@ -139,25 +138,19 @@ void nasal_parse::compile(const std::vector& toks) std::cout <<" have fatal syntax errors." <<"check \'(\',\'[\',\'{\',\')\',\']\',\'}\' match or not.\n"; - return; } -void nasal_parse::die(int line,const std::string&& info) +void nasal_parse::die(uint32_t line,const std::string& info) { ++error; std::cout<<"[parse] line "<1 || tmp.get_children()[0].get_type()==ast_subvec)) - die(tmp.get_line(),"bad left-value"); + 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)) + die(tmp.line(),"bad left-value"); } - else if(node.get_type()!=ast_id) - die(node.get_line(),"bad left-value"); + else if(node.type()!=ast_id) + die(node.line(),"bad left-value"); return; } -nasal_ast nasal_parse::null_node_gen() +nasal_ast nasal_parse::null() { - return nasal_ast(tok_list[ptr].line,ast_null); + return {tokens[ptr].line,ast_null}; } -nasal_ast nasal_parse::nil_gen() +nasal_ast nasal_parse::nil() { - return nasal_ast(tok_list[ptr].line,ast_nil); + return {tokens[ptr].line,ast_nil}; } -nasal_ast nasal_parse::num_gen() +nasal_ast nasal_parse::num() { - nasal_ast node(tok_list[ptr].line,ast_num); - node.set_num(str2num(tok_list[ptr].str.c_str())); + nasal_ast node(tokens[ptr].line,ast_num); + node.set_num(str2num(tokens[ptr].str.c_str())); return node; } -nasal_ast nasal_parse::str_gen() +nasal_ast nasal_parse::str() { - nasal_ast node(tok_list[ptr].line,ast_str); - node.set_str(tok_list[ptr].str); + nasal_ast node(tokens[ptr].line,ast_str); + node.set_str(tokens[ptr].str); return node; } -nasal_ast nasal_parse::id_gen() +nasal_ast nasal_parse::id() { - nasal_ast node(tok_list[ptr].line,ast_id); - node.set_str(tok_list[ptr].str); + nasal_ast node(tokens[ptr].line,ast_id); + node.set_str(tokens[ptr].str); return node; } -nasal_ast nasal_parse::vec_gen() +nasal_ast nasal_parse::vec() { // panic set for this token is not ',' // this is the FIRST set of calculation // array end with tok_null=0 - const int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_null}; - nasal_ast node(tok_list[ptr].line,ast_vec); + const uint32_t panic_set[]={ + tok_id,tok_str,tok_num, + tok_not,tok_sub,tok_nil, + tok_func,tok_var,tok_lcurve, + tok_lbrace,tok_lbracket,tok_null + }; + nasal_ast node(tokens[ptr].line,ast_vec); match(tok_lbracket); - while(tok_list[ptr].type!=tok_rbracket) + while(tokens[ptr].type!=tok_rbracket) { - node.add_child(calc()); - if(tok_list[ptr].type==tok_comma) + node.add(calc()); + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_eof) + else if(tokens[ptr].type==tok_eof) break; - else if(tok_list[ptr].type!=tok_rbracket && !check_comma(panic_set)) + else if(tokens[ptr].type!=tok_rbracket && !check_comma(panic_set)) break; } match(tok_rbracket,"expected \']\' when generating vector"); return node; } -nasal_ast nasal_parse::hash_gen() +nasal_ast nasal_parse::hash() { - nasal_ast node(tok_list[ptr].line,ast_hash); + nasal_ast node(tokens[ptr].line,ast_hash); match(tok_lbrace); - while(tok_list[ptr].type!=tok_rbrace) + while(tokens[ptr].type!=tok_rbrace) { - node.add_child(hmem_gen()); - if(tok_list[ptr].type==tok_comma) + node.add(hmem()); + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_id || tok_list[ptr].type==tok_str)// first set of hashmember + else if(tokens[ptr].type==tok_id || tokens[ptr].type==tok_str)// first set of hashmember die(error_line,"expected \',\' between hash members"); else break; @@ -336,53 +334,53 @@ nasal_ast nasal_parse::hash_gen() match(tok_rbrace,"expected \'}\' when generating hash"); return node; } -nasal_ast nasal_parse::hmem_gen() +nasal_ast nasal_parse::hmem() { - nasal_ast node(tok_list[ptr].line,ast_hashmember); - if(tok_list[ptr].type==tok_id) + nasal_ast node(tokens[ptr].line,ast_hashmember); + if(tokens[ptr].type==tok_id) { - node.add_child(id_gen()); + node.add(id()); match(tok_id); } - else if(tok_list[ptr].type==tok_str) + else if(tokens[ptr].type==tok_str) { - node.add_child(str_gen()); + node.add(str()); match(tok_str); } else match(tok_id); match(tok_colon); - node.add_child(calc()); + node.add(calc()); return node; } -nasal_ast nasal_parse::func_gen() +nasal_ast nasal_parse::func() { - nasal_ast node(tok_list[ptr].line,ast_func); + nasal_ast node(tokens[ptr].line,ast_func); match(tok_func); - if(tok_list[ptr].type==tok_lcurve) - node.add_child(args_gen()); + if(tokens[ptr].type==tok_lcurve) + node.add(args()); else - node.add_child(null_node_gen()); - node.add_child(exprs()); + node.add(null()); + node.add(exprs()); return node; } -nasal_ast nasal_parse::args_gen() +nasal_ast nasal_parse::args() { - nasal_ast node(tok_list[ptr].line,ast_args); + nasal_ast node(tokens[ptr].line,ast_args); match(tok_lcurve); - while(tok_list[ptr].type!=tok_rcurve) + while(tokens[ptr].type!=tok_rcurve) { - nasal_ast tmp=id_gen(); + nasal_ast tmp=id(); match(tok_id); - if(tok_list[ptr].type==tok_eq || tok_list[ptr].type==tok_ellipsis) + if(tokens[ptr].type==tok_eq || tokens[ptr].type==tok_ellipsis) { - nasal_ast special_arg(tok_list[ptr].line,ast_null); - if(tok_list[ptr].type==tok_eq) + nasal_ast special_arg(tokens[ptr].line,ast_null); + if(tokens[ptr].type==tok_eq) { match(tok_eq); special_arg=std::move(tmp); special_arg.set_type(ast_default_arg); - special_arg.add_child(calc()); + special_arg.add(calc()); } else { @@ -390,54 +388,54 @@ nasal_ast nasal_parse::args_gen() special_arg=std::move(tmp); special_arg.set_type(ast_dynamic_id); } - node.add_child(std::move(special_arg)); + node.add(std::move(special_arg)); } else - node.add_child(std::move(tmp)); - if(tok_list[ptr].type==tok_comma) + node.add(std::move(tmp)); + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_id)// first set of identifier + else if(tokens[ptr].type==tok_id)// first set of identifier die(error_line,"expected \',\' between identifiers"); else break; } match(tok_rcurve,"expected \')\' after parameter list"); - std::string args_format="func("; - for(auto& tmp:node.get_children()) + std::string format="func("; + for(auto& tmp:node.child()) { - switch(tmp.get_type()) + switch(tmp.type()) { - case ast_id: args_format+=tmp.get_str();break; - case ast_default_arg: args_format+=tmp.get_str()+"=val";break; - case ast_dynamic_id: args_format+=tmp.get_str()+"...";break; + case ast_id: format+=tmp.str();break; + case ast_default_arg: format+=tmp.str()+"=val";break; + case ast_dynamic_id: format+=tmp.str()+"...";break; } - args_format+=",)"[&tmp==&node.get_children().back()]; + format+=",)"[&tmp==&node.child().back()]; } bool checked_default_val=false,checked_dynamic_ids=false; - for(auto& tmp:node.get_children()) + for(auto& tmp:node.child()) { - if(tmp.get_type()==ast_default_arg) + if(tmp.type()==ast_default_arg) checked_default_val=true; - else if(tmp.get_type()==ast_dynamic_id) + else if(tmp.type()==ast_dynamic_id) checked_dynamic_ids=true; - if(checked_default_val && tmp.get_type()!=ast_default_arg) - die(tmp.get_line(),"must use default paras after using it once: "+args_format); - if(checked_dynamic_ids && &tmp!=&node.get_children().back()) - die(tmp.get_line(),"dynamic para must be the end: "+args_format); + 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()) + die(tmp.line(),"dynamic para must be the end: "+format); } std::unordered_map argname_table; - for(auto& tmp:node.get_children()) + for(auto& tmp:node.child()) { std::string new_name; - switch(tmp.get_type()) + switch(tmp.type()) { case ast_dynamic_id: - case ast_id: new_name=tmp.get_str();break; - case ast_default_arg:new_name=tmp.get_str();break; + case ast_id: new_name=tmp.str();break; + case ast_default_arg:new_name=tmp.str();break; } if(argname_table.count(new_name)) - die(tmp.get_line(),"parameter's name repeats: "+new_name); + die(tmp.line(),"parameter's name repeats: "+new_name); else argname_table[new_name]=true; } @@ -445,17 +443,16 @@ nasal_ast nasal_parse::args_gen() } nasal_ast nasal_parse::lcurve_expr() { - if(tok_list[ptr+1].type==tok_var) + if(tokens[ptr+1].type==tok_var) return definition(); return check_multi_scalar()?multi_assgin():calc(); } nasal_ast nasal_parse::expr() { - nasal_ast node(tok_list[ptr].line,ast_null); - int tok_type=tok_list[ptr].type; + 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"); - if(tok_type==tok_ret && !in_function) + if(tok_type==tok_ret && !in_func) die(error_line,"use return in the function"); switch(tok_type) { @@ -467,52 +464,52 @@ nasal_ast nasal_parse::expr() case tok_lbracket: case tok_lbrace: case tok_sub: - case tok_not: node=calc(); break; - case tok_var: node=definition(); break; - case tok_lcurve: node=lcurve_expr(); break; + case tok_not: return calc(); break; + case tok_var: return definition(); break; + case tok_lcurve: return lcurve_expr(); break; case tok_for: case tok_forindex: case tok_foreach: - case tok_while: node=loop(); break; - case tok_if: node=conditional(); break; - case tok_continue: node=continue_expr(); break; - case tok_break: node=break_expr(); break; - case tok_ret: node=ret_expr(); break; - case tok_semi: break; - default:error_token.push_back(tok_list[ptr]);++ptr;break; + case tok_while: return loop(); break; + case tok_if: return conditional(); break; + case tok_continue: return continue_expr(); break; + case tok_break: return break_expr(); break; + case tok_ret: return ret_expr(); break; + case tok_semi: break; + default:error_token.push_back(tokens[ptr]);++ptr;break; } - return node; + return {tokens[ptr].line,ast_null}; } nasal_ast nasal_parse::exprs() { - if(tok_list[ptr].type==tok_eof) + if(tokens[ptr].type==tok_eof) { die(error_line,"expected expression block"); - return null_node_gen(); + return null(); } - nasal_ast node(tok_list[ptr].line,ast_block); - if(tok_list[ptr].type==tok_lbrace) + nasal_ast node(tokens[ptr].line,ast_block); + if(tokens[ptr].type==tok_lbrace) { match(tok_lbrace); - while(tok_list[ptr].type!=tok_rbrace && tok_list[ptr].type!=tok_eof) + while(tokens[ptr].type!=tok_rbrace && tokens[ptr].type!=tok_eof) { - int err_tok_size=error_token.size(); - node.add_child(expr()); - if(tok_list[ptr].type==tok_semi) + uint32_t err_tok_size=error_token.size(); + node.add(expr()); + if(tokens[ptr].type==tok_semi) match(tok_semi); // if detect error token, avoid checking semicolon else if(error_token.size()>err_tok_size) continue; // the last expression can be recognized without semi - else if(need_semi_check(node.get_children().back()) && tok_list[ptr].type!=tok_rbrace) + else if(need_semi_check(node.child().back()) && tokens[ptr].type!=tok_rbrace) die(error_line,"expected \";\""); } match(tok_rbrace,"expected \'}\' when generating expressions"); } else { - node.add_child(expr()); - if(tok_list[ptr].type==tok_semi) + node.add(expr()); + if(tokens[ptr].type==tok_semi) match(tok_semi); } return node; @@ -520,25 +517,25 @@ nasal_ast nasal_parse::exprs() nasal_ast nasal_parse::calc() { nasal_ast node=or_expr(); - if(tok_list[ptr].type==tok_quesmark) + if(tokens[ptr].type==tok_quesmark) { // trinocular calculation - nasal_ast tmp(tok_list[ptr].line,ast_trino); + nasal_ast tmp(tokens[ptr].line,ast_trino); match(tok_quesmark); - tmp.add_child(std::move(node)); - tmp.add_child(calc()); + tmp.add(std::move(node)); + tmp.add(calc()); match(tok_colon); - tmp.add_child(calc()); + tmp.add(calc()); node=std::move(tmp); } - else if(tok_eq<=tok_list[ptr].type && tok_list[ptr].type<=tok_lnkeq) + else if(tok_eq<=tokens[ptr].type && tokens[ptr].type<=tok_lnkeq) { check_memory_reachable(node); // tok_eq~tok_lnkeq is 37 to 42,ast_equal~ast_lnkeq is 21~26 - nasal_ast tmp(tok_list[ptr].line,tok_list[ptr].type-tok_eq+ast_equal); - tmp.add_child(std::move(node)); - match(tok_list[ptr].type); - tmp.add_child(calc()); + nasal_ast tmp(tokens[ptr].line,tokens[ptr].type-tok_eq+ast_equal); + tmp.add(std::move(node)); + match(tokens[ptr].type); + tmp.add(calc()); node=std::move(tmp); } return node; @@ -546,12 +543,12 @@ nasal_ast nasal_parse::calc() nasal_ast nasal_parse::or_expr() { nasal_ast node=and_expr(); - while(tok_list[ptr].type==tok_or) + while(tokens[ptr].type==tok_or) { - nasal_ast tmp(tok_list[ptr].line,ast_or); - tmp.add_child(std::move(node)); + nasal_ast tmp(tokens[ptr].line,ast_or); + tmp.add(std::move(node)); match(tok_or); - tmp.add_child(and_expr()); + tmp.add(and_expr()); node=std::move(tmp); } return node; @@ -559,12 +556,12 @@ nasal_ast nasal_parse::or_expr() nasal_ast nasal_parse::and_expr() { nasal_ast node=cmp_expr(); - while(tok_list[ptr].type==tok_and) + while(tokens[ptr].type==tok_and) { - nasal_ast tmp(tok_list[ptr].line,ast_and); - tmp.add_child(std::move(node)); + nasal_ast tmp(tokens[ptr].line,ast_and); + tmp.add(std::move(node)); match(tok_and); - tmp.add_child(cmp_expr()); + tmp.add(cmp_expr()); node=std::move(tmp); } return node; @@ -572,13 +569,13 @@ nasal_ast nasal_parse::and_expr() nasal_ast nasal_parse::cmp_expr() { nasal_ast node=additive_expr(); - while(tok_cmpeq<=tok_list[ptr].type && tok_list[ptr].type<=tok_geq) + while(tok_cmpeq<=tokens[ptr].type && tokens[ptr].type<=tok_geq) { // tok_cmpeq~tok_geq is 43~48,ast_cmpeq~ast_geq is 27~32 - nasal_ast tmp(tok_list[ptr].line,tok_list[ptr].type-tok_cmpeq+ast_cmpeq); - tmp.add_child(std::move(node)); - match(tok_list[ptr].type); - tmp.add_child(additive_expr()); + nasal_ast tmp(tokens[ptr].line,tokens[ptr].type-tok_cmpeq+ast_cmpeq); + tmp.add(std::move(node)); + match(tokens[ptr].type); + tmp.add(additive_expr()); node=std::move(tmp); } return node; @@ -586,77 +583,77 @@ nasal_ast nasal_parse::cmp_expr() nasal_ast nasal_parse::additive_expr() { nasal_ast node=multive_expr(); - while(tok_list[ptr].type==tok_add || tok_list[ptr].type==tok_sub || tok_list[ptr].type==tok_link) + while(tokens[ptr].type==tok_add || tokens[ptr].type==tok_sub || tokens[ptr].type==tok_link) { - nasal_ast tmp(tok_list[ptr].line,ast_null); - switch(tok_list[ptr].type) + nasal_ast tmp(tokens[ptr].line,ast_null); + switch(tokens[ptr].type) { case tok_add: tmp.set_type(ast_add); break; case tok_sub: tmp.set_type(ast_sub); break; case tok_link: tmp.set_type(ast_link); break; } - tmp.add_child(std::move(node)); - match(tok_list[ptr].type); - tmp.add_child(multive_expr()); + tmp.add(std::move(node)); + match(tokens[ptr].type); + tmp.add(multive_expr()); node=std::move(tmp); } return node; } nasal_ast nasal_parse::multive_expr() { - nasal_ast node=(tok_list[ptr].type==tok_sub || tok_list[ptr].type==tok_not)?unary():scalar(); - while(tok_list[ptr].type==tok_mult || tok_list[ptr].type==tok_div) + nasal_ast node=(tokens[ptr].type==tok_sub || tokens[ptr].type==tok_not)?unary():scalar(); + while(tokens[ptr].type==tok_mult || tokens[ptr].type==tok_div) { - nasal_ast tmp(tok_list[ptr].line,tok_list[ptr].type-tok_mult+ast_mult); - tmp.add_child(std::move(node)); - match(tok_list[ptr].type); - tmp.add_child((tok_list[ptr].type==tok_sub || tok_list[ptr].type==tok_not)?unary():scalar()); + nasal_ast tmp(tokens[ptr].line,tokens[ptr].type-tok_mult+ast_mult); + tmp.add(std::move(node)); + match(tokens[ptr].type); + tmp.add((tokens[ptr].type==tok_sub || tokens[ptr].type==tok_not)?unary():scalar()); node=std::move(tmp); } return node; } nasal_ast nasal_parse::unary() { - nasal_ast node(tok_list[ptr].line,ast_null); - switch(tok_list[ptr].type) + nasal_ast node(tokens[ptr].line,ast_null); + switch(tokens[ptr].type) { case tok_sub:node.set_type(ast_neg);match(tok_sub);break; case tok_not:node.set_type(ast_not);match(tok_not);break; } - node.add_child((tok_list[ptr].type==tok_sub || tok_list[ptr].type==tok_not)?unary():scalar()); + node.add((tokens[ptr].type==tok_sub || tokens[ptr].type==tok_not)?unary():scalar()); return node; } nasal_ast nasal_parse::scalar() { - nasal_ast node(tok_list[ptr].line,ast_null); - if(tok_list[ptr].type==tok_nil) {node=nil_gen(); match(tok_nil);} - else if(tok_list[ptr].type==tok_num){node=num_gen(); match(tok_num);} - else if(tok_list[ptr].type==tok_str){node=str_gen(); match(tok_str);} - else if(tok_list[ptr].type==tok_id) {node=id_gen(); match(tok_id); } - else if(tok_list[ptr].type==tok_func) + nasal_ast node(tokens[ptr].line,ast_null); + if(tokens[ptr].type==tok_nil) {node=nil(); match(tok_nil);} + else if(tokens[ptr].type==tok_num){node=num(); match(tok_num);} + else if(tokens[ptr].type==tok_str){node=str(); match(tok_str);} + else if(tokens[ptr].type==tok_id) {node=id(); match(tok_id); } + else if(tokens[ptr].type==tok_func) { - ++in_function; - node=func_gen(); - --in_function; + ++in_func; + node=func(); + --in_func; } - else if(tok_list[ptr].type==tok_lbracket) - node=vec_gen(); - else if(tok_list[ptr].type==tok_lbrace) - node=hash_gen(); - else if(tok_list[ptr].type==tok_lcurve) + else if(tokens[ptr].type==tok_lbracket) + node=vec(); + else if(tokens[ptr].type==tok_lbrace) + node=hash(); + else if(tokens[ptr].type==tok_lcurve) { match(tok_lcurve); node=calc(); match(tok_rcurve); } - else if(tok_list[ptr].type==tok_var) + else if(tokens[ptr].type==tok_var) { match(tok_var); node.set_type(ast_def); - node.add_child(id_gen()); + node.add(id()); match(tok_id); match(tok_eq); - node.add_child(calc()); + node.add(calc()); } else { @@ -664,33 +661,32 @@ nasal_ast nasal_parse::scalar() return node; } // check call and avoid ambiguous syntax - if(is_call(tok_list[ptr].type) && !(tok_list[ptr].type==tok_lcurve && tok_list[ptr+1].type==tok_var)) + if(is_call(tokens[ptr].type) && !(tokens[ptr].type==tok_lcurve && tokens[ptr+1].type==tok_var)) { nasal_ast tmp=std::move(node); - node.set_line(tok_list[ptr].line); - node.set_type(ast_call); - node.add_child(std::move(tmp)); - while(is_call(tok_list[ptr].type)) - node.add_child(call_scalar()); + node={tokens[ptr].line,ast_call}; + node.add(std::move(tmp)); + while(is_call(tokens[ptr].type)) + node.add(call_scalar()); } return node; } nasal_ast nasal_parse::call_scalar() { - switch(tok_list[ptr].type) + switch(tokens[ptr].type) { case tok_lcurve: return callf(); break; case tok_lbracket: return callv(); break; case tok_dot: return callh(); break; } // should never run this expression - return nasal_ast(tok_list[ptr].line,ast_nil); + return {tokens[ptr].line,ast_nil}; } nasal_ast nasal_parse::callh() { - nasal_ast node(tok_list[ptr].line,ast_callh); + nasal_ast node(tokens[ptr].line,ast_callh); match(tok_dot); - node.set_str(tok_list[ptr].str); + node.set_str(tokens[ptr].str); match(tok_id); return node; } @@ -699,17 +695,23 @@ nasal_ast nasal_parse::callv() // panic set for this token is not ',' // this is the FIRST set of subvec // array end with tok_null=0 - const int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_colon,tok_null}; - nasal_ast node(tok_list[ptr].line,ast_callv); + const uint32_t panic_set[]={ + tok_id,tok_str,tok_num, + tok_not,tok_sub,tok_nil, + tok_func,tok_var,tok_lcurve, + tok_lbrace,tok_lbracket,tok_colon, + tok_null + }; + nasal_ast node(tokens[ptr].line,ast_callv); match(tok_lbracket); - while(tok_list[ptr].type!=tok_rbracket) + while(tokens[ptr].type!=tok_rbracket) { - node.add_child(subvec()); - if(tok_list[ptr].type==tok_comma) + node.add(subvec()); + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_eof) + else if(tokens[ptr].type==tok_eof) break; - else if(tok_list[ptr].type!=tok_rbracket && !check_comma(panic_set)) + else if(tokens[ptr].type!=tok_rbracket && !check_comma(panic_set)) break; } match(tok_rbracket,"expected \']\' when calling vector"); @@ -720,18 +722,23 @@ nasal_ast nasal_parse::callf() // panic set for this token is not ',' // this is the FIRST set of calculation/hashmember // array end with tok_null=0 - const int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_null}; - nasal_ast node(tok_list[ptr].line,ast_callf); + const uint32_t panic_set[]={ + tok_id,tok_str,tok_num, + tok_not,tok_sub,tok_nil, + tok_func,tok_var,tok_lcurve, + tok_lbrace,tok_lbracket,tok_null + }; + nasal_ast node(tokens[ptr].line,ast_callf); bool special_call=check_special_call(); match(tok_lcurve); - while(tok_list[ptr].type!=tok_rcurve) + while(tokens[ptr].type!=tok_rcurve) { - node.add_child(special_call?hmem_gen():calc()); - if(tok_list[ptr].type==tok_comma) + node.add(special_call?hmem():calc()); + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_eof) + else if(tokens[ptr].type==tok_eof) break; - else if(tok_list[ptr].type!=tok_rcurve && !check_comma(panic_set)) + else if(tokens[ptr].type!=tok_rcurve && !check_comma(panic_set)) break; } match(tok_rcurve,"expected \')\' when calling function"); @@ -739,42 +746,42 @@ nasal_ast nasal_parse::callf() } nasal_ast nasal_parse::subvec() { - nasal_ast node=tok_list[ptr].type==tok_colon?nil_gen():calc(); - if(tok_list[ptr].type==tok_colon) + nasal_ast node=tokens[ptr].type==tok_colon?nil():calc(); + if(tokens[ptr].type==tok_colon) { - nasal_ast tmp(node.get_line(),ast_subvec); + nasal_ast tmp(node.line(),ast_subvec); match(tok_colon); - tmp.add_child(std::move(node)); - tmp.add_child((tok_list[ptr].type==tok_comma || tok_list[ptr].type==tok_rbracket)?nil_gen():calc()); + tmp.add(std::move(node)); + tmp.add((tokens[ptr].type==tok_comma || tokens[ptr].type==tok_rbracket)?nil():calc()); node=std::move(tmp); } return node; } nasal_ast nasal_parse::definition() { - nasal_ast node(tok_list[ptr].line,ast_def); - if(tok_list[ptr].type==tok_var) + nasal_ast node(tokens[ptr].line,ast_def); + if(tokens[ptr].type==tok_var) { match(tok_var); - switch(tok_list[ptr].type) + switch(tokens[ptr].type) { - case tok_id: node.add_child(id_gen());match(tok_id); break; - case tok_lcurve: node.add_child(var_outcurve_def()); 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(tok_list[ptr].type==tok_lcurve) - node.add_child(var_incurve_def()); + else if(tokens[ptr].type==tok_lcurve) + node.add(var_incurve_def()); match(tok_eq); - if(tok_list[ptr].type==tok_lcurve) - node.add_child(check_multi_scalar()?multi_scalar(false):calc()); + if(tokens[ptr].type==tok_lcurve) + node.add(check_multi_scalar()?multi_scalar(false):calc()); else - node.add_child(calc()); - if(node.get_children()[0].get_type()==ast_id && node.get_children()[1].get_type()==ast_multi_scalar) - die(node.get_children()[1].get_line(),"one identifier cannot accept too many values"); - else if(node.get_children()[0].get_type()==ast_multi_id && node.get_children()[1].get_type()==ast_multi_scalar) - if(node.get_children()[0].get_children().size()!=node.get_children()[1].get_children().size()) - die(node.get_children()[0].get_line(),"too much or lack values in multi-definition"); + 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"); return node; } nasal_ast nasal_parse::var_incurve_def() @@ -794,19 +801,19 @@ nasal_ast nasal_parse::var_outcurve_def() } nasal_ast nasal_parse::multi_id() { - nasal_ast node(tok_list[ptr].line,ast_multi_id); - while(tok_list[ptr].type!=tok_eof) + nasal_ast node(tokens[ptr].line,ast_multi_id); + while(tokens[ptr].type!=tok_eof) { - node.add_child(id_gen()); + node.add(id()); match(tok_id); - if(is_call(tok_list[ptr].type)) + if(is_call(tokens[ptr].type)) { call_scalar();// recognize calls but this is still a syntax error die(error_line,"cannot call identifier in multi-definition"); } - if(tok_list[ptr].type==tok_comma) + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_id)// first set of identifier + else if(tokens[ptr].type==tok_id)// first set of identifier die(error_line,"expected \',\' between identifiers"); else break; @@ -816,19 +823,24 @@ nasal_ast nasal_parse::multi_id() nasal_ast nasal_parse::multi_scalar(bool check_call_memory) { // if check_call_memory is true,we will check if value called here can reach a memory space - const int panic_set[]={tok_id,tok_str,tok_num,tok_not,tok_sub,tok_nil,tok_func,tok_var,tok_lcurve,tok_lbrace,tok_lbracket,tok_null}; - nasal_ast node(tok_list[ptr].line,ast_multi_scalar); + const uint32_t panic_set[]={ + tok_id,tok_str,tok_num, + tok_not,tok_sub,tok_nil, + tok_func,tok_var,tok_lcurve, + tok_lbrace,tok_lbracket,tok_null + }; + nasal_ast node(tokens[ptr].line,ast_multi_scalar); match(tok_lcurve); - while(tok_list[ptr].type!=tok_rcurve) + while(tokens[ptr].type!=tok_rcurve) { - node.add_child(calc()); + node.add(calc()); if(check_call_memory) - check_memory_reachable(node.get_children().back()); - if(tok_list[ptr].type==tok_comma) + check_memory_reachable(node.child().back()); + if(tokens[ptr].type==tok_comma) match(tok_comma); - else if(tok_list[ptr].type==tok_eof) + else if(tokens[ptr].type==tok_eof) break; - else if(tok_list[ptr].type!=tok_rcurve && !check_comma(panic_set)) + else if(tokens[ptr].type!=tok_rcurve && !check_comma(panic_set)) break; } match(tok_rcurve,"expected \')\' after multi-scalar"); @@ -836,28 +848,28 @@ nasal_ast nasal_parse::multi_scalar(bool check_call_memory) } nasal_ast nasal_parse::multi_assgin() { - nasal_ast node(tok_list[ptr].line,ast_multi_assign); - node.add_child(multi_scalar(true)); + nasal_ast node(tokens[ptr].line,ast_multi_assign); + node.add(multi_scalar(true)); match(tok_eq); - if(tok_list[ptr].type==tok_eof) + if(tokens[ptr].type==tok_eof) { die(error_line,"expected value list"); return node; } - if(tok_list[ptr].type==tok_lcurve) - node.add_child(check_multi_scalar()?multi_scalar(false):calc()); + if(tokens[ptr].type==tok_lcurve) + node.add(check_multi_scalar()?multi_scalar(false):calc()); else - node.add_child(calc()); - if(node.get_children()[1].get_type()==ast_multi_scalar - && node.get_children()[0].get_children().size()!=node.get_children()[1].get_children().size()) - die(node.get_children()[0].get_line(),"too much or lack values in multi-assignment"); + 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"); return node; } nasal_ast nasal_parse::loop() { ++in_loop; nasal_ast node; - switch(tok_list[ptr].type) + switch(tokens[ptr].type) { case tok_while: node=while_loop(); break; case tok_for: node=for_loop(); break; @@ -869,56 +881,56 @@ nasal_ast nasal_parse::loop() } nasal_ast nasal_parse::while_loop() { - nasal_ast node(tok_list[ptr].line,ast_while); + nasal_ast node(tokens[ptr].line,ast_while); match(tok_while); match(tok_lcurve); - node.add_child(calc()); + node.add(calc()); match(tok_rcurve); - node.add_child(exprs()); + node.add(exprs()); return node; } nasal_ast nasal_parse::for_loop() { - nasal_ast node(tok_list[ptr].line,ast_for); + nasal_ast node(tokens[ptr].line,ast_for); match(tok_for); match(tok_lcurve); // first expression - if(tok_list[ptr].type==tok_eof) + if(tokens[ptr].type==tok_eof) die(error_line,"expected definition"); - if(tok_list[ptr].type==tok_semi) - node.add_child(null_node_gen()); - else if(tok_list[ptr].type==tok_var) - node.add_child(definition()); - else if(tok_list[ptr].type==tok_lcurve) - node.add_child(lcurve_expr()); + if(tokens[ptr].type==tok_semi) + node.add(null()); + else if(tokens[ptr].type==tok_var) + node.add(definition()); + else if(tokens[ptr].type==tok_lcurve) + node.add(lcurve_expr()); else - node.add_child(calc()); + node.add(calc()); // check first semi match(tok_semi,"expected \';\' in for(;;)"); // conditional expression - if(tok_list[ptr].type==tok_eof) + if(tokens[ptr].type==tok_eof) die(error_line,"expected conditional expr"); - if(tok_list[ptr].type==tok_semi) - node.add_child(null_node_gen()); + if(tokens[ptr].type==tok_semi) + node.add(null()); else - node.add_child(calc()); + node.add(calc()); // check second semi match(tok_semi,"expected \';\' in for(;;)"); //after loop expression - if(tok_list[ptr].type==tok_eof) + if(tokens[ptr].type==tok_eof) die(error_line,"expected calculation"); - if(tok_list[ptr].type==tok_rcurve) - node.add_child(null_node_gen()); + if(tokens[ptr].type==tok_rcurve) + node.add(null()); else - node.add_child(calc()); + node.add(calc()); match(tok_rcurve); - node.add_child(exprs()); + node.add(exprs()); return node; } nasal_ast nasal_parse::forei_loop() { - nasal_ast node(tok_list[ptr].line,ast_null); - switch(tok_list[ptr].type) + 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; @@ -926,89 +938,89 @@ nasal_ast nasal_parse::forei_loop() match(tok_lcurve); // first expression // foreach/forindex must have an iterator to loop through - if(tok_list[ptr].type!=tok_var && tok_list[ptr].type!=tok_id) + if(tokens[ptr].type!=tok_var && tokens[ptr].type!=tok_id) die(error_line,"expected iterator"); - node.add_child(new_iter_gen()); + node.add(new_iter_gen()); // check semi match(tok_semi,"expected \';\' in foreach/forindex(iter;vector)"); // check vector - if(tok_list[ptr].type==tok_eof) + if(tokens[ptr].type==tok_eof) die(error_line,"expected vector"); - node.add_child(calc()); + node.add(calc()); match(tok_rcurve); - node.add_child(exprs()); + node.add(exprs()); return node; } nasal_ast nasal_parse::new_iter_gen() { - nasal_ast node(tok_list[ptr].line,ast_null); - if(tok_list[ptr].type==tok_var) + nasal_ast node(tokens[ptr].line,ast_null); + if(tokens[ptr].type==tok_var) { match(tok_var); node.set_type(ast_new_iter); - node.add_child(id_gen()); + node.add(id()); match(tok_id); } else { node.set_type(ast_call); - node.add_child(id_gen()); + node.add(id()); match(tok_id); - while(is_call(tok_list[ptr].type)) - node.add_child(call_scalar()); + while(is_call(tokens[ptr].type)) + node.add(call_scalar()); } return node; } nasal_ast nasal_parse::conditional() { - nasal_ast node(tok_list[ptr].line,ast_conditional); - nasal_ast tmp(tok_list[ptr].line,ast_if); + nasal_ast node(tokens[ptr].line,ast_conditional); + nasal_ast tmp(tokens[ptr].line,ast_if); match(tok_if); match(tok_lcurve); - tmp.add_child(calc()); + tmp.add(calc()); match(tok_rcurve); - tmp.add_child(exprs()); - node.add_child(std::move(tmp)); + tmp.add(exprs()); + node.add(std::move(tmp)); // end of if-expression - while(tok_list[ptr].type==tok_elsif) + while(tokens[ptr].type==tok_elsif) { - nasal_ast tmp(tok_list[ptr].line,ast_elsif); + nasal_ast tmp(tokens[ptr].line,ast_elsif); match(tok_elsif); match(tok_lcurve); - tmp.add_child(calc()); + tmp.add(calc()); match(tok_rcurve); - tmp.add_child(exprs()); - node.add_child(std::move(tmp)); + tmp.add(exprs()); + node.add(std::move(tmp)); } - if(tok_list[ptr].type==tok_else) + if(tokens[ptr].type==tok_else) { - nasal_ast tmp(tok_list[ptr].line,ast_else); + nasal_ast tmp(tokens[ptr].line,ast_else); match(tok_else); - tmp.add_child(exprs()); - node.add_child(std::move(tmp)); + tmp.add(exprs()); + node.add(std::move(tmp)); } return node; } nasal_ast nasal_parse::continue_expr() { - nasal_ast node(tok_list[ptr].line,ast_continue); + nasal_ast node(tokens[ptr].line,ast_continue); match(tok_continue); return node; } nasal_ast nasal_parse::break_expr() { - nasal_ast node(tok_list[ptr].line,ast_break); + nasal_ast node(tokens[ptr].line,ast_break); match(tok_break); return node; } nasal_ast nasal_parse::ret_expr() { - nasal_ast node(tok_list[ptr].line,ast_ret); + nasal_ast node(tokens[ptr].line,ast_ret); match(tok_ret); - int type=tok_list[ptr].type; + 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) - node.add_child(calc()); + node.add(calc()); return node; } #endif diff --git a/nasal_vm.h b/nasal_vm.h index 8d0958c..6a218c8 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -12,14 +12,20 @@ private: std::stack ret; // ptr stack stores address for function to return std::stack func_stk; // stack to store function,this is used when getting upvalues std::stack counter; // iterator stack for forindex/foreach - std::vector num_table;// numbers used in process(const calculation) + const double* num_table;// numbers used in process(const calculation) std::vector str_table;// symbols used in process - std::vector imm; // immediate number + const uint32_t* imm; // immediate number nasal_ref* mem_addr; // used for mem_call nasal_gc gc; // garbage collector /* values used for debug */ std::vector bytecode; // bytecode std::vector files; // files + + void init( + const std::vector&, + const std::vector&, + const std::vector&); + void clear(); /* debug functions */ void bytecodeinfo(const uint32_t); void traceback(); @@ -107,15 +113,9 @@ private: void opr_mcallh(); void opr_ret(); public: - nasal_vm():stack_top(gc.stack_top){}; - void init( - const std::vector&, - const std::vector&, - const std::vector&); - void clear(); - void run( - const std::vector&, - const bool); + nasal_vm():stack_top(gc.stack_top){} + ~nasal_vm(){clear();} + void run(const nasal_codegen&,const nasal_import&,const bool); }; void nasal_vm::init( @@ -123,24 +123,20 @@ void nasal_vm::init( const std::vector& nums, const std::vector& filenames) { - gc.gc_init(strs); + gc.init(strs); gc.val_stack[STACK_MAX_DEPTH-1].value.gcobj=nullptr; - num_table=nums; // get constant numbers + num_table=nums.data(); // get constant numbers str_table=strs; // get constant strings & symbols files=filenames;// get filenames for debugger - return; } void nasal_vm::clear() { - gc.gc_clear(); + gc.clear(); while(!ret.empty()) ret.pop(); while(!counter.empty()) counter.pop(); - num_table.clear(); str_table.clear(); - imm.clear(); - return; } void nasal_vm::bytecodeinfo(const uint32_t p) { @@ -149,7 +145,6 @@ void nasal_vm::bytecodeinfo(const uint32_t p) if(code.op==op_callb) printf(" <%s>",builtin_func[code.num].name); printf(" (%s line %d)\n",files[code.fidx].c_str(),code.line); - return; } void nasal_vm::traceback() { @@ -172,7 +167,6 @@ void nasal_vm::traceback() } if(same_cnt) printf("\t0x%.8x: %d same call(s) ...\n",last_point,same_cnt); - return; } void nasal_vm::stackinfo(const uint32_t limit) { @@ -207,7 +201,6 @@ void nasal_vm::stackinfo(const uint32_t limit) } if(same_cnt) printf("\t... | %d same value(s)\n",same_cnt); - return; } void nasal_vm::die(std::string str) { @@ -246,56 +239,46 @@ inline void nasal_vm::opr_intg() for(uint32_t i=0;ilocal.resize(imm[pc],gc.nil); - return; } inline void nasal_vm::opr_loadg() { gc.val_stack[imm[pc]]=(stack_top--)[0]; - return; } inline void nasal_vm::opr_loadl() { gc.local.back().vec()->elems[imm[pc]]=(stack_top--)[0]; - return; } inline void nasal_vm::opr_loadu() { func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]=(stack_top--)[0]; - return; } inline void nasal_vm::opr_pnum() { (++stack_top)[0]={vm_num,num_table[imm[pc]]}; - return; } inline void nasal_vm::opr_pone() { (++stack_top)[0]={vm_num,(double)1}; - return; } inline void nasal_vm::opr_pzero() { (++stack_top)[0]={vm_num,(double)0}; - return; } inline void nasal_vm::opr_pnil() { (++stack_top)[0].type=vm_nil; - return; } inline void nasal_vm::opr_pstr() { (++stack_top)[0]=gc.str_addrs[imm[pc]]; - return; } inline void nasal_vm::opr_newv() { - nasal_ref vec_addr=gc.gc_alloc(vm_vec); + nasal_ref vec_addr=gc.alloc(vm_vec); nasal_ref* begin=stack_top-imm[pc]+1; auto& vec=vec_addr.vec()->elems;// stack_top-imm[pc] stores the vector vec.resize(imm[pc]); @@ -303,30 +286,26 @@ inline void nasal_vm::opr_newv() vec[i]=begin[i]; begin[0]=vec_addr; stack_top=begin; - return; } inline void nasal_vm::opr_newh() { - (++stack_top)[0]=gc.gc_alloc(vm_hash); - return; + (++stack_top)[0]=gc.alloc(vm_hash); } inline void nasal_vm::opr_newf() { newf_off=1; - (++stack_top)[0]=gc.gc_alloc(vm_func); + (++stack_top)[0]=gc.alloc(vm_func); stack_top[0].func()->entry=imm[pc]; if(!gc.local.empty()) { stack_top[0].func()->upvalue=func_stk.top()->upvalue; stack_top[0].func()->upvalue.push_back(gc.local.back()); } - return; } inline void nasal_vm::opr_happ() { stack_top[-1].hash()->elems[str_table[imm[pc]]]=stack_top[0]; --stack_top; - return; } inline void nasal_vm::opr_para() { @@ -335,7 +314,6 @@ inline void nasal_vm::opr_para() func->key_table[str_table[imm[pc]]]=size; func->local[newf_off]={vm_none}; ++newf_off; - return; } inline void nasal_vm::opr_defpara() { @@ -345,12 +323,10 @@ inline void nasal_vm::opr_defpara() func->key_table[str_table[imm[pc]]]=size; func->local[newf_off]=def_val; ++newf_off; - return; } inline void nasal_vm::opr_dynpara() { stack_top[0].func()->dynpara=imm[pc]; - return; } inline void nasal_vm::opr_unot() { @@ -370,12 +346,10 @@ inline void nasal_vm::opr_unot() break; default:die("unot: incorrect value type");break; } - return; } inline void nasal_vm::opr_usub() { stack_top[0]={vm_num,-stack_top[0].to_number()}; - return; } #define op_calc(type)\ @@ -388,10 +362,9 @@ inline void nasal_vm::opr_mul(){op_calc(*);} inline void nasal_vm::opr_div(){op_calc(/);} inline void nasal_vm::opr_lnk() { - nasal_ref new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.alloc(vm_str); *new_val.str()=stack_top[-1].to_string()+stack_top[0].to_string(); (--stack_top)[0]=new_val; - return; } #define op_calc_const(type)\ @@ -404,10 +377,9 @@ inline void nasal_vm::opr_mulc(){op_calc_const(*);} inline void nasal_vm::opr_divc(){op_calc_const(/);} inline void nasal_vm::opr_lnkc() { - nasal_ref new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.alloc(vm_str); *new_val.str()=stack_top[0].to_string()+str_table[imm[pc]]; stack_top[0]=new_val; - return; } #define op_calc_eq(type)\ @@ -420,10 +392,9 @@ inline void nasal_vm::opr_muleq(){op_calc_eq(*);} inline void nasal_vm::opr_diveq(){op_calc_eq(/);} inline void nasal_vm::opr_lnkeq() { - nasal_ref new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.alloc(vm_str); *new_val.str()=mem_addr[0].to_string()+stack_top[-1].to_string(); (--stack_top)[0]=mem_addr[0]=new_val; - return; } #define op_calc_eq_const(type)\ @@ -436,16 +407,14 @@ inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);} inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);} inline void nasal_vm::opr_lnkeqc() { - nasal_ref new_val=gc.gc_alloc(vm_str); + nasal_ref new_val=gc.alloc(vm_str); *new_val.str()=mem_addr[0].to_string()+str_table[imm[pc]]; stack_top[0]=mem_addr[0]=new_val; - return; } inline void nasal_vm::opr_meq() { mem_addr[0]=(--stack_top)[0]; - return; } inline void nasal_vm::opr_eq() { @@ -461,7 +430,6 @@ inline void nasal_vm::opr_eq() stack_top[0]=(val1.to_number()==val2.to_number())?gc.one:gc.zero; else stack_top[0]=(val1==val2)?gc.one:gc.zero; - return; } inline void nasal_vm::opr_neq() { @@ -477,7 +445,6 @@ inline void nasal_vm::opr_neq() stack_top[0]=(val1.to_number()!=val2.to_number())?gc.one:gc.zero; else stack_top[0]=(val1!=val2)?gc.one:gc.zero; - return; } #define op_cmp(type)\ @@ -500,37 +467,31 @@ inline void nasal_vm::opr_geqc(){op_cmp_const(>=);} inline void nasal_vm::opr_pop() { --stack_top; - return; } inline void nasal_vm::opr_jmp() { pc=imm[pc]-1; - return; } inline void nasal_vm::opr_jt() { if(condition(stack_top[0])) pc=imm[pc]-1; - return; } inline void nasal_vm::opr_jf() { if(!condition(stack_top[0])) pc=imm[pc]-1; --stack_top; - return; } inline void nasal_vm::opr_counter() { counter.push(-1); if(stack_top[0].type!=vm_vec) die("cnt: must use vector in forindex/foreach"); - return; } inline void nasal_vm::opr_cntpop() { counter.pop(); - return; } inline void nasal_vm::opr_findex() { @@ -540,7 +501,6 @@ inline void nasal_vm::opr_findex() return; } (++stack_top)[0]={vm_num,static_cast(counter.top())}; - return; } inline void nasal_vm::opr_feach() { @@ -551,22 +511,18 @@ inline void nasal_vm::opr_feach() return; } (++stack_top)[0]=ref[counter.top()]; - return; } inline void nasal_vm::opr_callg() { (++stack_top)[0]=gc.val_stack[imm[pc]]; - return; } inline void nasal_vm::opr_calll() { (++stack_top)[0]=gc.local.back().vec()->elems[imm[pc]]; - return; } inline void nasal_vm::opr_upval() { (++stack_top)[0]=func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; - return; } inline void nasal_vm::opr_callv() { @@ -599,7 +555,6 @@ inline void nasal_vm::opr_callv() } else die("callv: must call a vector/hash/string"); - return; } inline void nasal_vm::opr_callvi() { @@ -611,7 +566,6 @@ inline void nasal_vm::opr_callvi() (++stack_top)[0]=val.vec()->get_val(imm[pc]); if(stack_top[0].type==vm_none) die("callvi: index out of range:"+std::to_string(imm[pc])); - return; } inline void nasal_vm::opr_callh() { @@ -625,7 +579,6 @@ inline void nasal_vm::opr_callh() if(stack_top[0].type==vm_func) stack_top[0].func()->local[0]=val;// me - return; } inline void nasal_vm::opr_callfv() { @@ -639,7 +592,7 @@ inline void nasal_vm::opr_callfv() func_stk.push(func_addr.func()); auto& ref_func=*func_addr.func(); - gc.local.push_back(gc.gc_alloc(vm_vec)); + gc.local.push_back(gc.alloc(vm_vec)); gc.local.back().vec()->elems=ref_func.local; // load parameters auto& ref_closure=gc.local.back().vec()->elems; @@ -656,7 +609,7 @@ inline void nasal_vm::opr_callfv() // load dynamic argument if args_size>=para_size if(ref_func.dynpara>=0) { - nasal_ref vec_addr=gc.gc_alloc(vm_vec); + nasal_ref vec_addr=gc.alloc(vm_vec); for(uint32_t i=para_size;ielems.push_back(vec[i]); ref_closure.back()=vec_addr; @@ -665,7 +618,6 @@ inline void nasal_vm::opr_callfv() stack_top-=args_size;// pop arguments ret.push(pc); pc=ref_func.entry-1; - return; } inline void nasal_vm::opr_callfh() { @@ -677,7 +629,7 @@ inline void nasal_vm::opr_callfh() // push new local scope func_stk.push(func_addr.func()); auto& ref_func=*func_addr.func(); - gc.local.push_back(gc.gc_alloc(vm_vec)); + gc.local.push_back(gc.alloc(vm_vec)); gc.local.back().vec()->elems=ref_func.local; // load parameters @@ -696,14 +648,12 @@ inline void nasal_vm::opr_callfh() --stack_top;// pop hash ret.push(pc); pc=ref_func.entry-1; - return; } inline void nasal_vm::opr_callb() { (++stack_top)[0]=(*builtin_func[imm[pc]].func)(gc.local.back().vec()->elems,gc); if(stack_top[0].type==vm_none) die("native function error."); - return; } inline void nasal_vm::opr_slcbegin() { @@ -711,16 +661,14 @@ inline void nasal_vm::opr_slcbegin() // ---------------- // | resource_vec | <-- stack_top[-1] // ---------------- - (++stack_top)[0]=gc.gc_alloc(vm_vec); + (++stack_top)[0]=gc.alloc(vm_vec); if(stack_top[-1].type!=vm_vec) die("slcbegin: must slice a vector"); - return; } inline void nasal_vm::opr_slcend() { stack_top[-1]=stack_top[0]; --stack_top; - return; } inline void nasal_vm::opr_slc() { @@ -729,7 +677,6 @@ inline void nasal_vm::opr_slc() if(res.type==vm_none) die("slc: index out of range:"+std::to_string(val.to_number())); stack_top[0].vec()->elems.push_back(res); - return; } inline void nasal_vm::opr_slc2() { @@ -761,25 +708,21 @@ inline void nasal_vm::opr_slc2() else for(int i=num1;i<=num2;++i) aim.push_back(i>=0?ref[i]:ref[i+ref_size]); - return; } inline void nasal_vm::opr_mcallg() { mem_addr=gc.val_stack+imm[pc]; (++stack_top)[0]=mem_addr[0]; - return; } inline void nasal_vm::opr_mcalll() { mem_addr=&(gc.local.back().vec()->elems[imm[pc]]); (++stack_top)[0]=mem_addr[0]; - return; } inline void nasal_vm::opr_mupval() { mem_addr=&func_stk.top()->upvalue[(imm[pc]>>16)&0xffff].vec()->elems[imm[pc]&0xffff]; (++stack_top)[0]=mem_addr[0]; - return; } inline void nasal_vm::opr_mcallv() { @@ -806,7 +749,6 @@ inline void nasal_vm::opr_mcallv() } else die("mcallv: cannot get memory space in other types"); - return; } inline void nasal_vm::opr_mcallh() { @@ -821,7 +763,6 @@ inline void nasal_vm::opr_mcallh() ref.elems[str]=gc.nil; mem_addr=ref.get_mem(str); } - return; } inline void nasal_vm::opr_ret() { @@ -834,12 +775,10 @@ inline void nasal_vm::opr_ret() func_stk.pop(); // pop function stack gc.local.pop_back(); // pop local scope pc=ret.top();ret.pop(); // fetch pc - return; } -void nasal_vm::run( - const std::vector& exec, - const bool op_cnt) +void nasal_vm::run(const nasal_codegen& gen,const nasal_import& linker,const bool opcnt) { + init(gen.get_strs(),gen.get_nums(),linker.get_file()); uint64_t count[op_exit+1]={0}; const void* opr_table[]= { @@ -864,13 +803,16 @@ void nasal_vm::run( &&mcallg, &&mcalll, &&mupval, &&mcallv, &&mcallh, &&ret, &&vmexit }; - bytecode=exec; - std::vector code; - for(auto& i:exec) + bytecode=gen.get_code(); + std::vector codes; + std::vector imms; + for(auto& i:bytecode) { - code.push_back(opr_table[i.op]); - imm.push_back(i.num); + codes.push_back(opr_table[i.op]); + imms.push_back(i.num); } + auto code=codes.data(); + imm=imms.data(); // set canary and program counter auto& canary=gc.val_stack[STACK_MAX_DEPTH-1]; @@ -881,7 +823,7 @@ void nasal_vm::run( vmexit: if(canary.value.gcobj) stackoverflow(); - if(op_cnt) + if(opcnt) { std::cout<