diff --git a/README.md b/README.md index 9dd3309..3434afc 100644 --- a/README.md +++ b/README.md @@ -625,7 +625,7 @@ Use `import("filename.nas")` to get the nasal file including your built-in funct Also there's another way of importing nasal files, the two way of importing have the same function: ```javascript -import.dirname.dirname.filename; +use dirname.dirname.filename; import("./dirname/dirname/filename.nas"); ``` @@ -728,7 +728,7 @@ Windows(`.dll`): Then we write a test nasal file to run this fib function, using `os.platform()` we could write a cross-platform program: ```javascript -import.std.dylib; +use std.dylib; var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); var fib = dlhandle.fib; for(var i = 1; i<30; i+=1) @@ -745,7 +745,7 @@ dylib.dlclose(dlhandle.lib); `dylib.limitcall` is used to get `dlcall` function that has limited parameter size, this function will prove the performance of your code because it does not use `vm_vec` to store the arguments, instead it uses local scope to store them, so this could avoid frequently garbage collecting. And the code above could also be written like this: ```javascript -import.std.dylib; +use std.dylib; var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); var fib = dlhandle.fib; var invoke = dylib.limitcall(1); # this means the called function has only one parameter diff --git a/doc/README_zh.md b/doc/README_zh.md index c1fb67f..b8eeb4e 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -605,7 +605,7 @@ var print=func(elems...){ 当然也有另外一种办法来导入这些nasal文件,下面两种导入方式的效果是一样的: ```javascript -import.dirname.dirname.filename; +use dirname.dirname.filename; import("./dirname/dirname/filename.nas"); ``` @@ -702,7 +702,7 @@ Windows(`.dll`): 下面例子中`os.platform()`是用来检测当前运行的系统环境的,这样可以实现跨平台: ```javascript -import.std.dylib; +use std.dylib; var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); var fib = dlhandle.fib; for(var i = 1; i<30; i+=1) @@ -719,7 +719,7 @@ dylib.dlclose(dlhandle.lib); `dylib.limitcall`用于获取使用固定长度传参的 `dlcall` 函数,这种函数可以提高你的程序运行效率,因为它不需要用 `vm_vec` 来存储传入参数,而是使用局部作用域来直接存储,从而避免了频繁调用可能导致的频繁垃圾收集。所以上面展示的代码同样可以这样写: ```javascript -import.std.dylib; +use std.dylib; var dlhandle = dylib.dlopen("libfib."~(os.platform()=="windows"?"dll":"so")); var fib = dlhandle.fib; var invoke = dylib.limitcall(1); # this means the called function has only one parameter diff --git a/src/nasal_import.cpp b/src/nasal_import.cpp index d6cdebc..874cc02 100644 --- a/src/nasal_import.cpp +++ b/src/nasal_import.cpp @@ -97,27 +97,27 @@ bool linker::import_check(expr* node) { if (node->get_type()!=expr_type::ast_call) { return false; } - auto tmp = reinterpret_cast(node); - auto first_expr = tmp->get_first(); + auto call_node = reinterpret_cast(node); + auto first_expr = call_node->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()) { + if (!call_node->get_calls().size()) { return false; } // import("xxx"); - if (tmp->get_calls().size()!=1) { + if (call_node->get_calls().size()!=1) { return false; } - if (tmp->get_calls()[0]->get_type()!=expr_type::ast_callf) { + if (call_node->get_calls()[0]->get_type()!=expr_type::ast_callf) { return false; } - auto func_call = (call_function*)tmp->get_calls()[0]; + auto func_call = (call_function*)call_node->get_calls()[0]; if (func_call->get_argument().size()!=1) { return false; } @@ -171,10 +171,8 @@ code_block* linker::import_regular_file( // avoid infinite loading loop filename = find_real_file_path(filename, node->get_location()); - if (!filename.length()) { - return new code_block({0, 0, 0, 0, filename}); - } - if (used_modules.count(filename)) { + // if get empty string(error) or this file is used before, do not parse + if (!filename.length() || used_modules.count(filename)) { return new code_block({0, 0, 0, 0, filename}); } @@ -286,20 +284,11 @@ std::string linker::generate_module_name(const std::string& file_path) { "get empty module name from <" + file_path + ">, " + "will not be easily accessed." ); + return module_name; } - if (module_name.length() && '0' <= module_name[0] && module_name[0] <= '9') { - err.warn("link", - "get module <" + module_name + "> from <" + 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." - ); - } - if (module_name.length() && module_name.find("-")!=std::string::npos) { + if (std::isdigit(module_name[0]) || + module_name.find(".")!=std::string::npos || + module_name.find("-")!=std::string::npos) { err.warn("link", "get module <" + module_name + "> from <" + file_path + ">, " + "will not be easily accessed." @@ -358,28 +347,29 @@ code_block* linker::load(code_block* program_root, const std::string& filename) // load imported modules std::unordered_set used_modules = {}; - for(auto& import_ast_node : program_root->get_expressions()) { - if (!import_check(import_ast_node)) { + for(auto& import_node : program_root->get_expressions()) { + if (!import_check(import_node)) { break; } - auto module_code_block = import_regular_file(import_ast_node, used_modules); - // this location should not be a reference, may cause use after free! - const auto location = import_ast_node->get_location(); + // parse file and get ast + 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_ast_node; + delete import_node; // and replace the node with null_expr node - import_ast_node = new null_expr(location); + import_node = replace_node; + // avoid repeatedly importing the same module const auto& module_path = module_code_block->get_location().file; if (used_modules.count(module_path)) { delete module_code_block; continue; - } else { - used_modules.insert(module_path); } + // 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 + used_modules.insert(module_path); tree->add_expression(generate_module_definition(module_code_block)); }