aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--spec/inputs/funcs.yue35
-rw-r--r--spec/outputs/funcs.lua70
-rw-r--r--src/yuescript/yue_ast.cpp14
-rw-r--r--src/yuescript/yue_ast.h3
-rw-r--r--src/yuescript/yue_compiler.cpp40
-rw-r--r--src/yuescript/yue_parser.cpp21
-rw-r--r--src/yuescript/yue_parser.h3
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
161do
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
161nil 196nil
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)
221end 221end
222do
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())
291end
222return nil 292return 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}
1324std::string MacroInPlace_t::to_string(void* ud) const { 1334std::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
757AST_NODE(FunLit) 757AST_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)
762AST_END(FunLit, "fun_lit"sv) 763AST_END(FunLit, "fun_lit"sv)
763 764
764AST_NODE(MacroName) 765AST_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
78const std::string_view version = "0.22.1"sv; 78const std::string_view version = "0.22.2"sv;
79const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
80 80
81class CompileError : public std::logic_error { 81class 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);