diff options
author | Li Jin <dragon-fly@qq.com> | 2024-03-04 11:13:18 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2024-03-04 11:13:18 +0800 |
commit | 4e9a508a11c16db9aeff44b27e88713ab413bff7 (patch) | |
tree | 2ef6f1e4904e32379e67b1c35b7bc8031685088a | |
parent | 412bc3d7606cb0d07c39861c7ae4e89c7139da31 (diff) | |
download | yuescript-0.22.2.tar.gz yuescript-0.22.2.tar.bz2 yuescript-0.22.2.zip |
add default return declaration for function literal.v0.22.2
-rw-r--r-- | spec/inputs/funcs.yue | 35 | ||||
-rw-r--r-- | spec/outputs/funcs.lua | 70 | ||||
-rw-r--r-- | src/yuescript/yue_ast.cpp | 14 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 3 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 40 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 21 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 3 |
7 files changed, 176 insertions, 10 deletions
diff --git a/spec/inputs/funcs.yue b/spec/inputs/funcs.yue index 0e45ff1..e647edc 100644 --- a/spec/inputs/funcs.yue +++ b/spec/inputs/funcs.yue | |||
@@ -158,4 +158,39 @@ args = (f,g,m | |||
158 | return 1 if n == 0 | 158 | return 1 if n == 0 |
159 | n * @(n-1) | 159 | n * @(n-1) |
160 | 160 | ||
161 | do | ||
162 | items.every (item) -> | ||
163 | if item.field | ||
164 | value = item.field.get "abc" | ||
165 | if value | ||
166 | switch value\get! | ||
167 | when 123 | ||
168 | return false | ||
169 | when 456 | ||
170 | handle item | ||
171 | true | ||
172 | |||
173 | items.every (item): true -> | ||
174 | if item.field | ||
175 | value = item.field.get "abc" | ||
176 | if value | ||
177 | switch value\get! | ||
178 | when 123 | ||
179 | return false | ||
180 | when 456 | ||
181 | -- prevent implicit return for next line | ||
182 | handle item | ||
183 | |||
184 | HttpServer\post "/login", (req): success: false -> | ||
185 | switch req when {:name, :pwd} | ||
186 | if name ~= "" | ||
187 | if user := DB\queryUser name, pwd | ||
188 | if user.status == "available" | ||
189 | return success: true | ||
190 | |||
191 | check = (num) -> return num | ||
192 | -- func without implicit return | ||
193 | func = (): -> check 123 | ||
194 | print func! -- get nil | ||
195 | |||
161 | nil | 196 | nil |
diff --git a/spec/outputs/funcs.lua b/spec/outputs/funcs.lua index 03281e4..c07989e 100644 --- a/spec/outputs/funcs.lua +++ b/spec/outputs/funcs.lua | |||
@@ -219,4 +219,74 @@ self = function(n) | |||
219 | end | 219 | end |
220 | return n * self(n - 1) | 220 | return n * self(n - 1) |
221 | end | 221 | end |
222 | do | ||
223 | items.every(function(item) | ||
224 | if item.field then | ||
225 | local value = item.field.get("abc") | ||
226 | if value then | ||
227 | do | ||
228 | local _exp_0 = value:get() | ||
229 | if 123 == _exp_0 then | ||
230 | return false | ||
231 | elseif 456 == _exp_0 then | ||
232 | handle(item) | ||
233 | end | ||
234 | end | ||
235 | end | ||
236 | end | ||
237 | return true | ||
238 | end) | ||
239 | items.every(function(item) | ||
240 | if item.field then | ||
241 | local value = item.field.get("abc") | ||
242 | if value then | ||
243 | do | ||
244 | local _exp_0 = value:get() | ||
245 | if 123 == _exp_0 then | ||
246 | return false | ||
247 | elseif 456 == _exp_0 then | ||
248 | handle(item) | ||
249 | end | ||
250 | end | ||
251 | end | ||
252 | end | ||
253 | return true | ||
254 | end) | ||
255 | HttpServer:post("/login", function(req) | ||
256 | do | ||
257 | local _type_0 = type(req) | ||
258 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
259 | if _tab_0 then | ||
260 | local name = req.name | ||
261 | local pwd = req.pwd | ||
262 | if name ~= nil and pwd ~= nil then | ||
263 | if name ~= "" then | ||
264 | do | ||
265 | local user = DB:queryUser(name, pwd) | ||
266 | if user then | ||
267 | if user.status == "available" then | ||
268 | return { | ||
269 | success = true | ||
270 | } | ||
271 | end | ||
272 | end | ||
273 | end | ||
274 | end | ||
275 | end | ||
276 | end | ||
277 | end | ||
278 | return { | ||
279 | success = false | ||
280 | } | ||
281 | end) | ||
282 | local check | ||
283 | check = function(num) | ||
284 | return num | ||
285 | end | ||
286 | local func | ||
287 | func = function() | ||
288 | check(123) | ||
289 | end | ||
290 | print(func()) | ||
291 | end | ||
222 | return nil | 292 | return nil |
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index faa175d..fbf7a63 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
@@ -1279,6 +1279,16 @@ std::string FunLit_t::to_string(void* ud) const { | |||
1279 | if (argsDef) { | 1279 | if (argsDef) { |
1280 | line = argsDef->to_string(ud); | 1280 | line = argsDef->to_string(ud); |
1281 | } | 1281 | } |
1282 | if (defaultReturn) { | ||
1283 | if (defaultReturn.is<DefaultValue_t>()) { | ||
1284 | line += ':'; | ||
1285 | } else { | ||
1286 | line += ": "s + defaultReturn->to_string(ud); | ||
1287 | } | ||
1288 | } | ||
1289 | if (!line.empty()) { | ||
1290 | line += ' '; | ||
1291 | } | ||
1282 | line += arrow->to_string(ud); | 1292 | line += arrow->to_string(ud); |
1283 | if (body) { | 1293 | if (body) { |
1284 | if (body->content.is<Statement_t>()) { | 1294 | if (body->content.is<Statement_t>()) { |
@@ -1302,7 +1312,7 @@ std::string MacroLit_t::to_string(void* ud) const { | |||
1302 | auto info = reinterpret_cast<YueFormat*>(ud); | 1312 | auto info = reinterpret_cast<YueFormat*>(ud); |
1303 | std::string line; | 1313 | std::string line; |
1304 | if (argsDef) { | 1314 | if (argsDef) { |
1305 | line = '(' + argsDef->to_string(ud) + ')'; | 1315 | line = '(' + argsDef->to_string(ud) + ") "s; |
1306 | } | 1316 | } |
1307 | line += "->"s; | 1317 | line += "->"s; |
1308 | if (body->content.is<Statement_t>()) { | 1318 | if (body->content.is<Statement_t>()) { |
@@ -1323,7 +1333,7 @@ std::string Macro_t::to_string(void* ud) const { | |||
1323 | } | 1333 | } |
1324 | std::string MacroInPlace_t::to_string(void* ud) const { | 1334 | std::string MacroInPlace_t::to_string(void* ud) const { |
1325 | auto info = reinterpret_cast<YueFormat*>(ud); | 1335 | auto info = reinterpret_cast<YueFormat*>(ud); |
1326 | auto line = "$->"s; | 1336 | auto line = "$ ->"s; |
1327 | if (body->content.is<Statement_t>()) { | 1337 | if (body->content.is<Statement_t>()) { |
1328 | line += ' ' + body->to_string(ud); | 1338 | line += ' ' + body->to_string(ud); |
1329 | } else { | 1339 | } else { |
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 90dce7a..73ffc9a 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
@@ -756,9 +756,10 @@ AST_END(FnArrow, "fn_arrow"sv) | |||
756 | 756 | ||
757 | AST_NODE(FunLit) | 757 | AST_NODE(FunLit) |
758 | ast_ptr<false, FnArgsDef_t> argsDef; | 758 | ast_ptr<false, FnArgsDef_t> argsDef; |
759 | ast_sel<false, ExpListLow_t, DefaultValue_t> defaultReturn; | ||
759 | ast_ptr<true, FnArrow_t> arrow; | 760 | ast_ptr<true, FnArrow_t> arrow; |
760 | ast_ptr<false, Body_t> body; | 761 | ast_ptr<false, Body_t> body; |
761 | AST_MEMBER(FunLit, &argsDef, &arrow, &body) | 762 | AST_MEMBER(FunLit, &argsDef, &defaultReturn, &arrow, &body) |
762 | AST_END(FunLit, "fun_lit"sv) | 763 | AST_END(FunLit, "fun_lit"sv) |
763 | 764 | ||
764 | AST_NODE(MacroName) | 765 | AST_NODE(MacroName) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 0d38fa5..f23d5f0 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
@@ -75,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
75 | "close"s // Lua 5.4 | 75 | "close"s // Lua 5.4 |
76 | }; | 76 | }; |
77 | 77 | ||
78 | const std::string_view version = "0.22.1"sv; | 78 | const std::string_view version = "0.22.2"sv; |
79 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
80 | 80 | ||
81 | class CompileError : public std::logic_error { | 81 | class CompileError : public std::logic_error { |
@@ -3787,11 +3787,44 @@ private: | |||
3787 | str_list temp; | 3787 | str_list temp; |
3788 | if (auto argsDef = funLit->argsDef.get()) { | 3788 | if (auto argsDef = funLit->argsDef.get()) { |
3789 | transformFnArgsDef(argsDef, temp); | 3789 | transformFnArgsDef(argsDef, temp); |
3790 | } | ||
3791 | if (funLit->defaultReturn) { | ||
3792 | auto newBlock = funLit->new_ptr<Block_t>(); | ||
3793 | if (funLit->body) { | ||
3794 | auto last = lastStatementFrom(funLit->body); | ||
3795 | if (!last->appendix && last->content.is<Return_t>() && !funLit->defaultReturn.is<DefaultValue_t>()) { | ||
3796 | throw CompileError("duplicated return statement", last->content); | ||
3797 | } | ||
3798 | auto content = funLit->body->content.get(); | ||
3799 | switch (content->get_id()) { | ||
3800 | case id<Block_t>(): { | ||
3801 | auto block = static_cast<Block_t*>(content); | ||
3802 | newBlock->statements.dup(block->statements); | ||
3803 | break; | ||
3804 | } | ||
3805 | case id<Statement_t>(): { | ||
3806 | newBlock->statements.push_back(content); | ||
3807 | break; | ||
3808 | } | ||
3809 | default: YUEE("AST node mismatch", content); break; | ||
3810 | } | ||
3811 | } | ||
3812 | if (funLit->defaultReturn.is<ExpListLow_t>()) { | ||
3813 | auto returnNode = newBlock->new_ptr<Return_t>(); | ||
3814 | returnNode->valueList.set(funLit->defaultReturn); | ||
3815 | auto stmt = newBlock->new_ptr<Statement_t>(); | ||
3816 | stmt->content.set(returnNode); | ||
3817 | newBlock->statements.push_back(stmt); | ||
3818 | } | ||
3819 | transformBlock(newBlock, temp, ExpUsage::Common); | ||
3820 | } else { | ||
3790 | if (funLit->body) { | 3821 | if (funLit->body) { |
3791 | transformBody(funLit->body, temp, ExpUsage::Return); | 3822 | transformBody(funLit->body, temp, ExpUsage::Return); |
3792 | } else { | 3823 | } else { |
3793 | temp.push_back(Empty); | 3824 | temp.push_back(Empty); |
3794 | } | 3825 | } |
3826 | } | ||
3827 | if (auto argsDef = funLit->argsDef.get()) { | ||
3795 | auto it = temp.begin(); | 3828 | auto it = temp.begin(); |
3796 | auto& args = *it; | 3829 | auto& args = *it; |
3797 | auto& initArgs = *(++it); | 3830 | auto& initArgs = *(++it); |
@@ -3811,11 +3844,6 @@ private: | |||
3811 | _buf << " end"sv; | 3844 | _buf << " end"sv; |
3812 | } | 3845 | } |
3813 | } else { | 3846 | } else { |
3814 | if (funLit->body) { | ||
3815 | transformBody(funLit->body, temp, ExpUsage::Return); | ||
3816 | } else { | ||
3817 | temp.push_back(Empty); | ||
3818 | } | ||
3819 | auto& bodyCodes = temp.back(); | 3847 | auto& bodyCodes = temp.back(); |
3820 | _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')'; | 3848 | _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')'; |
3821 | if (!bodyCodes.empty()) { | 3849 | if (!bodyCodes.empty()) { |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index d138979..3ffaf18 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
@@ -416,6 +416,18 @@ YueParser::YueParser() { | |||
416 | return true; | 416 | return true; |
417 | }); | 417 | }); |
418 | 418 | ||
419 | disable_fun_lit = pl::user(true_(), [](const item_t& item) { | ||
420 | State* st = reinterpret_cast<State*>(item.user_data); | ||
421 | st->fnArrowAvailable = false; | ||
422 | return true; | ||
423 | }); | ||
424 | |||
425 | enable_fun_lit = pl::user(true_(), [](const item_t& item) { | ||
426 | State* st = reinterpret_cast<State*>(item.user_data); | ||
427 | st->fnArrowAvailable = true; | ||
428 | return true; | ||
429 | }); | ||
430 | |||
419 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 431 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
420 | State* st = reinterpret_cast<State*>(item.user_data); | 432 | State* st = reinterpret_cast<State*>(item.user_data); |
421 | st->noDoStack.push(true); | 433 | st->noDoStack.push(true); |
@@ -846,7 +858,14 @@ YueParser::YueParser() { | |||
846 | 858 | ||
847 | FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> ')'; | 859 | FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> ')'; |
848 | FnArrow = expr("->") | "=>"; | 860 | FnArrow = expr("->") | "=>"; |
849 | FunLit = -FnArgsDef >> space >> FnArrow >> -(space >> Body); | 861 | FunLit = pl::user(true_(), [](const item_t& item) { |
862 | State* st = reinterpret_cast<State*>(item.user_data); | ||
863 | return st->fnArrowAvailable; | ||
864 | }) >> -(FnArgsDef >> | ||
865 | -(':' >> space >> | ||
866 | disable_fun_lit >> ensure(ExpListLow | DefaultValue, enable_fun_lit) | ||
867 | ) | ||
868 | ) >> space >> FnArrow >> -(space >> Body); | ||
850 | 869 | ||
851 | MacroName = '$' >> UnicodeName; | 870 | MacroName = '$' >> UnicodeName; |
852 | macro_args_def = '(' >> white >> -FnArgDefList >> white >> ')'; | 871 | macro_args_def = '(' >> white >> -FnArgDefList >> white >> ')'; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 39b7cce..05aa9e6 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
@@ -105,6 +105,7 @@ protected: | |||
105 | bool exportMacro = false; | 105 | bool exportMacro = false; |
106 | bool exportMetatable = false; | 106 | bool exportMetatable = false; |
107 | bool exportMetamethod = false; | 107 | bool exportMetamethod = false; |
108 | bool fnArrowAvailable = true; | ||
108 | int exportCount = 0; | 109 | int exportCount = 0; |
109 | int expLevel = 0; | 110 | int expLevel = 0; |
110 | size_t stringOpen = 0; | 111 | size_t stringOpen = 0; |
@@ -198,6 +199,8 @@ private: | |||
198 | NONE_AST_RULE(enable_arg_table_block); | 199 | NONE_AST_RULE(enable_arg_table_block); |
199 | NONE_AST_RULE(disable_for); | 200 | NONE_AST_RULE(disable_for); |
200 | NONE_AST_RULE(enable_for); | 201 | NONE_AST_RULE(enable_for); |
202 | NONE_AST_RULE(enable_fun_lit); | ||
203 | NONE_AST_RULE(disable_fun_lit); | ||
201 | NONE_AST_RULE(switch_else); | 204 | NONE_AST_RULE(switch_else); |
202 | NONE_AST_RULE(switch_block); | 205 | NONE_AST_RULE(switch_block); |
203 | NONE_AST_RULE(if_else_if); | 206 | NONE_AST_RULE(if_else_if); |