optimize import module

This commit is contained in:
ValKmjolnir 2023-12-22 00:15:31 +08:00
parent d3840edd73
commit 7ce8d3af25
2 changed files with 23 additions and 37 deletions

View File

@ -6,7 +6,7 @@
namespace nasal { namespace nasal {
linker::linker(): show_path_flag(false), library_loaded(false), this_file("") { linker::linker(): show_path_flag(false), this_file("") {
const auto seperator = is_windows()? ';':':'; const auto seperator = is_windows()? ';':':';
const auto PATH = std::string(getenv("PATH")); const auto PATH = std::string(getenv("PATH"));
usize last = 0, position = PATH.find(seperator, 0); usize last = 0, position = PATH.find(seperator, 0);
@ -155,7 +155,7 @@ std::string linker::generate_self_import_path(const std::string& filename) {
return res + "[" + filename + "]"; return res + "[" + filename + "]";
} }
void linker::link(code_block* new_tree_root, code_block* old_tree_root) { void linker::merge_tree(code_block* new_tree_root, code_block* old_tree_root) {
// add children of add_root to the back of root // add children of add_root to the back of root
for(auto& i : old_tree_root->get_expressions()) { for(auto& i : old_tree_root->get_expressions()) {
new_tree_root->add_expression(i); new_tree_root->add_expression(i);
@ -186,7 +186,7 @@ code_block* linker::import_regular_file(
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) { if (module_load_stack.size()>MAX_RECURSION_DEPTH) {
err.err("link", err.err("link",
@ -217,9 +217,9 @@ code_block* linker::import_regular_file(
auto parse_result = nasal_parser.swap(nullptr); auto parse_result = nasal_parser.swap(nullptr);
// check if parse result has 'import' // check if parse result has 'import'
auto result = load(parse_result, filename); load(parse_result, filename);
module_load_stack.pop_back(); module_load_stack.pop_back();
return result; return parse_result;
} }
code_block* linker::import_nasal_lib() { code_block* linker::import_nasal_lib() {
@ -253,7 +253,8 @@ code_block* linker::import_nasal_lib() {
// swap result out // swap result out
auto parse_result = nasal_parser.swap(nullptr); auto parse_result = nasal_parser.swap(nullptr);
// check if library has 'import' (in fact it should not) // check if library has 'import' (in fact it should not)
return load(parse_result, path); load(parse_result, path);
return parse_result;
} }
std::string linker::generate_module_name(const std::string& file_path) { std::string linker::generate_module_name(const std::string& file_path) {
@ -348,18 +349,7 @@ definition_expr* linker::generate_module_definition(code_block* block) {
return def; return def;
} }
code_block* linker::load(code_block* program_root, const std::string& filename) { void 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 (!library_loaded) {
auto nasal_lib_code_block = import_nasal_lib();
// insert nasal lib code to the back of tree
link(tree, nasal_lib_code_block);
delete nasal_lib_code_block;
library_loaded = true;
}
// load imported modules // load imported modules
std::unordered_set<std::string> used_modules = {}; std::unordered_set<std::string> used_modules = {};
for(auto& import_node : program_root->get_expressions()) { for(auto& import_node : program_root->get_expressions()) {
@ -368,29 +358,25 @@ code_block* linker::load(code_block* program_root, const std::string& filename)
} }
// parse file and get ast // parse file and get ast
auto module_code_block = import_regular_file(import_node, used_modules); auto module_code_block = import_regular_file(import_node, used_modules);
auto replace_node = new null_expr(import_node->get_location());
// after importing the regular file as module, delete this node
delete import_node;
// and replace the node with null_expr node
import_node = replace_node;
// avoid repeatedly importing the same module // avoid repeatedly importing the same module in one file
const auto& module_path = module_code_block->get_location().file; const auto& module_path = module_code_block->get_location().file;
if (used_modules.count(module_path)) { if (used_modules.count(module_path)) {
delete module_code_block; delete module_code_block;
auto replace_node = new null_expr(import_node->get_location());
// after importing the regular file as module, delete this node
delete import_node;
// and replace the node with null_expr node
import_node = replace_node;
continue; continue;
} }
used_modules.insert(module_path);
delete import_node;
// then we generate a function warping the code block, // then we generate a function warping the code block,
// and export the necessary global symbols in this code block // and export the necessary global symbols in this code block
// by generate a return statement, with a hashmap return value // by generate a return statement, with a hashmap return value
used_modules.insert(module_path); import_node = generate_module_definition(module_code_block);
tree->add_expression(generate_module_definition(module_code_block));
} }
// insert program root to the back of tree
link(tree, program_root);
return tree;
} }
const error& linker::link(parse& parse, bool spath = false) { const error& linker::link(parse& parse, bool spath = false) {
@ -405,9 +391,10 @@ const error& linker::link(parse& parse, bool spath = false) {
// 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
// dfs load file // dfs load file
auto new_tree_root = load(parse.tree(), this_file); auto library = import_nasal_lib();
auto old_tree_root = parse.swap(new_tree_root); load(parse.tree(), this_file);
delete old_tree_root; merge_tree(library, parse.tree());
delete parse.swap(library);
return err; return err;
} }

View File

@ -25,7 +25,6 @@ class linker {
private: private:
const u32 MAX_RECURSION_DEPTH = 256; const u32 MAX_RECURSION_DEPTH = 256;
bool show_path_flag; bool show_path_flag;
bool library_loaded;
std::string this_file; std::string this_file;
error err; error err;
std::vector<std::string> imported_files; std::vector<std::string> imported_files;
@ -37,7 +36,7 @@ private:
bool check_exist_or_record_file(const std::string&); bool check_exist_or_record_file(const std::string&);
bool check_self_import(const std::string&); bool check_self_import(const std::string&);
std::string generate_self_import_path(const std::string&); std::string generate_self_import_path(const std::string&);
void link(code_block*, code_block*); void merge_tree(code_block*, code_block*);
std::string get_path(expr*); std::string get_path(expr*);
std::string find_real_file_path(const std::string&, const span&); std::string find_real_file_path(const std::string&, const span&);
code_block* import_regular_file(expr*, std::unordered_set<std::string>&); code_block* import_regular_file(expr*, std::unordered_set<std::string>&);
@ -45,7 +44,7 @@ private:
std::string generate_module_name(const std::string&); std::string generate_module_name(const std::string&);
return_expr* generate_module_return(code_block*); return_expr* generate_module_return(code_block*);
definition_expr* generate_module_definition(code_block*); definition_expr* generate_module_definition(code_block*);
code_block* load(code_block*, const std::string&); void load(code_block*, const std::string&);
public: public:
linker(); linker();