From fe65085a7a7fe90f093bcc1d4ebd92dc544644db Mon Sep 17 00:00:00 2001 From: ValKmjolnir Date: Fri, 21 Jul 2023 23:40:59 +0800 Subject: [PATCH] :zap: add check for self-imported module --- src/nasal_import.cpp | 55 ++++++++++++++++++++++++++++++++--- src/nasal_import.h | 4 +++ test/self_ref_module/a.nas | 5 ++++ test/self_ref_module/b.nas | 3 ++ test/self_ref_module/c.nas | 3 ++ test/self_ref_module/main.nas | 12 ++++++++ 6 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 test/self_ref_module/a.nas create mode 100644 test/self_ref_module/b.nas create mode 100644 test/self_ref_module/c.nas create mode 100644 test/self_ref_module/main.nas diff --git a/src/nasal_import.cpp b/src/nasal_import.cpp index ed5d3d5..d79ac30 100644 --- a/src/nasal_import.cpp +++ b/src/nasal_import.cpp @@ -135,6 +135,43 @@ 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) { + return true; + } + } + return false; +} + +std::string linker::generate_self_import_path() { + std::string res = ""; + usize size = module_load_stack.size(); + if (!size) { + return res; + } + usize count = 0; + for(const auto& i : module_load_stack) { + res += "<" + i + ">"; + if (count!=size-1) { + res += " -> "; + } + ++count; + } + return res; +} + void linker::link(code_block* new_tree_root, code_block* old_tree_root) { // add children of add_root to the back of root for(auto& i : old_tree_root->get_expressions()) { @@ -160,10 +197,17 @@ code_block* linker::import_regular_file(call_expr* node) { // avoid infinite loading loop filename = find_file(filename, node->get_location()); - if (!filename.length() || exist(filename)) { + if (!filename.length()) { return new code_block({0, 0, 0, 0, filename}); } + if (check_self_import(filename)) { + err.err("link", "self-referenced module <" + filename + ">\n" + + " reference path: " + generate_self_import_path()); + return new code_block({0, 0, 0, 0, filename}); + } + exist(filename); + module_load_stack.push_back(filename); // start importing... if (lex.scan(filename).geterr()) { err.err("link", "error occurred when analysing <" + filename + ">"); @@ -174,7 +218,9 @@ code_block* linker::import_regular_file(call_expr* node) { auto tmp = par.swap(nullptr); // check if tmp has 'import' - return load(tmp, files.size()-1); + auto res = load(tmp, find(filename)); + module_load_stack.pop_back(); + return res; } code_block* linker::import_nasal_lib() { @@ -186,7 +232,7 @@ code_block* linker::import_nasal_lib() { } lib_path = filename; - // avoid infinite loading loop + // avoid infinite loading library if (exist(filename)) { return new code_block({0, 0, 0, 0, filename}); } @@ -201,7 +247,7 @@ code_block* linker::import_nasal_lib() { auto tmp = par.swap(nullptr); // check if tmp has 'import' - return load(tmp, files.size()-1); + return load(tmp, find(filename)); } std::string linker::generate_module_name(const std::string& filename) { @@ -294,6 +340,7 @@ const error& linker::link( // initializing this_file = self; files = {self}; + module_load_stack = {self}; // scan root and import files // then generate a new ast and return to import_ast // the main file's index is 0 diff --git a/src/nasal_import.h b/src/nasal_import.h index f06bf8d..4ea57ba 100644 --- a/src/nasal_import.h +++ b/src/nasal_import.h @@ -28,10 +28,14 @@ private: std::string lib_path; error err; std::vector files; + std::vector module_load_stack; std::vector envpath; 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(); void link(code_block*, code_block*); std::string get_path(call_expr*); std::string find_file(const std::string&, const span&); diff --git a/test/self_ref_module/a.nas b/test/self_ref_module/a.nas new file mode 100644 index 0000000..d84ea33 --- /dev/null +++ b/test/self_ref_module/a.nas @@ -0,0 +1,5 @@ +# this will cause error +# import.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 new file mode 100644 index 0000000..dcace50 --- /dev/null +++ b/test/self_ref_module/b.nas @@ -0,0 +1,3 @@ +import.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 new file mode 100644 index 0000000..cb81e5d --- /dev/null +++ b/test/self_ref_module/c.nas @@ -0,0 +1,3 @@ +import.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 new file mode 100644 index 0000000..36b0a1a --- /dev/null +++ b/test/self_ref_module/main.nas @@ -0,0 +1,12 @@ +import.c; +import.a; +import.b; + +println(a); +println(b); +println(c); + + +println(id(a)); +println(id(b), " ", id(b.a)); +println(id(c), " ", id(c.b), " ", id(c.b.a)); \ No newline at end of file