diff --git a/main.cpp b/main.cpp index c071c29..e442544 100644 --- a/main.cpp +++ b/main.cpp @@ -83,6 +83,7 @@ void execute(const std::string& file,const uint32_t cmd) parse.print(); // code generator gets parser's ast and linker's import file list to generate code + optimize(parse.ast()); gen.compile(parse,linker); if(cmd&VM_CODEINFO) gen.print(); diff --git a/makefile b/makefile index beeff76..a98f9b6 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ .PHONY=test -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 +nasal:main.cpp nasal_ast.h nasal_err.h nasal_builtin.h nasal_opt.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 diff --git a/nasal.h b/nasal.h index 5451c88..b9505c8 100644 --- a/nasal.h +++ b/nasal.h @@ -132,6 +132,7 @@ std::string rawstr(const std::string& str) #include "nasal_ast.h" #include "nasal_parse.h" #include "nasal_import.h" +#include "nasal_opt.h" #include "nasal_gc.h" #include "nasal_builtin.h" #include "nasal_codegen.h" diff --git a/nasal_opt.h b/nasal_opt.h new file mode 100644 index 0000000..037c3fe --- /dev/null +++ b/nasal_opt.h @@ -0,0 +1,43 @@ +#ifndef __NASAL_OPT_H__ +#define __NASAL_OPT_H__ + +void calc_const_num(nasal_ast& root) +{ + auto& vec=root.child(); + for(auto& i:vec) + calc_const_num(i); + if(root.type()!=ast_add && + root.type()!=ast_sub && + root.type()!=ast_mult && + root.type()!=ast_div && + root.type()!=ast_less && + root.type()!=ast_leq && + root.type()!=ast_grt && + root.type()!=ast_geq) + return; + if(vec.size()!=2 || vec[0].type()!=ast_num || vec[1].type()!=ast_num) + return; + double res; + switch(root.type()) + { + case ast_add:res=vec[0].num()+vec[1].num();break; + case ast_sub:res=vec[0].num()-vec[1].num();break; + case ast_mult:res=vec[0].num()*vec[1].num();break; + case ast_div:res=vec[0].num()/vec[1].num();break; + case ast_less:res=vec[0].num()vec[1].num();break; + case ast_geq:res=vec[0].num()>=vec[1].num();break; + } + if(std::isinf(res) || std::isnan(res)) // inf and nan will cause number hashmap error in codegen + return; + root.set_num(res); + root.child().clear(); + root.set_type(ast_num); +} +void optimize(nasal_ast& root) +{ + for(auto& i:root.child()) + calc_const_num(i); +} +#endif \ No newline at end of file diff --git a/test/calc.nas b/test/calc.nas index 2125cb5..f4b9b1a 100644 --- a/test/calc.nas +++ b/test/calc.nas @@ -5,6 +5,7 @@ var filename=[ "nasal_ast.h", "nasal_builtin.h", "nasal_codegen.h", + "nasal_opt.h", "nasal_gc.h", "nasal_import.h", "nasal_lexer.h", @@ -19,6 +20,7 @@ var space=[ " ", "", "", + " ", " ", " ", " ",