aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE2
-rw-r--r--spec/inputs/assign.yue18
-rw-r--r--spec/outputs/assign.lua25
-rw-r--r--spec/outputs/codes_from_doc.lua18
-rw-r--r--spec/outputs/codes_from_doc_zh.lua18
-rw-r--r--spec/outputs/macro.lua24
-rw-r--r--spec/outputs/plus.lua3
-rw-r--r--spec/outputs/unicode/macro.lua6
-rw-r--r--spec/outputs/unicode/plus.lua3
-rw-r--r--src/yuescript/yue_compiler.cpp78
-rw-r--r--src/yuescript/yue_parser.cpp2
-rw-r--r--src/yuescript/yuescript.h8
12 files changed, 123 insertions, 82 deletions
diff --git a/LICENSE b/LICENSE
index f1cdba4..ca28207 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
1MIT License 1MIT License
2 2
3Copyright (c) 2017-2025 Li Jin 3Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com>
4 4
5Permission is hereby granted, free of charge, to any person obtaining a copy 5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal 6of this software and associated documentation files (the "Software"), to deal
diff --git a/spec/inputs/assign.yue b/spec/inputs/assign.yue
index 514aeed..ad1eda3 100644
--- a/spec/inputs/assign.yue
+++ b/spec/inputs/assign.yue
@@ -109,4 +109,22 @@ do
109 val = 123 109 val = 123
110 a = b = c = val 110 a = b = c = val
111 111
112do
113 -- update
114 a ..= "abc"
115 a //= 2
116 a or= def
117 a and= false
118 a >>= 10
119 a <<= 10
120 a.b.c ??= 123
121 a.b.c += 1
122 a.b.c -= 2
123 a.b.c *= 3
124 a.b.c /= 4
125 a.b.c %= 5
126 a &= 6
127 a |= 7
128 a ^= 8
129
112nil 130nil
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua
index 162a563..f889865 100644
--- a/spec/outputs/assign.lua
+++ b/spec/outputs/assign.lua
@@ -181,5 +181,30 @@ return _(function()
181 local b = val 181 local b = val
182 local c = val 182 local c = val
183 end 183 end
184 do
185 local a = a .. "abc"
186 a = a // 2
187 a = a or def
188 a = a and false
189 a = a >> 10
190 a = a << 10
191 local _obj_0 = a.b
192 if _obj_0.c == nil then
193 _obj_0.c = 123
194 end
195 local _obj_1 = a.b
196 _obj_1.c = _obj_1.c + 1
197 local _obj_2 = a.b
198 _obj_2.c = _obj_2.c - 2
199 local _obj_3 = a.b
200 _obj_3.c = _obj_3.c * 3
201 local _obj_4 = a.b
202 _obj_4.c = _obj_4.c / 4
203 local _obj_5 = a.b
204 _obj_5.c = _obj_5.c % 5
205 a = a & 6
206 a = a | 7
207 a = a ^ 8
208 end
184 return nil 209 return nil
185end) 210end)
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua
index 74db469..a37b459 100644
--- a/spec/outputs/codes_from_doc.lua
+++ b/spec/outputs/codes_from_doc.lua
@@ -467,8 +467,7 @@ local x = f()
467local y = x 467local y = x
468local z = x 468local z = x
469do 469do
470 local a 470 local a = 1
471 a = 1
472 local x, y, z 471 local x, y, z
473 print("forward declare all variables as locals") 472 print("forward declare all variables as locals")
474 x = function() 473 x = function()
@@ -478,8 +477,7 @@ do
478 instance = Item:new() 477 instance = Item:new()
479end 478end
480do 479do
481 local X 480 local X = 1
482 X = 1
483 local B 481 local B
484 print("only forward declare upper case variables") 482 print("only forward declare upper case variables")
485 local a = 1 483 local a = 1
@@ -499,8 +497,7 @@ do
499 print("only declare upper case variables as globals") 497 print("only declare upper case variables as globals")
500 local a = 1 498 local a = 1
501 local B = 2 499 local B = 2
502 local Temp 500 local Temp = "a local value"
503 Temp = "a local value"
504end 501end
505local thing = { 502local thing = {
506 1, 503 1,
@@ -2478,8 +2475,7 @@ local x = f()
2478local y = x 2475local y = x
2479local z = x 2476local z = x
2480do 2477do
2481 local a 2478 local a = 1
2482 a = 1
2483 local x, y, z 2479 local x, y, z
2484 print("forward declare all variables as locals") 2480 print("forward declare all variables as locals")
2485 x = function() 2481 x = function()
@@ -2489,8 +2485,7 @@ do
2489 instance = Item:new() 2485 instance = Item:new()
2490end 2486end
2491do 2487do
2492 local X 2488 local X = 1
2493 X = 1
2494 local B 2489 local B
2495 print("only forward declare upper case variables") 2490 print("only forward declare upper case variables")
2496 local a = 1 2491 local a = 1
@@ -2510,8 +2505,7 @@ do
2510 print("only declare upper case variables as globals") 2505 print("only declare upper case variables as globals")
2511 local a = 1 2506 local a = 1
2512 local B = 2 2507 local B = 2
2513 local Temp 2508 local Temp = "a local value"
2514 Temp = "a local value"
2515end 2509end
2516local thing = { 2510local thing = {
2517 1, 2511 1,
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index 1a10555..a23044d 100644
--- a/spec/outputs/codes_from_doc_zh.lua
+++ b/spec/outputs/codes_from_doc_zh.lua
@@ -467,8 +467,7 @@ local x = f()
467local y = x 467local y = x
468local z = x 468local z = x
469do 469do
470 local a 470 local a = 1
471 a = 1
472 local x, y, z 471 local x, y, z
473 print("预先声明后续所有变量为局部变量") 472 print("预先声明后续所有变量为局部变量")
474 x = function() 473 x = function()
@@ -478,8 +477,7 @@ do
478 instance = Item:new() 477 instance = Item:new()
479end 478end
480do 479do
481 local X 480 local X = 1
482 X = 1
483 local B 481 local B
484 print("只预先声明后续大写的变量为局部变量") 482 print("只预先声明后续大写的变量为局部变量")
485 local a = 1 483 local a = 1
@@ -499,8 +497,7 @@ do
499 print("只预先声明大写的变量为全局变量") 497 print("只预先声明大写的变量为全局变量")
500 local a = 1 498 local a = 1
501 local B = 2 499 local B = 2
502 local Temp 500 local Temp = "一个局部值"
503 Temp = "一个局部值"
504end 501end
505local thing = { 502local thing = {
506 1, 503 1,
@@ -2472,8 +2469,7 @@ local x = f()
2472local y = x 2469local y = x
2473local z = x 2470local z = x
2474do 2471do
2475 local a 2472 local a = 1
2476 a = 1
2477 local x, y, z 2473 local x, y, z
2478 print("预先声明后续所有变量为局部变量") 2474 print("预先声明后续所有变量为局部变量")
2479 x = function() 2475 x = function()
@@ -2483,8 +2479,7 @@ do
2483 instance = Item:new() 2479 instance = Item:new()
2484end 2480end
2485do 2481do
2486 local X 2482 local X = 1
2487 X = 1
2488 local B 2483 local B
2489 print("只预先声明后续大写的变量为局部变量") 2484 print("只预先声明后续大写的变量为局部变量")
2490 local a = 1 2485 local a = 1
@@ -2504,8 +2499,7 @@ do
2504 print("只预先声明大写的变量为全局变量") 2499 print("只预先声明大写的变量为全局变量")
2505 local a = 1 2500 local a = 1
2506 local B = 2 2501 local B = 2
2507 local Temp 2502 local Temp = "一个局部值"
2508 Temp = "一个局部值"
2509end 2503end
2510local thing = { 2504local thing = {
2511 1, 2505 1,
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua
index aa74ed9..4d31574 100644
--- a/spec/outputs/macro.lua
+++ b/spec/outputs/macro.lua
@@ -191,13 +191,11 @@ end
191do 191do
192 local a = 8 192 local a = 8
193 a = (function() 193 a = (function()
194 local a 194 local a = 1
195 a = 1
196 return a + 1 195 return a + 1
197 end)() 196 end)()
198 a = a + (function() 197 a = a + (function()
199 local a 198 local a = 1
200 a = 1
201 return a + 1 199 return a + 1
202 end)() 200 end)()
203 print(a) 201 print(a)
@@ -274,18 +272,12 @@ local result = ((((((origin.transform.root.gameObject:Parents()):Descendants()):
274end)):Destroy() 272end)):Destroy()
275do 273do
276 do 274 do
277 local _1 275 local _1 = origin.transform.root.gameObject:Parents()
278 _1 = origin.transform.root.gameObject:Parents() 276 local _2 = _1:Descendants()
279 local _2 277 local _3 = _2:SelectEnable()
280 _2 = _1:Descendants() 278 local _4 = _3:SelectVisible()
281 local _3 279 local _5 = _4:TagEqual("fx")
282 _3 = _2:SelectEnable() 280 local _6 = _5:Where(function(x)
283 local _4
284 _4 = _3:SelectVisible()
285 local _5
286 _5 = _4:TagEqual("fx")
287 local _6
288 _6 = _5:Where(function(x)
289 return x.name:EndsWith("(Clone)") 281 return x.name:EndsWith("(Clone)")
290 end) 282 end)
291 _6:Destroy() 283 _6:Destroy()
diff --git a/spec/outputs/plus.lua b/spec/outputs/plus.lua
index bd89bfe..dda0660 100644
--- a/spec/outputs/plus.lua
+++ b/spec/outputs/plus.lua
@@ -65,7 +65,6 @@ backpack = {
65local start = { 65local start = {
66 something = "cold" 66 something = "cold"
67} 67}
68local bathe 68local bathe = {
69bathe = {
70 on = "fire" 69 on = "fire"
71} 70}
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua
index e2195e4..099080f 100644
--- a/spec/outputs/unicode/macro.lua
+++ b/spec/outputs/unicode/macro.lua
@@ -167,13 +167,11 @@ end
167do 167do
168 local _u53d8_u91cfa = 8 168 local _u53d8_u91cfa = 8
169 _u53d8_u91cfa = (function() 169 _u53d8_u91cfa = (function()
170 local _u53d8_u91cfa 170 local _u53d8_u91cfa = 1
171 _u53d8_u91cfa = 1
172 return _u53d8_u91cfa + 1 171 return _u53d8_u91cfa + 1
173 end)() 172 end)()
174 _u53d8_u91cfa = _u53d8_u91cfa + (function() 173 _u53d8_u91cfa = _u53d8_u91cfa + (function()
175 local _u53d8_u91cfa 174 local _u53d8_u91cfa = 1
176 _u53d8_u91cfa = 1
177 return _u53d8_u91cfa + 1 175 return _u53d8_u91cfa + 1
178 end)() 176 end)()
179 _u6253_u5370(_u53d8_u91cfa) 177 _u6253_u5370(_u53d8_u91cfa)
diff --git a/spec/outputs/unicode/plus.lua b/spec/outputs/unicode/plus.lua
index 75e4aac..adce62e 100644
--- a/spec/outputs/unicode/plus.lua
+++ b/spec/outputs/unicode/plus.lua
@@ -67,7 +67,6 @@ _u80cc_u5305 = {
67local _u5f00_u59cb = { 67local _u5f00_u59cb = {
68 ["东西"] = "冷" 68 ["东西"] = "冷"
69} 69}
70local _u6d17_u6fa1 70local _u6d17_u6fa1 = {
71_u6d17_u6fa1 = {
72 ["在"] = "火" 71 ["在"] = "火"
73} 72}
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index e7fe0c0..3d98fbc 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.27.0"sv; 78const std::string_view version = "0.27.1"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 {
@@ -1486,7 +1486,7 @@ private:
1486 } 1486 }
1487 } 1487 }
1488 1488
1489 bool isPureBackcall(Exp_t* exp) const { 1489 bool isPurePipeChain(Exp_t* exp) const {
1490 return exp->opValues.empty() && exp->pipeExprs.size() > 1; 1490 return exp->opValues.empty() && exp->pipeExprs.size() > 1;
1491 } 1491 }
1492 1492
@@ -1869,7 +1869,7 @@ private:
1869 } 1869 }
1870 } else if (expList->exprs.size() == 1) { 1870 } else if (expList->exprs.size() == 1) {
1871 auto exp = static_cast<Exp_t*>(expList->exprs.back()); 1871 auto exp = static_cast<Exp_t*>(expList->exprs.back());
1872 if (isPureBackcall(exp)) { 1872 if (isPurePipeChain(exp)) {
1873 transformExp(exp, out, ExpUsage::Common); 1873 transformExp(exp, out, ExpUsage::Common);
1874 break; 1874 break;
1875 } 1875 }
@@ -2061,7 +2061,7 @@ private:
2061 } 2061 }
2062 } 2062 }
2063 2063
2064 void transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { 2064 bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) {
2065 checkAssignable(assignment->expList); 2065 checkAssignable(assignment->expList);
2066 BLOCK_START 2066 BLOCK_START
2067 auto assign = ast_cast<Assign_t>(assignment->action); 2067 auto assign = ast_cast<Assign_t>(assignment->action);
@@ -2176,7 +2176,7 @@ private:
2176 temp.push_back(indent() + "end"s + nll(assignment)); 2176 temp.push_back(indent() + "end"s + nll(assignment));
2177 } 2177 }
2178 out.push_back(join(temp)); 2178 out.push_back(join(temp));
2179 return; 2179 return false;
2180 BLOCK_END 2180 BLOCK_END
2181 } 2181 }
2182 { 2182 {
@@ -2248,7 +2248,7 @@ private:
2248 transformAssignment(afterAssignment, temp); 2248 transformAssignment(afterAssignment, temp);
2249 } 2249 }
2250 out.push_back(join(temp)); 2250 out.push_back(join(temp));
2251 return; 2251 return false;
2252 } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) { 2252 } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) {
2253 str_list temp; 2253 str_list temp;
2254 auto [beforeAssignment, afterAssignment] = splitAssignment(); 2254 auto [beforeAssignment, afterAssignment] = splitAssignment();
@@ -2300,7 +2300,7 @@ private:
2300 transformAssignment(afterAssignment, temp); 2300 transformAssignment(afterAssignment, temp);
2301 } 2301 }
2302 out.push_back(join(temp)); 2302 out.push_back(join(temp));
2303 return; 2303 return false;
2304 } else { 2304 } else {
2305 break; 2305 break;
2306 } 2306 }
@@ -2322,7 +2322,7 @@ private:
2322 std::string preDefine = getPreDefineLine(assignment); 2322 std::string preDefine = getPreDefineLine(assignment);
2323 transformIf(ifNode, out, ExpUsage::Assignment, assignList); 2323 transformIf(ifNode, out, ExpUsage::Assignment, assignList);
2324 out.back().insert(0, preDefine); 2324 out.back().insert(0, preDefine);
2325 return; 2325 return false;
2326 } 2326 }
2327 case id<Switch_t>(): { 2327 case id<Switch_t>(): {
2328 auto switchNode = static_cast<Switch_t*>(value); 2328 auto switchNode = static_cast<Switch_t*>(value);
@@ -2330,7 +2330,7 @@ private:
2330 std::string preDefine = getPreDefineLine(assignment); 2330 std::string preDefine = getPreDefineLine(assignment);
2331 transformSwitch(switchNode, out, ExpUsage::Assignment, assignList); 2331 transformSwitch(switchNode, out, ExpUsage::Assignment, assignList);
2332 out.back().insert(0, preDefine); 2332 out.back().insert(0, preDefine);
2333 return; 2333 return false;
2334 } 2334 }
2335 case id<With_t>(): { 2335 case id<With_t>(): {
2336 auto withNode = static_cast<With_t*>(value); 2336 auto withNode = static_cast<With_t*>(value);
@@ -2338,7 +2338,7 @@ private:
2338 std::string preDefine = getPreDefineLine(assignment); 2338 std::string preDefine = getPreDefineLine(assignment);
2339 transformWith(withNode, out, expList); 2339 transformWith(withNode, out, expList);
2340 out.back().insert(0, preDefine); 2340 out.back().insert(0, preDefine);
2341 return; 2341 return false;
2342 } 2342 }
2343 case id<Do_t>(): { 2343 case id<Do_t>(): {
2344 auto expList = assignment->expList.get(); 2344 auto expList = assignment->expList.get();
@@ -2346,7 +2346,7 @@ private:
2346 std::string preDefine = getPreDefineLine(assignment); 2346 std::string preDefine = getPreDefineLine(assignment);
2347 transformDo(doNode, out, ExpUsage::Assignment, expList); 2347 transformDo(doNode, out, ExpUsage::Assignment, expList);
2348 out.back().insert(0, preDefine); 2348 out.back().insert(0, preDefine);
2349 return; 2349 return false;
2350 } 2350 }
2351 case id<Comprehension_t>(): { 2351 case id<Comprehension_t>(): {
2352 auto comp = static_cast<Comprehension_t*>(value); 2352 auto comp = static_cast<Comprehension_t*>(value);
@@ -2358,42 +2358,42 @@ private:
2358 } else { 2358 } else {
2359 transformComprehension(comp, out, ExpUsage::Assignment, expList); 2359 transformComprehension(comp, out, ExpUsage::Assignment, expList);
2360 } 2360 }
2361 return; 2361 return false;
2362 } 2362 }
2363 case id<TblComprehension_t>(): { 2363 case id<TblComprehension_t>(): {
2364 auto expList = assignment->expList.get(); 2364 auto expList = assignment->expList.get();
2365 std::string preDefine = getPreDefineLine(assignment); 2365 std::string preDefine = getPreDefineLine(assignment);
2366 transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Assignment, expList); 2366 transformTblComprehension(static_cast<TblComprehension_t*>(value), out, ExpUsage::Assignment, expList);
2367 out.back().insert(0, preDefine); 2367 out.back().insert(0, preDefine);
2368 return; 2368 return false;
2369 } 2369 }
2370 case id<For_t>(): { 2370 case id<For_t>(): {
2371 auto expList = assignment->expList.get(); 2371 auto expList = assignment->expList.get();
2372 std::string preDefine = getPreDefineLine(assignment); 2372 std::string preDefine = getPreDefineLine(assignment);
2373 transformForInPlace(static_cast<For_t*>(value), out, expList); 2373 transformForInPlace(static_cast<For_t*>(value), out, expList);
2374 out.back().insert(0, preDefine); 2374 out.back().insert(0, preDefine);
2375 return; 2375 return false;
2376 } 2376 }
2377 case id<ForEach_t>(): { 2377 case id<ForEach_t>(): {
2378 auto expList = assignment->expList.get(); 2378 auto expList = assignment->expList.get();
2379 std::string preDefine = getPreDefineLine(assignment); 2379 std::string preDefine = getPreDefineLine(assignment);
2380 transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList); 2380 transformForEachInPlace(static_cast<ForEach_t*>(value), out, expList);
2381 out.back().insert(0, preDefine); 2381 out.back().insert(0, preDefine);
2382 return; 2382 return false;
2383 } 2383 }
2384 case id<ClassDecl_t>(): { 2384 case id<ClassDecl_t>(): {
2385 auto expList = assignment->expList.get(); 2385 auto expList = assignment->expList.get();
2386 std::string preDefine = getPreDefineLine(assignment); 2386 std::string preDefine = getPreDefineLine(assignment);
2387 transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList); 2387 transformClassDecl(static_cast<ClassDecl_t*>(value), out, ExpUsage::Assignment, expList);
2388 out.back().insert(0, preDefine); 2388 out.back().insert(0, preDefine);
2389 return; 2389 return false;
2390 } 2390 }
2391 case id<While_t>(): { 2391 case id<While_t>(): {
2392 auto expList = assignment->expList.get(); 2392 auto expList = assignment->expList.get();
2393 std::string preDefine = getPreDefineLine(assignment); 2393 std::string preDefine = getPreDefineLine(assignment);
2394 transformWhileInPlace(static_cast<While_t*>(value), out, expList); 2394 transformWhileInPlace(static_cast<While_t*>(value), out, expList);
2395 out.back().insert(0, preDefine); 2395 out.back().insert(0, preDefine);
2396 return; 2396 return false;
2397 } 2397 }
2398 case id<TableLit_t>(): { 2398 case id<TableLit_t>(): {
2399 auto tableLit = static_cast<TableLit_t*>(value); 2399 auto tableLit = static_cast<TableLit_t*>(value);
@@ -2402,7 +2402,7 @@ private:
2402 std::string preDefine = getPreDefineLine(assignment); 2402 std::string preDefine = getPreDefineLine(assignment);
2403 transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Assignment, expList, false); 2403 transformSpreadTable(tableLit->values.objects(), out, ExpUsage::Assignment, expList, false);
2404 out.back().insert(0, preDefine); 2404 out.back().insert(0, preDefine);
2405 return; 2405 return false;
2406 } 2406 }
2407 break; 2407 break;
2408 } 2408 }
@@ -2413,31 +2413,31 @@ private:
2413 std::string preDefine = getPreDefineLine(assignment); 2413 std::string preDefine = getPreDefineLine(assignment);
2414 transformSpreadTable(tableBlock->values.objects(), out, ExpUsage::Assignment, expList, false); 2414 transformSpreadTable(tableBlock->values.objects(), out, ExpUsage::Assignment, expList, false);
2415 out.back().insert(0, preDefine); 2415 out.back().insert(0, preDefine);
2416 return; 2416 return false;
2417 } 2417 }
2418 break; 2418 break;
2419 } 2419 }
2420 } 2420 }
2421 auto exp = ast_cast<Exp_t>(value); 2421 auto exp = ast_cast<Exp_t>(value);
2422 BREAK_IF(!exp); 2422 BREAK_IF(!exp);
2423 if (isPureBackcall(exp)) { 2423 if (isPurePipeChain(exp)) {
2424 auto expList = assignment->expList.get(); 2424 auto expList = assignment->expList.get();
2425 transformExp(exp, out, ExpUsage::Assignment, expList); 2425 transformExp(exp, out, ExpUsage::Assignment, expList);
2426 return; 2426 return false;
2427 } else if (isPureNilCoalesed(exp)) { 2427 } else if (isPureNilCoalesed(exp)) {
2428 auto expList = assignment->expList.get(); 2428 auto expList = assignment->expList.get();
2429 transformNilCoalesedExp(exp, out, ExpUsage::Assignment, expList); 2429 transformNilCoalesedExp(exp, out, ExpUsage::Assignment, expList);
2430 return; 2430 return false;
2431 } else if (auto unary = unaryGeneratingAnonFunc(exp)) { 2431 } else if (auto unary = unaryGeneratingAnonFunc(exp)) {
2432 std::string preDefine = getPreDefineLine(assignment); 2432 std::string preDefine = getPreDefineLine(assignment);
2433 auto expList = assignment->expList.get(); 2433 auto expList = assignment->expList.get();
2434 transformUnaryExp(unary, out, ExpUsage::Assignment, expList); 2434 transformUnaryExp(unary, out, ExpUsage::Assignment, expList);
2435 out.back().insert(0, preDefine); 2435 out.back().insert(0, preDefine);
2436 return; 2436 return false;
2437 } else if (isConditionChaining(exp)) { 2437 } else if (isConditionChaining(exp)) {
2438 auto expList = assignment->expList.get(); 2438 auto expList = assignment->expList.get();
2439 transformExp(exp, out, ExpUsage::Assignment, expList); 2439 transformExp(exp, out, ExpUsage::Assignment, expList);
2440 return; 2440 return false;
2441 } 2441 }
2442 auto singleVal = singleValueFrom(exp); 2442 auto singleVal = singleValueFrom(exp);
2443 BREAK_IF(!singleVal); 2443 BREAK_IF(!singleVal);
@@ -2451,13 +2451,13 @@ private:
2451 std::string preDefine = getPreDefineLine(assignment); 2451 std::string preDefine = getPreDefineLine(assignment);
2452 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); 2452 transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct);
2453 out.back().insert(0, preDefine); 2453 out.back().insert(0, preDefine);
2454 return; 2454 return false;
2455 } 2455 }
2456 case ChainType::HasKeyword: 2456 case ChainType::HasKeyword:
2457 case ChainType::HasUnicode: 2457 case ChainType::HasUnicode:
2458 case ChainType::Macro: 2458 case ChainType::Macro:
2459 transformChainValue(chainValue, out, ExpUsage::Assignment, expList); 2459 transformChainValue(chainValue, out, ExpUsage::Assignment, expList);
2460 return; 2460 return false;
2461 case ChainType::Common: 2461 case ChainType::Common:
2462 case ChainType::EndWithEOP: 2462 case ChainType::EndWithEOP:
2463 case ChainType::Metatable: 2463 case ChainType::Metatable:
@@ -2468,6 +2468,7 @@ private:
2468 auto info = extractDestructureInfo(assignment, false, optionalDestruct); 2468 auto info = extractDestructureInfo(assignment, false, optionalDestruct);
2469 if (info.destructures.empty()) { 2469 if (info.destructures.empty()) {
2470 transformAssignmentCommon(assignment, out); 2470 transformAssignmentCommon(assignment, out);
2471 return true;
2471 } else { 2472 } else {
2472 auto x = assignment; 2473 auto x = assignment;
2473 str_list temp; 2474 str_list temp;
@@ -2733,6 +2734,7 @@ private:
2733 } 2734 }
2734 out.push_back(join(temp)); 2735 out.push_back(join(temp));
2735 } 2736 }
2737 return false;
2736 } 2738 }
2737 2739
2738 void transformAssignItem(ast_node* value, str_list& out) { 2740 void transformAssignItem(ast_node* value, str_list& out) {
@@ -5313,7 +5315,7 @@ private:
5313 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { 5315 if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) {
5314 if (valueList->exprs.size() == 1) { 5316 if (valueList->exprs.size() == 1) {
5315 auto exp = static_cast<Exp_t*>(valueList->exprs.back()); 5317 auto exp = static_cast<Exp_t*>(valueList->exprs.back());
5316 if (isPureBackcall(exp)) { 5318 if (isPurePipeChain(exp)) {
5317 transformExp(exp, out, ExpUsage::Return); 5319 transformExp(exp, out, ExpUsage::Return);
5318 return; 5320 return;
5319 } else if (isPureNilCoalesed(exp)) { 5321 } else if (isPureNilCoalesed(exp)) {
@@ -10676,6 +10678,7 @@ private:
10676 10678
10677 void transformLocal(Local_t* local, str_list& out) { 10679 void transformLocal(Local_t* local, str_list& out) {
10678 str_list temp; 10680 str_list temp;
10681 bool defined = local->defined;
10679 if (!local->defined) { 10682 if (!local->defined) {
10680 local->defined = true; 10683 local->defined = true;
10681 transformLocalDef(local, temp); 10684 transformLocalDef(local, temp);
@@ -10704,7 +10707,26 @@ private:
10704 assign->values.push_back(tableBlock); 10707 assign->values.push_back(tableBlock);
10705 } 10708 }
10706 assignment->action.set(assign); 10709 assignment->action.set(assign);
10707 transformAssignment(assignment, temp); 10710 bool oneLined = transformAssignment(assignment, temp);
10711 for (auto val : assign->values.objects()) {
10712 if (auto value = singleValueFrom(val)) {
10713 if (auto spValue = value->item.as<SimpleValue_t>()) {
10714 if (auto funLit = spValue->value.as<FunLit_t>()) {
10715 if (!funLit->noRecursion) {
10716 oneLined = false;
10717 }
10718 break;
10719 }
10720 }
10721 }
10722 }
10723 if (!defined && oneLined && temp.size() == 2) {
10724 auto pos = temp.back().find_first_not_of(" \t"sv);
10725 if (pos != std::string::npos) {
10726 temp.back().insert(pos, "local ");
10727 temp.pop_front();
10728 }
10729 }
10708 } 10730 }
10709 break; 10731 break;
10710 } 10732 }
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 5993ed5..ceb1f7c 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -519,7 +519,7 @@ YueParser::YueParser() {
519 UpdateOp = 519 UpdateOp =
520 expr("..") | "//" | "or" | "and" | 520 expr("..") | "//" | "or" | "and" |
521 ">>" | "<<" | "??" | 521 ">>" | "<<" | "??" |
522 set("+-*/%&|"); 522 set("+-*/%&|^");
523 523
524 Update = UpdateOp >> '=' >> space >> Exp; 524 Update = UpdateOp >> '=' >> space >> Exp;
525 525
diff --git a/src/yuescript/yuescript.h b/src/yuescript/yuescript.h
index ebe90cb..83a4350 100644
--- a/src/yuescript/yuescript.h
+++ b/src/yuescript/yuescript.h
@@ -187,10 +187,10 @@ local function dump(what)
187 depth = depth or 0 187 depth = depth or 0
188 local t = type(what) 188 local t = type(what)
189 if "string" == t then 189 if "string" == t then
190 return "\"" .. tostring(what) .. "\"\n" 190 return "\"" .. tostring(what) .. "\""
191 elseif "table" == t then 191 elseif "table" == t then
192 if seen[what] then 192 if seen[what] then
193 return "recursion(" .. tostring(what) .. ")...\n" 193 return "recursion(" .. tostring(what) .. ")..."
194 end 194 end
195 seen[what] = true 195 seen[what] = true
196 depth = depth + 1 196 depth = depth + 1
@@ -199,9 +199,9 @@ local function dump(what)
199 insert(lines, ('\t'):rep(depth) .. "[" .. tostring(k) .. "] = " .. _dump(v, depth)) 199 insert(lines, ('\t'):rep(depth) .. "[" .. tostring(k) .. "] = " .. _dump(v, depth))
200 end 200 end
201 seen[what] = false 201 seen[what] = false
202 return "{\n" .. concat(lines) .. ('\t'):rep(depth - 1) .. "}\n" 202 return "{\n" .. concat(lines, "\n") .. "\n" .. ('\t'):rep(depth - 1) .. "}"
203 else 203 else
204 return tostring(what) .. "\n" 204 return tostring(what)
205 end 205 end
206 end 206 end
207 return _dump(what) 207 return _dump(what)