From 3106afc2473ce12787e1fcae2e2c3a101214045d Mon Sep 17 00:00:00 2001 From: Li Jin Date: Tue, 5 Jul 2022 11:25:59 +0800 Subject: disable exporting macro from a normal module. --- spec/inputs/macro-export.yue | 25 ++++++++++++------ spec/inputs/macro.yue | 2 +- spec/outputs/macro-export.lua | 2 -- spec/outputs/macro-teal.tl | 2 -- spec/outputs/macro-todo.lua | 2 -- src/yue.cpp | 3 +++ src/yuescript/yue_compiler.cpp | 59 ++++++++++++++++++++++++++++++++++++------ src/yuescript/yue_parser.cpp | 7 ++++- src/yuescript/yue_parser.h | 2 ++ 9 files changed, 80 insertions(+), 24 deletions(-) delete mode 100644 spec/outputs/macro-export.lua delete mode 100644 spec/outputs/macro-teal.tl delete mode 100644 spec/outputs/macro-todo.lua diff --git a/spec/inputs/macro-export.yue b/spec/inputs/macro-export.yue index d669975..22ef424 100644 --- a/spec/inputs/macro-export.yue +++ b/spec/inputs/macro-export.yue @@ -1,15 +1,22 @@ +$ -> package.path = "?.lua;./spec/inputs/?.lua" + +import "macro-todo" as $ + +import "macro-todo" as {$, :$todo} + export macro config = (debugging = true)-> global debugMode = debugging == "true" global debugMacro = true "" -export macro showMacro = (name,res)-> - if debugMacro - "do - txt = #{res} - print '[macro '..#{name}..']' - print txt - txt" +export macro showMacro = (name, res)-> + if debugMacro then " +do + txt = #{res} + print '[macro ' .. #{name} .. ']' + print txt + txt +" else res @@ -25,5 +32,7 @@ export macro assert = (cond)-> else "#{cond}" -$config! +$ -> + global debugMode = true + global debugMacro = true diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 37702d1..e391b9e 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue @@ -3,7 +3,7 @@ $ -> import "macro-export" as { $, -- import all macros - $config:$myconfig, -- rename macro $config to $myconfig + $config: $myconfig, -- rename macro $config to $myconfig } import "macro-todo" as $ diff --git a/spec/outputs/macro-export.lua b/spec/outputs/macro-export.lua deleted file mode 100644 index b5a63f8..0000000 --- a/spec/outputs/macro-export.lua +++ /dev/null @@ -1,2 +0,0 @@ -local _module_0 = { } -return _module_0 diff --git a/spec/outputs/macro-teal.tl b/spec/outputs/macro-teal.tl deleted file mode 100644 index b5a63f8..0000000 --- a/spec/outputs/macro-teal.tl +++ /dev/null @@ -1,2 +0,0 @@ -local _module_0 = { } -return _module_0 diff --git a/spec/outputs/macro-todo.lua b/spec/outputs/macro-todo.lua deleted file mode 100644 index b5a63f8..0000000 --- a/spec/outputs/macro-todo.lua +++ /dev/null @@ -1,2 +0,0 @@ -local _module_0 = { } -return _module_0 diff --git a/src/yue.cpp b/src/yue.cpp index 04b7099..96649c4 100644 --- a/src/yue.cpp +++ b/src/yue.cpp @@ -498,6 +498,9 @@ int main(int narg, const char** args) { if (!targetPath.empty()) { fs::create_directories(targetFile.parent_path()); } + if (result.codes.empty()) { + return std::tuple{0, targetFile.string(), std::string("Built "sv) + file.first + '\n'}; + } std::ofstream output(targetFile, std::ios::trunc | std::ios::out); if (output) { const auto& codes = result.codes; diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 3a4ef8c..84cbf37 100755 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp @@ -56,7 +56,7 @@ using namespace parserlib; typedef std::list str_list; -const std::string_view version = "0.11.1"sv; +const std::string_view version = "0.12.0"sv; const std::string_view extension = "yue"sv; class YueCompilerImpl { @@ -104,19 +104,55 @@ public: DEFER(clear()); if (_info.node) { try { + auto block = _info.node.to()->block.get(); + if (_info.exportMacro) { + for (auto _stmt : block->statements.objects()) { + auto stmt = static_cast(_stmt); + switch (stmt->content->getId()) { + case id(): + case id(): + break; + case id(): + case id(): + if (auto importNode = stmt->content.as()) { + if (auto importAs = importNode->content.as()) { + if (importAs->target.is()) { + break; + } else if (auto tab = importAs->target.as()) { + bool macroImportingOnly = true; + for (auto item : tab->items.objects()) { + if (!ast_is< + MacroName_t, + macro_name_pair_t, + import_all_macro_t>(item)) { + macroImportingOnly = false; + } + } + if (macroImportingOnly) break; + } + } + } else if (auto exportNode = stmt->content.as()) { + if (exportNode->target.is()) break; + } + default: + throw std::logic_error(_info.errorMessage("macro exporting module only accepts macro definition, macro importing and macro expansion in place", stmt)); + break; + } + } + } str_list out; pushScope(); _enableReturn.push(_info.moduleName.empty()); _varArgs.push({true, false}); - transformBlock(_info.node.to()->block, out, + transformBlock(block, out, config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, nullptr, true); popScope(); if (config.lintGlobalVariable) { globals = std::make_unique(); for (const auto& var : _globals) { - int line,col; - std::tie(line,col) = var.second; + int line, col; + std::tie(line, col) = var.second; globals->push_back({var.first, line, col}); } } @@ -205,7 +241,7 @@ private: }; std::stack _continueVars; std::list> _codeCache; - std::unordered_map> _globals; + std::unordered_map> _globals; std::ostringstream _buf; std::ostringstream _joinBuf; const std::string _newLine = "\n"; @@ -286,7 +322,7 @@ private: } } decltype(_scopes.back().allows.get()) allows = nullptr; - for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { + for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { if (it->allows) allows = it->allows.get(); } bool checkShadowScopeOnly = false; @@ -1281,6 +1317,13 @@ private: temp.push_back(clearBuf()); } else if (ast_is(chainValue->items.back())) { chainValue->items.pop_back(); + if (chainValue->items.empty()) { + if (_withVars.empty()) { + throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x)); + } else { + chainValue->items.push_back(toAst(_withVars.top(), chainValue)); + } + } auto varName = singleVariableFrom(chainValue); bool isScoped = false; if (varName.empty() || !isLocal(varName)) { @@ -3045,7 +3088,7 @@ private: } } } - if (isRoot && !_info.moduleName.empty()) { + if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { block->statements.push_front(toAst(_info.moduleName + (_info.exportDefault ? "=nil"s : "={}"s), block)); } switch (usage) { @@ -3125,7 +3168,7 @@ private: } else { out.push_back(Empty); } - if (isRoot && !_info.moduleName.empty()) { + if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { out.back().append(indent() + "return "s + _info.moduleName + nlr(block)); } } diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index 5c42963..78b4713 100755 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp @@ -532,7 +532,11 @@ YueParser::YueParser() { return true; } }) >> ExpList >> -Assign) - | Space >> Macro) >> not_(Space >> statement_appendix); + | Space >> pl::user(Macro, [](const item_t& item) { + State* st = reinterpret_cast(item.user_data); + st->exportMacro = true; + return true; + })) >> not_(Space >> statement_appendix); variable_pair = sym(':') >> Variable >> not_('#'); @@ -664,6 +668,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { if (state.exportCount > 0) { res.moduleName = std::move(state.moduleName); res.exportDefault = state.exportDefault; + res.exportMacro = state.exportMacro; } } catch (const std::logic_error& err) { res.error = err.what(); diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 1532adf..eea3027 100755 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h @@ -28,6 +28,7 @@ struct ParseInfo { std::string error; std::unique_ptr codes; bool exportDefault = false; + bool exportMacro = false; std::string moduleName; std::string errorMessage(std::string_view msg, const input_range* loc) const; }; @@ -72,6 +73,7 @@ protected: indents.push(0); } bool exportDefault = false; + bool exportMacro = false; int exportCount = 0; int moduleFix = 0; size_t stringOpen = 0; -- cgit v1.2.3-55-g6feb