⚡ avoid infinite recursion when loading module
This commit is contained in:
parent
6e819391aa
commit
d3840edd73
|
@ -132,7 +132,7 @@ void execute(
|
||||||
}
|
}
|
||||||
|
|
||||||
// linker gets parser's ast and load import files to this ast
|
// linker gets parser's ast and load import files to this ast
|
||||||
ld.link(parse, file, cmd&VM_DETAIL).chkerr();
|
ld.link(parse, cmd&VM_DETAIL).chkerr();
|
||||||
if (cmd&VM_REF_FILE) {
|
if (cmd&VM_REF_FILE) {
|
||||||
if (ld.get_file_list().size()) {
|
if (ld.get_file_list().size()) {
|
||||||
std::cout << "referenced file(s):\n";
|
std::cout << "referenced file(s):\n";
|
||||||
|
|
|
@ -179,23 +179,38 @@ code_block* linker::import_regular_file(
|
||||||
// check self import, avoid infinite loading loop
|
// check self import, avoid infinite loading loop
|
||||||
if (check_self_import(filename)) {
|
if (check_self_import(filename)) {
|
||||||
err.err("link",
|
err.err("link",
|
||||||
"self-referenced module <" + filename + ">:\n" +
|
node->get_location(),
|
||||||
" reference path: " + generate_self_import_path(filename)
|
"self-referenced module <" + filename + ">, " +
|
||||||
|
"reference path: " + generate_self_import_path(filename)
|
||||||
);
|
);
|
||||||
return new code_block({0, 0, 0, 0, filename});
|
return new code_block({0, 0, 0, 0, filename});
|
||||||
}
|
}
|
||||||
check_exist_or_record_file(filename);
|
check_exist_or_record_file(filename);
|
||||||
|
|
||||||
module_load_stack.push_back(filename);
|
module_load_stack.push_back(filename);
|
||||||
|
if (module_load_stack.size()>MAX_RECURSION_DEPTH) {
|
||||||
|
err.err("link",
|
||||||
|
node->get_location(),
|
||||||
|
"too deep module import stack (>" +
|
||||||
|
std::to_string(MAX_RECURSION_DEPTH) + ")."
|
||||||
|
);
|
||||||
|
return new code_block({0, 0, 0, 0, filename});
|
||||||
|
}
|
||||||
// start importing...
|
// start importing...
|
||||||
lexer nasal_lexer;
|
lexer nasal_lexer;
|
||||||
parse nasal_parser;
|
parse nasal_parser;
|
||||||
if (nasal_lexer.scan(filename).geterr()) {
|
if (nasal_lexer.scan(filename).geterr()) {
|
||||||
err.err("link", "error occurred when analysing <" + filename + ">");
|
err.err("link",
|
||||||
|
node->get_location(),
|
||||||
|
"error occurred when analysing <" + filename + ">"
|
||||||
|
);
|
||||||
return new code_block({0, 0, 0, 0, filename});
|
return new code_block({0, 0, 0, 0, filename});
|
||||||
}
|
}
|
||||||
if (nasal_parser.compile(nasal_lexer).geterr()) {
|
if (nasal_parser.compile(nasal_lexer).geterr()) {
|
||||||
err.err("link", "error occurred when analysing <" + filename + ">");
|
err.err("link",
|
||||||
|
node->get_location(),
|
||||||
|
"error occurred when analysing <" + filename + ">"
|
||||||
|
);
|
||||||
return new code_block({0, 0, 0, 0, filename});
|
return new code_block({0, 0, 0, 0, filename});
|
||||||
}
|
}
|
||||||
// swap result out
|
// swap result out
|
||||||
|
@ -378,19 +393,19 @@ code_block* linker::load(code_block* program_root, const std::string& filename)
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
const error& linker::link(
|
const error& linker::link(parse& parse, bool spath = false) {
|
||||||
parse& parse, const std::string& self, bool spath = false) {
|
|
||||||
// switch for showing path when errors occur
|
// switch for showing path when errors occur
|
||||||
show_path_flag = spath;
|
show_path_flag = spath;
|
||||||
|
|
||||||
// initializing file map
|
// initializing file map
|
||||||
this_file = self;
|
this_file = parse.tree()->get_location().file;
|
||||||
imported_files = {self};
|
imported_files = {this_file};
|
||||||
module_load_stack = {self};
|
module_load_stack = {this_file};
|
||||||
|
|
||||||
// scan root and import files
|
// scan root and import files
|
||||||
// then generate a new ast and return to import_ast
|
// then generate a new ast and return to import_ast
|
||||||
auto new_tree_root = load(parse.tree(), self);
|
// dfs load file
|
||||||
|
auto new_tree_root = load(parse.tree(), this_file);
|
||||||
auto old_tree_root = parse.swap(new_tree_root);
|
auto old_tree_root = parse.swap(new_tree_root);
|
||||||
delete old_tree_root;
|
delete old_tree_root;
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace nasal {
|
||||||
|
|
||||||
class linker {
|
class linker {
|
||||||
private:
|
private:
|
||||||
|
const u32 MAX_RECURSION_DEPTH = 256;
|
||||||
bool show_path_flag;
|
bool show_path_flag;
|
||||||
bool library_loaded;
|
bool library_loaded;
|
||||||
std::string this_file;
|
std::string this_file;
|
||||||
|
@ -48,7 +49,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
linker();
|
linker();
|
||||||
const error& link(parse&, const std::string&, bool);
|
const error& link(parse&, bool);
|
||||||
const auto& get_file_list() const {return imported_files;}
|
const auto& get_file_list() const {return imported_files;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool repl::run() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nasal_linker->link(*nasal_parser, "<nasal-repl>", true).geterr()) {
|
if (nasal_linker->link(*nasal_parser, true).geterr()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue