diff --git a/main.cpp b/main.cpp index 911aad0..c071c29 100644 --- a/main.cpp +++ b/main.cpp @@ -51,12 +51,6 @@ void logo() <<"input to get help .\n"; } -void die(const char* stage,const std::string& filename) -{ - std::cout<<"["<: error(s) occurred,stop.\n"; - std::exit(1); -} - void err() { std::cout @@ -67,43 +61,37 @@ void err() void execute(const std::string& file,const uint32_t cmd) { - nasal_lexer lexer; - nasal_parse parse; - nasal_import linker; - nasal_codegen gen; + // front end use the same error module + nasal_err nerr; + nasal_lexer lexer(nerr); + nasal_parse parse(nerr); + nasal_import linker(nerr); + nasal_codegen gen(nerr); + // back end nasal_vm vm; // lexer scans file to get tokens lexer.scan(file); - if(lexer.err()) - die("lexer",file); if(cmd&VM_LEXINFO) lexer.print(); // 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); if(cmd&VM_ASTINFO) parse.print(); // 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_CODEINFO) gen.print(); // run bytecode if(cmd&VM_DEBUG) { - nasal_dbg dbg; - dbg.run(gen,linker); + nasal_dbg debugger; + debugger.run(gen,linker); } else if(cmd&VM_EXECTIME) { @@ -119,7 +107,7 @@ int main(int argc,const char* argv[]) { if(argc==1) { - help(); + logo(); return 0; } if(argc==2) diff --git a/makefile b/makefile index c65115b..21bb601 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ .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_dbg.h nasal.h +nasal:main.cpp nasal_ast.h nasal_err.h nasal_builtin.h nasal_codegen.h nasal_gc.h nasal_import.h nasal_lexer.h nasal_parse.h nasal_vm.h nasal_dbg.h nasal.h clang++ -std=c++11 -O3 main.cpp -o nasal -fno-exceptions -ldl -Wshadow -Wall test:nasal ./nasal test/ascii-art.nas @@ -11,18 +11,18 @@ test:nasal ./nasal test/calc.nas ./nasal test/choice.nas ./nasal test/class.nas - # ./nasal test/exception.nas + ./nasal -c test/exception.nas ./nasal -t test/fib.nas ./nasal test/filesystem.nas ./nasal test/hexdump.nas ./nasal test/json.nas ./nasal test/leetcode1319.nas ./nasal test/lexer.nas - ./nasal -c test/life.nas + ./nasal test/life.nas ./nasal -t test/loop.nas ./nasal -c test/mandel.nas ./nasal -t test/mandelbrot.nas - # ./nasal -t test/module_test.nas + ./nasal -c test/module_test.nas ./nasal test/nasal_test.nas ./nasal -t test/pi.nas ./nasal -t test/prime.nas diff --git a/nasal.h b/nasal.h index 402c5a1..5451c88 100644 --- a/nasal.h +++ b/nasal.h @@ -127,6 +127,7 @@ std::string rawstr(const std::string& str) } return ret; } +#include "nasal_err.h" #include "nasal_lexer.h" #include "nasal_ast.h" #include "nasal_parse.h" diff --git a/nasal_codegen.h b/nasal_codegen.h index 8a1032b..ab71cf5 100644 --- a/nasal_codegen.h +++ b/nasal_codegen.h @@ -193,6 +193,7 @@ class nasal_codegen private: uint32_t error; uint16_t fileindex; + nasal_err& nerr; const std::string* file; std::stack in_iterloop; std::unordered_map num_table; @@ -205,7 +206,7 @@ private: std::vector global; // global : max 4095 values std::list> local; // local : max 32768 upvalues 65536 values - void die(const std::string,const int); + void die(const std::string&,const uint32_t); void regist_number(const double); void regist_string(const std::string&); void find_symbol(const nasal_ast&); @@ -246,6 +247,7 @@ private: void block_gen(const nasal_ast&); void ret_gen(const nasal_ast&); public: + nasal_codegen(nasal_err& e):nerr(e){} uint32_t err(){return error;} void compile(const nasal_parse&,const nasal_import&); void print_op(uint32_t); @@ -255,10 +257,10 @@ public: const std::vector& get_code() const {return code;} }; -void nasal_codegen::die(const std::string info,const int line) +void nasal_codegen::die(const std::string& info,const uint32_t line) { - ++error; - std::cout<<"[code] <"< "<=STACK_MAX_DEPTH) die("too many global variants: "+std::to_string(global.size())+".",0); + nerr.chkerr(); } void nasal_codegen::print_op(uint32_t index) diff --git a/nasal_dbg.h b/nasal_dbg.h index 51e9670..da6abc5 100644 --- a/nasal_dbg.h +++ b/nasal_dbg.h @@ -7,22 +7,19 @@ class nasal_dbg:public nasal_vm { private: bool next_step; - uint16_t last_fidx; uint16_t bk_fidx; uint32_t bk_line; - std::vector src; + file_line src; - std::vector parse(std::string&); - uint16_t get_fileindex(std::string&); + std::vector parse(const std::string&); + uint16_t get_fileindex(const std::string&); void err(); void help(); - void load_src(const std::string&); void stepinfo(); void interact(); public: nasal_dbg(): next_step(false), - last_fidx(0), bk_fidx(0),bk_line(0){} void run( const nasal_codegen&, @@ -30,7 +27,7 @@ public: ); }; -std::vector nasal_dbg::parse(std::string& cmd) +std::vector nasal_dbg::parse(const std::string& cmd) { std::vector res; std::string tmp=""; @@ -49,7 +46,7 @@ std::vector nasal_dbg::parse(std::string& cmd) return res; } -uint16_t nasal_dbg::get_fileindex(std::string& filename) +uint16_t nasal_dbg::get_fileindex(const std::string& filename) { for(uint16_t i=0;i\n"; - std::exit(-1); - } - std::string tmp; - while(!fin.eof()) - { - std::getline(fin,tmp); - src.push_back(tmp); - } -} - void nasal_dbg::stepinfo() { uint32_t begin,end; uint32_t line=bytecode[pc].line==0?0:bytecode[pc].line-1; - if(bytecode[pc].fidx!=last_fidx) - load_src(files[bytecode[pc].fidx]); - last_fidx=bytecode[pc].fidx; + src.load(files[bytecode[pc].fidx]); printf("source code:\n"); begin=(line>>3)==0?0:((line>>3)<<3); end=(1+(line>>3))<<3; @@ -203,7 +181,6 @@ void nasal_dbg::run( { detail_info=true; init(gen.get_strs(),gen.get_nums(),linker.get_file()); - load_src(files[0]); const void* opr_table[]= { &&nop, &&intg, &&intl, &&loadg, diff --git a/nasal_err.h b/nasal_err.h new file mode 100644 index 0000000..87b5da0 --- /dev/null +++ b/nasal_err.h @@ -0,0 +1,70 @@ +#ifndef __NASAL_ERR_H__ +#define __NASAL_ERR_H__ + +#include +#include +#include + +class file_line +{ +protected: + std::string file; + std::vector res; +public: + void load(const std::string& f) + { + if(file==f) + return; + file=f; + res.clear(); + std::ifstream fin(f,std::ios::binary); + if(fin.fail()) + { + std::cout<<"[src] cannot open file <"<\n"; + std::exit(1); + } + std::string line; + while(!fin.eof()) + { + std::getline(fin,line); + res.push_back(line); + } + } + void clear() + { + std::vector tmp; + res.swap(tmp); + } + const std::string& operator[](const uint32_t line){return res[line];} + const std::string& name(){return file;} + size_t size(){return res.size();} +}; + +class nasal_err:public file_line +{ +private: + uint32_t error; +public: + void err(const char* stage,const std::string& info) + { + ++error; + std::cout<<"["< files; - void die(const std::string&,const char*); bool check_import(const nasal_ast&); bool check_exist(const std::string&); void linker(nasal_ast&,nasal_ast&&); nasal_ast file_import(nasal_ast&); nasal_ast load(nasal_ast&,uint16_t); public: - uint32_t err(){return error;} - void link(nasal_parse&,const std::string&); + nasal_import(nasal_err& e):nerr(e){} + void link(nasal_parse&,const std::string&); const std::vector& get_file() const {return files;} }; -void nasal_import::die(const std::string& file,const char* stage) -{ - ++error; - std::cout<<"[import] in <\""<: error(s) occurred in "< tokens; uint32_t get_type(const std::string&); - void die(const char*); + void die(const char* info){nerr.err("lexer",line,column,info);}; void open(const std::string&); std::string id_gen(); std::string num_gen(); std::string str_gen(); public: - uint32_t err(){return error;} + nasal_lexer(nasal_err& e):nerr(e){} void scan(const std::string&); void print(); const std::vector& get_tokens() const {return tokens;} @@ -121,13 +127,11 @@ public: void nasal_lexer::open(const std::string& file) { - filename=file; std::ifstream fin(file,std::ios::binary); if(fin.fail()) - { - ++error; - std::cout<<"[lexer] cannot open file <"<.\n"; - } + nerr.err("lexer","cannot open file <"+file+">."); + else + nerr.load(file); std::stringstream ss; ss<=res.size()) break; @@ -294,20 +291,20 @@ void nasal_lexer::scan(const std::string& file) { str=id_gen(); uint32_t type=get_type(str); - tokens.push_back({line,type?type:tok_id,str}); + tokens.push_back({line,column,type?type:tok_id,str}); } else if(DIGIT(res[ptr])) - tokens.push_back({line,tok_num,num_gen()}); + tokens.push_back({line,column,tok_num,num_gen()}); else if(STR(res[ptr])) - tokens.push_back({line,tok_str,str_gen()}); + tokens.push_back({line,column,tok_str,str_gen()}); else if(SINGLE_OPERATOR(res[ptr])) { str=res[ptr]; - code+=res[ptr]; + ++column; uint32_t type=get_type(str); if(!type) die("invalid operator."); - tokens.push_back({line,type,str}); + tokens.push_back({line,column,type,str}); ++ptr; } else if(res[ptr]=='.') @@ -316,8 +313,8 @@ void nasal_lexer::scan(const std::string& file) if(ptr+2