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.
-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; |