diff options
| author | Li Jin <dragon-fly@qq.com> | 2022-07-05 11:25:59 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2022-07-05 11:25:59 +0800 |
| commit | 3106afc2473ce12787e1fcae2e2c3a101214045d (patch) | |
| tree | d85296ea11e389fcd989ed5a4d3a71add73dde02 | |
| parent | ce9338c540ac3397f3d15c442033a618d12c5105 (diff) | |
| download | yuescript-3106afc2473ce12787e1fcae2e2c3a101214045d.tar.gz yuescript-3106afc2473ce12787e1fcae2e2c3a101214045d.tar.bz2 yuescript-3106afc2473ce12787e1fcae2e2c3a101214045d.zip | |
disable exporting macro from a normal module.
Diffstat (limited to '')
| -rw-r--r-- | spec/inputs/macro-export.yue | 25 | ||||
| -rw-r--r-- | spec/inputs/macro.yue | 2 | ||||
| -rw-r--r-- | spec/outputs/macro-export.lua | 2 | ||||
| -rw-r--r-- | spec/outputs/macro-teal.tl | 2 | ||||
| -rw-r--r-- | spec/outputs/macro-todo.lua | 2 | ||||
| -rw-r--r-- | src/yue.cpp | 3 | ||||
| -rwxr-xr-x | src/yuescript/yue_compiler.cpp | 59 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.cpp | 7 | ||||
| -rwxr-xr-x | src/yuescript/yue_parser.h | 2 |
9 files changed, 80 insertions, 24 deletions
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 @@ | |||
| 1 | $ -> package.path = "?.lua;./spec/inputs/?.lua" | ||
| 2 | |||
| 3 | import "macro-todo" as $ | ||
| 4 | |||
| 5 | import "macro-todo" as {$, :$todo} | ||
| 6 | |||
| 1 | export macro config = (debugging = true)-> | 7 | export macro config = (debugging = true)-> |
| 2 | global debugMode = debugging == "true" | 8 | global debugMode = debugging == "true" |
| 3 | global debugMacro = true | 9 | global debugMacro = true |
| 4 | "" | 10 | "" |
| 5 | 11 | ||
| 6 | export macro showMacro = (name,res)-> | 12 | export macro showMacro = (name, res)-> |
| 7 | if debugMacro | 13 | if debugMacro then " |
| 8 | "do | 14 | do |
| 9 | txt = #{res} | 15 | txt = #{res} |
| 10 | print '[macro '..#{name}..']' | 16 | print '[macro ' .. #{name} .. ']' |
| 11 | print txt | 17 | print txt |
| 12 | txt" | 18 | txt |
| 19 | " | ||
| 13 | else | 20 | else |
| 14 | res | 21 | res |
| 15 | 22 | ||
| @@ -25,5 +32,7 @@ export macro assert = (cond)-> | |||
| 25 | else | 32 | else |
| 26 | "#{cond}" | 33 | "#{cond}" |
| 27 | 34 | ||
| 28 | $config! | 35 | $ -> |
| 36 | global debugMode = true | ||
| 37 | global debugMacro = true | ||
| 29 | 38 | ||
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 @@ $ -> | |||
| 3 | 3 | ||
| 4 | import "macro-export" as { | 4 | import "macro-export" as { |
| 5 | $, -- import all macros | 5 | $, -- import all macros |
| 6 | $config:$myconfig, -- rename macro $config to $myconfig | 6 | $config: $myconfig, -- rename macro $config to $myconfig |
| 7 | } | 7 | } |
| 8 | 8 | ||
| 9 | import "macro-todo" as $ | 9 | 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 @@ | |||
| 1 | local _module_0 = { } | ||
| 2 | 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 @@ | |||
| 1 | local _module_0 = { } | ||
| 2 | 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 @@ | |||
| 1 | local _module_0 = { } | ||
| 2 | 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) { | |||
| 498 | if (!targetPath.empty()) { | 498 | if (!targetPath.empty()) { |
| 499 | fs::create_directories(targetFile.parent_path()); | 499 | fs::create_directories(targetFile.parent_path()); |
| 500 | } | 500 | } |
| 501 | if (result.codes.empty()) { | ||
| 502 | return std::tuple{0, targetFile.string(), std::string("Built "sv) + file.first + '\n'}; | ||
| 503 | } | ||
| 501 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); | 504 | std::ofstream output(targetFile, std::ios::trunc | std::ios::out); |
| 502 | if (output) { | 505 | if (output) { |
| 503 | const auto& codes = result.codes; | 506 | 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; | |||
| 56 | 56 | ||
| 57 | typedef std::list<std::string> str_list; | 57 | typedef std::list<std::string> str_list; |
| 58 | 58 | ||
| 59 | const std::string_view version = "0.11.1"sv; | 59 | const std::string_view version = "0.12.0"sv; |
| 60 | const std::string_view extension = "yue"sv; | 60 | const std::string_view extension = "yue"sv; |
| 61 | 61 | ||
| 62 | class YueCompilerImpl { | 62 | class YueCompilerImpl { |
| @@ -104,19 +104,55 @@ public: | |||
| 104 | DEFER(clear()); | 104 | DEFER(clear()); |
| 105 | if (_info.node) { | 105 | if (_info.node) { |
| 106 | try { | 106 | try { |
| 107 | auto block = _info.node.to<File_t>()->block.get(); | ||
| 108 | if (_info.exportMacro) { | ||
| 109 | for (auto _stmt : block->statements.objects()) { | ||
| 110 | auto stmt = static_cast<Statement_t*>(_stmt); | ||
| 111 | switch (stmt->content->getId()) { | ||
| 112 | case id<MacroInPlace_t>(): | ||
| 113 | case id<Macro_t>(): | ||
| 114 | break; | ||
| 115 | case id<Import_t>(): | ||
| 116 | case id<Export_t>(): | ||
| 117 | if (auto importNode = stmt->content.as<Import_t>()) { | ||
| 118 | if (auto importAs = importNode->content.as<ImportAs_t>()) { | ||
| 119 | if (importAs->target.is<import_all_macro_t>()) { | ||
| 120 | break; | ||
| 121 | } else if (auto tab = importAs->target.as<ImportTabLit_t>()) { | ||
| 122 | bool macroImportingOnly = true; | ||
| 123 | for (auto item : tab->items.objects()) { | ||
| 124 | if (!ast_is< | ||
| 125 | MacroName_t, | ||
| 126 | macro_name_pair_t, | ||
| 127 | import_all_macro_t>(item)) { | ||
| 128 | macroImportingOnly = false; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | if (macroImportingOnly) break; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } else if (auto exportNode = stmt->content.as<Export_t>()) { | ||
| 135 | if (exportNode->target.is<Macro_t>()) break; | ||
| 136 | } | ||
| 137 | default: | ||
| 138 | throw std::logic_error(_info.errorMessage("macro exporting module only accepts macro definition, macro importing and macro expansion in place", stmt)); | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 107 | str_list out; | 143 | str_list out; |
| 108 | pushScope(); | 144 | pushScope(); |
| 109 | _enableReturn.push(_info.moduleName.empty()); | 145 | _enableReturn.push(_info.moduleName.empty()); |
| 110 | _varArgs.push({true, false}); | 146 | _varArgs.push({true, false}); |
| 111 | transformBlock(_info.node.to<File_t>()->block, out, | 147 | transformBlock(block, out, |
| 112 | config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, | 148 | config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common, |
| 113 | nullptr, true); | 149 | nullptr, true); |
| 114 | popScope(); | 150 | popScope(); |
| 115 | if (config.lintGlobalVariable) { | 151 | if (config.lintGlobalVariable) { |
| 116 | globals = std::make_unique<GlobalVars>(); | 152 | globals = std::make_unique<GlobalVars>(); |
| 117 | for (const auto& var : _globals) { | 153 | for (const auto& var : _globals) { |
| 118 | int line,col; | 154 | int line, col; |
| 119 | std::tie(line,col) = var.second; | 155 | std::tie(line, col) = var.second; |
| 120 | globals->push_back({var.first, line, col}); | 156 | globals->push_back({var.first, line, col}); |
| 121 | } | 157 | } |
| 122 | } | 158 | } |
| @@ -205,7 +241,7 @@ private: | |||
| 205 | }; | 241 | }; |
| 206 | std::stack<ContinueVar> _continueVars; | 242 | std::stack<ContinueVar> _continueVars; |
| 207 | std::list<std::unique_ptr<input>> _codeCache; | 243 | std::list<std::unique_ptr<input>> _codeCache; |
| 208 | std::unordered_map<std::string,std::pair<int,int>> _globals; | 244 | std::unordered_map<std::string,std::pair<int, int>> _globals; |
| 209 | std::ostringstream _buf; | 245 | std::ostringstream _buf; |
| 210 | std::ostringstream _joinBuf; | 246 | std::ostringstream _joinBuf; |
| 211 | const std::string _newLine = "\n"; | 247 | const std::string _newLine = "\n"; |
| @@ -286,7 +322,7 @@ private: | |||
| 286 | } | 322 | } |
| 287 | } | 323 | } |
| 288 | decltype(_scopes.back().allows.get()) allows = nullptr; | 324 | decltype(_scopes.back().allows.get()) allows = nullptr; |
| 289 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | 325 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { |
| 290 | if (it->allows) allows = it->allows.get(); | 326 | if (it->allows) allows = it->allows.get(); |
| 291 | } | 327 | } |
| 292 | bool checkShadowScopeOnly = false; | 328 | bool checkShadowScopeOnly = false; |
| @@ -1281,6 +1317,13 @@ private: | |||
| 1281 | temp.push_back(clearBuf()); | 1317 | temp.push_back(clearBuf()); |
| 1282 | } else if (ast_is<table_appending_op_t>(chainValue->items.back())) { | 1318 | } else if (ast_is<table_appending_op_t>(chainValue->items.back())) { |
| 1283 | chainValue->items.pop_back(); | 1319 | chainValue->items.pop_back(); |
| 1320 | if (chainValue->items.empty()) { | ||
| 1321 | if (_withVars.empty()) { | ||
| 1322 | throw std::logic_error(_info.errorMessage("short table appending must be called within a with block"sv, x)); | ||
| 1323 | } else { | ||
| 1324 | chainValue->items.push_back(toAst<Callable_t>(_withVars.top(), chainValue)); | ||
| 1325 | } | ||
| 1326 | } | ||
| 1284 | auto varName = singleVariableFrom(chainValue); | 1327 | auto varName = singleVariableFrom(chainValue); |
| 1285 | bool isScoped = false; | 1328 | bool isScoped = false; |
| 1286 | if (varName.empty() || !isLocal(varName)) { | 1329 | if (varName.empty() || !isLocal(varName)) { |
| @@ -3045,7 +3088,7 @@ private: | |||
| 3045 | } | 3088 | } |
| 3046 | } | 3089 | } |
| 3047 | } | 3090 | } |
| 3048 | if (isRoot && !_info.moduleName.empty()) { | 3091 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { |
| 3049 | block->statements.push_front(toAst<Statement_t>(_info.moduleName + (_info.exportDefault ? "=nil"s : "={}"s), block)); | 3092 | block->statements.push_front(toAst<Statement_t>(_info.moduleName + (_info.exportDefault ? "=nil"s : "={}"s), block)); |
| 3050 | } | 3093 | } |
| 3051 | switch (usage) { | 3094 | switch (usage) { |
| @@ -3125,7 +3168,7 @@ private: | |||
| 3125 | } else { | 3168 | } else { |
| 3126 | out.push_back(Empty); | 3169 | out.push_back(Empty); |
| 3127 | } | 3170 | } |
| 3128 | if (isRoot && !_info.moduleName.empty()) { | 3171 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { |
| 3129 | out.back().append(indent() + "return "s + _info.moduleName + nlr(block)); | 3172 | out.back().append(indent() + "return "s + _info.moduleName + nlr(block)); |
| 3130 | } | 3173 | } |
| 3131 | } | 3174 | } |
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() { | |||
| 532 | return true; | 532 | return true; |
| 533 | } | 533 | } |
| 534 | }) >> ExpList >> -Assign) | 534 | }) >> ExpList >> -Assign) |
| 535 | | Space >> Macro) >> not_(Space >> statement_appendix); | 535 | | Space >> pl::user(Macro, [](const item_t& item) { |
| 536 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 537 | st->exportMacro = true; | ||
| 538 | return true; | ||
| 539 | })) >> not_(Space >> statement_appendix); | ||
| 536 | 540 | ||
| 537 | variable_pair = sym(':') >> Variable >> not_('#'); | 541 | variable_pair = sym(':') >> Variable >> not_('#'); |
| 538 | 542 | ||
| @@ -664,6 +668,7 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
| 664 | if (state.exportCount > 0) { | 668 | if (state.exportCount > 0) { |
| 665 | res.moduleName = std::move(state.moduleName); | 669 | res.moduleName = std::move(state.moduleName); |
| 666 | res.exportDefault = state.exportDefault; | 670 | res.exportDefault = state.exportDefault; |
| 671 | res.exportMacro = state.exportMacro; | ||
| 667 | } | 672 | } |
| 668 | } catch (const std::logic_error& err) { | 673 | } catch (const std::logic_error& err) { |
| 669 | res.error = err.what(); | 674 | 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 { | |||
| 28 | std::string error; | 28 | std::string error; |
| 29 | std::unique_ptr<input> codes; | 29 | std::unique_ptr<input> codes; |
| 30 | bool exportDefault = false; | 30 | bool exportDefault = false; |
| 31 | bool exportMacro = false; | ||
| 31 | std::string moduleName; | 32 | std::string moduleName; |
| 32 | std::string errorMessage(std::string_view msg, const input_range* loc) const; | 33 | std::string errorMessage(std::string_view msg, const input_range* loc) const; |
| 33 | }; | 34 | }; |
| @@ -72,6 +73,7 @@ protected: | |||
| 72 | indents.push(0); | 73 | indents.push(0); |
| 73 | } | 74 | } |
| 74 | bool exportDefault = false; | 75 | bool exportDefault = false; |
| 76 | bool exportMacro = false; | ||
| 75 | int exportCount = 0; | 77 | int exportCount = 0; |
| 76 | int moduleFix = 0; | 78 | int moduleFix = 0; |
| 77 | size_t stringOpen = 0; | 79 | size_t stringOpen = 0; |
