diff --git a/module/libfib.nas b/module/libfib.nas index 355a357..a42ed9b 100644 --- a/module/libfib.nas +++ b/module/libfib.nas @@ -1,4 +1,4 @@ -import.std.dylib; +use std.dylib; var _dl = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); diff --git a/module/libkey.nas b/module/libkey.nas index a494c22..829e99c 100644 --- a/module/libkey.nas +++ b/module/libkey.nas @@ -1,4 +1,4 @@ -import.std.dylib; +use std.dylib; var ( kbhit, diff --git a/module/libmat.nas b/module/libmat.nas index cd06928..be7ef60 100644 --- a/module/libmat.nas +++ b/module/libmat.nas @@ -1,4 +1,4 @@ -import.std.dylib; +use std.dylib; var _dl = dylib.dlopen("libmat."~(os.platform()=="windows"?"dll":"so")); diff --git a/module/libsock.nas b/module/libsock.nas index 15a57c1..fa6b356 100644 --- a/module/libsock.nas +++ b/module/libsock.nas @@ -1,4 +1,4 @@ -import.std.dylib; +use std.dylib; var socket=func(){ var lib=dylib.dlopen("libnasock"~(os.platform()=="windows"?".dll":".so")); diff --git a/src/nasal_ast.h b/src/nasal_ast.h index eb75e16..480e304 100644 --- a/src/nasal_ast.h +++ b/src/nasal_ast.h @@ -136,7 +136,7 @@ public: string_literal(const span& location, const std::string& str): expr(location, expr_type::ast_str), content(str) {} ~string_literal() override = default; - const std::string get_content() const {return content;} + const std::string& get_content() const {return content;} void accept(ast_visitor*) override; }; diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp index a3c5afc..a1018b4 100644 --- a/src/nasal_codegen.cpp +++ b/src/nasal_codegen.cpp @@ -307,7 +307,7 @@ void codegen::func_gen(function* node) { void codegen::call_gen(call_expr* node) { calc_gen(node->get_first()); - if (code.back().op==op_callb) { + if (code.size() && code.back().op==op_callb) { return; } for(auto i : node->get_calls()) { @@ -349,6 +349,8 @@ void codegen::call_id(identifier* node) { return; } die("undefined symbol \"" + name + "\"", node->get_location()); + // generation failed, put a push nil operand here to fill the space + emit(op_pnil, index, node->get_location()); } void codegen::call_hash_gen(call_hash* node) { diff --git a/src/nasal_import.cpp b/src/nasal_import.cpp index f5b31f0..f00abdb 100644 --- a/src/nasal_import.cpp +++ b/src/nasal_import.cpp @@ -24,19 +24,21 @@ linker::linker(): } } -std::string linker::get_path(call_expr* node) { - if (node->get_calls()[0]->get_type()==expr_type::ast_callf) { - auto tmp = (call_function*)node->get_calls()[0]; - return ((string_literal*)tmp->get_argument()[0])->get_content(); +std::string linker::get_path(expr* node) { + if (node->get_type()==expr_type::ast_use) { + auto file_relative_path = std::string("."); + for(auto i : reinterpret_cast(node)->get_path()) { + file_relative_path += (is_windows()? "\\":"/") +i->get_name(); + } + return file_relative_path + ".nas"; } - auto fpath = std::string("."); - for(auto i : node->get_calls()) { - fpath += (is_windows()? "\\":"/") + ((call_hash*)i)->get_field(); - } - return fpath + ".nas"; + auto call_node = reinterpret_cast(node); + auto tmp = reinterpret_cast(call_node->get_calls()[0]); + auto content = reinterpret_cast(tmp->get_argument()[0]); + return content->get_content(); } -std::string linker::find_file( +std::string linker::find_real_file_path( const std::string& filename, const span& location) { // first add file name itself into the file path std::vector fpath = {filename}; @@ -56,65 +58,58 @@ std::string linker::find_file( // we will find lib.nas in nasal std directory if (filename=="lib.nas") { return is_windows()? - find_file("std\\lib.nas", location): - find_file("std/lib.nas", location); + find_real_file_path("std\\lib.nas", location): + find_real_file_path("std/lib.nas", location); } if (!show_path) { err.err("link", "in <" + location.file + ">: " + "cannot find file <" + filename + ">, " + - "use <-d> to get detail search path"); + "use <-d> to get detail search path" + ); return ""; } - std::string paths = ""; + auto paths = std::string(""); for(const auto& i : fpath) { paths += " -> " + i + "\n"; } err.err("link", "in <" + location.file + ">: " + - "cannot find file <" + filename + "> in these paths:\n" + paths); + "cannot find file <" + filename + "> in these paths:\n" + paths + ); return ""; } bool linker::import_check(expr* node) { -/* - call - |_id:import - |_callh:std - |_callh:file -*/ - if (node->get_type()!=expr_type::ast_call) { - return false; - } - auto tmp = (call_expr*)node; - if (tmp->get_first()->get_type()!=expr_type::ast_id) { - return false; - } - if (((identifier*)tmp->get_first())->get_name()!="import") { - return false; - } - if (!tmp->get_calls().size()) { - return false; - } - // import.xxx.xxx; - if (tmp->get_calls()[0]->get_type()==expr_type::ast_callh) { - for(auto i : tmp->get_calls()) { - if (i->get_type()!=expr_type::ast_callh) { - return false; - } - } + if (node->get_type()==expr_type::ast_use) { return true; } - // import("xxx"); - if (tmp->get_calls().size()!=1) { - return false; - } /* call |_id:import |_call_func |_string:'filename' */ + if (node->get_type()!=expr_type::ast_call) { + return false; + } + auto tmp = reinterpret_cast(node); + auto first_expr = tmp->get_first(); + if (first_expr->get_type()!=expr_type::ast_id) { + return false; + } + if (reinterpret_cast(first_expr)->get_name()!="import") { + return false; + } + if (!tmp->get_calls().size()) { + return false; + } + + // import("xxx"); + if (tmp->get_calls().size()!=1) { + return false; + } + if (tmp->get_calls()[0]->get_type()!=expr_type::ast_callf) { return false; } @@ -139,17 +134,6 @@ bool linker::exist(const std::string& file) { return false; } -u16 linker::find(const std::string& file) { - for(usize i = 0; i(i); - } - } - std::cerr << "unreachable: using this method incorrectly\n"; - std::exit(-1); - return UINT16_MAX; -} - bool linker::check_self_import(const std::string& file) { for(const auto& i : module_load_stack) { if (file==i) { @@ -176,24 +160,26 @@ void linker::link(code_block* new_tree_root, code_block* old_tree_root) { old_tree_root->get_expressions().clear(); } -code_block* linker::import_regular_file(call_expr* node) { - lexer lex; - parse par; +code_block* linker::import_regular_file(expr* node) { // get filename auto filename = get_path(node); - // clear this node - for(auto i : node->get_calls()) { - delete i; + + // clear import("xxx/xxx.nas") node + if (node->get_type()!=expr_type::ast_use) { + auto cast_node = reinterpret_cast(node); + for(auto i : cast_node->get_calls()) { + delete i; + } + cast_node->get_calls().clear(); + const auto& location = cast_node->get_first()->get_location(); + delete cast_node->get_first(); + cast_node->set_first(new nil_expr(location)); + // this will make node to call_expr(nil), + // will not be optimized when generating bytecodes } - node->get_calls().clear(); - auto location = node->get_first()->get_location(); - delete node->get_first(); - node->set_first(new nil_expr(location)); - // this will make node to call_expr(nil), - // will not be optimized when generating bytecodes // avoid infinite loading loop - filename = find_file(filename, node->get_location()); + filename = find_real_file_path(filename, node->get_location()); if (!filename.length()) { return new code_block({0, 0, 0, 0, filename}); } @@ -208,27 +194,27 @@ code_block* linker::import_regular_file(call_expr* node) { module_load_stack.push_back(filename); // start importing... - if (lex.scan(filename).geterr()) { + lexer nasal_lexer; + parse nasal_parser; + if (nasal_lexer.scan(filename).geterr()) { err.err("link", "error occurred when analysing <" + filename + ">"); return new code_block({0, 0, 0, 0, filename}); } - if (par.compile(lex).geterr()) { + if (nasal_parser.compile(nasal_lexer).geterr()) { err.err("link", "error occurred when analysing <" + filename + ">"); return new code_block({0, 0, 0, 0, filename}); } - - auto parse_result = par.swap(nullptr); + // swap result out + auto parse_result = nasal_parser.swap(nullptr); // check if parse result has 'import' - auto result = load(parse_result, find(filename)); + auto result = load(parse_result, filename); module_load_stack.pop_back(); return result; } code_block* linker::import_nasal_lib() { - lexer lex; - parse par; - auto filename = find_file("lib.nas", {0, 0, 0, 0, files[0]}); + auto filename = find_real_file_path("lib.nas", {0, 0, 0, 0, files[0]}); if (!filename.length()) { return new code_block({0, 0, 0, 0, filename}); } @@ -240,22 +226,24 @@ code_block* linker::import_nasal_lib() { } // start importing... - if (lex.scan(filename).geterr()) { + lexer nasal_lexer; + parse nasal_parser; + if (nasal_lexer.scan(filename).geterr()) { err.err("link", "error occurred when analysing library <" + filename + ">" ); return new code_block({0, 0, 0, 0, filename}); } - if (par.compile(lex).geterr()) { + if (nasal_parser.compile(nasal_lexer).geterr()) { err.err("link", "error occurred when analysing library <" + filename + ">" ); return new code_block({0, 0, 0, 0, filename}); } - - auto parse_result = par.swap(nullptr); + // swap result out + auto parse_result = nasal_parser.swap(nullptr); // check if library has 'import' (in fact it should not) - return load(parse_result, find(filename)); + return load(parse_result, filename); } std::string linker::generate_module_name(const std::string& file_path) { @@ -314,6 +302,12 @@ std::string linker::generate_module_name(const std::string& file_path) { "will not be easily accessed." ); } + if (module_name.length() && module_name.find("-")!=std::string::npos) { + err.warn("link", + "get module <" + module_name + "> from <" + file_path + ">, " + + "will not be easily accessed." + ); + } return module_name; } @@ -353,8 +347,8 @@ definition_expr* linker::generate_module_definition(code_block* block) { return def; } -code_block* linker::load(code_block* program_root, u16 fileindex) { - auto tree = new code_block({0, 0, 0, 0, files[fileindex]}); +code_block* linker::load(code_block* program_root, const std::string& filename) { + auto tree = new code_block({0, 0, 0, 0, filename}); // load library, this ast will be linked with root directly // so no extra namespace is generated if (!lib_loaded) { @@ -370,12 +364,13 @@ code_block* linker::load(code_block* program_root, u16 fileindex) { if (!import_check(import_ast_node)) { break; } - auto module_code_block = import_regular_file((call_expr*)import_ast_node); + auto module_code_block = import_regular_file(import_ast_node); + // this location should not be a reference, may cause use after free! + const auto location = import_ast_node->get_location(); // after importing the regular file as module, delete this node - const auto loc = import_ast_node->get_location(); delete import_ast_node; // and replace the node with null_expr node - import_ast_node = new null_expr(loc); + import_ast_node = new null_expr(location); // then we generate a function warping the code block, // and export the necessary global symbols in this code block // by generate a return statement, with a hashmap return value @@ -397,7 +392,7 @@ const error& linker::link( // scan root and import files // then generate a new ast and return to import_ast // the main file's index is 0 - auto new_tree_root = load(parse.tree(), 0); + auto new_tree_root = load(parse.tree(), self); auto old_tree_root = parse.swap(new_tree_root); delete old_tree_root; return err; diff --git a/src/nasal_import.h b/src/nasal_import.h index fc53fe9..c09eabe 100644 --- a/src/nasal_import.h +++ b/src/nasal_import.h @@ -36,18 +36,17 @@ private: private: bool import_check(expr*); bool exist(const std::string&); - u16 find(const std::string&); bool check_self_import(const std::string&); std::string generate_self_import_path(const std::string&); void link(code_block*, code_block*); - std::string get_path(call_expr*); - std::string find_file(const std::string&, const span&); - code_block* import_regular_file(call_expr*); + std::string get_path(expr*); + std::string find_real_file_path(const std::string&, const span&); + code_block* import_regular_file(expr*); code_block* import_nasal_lib(); std::string generate_module_name(const std::string&); return_expr* generate_module_return(code_block*); definition_expr* generate_module_definition(code_block*); - code_block* load(code_block*, u16); + code_block* load(code_block*, const std::string&); public: linker(); diff --git a/std/fg_env.nas b/std/fg_env.nas index 47d435d..81bfb92 100644 --- a/std/fg_env.nas +++ b/std/fg_env.nas @@ -1,6 +1,6 @@ # flightgear developer environments simulator (beta) # ValKmjolnir 2022 -import.std.runtime; +use std.runtime; println("-------------------------------------------------------------"); println(" FlightGear simulated-env for developers project, since 2019"); diff --git a/std/lib.nas b/std/lib.nas index 95cb4a6..ce2afef 100644 --- a/std/lib.nas +++ b/std/lib.nas @@ -1,13 +1,13 @@ # lib.nas # 2019 ValKmjolnir -import.std.coroutine; -import.std.math; -import.std.string; -import.std.io; -import.std.os; -import.std.bits; -import.std.unix; +use std.coroutine; +use std.math; +use std.string; +use std.io; +use std.os; +use std.bits; +use std.unix; # print is used to print all things in nasal, try and see how it works. # this function uses std::cout to output logs. diff --git a/test/ascii-art.nas b/test/ascii-art.nas index 9e8335f..2f04b89 100644 --- a/test/ascii-art.nas +++ b/test/ascii-art.nas @@ -1,5 +1,5 @@ -import.std.padding; -import.std.process_bar; +use std.padding; +use std.process_bar; var char_ttf=[ [" "," "," "," "," "," "], diff --git a/test/auto_crash.nas b/test/auto_crash.nas index b277c4b..3700395 100644 --- a/test/auto_crash.nas +++ b/test/auto_crash.nas @@ -1,5 +1,5 @@ # Road check and auto pilot by ValKmjolnir -import.std.fg_env; +use std.fg_env; var props = fg_env.props; var geodinfo = fg_env.geodinfo; diff --git a/test/bfs.nas b/test/bfs.nas index 4568d6b..1520e7a 100644 --- a/test/bfs.nas +++ b/test/bfs.nas @@ -1,4 +1,4 @@ -import.std.queue; +use std.queue; rand(time(0)); var pixel=[' ','#','.','*']; diff --git a/test/bp.nas b/test/bp.nas index f685a68..88dadf9 100644 --- a/test/bp.nas +++ b/test/bp.nas @@ -1,4 +1,4 @@ -import.std.mat; +use std.mat; rand(time(0)); diff --git a/test/burningship.nas b/test/burningship.nas index a247522..7075059 100644 --- a/test/burningship.nas +++ b/test/burningship.nas @@ -1,4 +1,4 @@ -import.std.process_bar; +use std.process_bar; var ppm = func(filename, width, height, RGB) { # P3 use ASCII number diff --git a/test/calc.nas b/test/calc.nas index 440701e..516a2db 100644 --- a/test/calc.nas +++ b/test/calc.nas @@ -1,5 +1,5 @@ -import.std.padding; -import.std.file; +use std.padding; +use std.file; var source=file.find_all_files_with_extension("./src","cpp","h"); sort(source,func(a,b){return cmp(a,b)<0}); diff --git a/test/console3D.nas b/test/console3D.nas index ccc3332..9226d68 100644 --- a/test/console3D.nas +++ b/test/console3D.nas @@ -21,8 +21,8 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import.module.libmat; -import.std.runtime; +use module.libmat; +use std.runtime; func(){ # allocate more spaces diff --git a/test/coroutine.nas b/test/coroutine.nas index 4d6c09a..3eeacbb 100644 --- a/test/coroutine.nas +++ b/test/coroutine.nas @@ -1,7 +1,7 @@ # coroutine.nas by ValKmjolnir # 2022/5/19 -import.std.process_bar; -import.std.padding; +use std.process_bar; +use std.padding; if(os.platform()=="windows"){ system("chcp 65001"); diff --git a/test/datalog.nas b/test/datalog.nas index 6757856..eab13ef 100644 --- a/test/datalog.nas +++ b/test/datalog.nas @@ -1,5 +1,5 @@ -import.std.padding; -import.std.process_bar; +use std.padding; +use std.process_bar; var mess=func(vec) { srand(); diff --git a/test/donuts.nas b/test/donuts.nas index 5fe5c27..58dac11 100644 --- a/test/donuts.nas +++ b/test/donuts.nas @@ -1,4 +1,4 @@ -import.std.runtime; +use std.runtime; var mod = math.mod; diff --git a/test/feigenbaum.nas b/test/feigenbaum.nas index b235ae8..e7aab39 100644 --- a/test/feigenbaum.nas +++ b/test/feigenbaum.nas @@ -1,4 +1,4 @@ -import.std.process_bar; +use std.process_bar; var ppm = func(filename, width, height, RGB) { # P3 use ASCII number diff --git a/test/flush_screen.nas b/test/flush_screen.nas index 2c24113..499797a 100644 --- a/test/flush_screen.nas +++ b/test/flush_screen.nas @@ -1,4 +1,4 @@ -import.module.libkey; +use module.libkey; srand(); diff --git a/test/gc_test.nas b/test/gc_test.nas index b7e223c..fd3f28e 100644 --- a/test/gc_test.nas +++ b/test/gc_test.nas @@ -1,4 +1,4 @@ -import.std.runtime; +use std.runtime; var test_func = func(test_processes...) { var test_process_total = maketimestamp(); diff --git a/test/hexdump.nas b/test/hexdump.nas index dcfaafc..d77c15e 100644 --- a/test/hexdump.nas +++ b/test/hexdump.nas @@ -1,7 +1,7 @@ # hexdump.nas by ValKmjolnir # 2021/8/13 -import.std.file; -import.std.runtime; +use std.file; +use std.runtime; # init var hex=func(){ diff --git a/test/httptest.nas b/test/httptest.nas index be0f6bb..3b8fcaf 100644 --- a/test/httptest.nas +++ b/test/httptest.nas @@ -1,4 +1,4 @@ -import.module.libsock; +use module.libsock; var socket = libsock.socket; diff --git a/test/json.nas b/test/json.nas index d5be934..fbc053d 100644 --- a/test/json.nas +++ b/test/json.nas @@ -1,5 +1,5 @@ -import.std.json; -import.std.process_bar; +use std.json; +use std.process_bar; var ss = json.stringify({ vec:[0,1,2], diff --git a/test/jsonrpc.nas b/test/jsonrpc.nas index f976fc5..56b4484 100644 --- a/test/jsonrpc.nas +++ b/test/jsonrpc.nas @@ -1,6 +1,6 @@ -import.module.libsock; -import.std.json; -import.std.runtime; +use module.libsock; +use std.json; +use std.runtime; var socket = libsock.socket; diff --git a/test/life.nas b/test/life.nas index 9e29298..3b6fb0e 100644 --- a/test/life.nas +++ b/test/life.nas @@ -1,5 +1,5 @@ -import.std.process_bar; -import.std.runtime; +use std.process_bar; +use std.runtime; var new_map=func(width,height){ var tmp=[]; diff --git a/test/md5compare.nas b/test/md5compare.nas index 7ffca1b..29cd027 100644 --- a/test/md5compare.nas +++ b/test/md5compare.nas @@ -1,6 +1,6 @@ -import.test.md5_self; -import.std.process_bar; -import.std.file; +use test.md5_self; +use std.process_bar; +use std.file; srand(); diff --git a/test/module_test.nas b/test/module_test.nas index da9678c..109ceda 100644 --- a/test/module_test.nas +++ b/test/module_test.nas @@ -1,5 +1,5 @@ -import.std.dylib; -import.module.libfib; +use std.dylib; +use module.libfib; println(keys(libfib)); libfib.test_ghost(); diff --git a/test/occupation.nas b/test/occupation.nas index 9ea4302..99e5aa0 100644 --- a/test/occupation.nas +++ b/test/occupation.nas @@ -1,6 +1,6 @@ -import.std.process_bar; -import.module.libkey; -import.std.runtime; +use std.process_bar; +use module.libkey; +use std.runtime; var is_windows_platform=os.platform()=="windows"; var is_macos_platform=os.platform()=="macOS"; diff --git a/test/ppmgen.nas b/test/ppmgen.nas index f200056..857b5e4 100644 --- a/test/ppmgen.nas +++ b/test/ppmgen.nas @@ -1,4 +1,4 @@ -import.std.process_bar; +use std.process_bar; var ppm = func(filename, width, height, RGB) { # P3 use ASCII number diff --git a/test/scalar.nas b/test/scalar.nas index 3e6039f..e2c9feb 100644 --- a/test/scalar.nas +++ b/test/scalar.nas @@ -1,4 +1,4 @@ -import.std.runtime; +use std.runtime; # basic type nil; diff --git a/test/self_ref_module/a.nas b/test/self_ref_module/a.nas index d84ea33..a25d913 100644 --- a/test/self_ref_module/a.nas +++ b/test/self_ref_module/a.nas @@ -1,5 +1,5 @@ # this will cause error -# import.b; +# use b; println("init a"); var a = "hello"; \ No newline at end of file diff --git a/test/self_ref_module/b.nas b/test/self_ref_module/b.nas index dcace50..a8a6634 100644 --- a/test/self_ref_module/b.nas +++ b/test/self_ref_module/b.nas @@ -1,3 +1,3 @@ -import.a; +use a; println("init b"); \ No newline at end of file diff --git a/test/self_ref_module/c.nas b/test/self_ref_module/c.nas index cb81e5d..039b2f7 100644 --- a/test/self_ref_module/c.nas +++ b/test/self_ref_module/c.nas @@ -1,3 +1,3 @@ -import.b; +use b; println("init c"); \ No newline at end of file diff --git a/test/self_ref_module/main.nas b/test/self_ref_module/main.nas index 36b0a1a..da69dff 100644 --- a/test/self_ref_module/main.nas +++ b/test/self_ref_module/main.nas @@ -1,6 +1,6 @@ -import.c; -import.a; -import.b; +use c; +use a; +use b; println(a); println(b); diff --git a/test/snake.nas b/test/snake.nas index 08b82a9..27babbb 100644 --- a/test/snake.nas +++ b/test/snake.nas @@ -1,6 +1,6 @@ -import.module.libkey; -import.std.list; -import.std.runtime; +use module.libkey; +use std.list; +use std.runtime; var game=func(x,y){ rand(time(0)); diff --git a/test/tetris.nas b/test/tetris.nas index e2e1cf4..0d8ccc9 100644 --- a/test/tetris.nas +++ b/test/tetris.nas @@ -1,5 +1,5 @@ -import.module.libkey; -import.std.runtime; +use module.libkey; +use std.runtime; var color=[ "\e[31m","\e[32m","\e[33m","\e[34m","\e[35m","\e[36m", diff --git a/test/watchdog.nas b/test/watchdog.nas index a27813c..f89c59a 100644 --- a/test/watchdog.nas +++ b/test/watchdog.nas @@ -1,4 +1,4 @@ -import.std.runtime; +use std.runtime; var os_time=func(){ return "[\e[33;1m"~os.time()~"\e[0m] "; diff --git a/test/word_collector.nas b/test/word_collector.nas index 87e7151..32d6916 100644 --- a/test/word_collector.nas +++ b/test/word_collector.nas @@ -1,4 +1,4 @@ -import.std.runtime; +use std.runtime; var to_lower=func(s){ var tmp=""; diff --git a/tools/search_file.nas b/tools/search_file.nas index bce4c1e..72e52d2 100644 --- a/tools/search_file.nas +++ b/tools/search_file.nas @@ -1,4 +1,4 @@ -import.std.file; +use std.file; var tips = func() { println("usage:");