aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdoc/docs/doc/README.md38
-rwxr-xr-xdoc/docs/zh/doc/README.md38
-rw-r--r--spec/inputs/lists.yue10
-rw-r--r--spec/outputs/codes_from_doc.lua84
-rw-r--r--spec/outputs/codes_from_doc_zh.lua84
-rw-r--r--spec/outputs/lists.lua49
-rw-r--r--src/yuescript/yue_ast.h2
-rw-r--r--src/yuescript/yue_compiler.cpp47
-rw-r--r--src/yuescript/yue_parser.cpp2
9 files changed, 338 insertions, 16 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index ad26be5..2a3047a 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -595,6 +595,23 @@ tab[] = "Value"
595</pre> 595</pre>
596</YueDisplay> 596</YueDisplay>
597 597
598You can also use the spread operator `...` to append all elements from one list to another:
599
600```moonscript
601tbA = [1, 2, 3]
602tbB = [4, 5, 6]
603tbA[] = ...tbB
604-- tbA is now [1, 2, 3, 4, 5, 6]
605```
606<YueDisplay>
607<pre>
608tbA = [1, 2, 3]
609tbB = [4, 5, 6]
610tbA[] = ...tbB
611-- tbA is now [1, 2, 3, 4, 5, 6]
612</pre>
613</YueDisplay>
614
598### Table Spreading 615### Table Spreading
599 616
600You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals. 617You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals.
@@ -2465,6 +2482,27 @@ doubled = [item * 2 for item in *items]
2465</pre> 2482</pre>
2466</YueDisplay> 2483</YueDisplay>
2467 2484
2485In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect:
2486
2487```moonscript
2488data =
2489 a: {1,2,3}
2490 b: {4,5,6}
2491
2492flat = [...v for k,v in pairs data]
2493-- flat is now [1, 2, 3, 4, 5, 6]
2494```
2495<YueDisplay>
2496<pre>
2497data =
2498 a: {1,2,3}
2499 b: {4,5,6}
2500
2501flat = [...v for k,v in pairs data]
2502-- flat is now [1, 2, 3, 4, 5, 6]
2503</pre>
2504</YueDisplay>
2505
2468The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause. 2506The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause.
2469 2507
2470Using multiple for clauses is the same as using nested loops: 2508Using multiple for clauses is the same as using nested loops:
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 86796e9..a799a5b 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -594,6 +594,23 @@ tab[] = "Value"
594</pre> 594</pre>
595</YueDisplay> 595</YueDisplay>
596 596
597你还可以使用展开操作符 `...` 来将一个列表中的所有元素追加到另一个列表中:
598
599```moonscript
600tbA = [1, 2, 3]
601tbB = [4, 5, 6]
602tbA[] = ...tbB
603-- tbA 现在为 [1, 2, 3, 4, 5, 6]
604```
605<YueDisplay>
606<pre>
607tbA = [1, 2, 3]
608tbB = [4, 5, 6]
609tbA[] = ...tbB
610-- tbA 现在为 [1, 2, 3, 4, 5, 6]
611</pre>
612</YueDisplay>
613
597### 表扩展 614### 表扩展
598 615
599你可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。 616你可以使用前置 `...` 操作符在Lua表中插入数组表或哈希表。
@@ -2425,6 +2442,27 @@ doubled = [item * 2 for item in *items]
2425</pre> 2442</pre>
2426</YueDisplay> 2443</YueDisplay>
2427 2444
2445在列表推导式中,你还可以使用展开操作符 `...` 来实现对列表嵌套层级进行扁平化的处理:
2446
2447```moonscript
2448data =
2449 a: {1,2,3}
2450 b: {4,5,6}
2451
2452flat = [...v for k,v in pairs data]
2453-- flat 现在为 [1, 2, 3, 4, 5, 6]
2454```
2455<YueDisplay>
2456<pre>
2457data =
2458 a: {1,2,3}
2459 b: {4,5,6}
2460
2461flat = [...v for k,v in pairs data]
2462-- flat 现在为 [1, 2, 3, 4, 5, 6]
2463</pre>
2464</YueDisplay>
2465
2428for和when子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个for子句。 2466for和when子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个for子句。
2429 2467
2430使用多个for子句与使用多重循环的效果相同: 2468使用多个for子句与使用多重循环的效果相同:
diff --git a/spec/inputs/lists.yue b/spec/inputs/lists.yue
index f754cc1..dd951a5 100644
--- a/spec/inputs/lists.yue
+++ b/spec/inputs/lists.yue
@@ -267,4 +267,14 @@ do
267 f = -> globalTB[#][#] = 1 267 f = -> globalTB[#][#] = 1
268 f1 = -> globalTB[#][# - 1] 268 f1 = -> globalTB[#][# - 1]
269 269
270do
271 tbA[] = ...tbB
272 a, tb[], b[], c = 1, ...x, 3, 4
273
274 data =
275 a: {1,2,3}
276 b: {4,5,6}
277
278 flat = [...v for k,v in pairs data]
279
270nil 280nil
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua
index 3971bb7..00b3b8b 100644
--- a/spec/outputs/codes_from_doc.lua
+++ b/spec/outputs/codes_from_doc.lua
@@ -147,6 +147,21 @@ print((function()
147end)()) 147end)())
148local tab = { } 148local tab = { }
149tab[#tab + 1] = "Value" 149tab[#tab + 1] = "Value"
150local tbA = {
151 1,
152 2,
153 3
154}
155local tbB = {
156 4,
157 5,
158 6
159}
160local _len_0 = #tbA + 1
161for _index_0 = 1, #tbB do
162 local _elm_0 = tbB[_index_0]
163 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
164end
150local parts = { 165local parts = {
151 "shoulders", 166 "shoulders",
152 "knees" 167 "knees"
@@ -1080,6 +1095,33 @@ for _index_0 = 1, #_list_0 do
1080 _len_0 = _len_0 + 1 1095 _len_0 = _len_0 + 1
1081end 1096end
1082doubled = _accum_0 1097doubled = _accum_0
1098local data = {
1099 a = {
1100 1,
1101 2,
1102 3
1103 },
1104 b = {
1105 4,
1106 5,
1107 6
1108 }
1109}
1110local flat
1111local _accum_0 = { }
1112local _len_0 = 1
1113for k, v in pairs(data) do
1114 do
1115 local _obj_0 = _accum_0[_len_0]
1116 local _len_1 = #_obj_0 + 1
1117 for _index_0 = 1, #v do
1118 local _elm_0 = v[_index_0]
1119 _obj_0[_len_1], _len_1 = _elm_0, _len_1 + 1
1120 end
1121 end
1122 _len_0 = _len_0 + 1
1123end
1124flat = _accum_0
1083local x_coords = { 1125local x_coords = {
1084 4, 1126 4,
1085 5, 1127 5,
@@ -2588,6 +2630,21 @@ print((function()
2588end)()) 2630end)())
2589local tab = { } 2631local tab = { }
2590tab[#tab + 1] = "Value" 2632tab[#tab + 1] = "Value"
2633local tbA = {
2634 1,
2635 2,
2636 3
2637}
2638local tbB = {
2639 4,
2640 5,
2641 6
2642}
2643local _len_0 = #tbA + 1
2644for _index_0 = 1, #tbB do
2645 local _elm_0 = tbB[_index_0]
2646 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
2647end
2591local parts = { 2648local parts = {
2592 "shoulders", 2649 "shoulders",
2593 "knees" 2650 "knees"
@@ -3551,6 +3608,33 @@ for _index_0 = 1, #_list_0 do
3551 _len_0 = _len_0 + 1 3608 _len_0 = _len_0 + 1
3552end 3609end
3553doubled = _accum_0 3610doubled = _accum_0
3611local data = {
3612 a = {
3613 1,
3614 2,
3615 3
3616 },
3617 b = {
3618 4,
3619 5,
3620 6
3621 }
3622}
3623local flat
3624local _accum_0 = { }
3625local _len_0 = 1
3626for k, v in pairs(data) do
3627 do
3628 local _obj_0 = _accum_0[_len_0]
3629 local _len_1 = #_obj_0 + 1
3630 for _index_0 = 1, #v do
3631 local _elm_0 = v[_index_0]
3632 _obj_0[_len_1], _len_1 = _elm_0, _len_1 + 1
3633 end
3634 end
3635 _len_0 = _len_0 + 1
3636end
3637flat = _accum_0
3554local x_coords = { 3638local x_coords = {
3555 4, 3639 4,
3556 5, 3640 5,
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua
index 403ad3e..c382bca 100644
--- a/spec/outputs/codes_from_doc_zh.lua
+++ b/spec/outputs/codes_from_doc_zh.lua
@@ -147,6 +147,21 @@ print((function()
147end)()) 147end)())
148local tab = { } 148local tab = { }
149tab[#tab + 1] = "Value" 149tab[#tab + 1] = "Value"
150local tbA = {
151 1,
152 2,
153 3
154}
155local tbB = {
156 4,
157 5,
158 6
159}
160local _len_0 = #tbA + 1
161for _index_0 = 1, #tbB do
162 local _elm_0 = tbB[_index_0]
163 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
164end
150local parts = { 165local parts = {
151 "shoulders", 166 "shoulders",
152 "knees" 167 "knees"
@@ -1074,6 +1089,33 @@ for _index_0 = 1, #_list_0 do
1074 _len_0 = _len_0 + 1 1089 _len_0 = _len_0 + 1
1075end 1090end
1076doubled = _accum_0 1091doubled = _accum_0
1092local data = {
1093 a = {
1094 1,
1095 2,
1096 3
1097 },
1098 b = {
1099 4,
1100 5,
1101 6
1102 }
1103}
1104local flat
1105local _accum_0 = { }
1106local _len_0 = 1
1107for k, v in pairs(data) do
1108 do
1109 local _obj_0 = _accum_0[_len_0]
1110 local _len_1 = #_obj_0 + 1
1111 for _index_0 = 1, #v do
1112 local _elm_0 = v[_index_0]
1113 _obj_0[_len_1], _len_1 = _elm_0, _len_1 + 1
1114 end
1115 end
1116 _len_0 = _len_0 + 1
1117end
1118flat = _accum_0
1077local x_coords = { 1119local x_coords = {
1078 4, 1120 4,
1079 5, 1121 5,
@@ -2582,6 +2624,21 @@ print((function()
2582end)()) 2624end)())
2583local tab = { } 2625local tab = { }
2584tab[#tab + 1] = "Value" 2626tab[#tab + 1] = "Value"
2627local tbA = {
2628 1,
2629 2,
2630 3
2631}
2632local tbB = {
2633 4,
2634 5,
2635 6
2636}
2637local _len_0 = #tbA + 1
2638for _index_0 = 1, #tbB do
2639 local _elm_0 = tbB[_index_0]
2640 tbA[_len_0], _len_0 = _elm_0, _len_0 + 1
2641end
2585local parts = { 2642local parts = {
2586 "shoulders", 2643 "shoulders",
2587 "knees" 2644 "knees"
@@ -3539,6 +3596,33 @@ for _index_0 = 1, #_list_0 do
3539 _len_0 = _len_0 + 1 3596 _len_0 = _len_0 + 1
3540end 3597end
3541doubled = _accum_0 3598doubled = _accum_0
3599local data = {
3600 a = {
3601 1,
3602 2,
3603 3
3604 },
3605 b = {
3606 4,
3607 5,
3608 6
3609 }
3610}
3611local flat
3612local _accum_0 = { }
3613local _len_0 = 1
3614for k, v in pairs(data) do
3615 do
3616 local _obj_0 = _accum_0[_len_0]
3617 local _len_1 = #_obj_0 + 1
3618 for _index_0 = 1, #v do
3619 local _elm_0 = v[_index_0]
3620 _obj_0[_len_1], _len_1 = _elm_0, _len_1 + 1
3621 end
3622 end
3623 _len_0 = _len_0 + 1
3624end
3625flat = _accum_0
3542local x_coords = { 3626local x_coords = {
3543 4, 3627 4,
3544 5, 3628 5,
diff --git a/spec/outputs/lists.lua b/spec/outputs/lists.lua
index 2dd19e5..6115700 100644
--- a/spec/outputs/lists.lua
+++ b/spec/outputs/lists.lua
@@ -857,4 +857,53 @@ do
857 end 857 end
858 end 858 end
859end 859end
860do
861 do
862 local _obj_0 = tbA
863 local _len_0 = #_obj_0 + 1
864 local _list_0 = tbB
865 for _index_0 = 1, #_list_0 do
866 local _elm_0 = _list_0[_index_0]
867 _obj_0[_len_0], _len_0 = _elm_0, _len_0 + 1
868 end
869 end
870 a = 1
871 do
872 local _obj_0 = tb
873 local _len_0 = #_obj_0 + 1
874 for _index_0 = 1, #x do
875 local _elm_0 = x[_index_0]
876 _obj_0[_len_0], _len_0 = _elm_0, _len_0 + 1
877 end
878 end
879 b[#b + 1] = 3
880 c = 4
881 local data = {
882 a = {
883 1,
884 2,
885 3
886 },
887 b = {
888 4,
889 5,
890 6
891 }
892 }
893 local flat
894 local _accum_0 = { }
895 local _len_0 = 1
896 for k, v in pairs(data) do
897 do
898 local _obj_0 = _accum_0[_len_0]
899 local _len_1 = #_obj_0 + 1
900 for _index_0 = 1, #v do
901 local _elm_0 = v[_index_0]
902 _obj_0[_len_1], _len_1 = _elm_0, _len_1 + 1
903 end
904 end
905 _len_0 = _len_0 + 1
906 end
907 flat = _accum_0
908end
860return nil 909return nil
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index b1a369b..0008fd6 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -443,7 +443,7 @@ AST_END(CompInner)
443 443
444AST_NODE(Assign) 444AST_NODE(Assign)
445 ast_ptr<true, Seperator_t> sep; 445 ast_ptr<true, Seperator_t> sep;
446 ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t> values; 446 ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t, SpreadListExp_t> values;
447 AST_MEMBER(Assign, &sep, &values) 447 AST_MEMBER(Assign, &sep, &values)
448AST_END(Assign) 448AST_END(Assign)
449 449
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index ed0a587..8c28e61 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = {
78 "close"s // Lua 5.4 78 "close"s // Lua 5.4
79}; 79};
80 80
81const std::string_view version = "0.29.7"sv; 81const std::string_view version = "0.29.8"sv;
82const std::string_view extension = "yue"sv; 82const std::string_view extension = "yue"sv;
83 83
84class CompileError : public std::logic_error { 84class CompileError : public std::logic_error {
@@ -2321,15 +2321,27 @@ private:
2321 transformAssignment(newAssignment, temp); 2321 transformAssignment(newAssignment, temp);
2322 varName = objVar; 2322 varName = objVar;
2323 } 2323 }
2324 auto newAssignment = x->new_ptr<ExpListAssign_t>(); 2324 if (auto spread = ast_cast<SpreadListExp_t>(*vit)) {
2325 newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); 2325 auto lenVar = getUnusedName("_len_"sv);
2326 auto assign = x->new_ptr<Assign_t>(); 2326 forceAddToScope(lenVar);
2327 if (vit == values.end()) { 2327 temp.push_back(indent() + "local "s + lenVar + " = #"s + varName + " + 1"s + nll(spread));
2328 throw CompileError("right value missing"sv, values.front()); 2328 auto elmVar = getUnusedName("_elm_"sv);
2329 _buf << varName << '[' << lenVar << "],"s << lenVar << "="s << elmVar << ',' << lenVar << "+1 for "s << elmVar << " in *nil"s;
2330 auto stmt = toAst<Statement_t>(clearBuf(), spread);
2331 auto comp = stmt->appendix->item.to<CompInner_t>();
2332 ast_to<CompForEach_t>(comp->items.front())->loopValue.to<StarExp_t>()->value.set(spread->exp);
2333 transformStatement(stmt, temp);
2334 } else {
2335 auto newAssignment = x->new_ptr<ExpListAssign_t>();
2336 newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x));
2337 auto assign = x->new_ptr<Assign_t>();
2338 if (vit == values.end()) {
2339 throw CompileError("right value missing"sv, values.front());
2340 }
2341 assign->values.push_back(*vit);
2342 newAssignment->action.set(assign);
2343 transformAssignment(newAssignment, temp);
2329 } 2344 }
2330 assign->values.push_back(*vit);
2331 newAssignment->action.set(assign);
2332 transformAssignment(newAssignment, temp);
2333 if (extraScoped) { 2345 if (extraScoped) {
2334 popScope(); 2346 popScope();
2335 temp.push_back(indent() + "end"s + nlr(x)); 2347 temp.push_back(indent() + "end"s + nlr(x));
@@ -2848,6 +2860,7 @@ private:
2848 case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; 2860 case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break;
2849 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; 2861 case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break;
2850 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; 2862 case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break;
2863 case id<SpreadListExp_t>(): throw CompileError("can only be used for ranged table append assignments"sv, value); break;
2851 default: YUEE("AST node mismatch", value); break; 2864 default: YUEE("AST node mismatch", value); break;
2852 } 2865 }
2853 } 2866 }
@@ -8268,9 +8281,16 @@ private:
8268 } 8281 }
8269 return; 8282 return;
8270 } 8283 }
8271 auto def = ast_cast<NormalDef_t>(comp->items.front()); 8284 ast_node* value = nullptr;
8272 if (!def || def->defVal) { 8285 bool isSpread = ast_is<SpreadListExp_t>(comp->items.front());
8273 throw CompileError("invalid comprehension expression", comp->items.front()); 8286 if (isSpread) {
8287 value = comp->items.front();
8288 } else {
8289 auto def = ast_cast<NormalDef_t>(comp->items.front());
8290 if (!def || def->defVal) {
8291 throw CompileError("invalid comprehension expression", comp->items.front());
8292 }
8293 value = def->item.get();
8274 } 8294 }
8275 bool extraScope = false; 8295 bool extraScope = false;
8276 switch (usage) { 8296 switch (usage) {
@@ -8294,7 +8314,6 @@ private:
8294 default: 8314 default:
8295 break; 8315 break;
8296 } 8316 }
8297 auto value = def->item.get();
8298 auto compInner = static_cast<CompInner_t*>(comp->items.back()); 8317 auto compInner = static_cast<CompInner_t*>(comp->items.back());
8299 str_list temp; 8318 str_list temp;
8300 std::string accumVar = getUnusedName("_accum_"sv); 8319 std::string accumVar = getUnusedName("_accum_"sv);
@@ -8318,7 +8337,7 @@ private:
8318 } 8337 }
8319 } 8338 }
8320 { 8339 {
8321 auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); 8340 auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + (isSpread ? "][]"s : "]"s), x);
8322 auto assign = x->new_ptr<Assign_t>(); 8341 auto assign = x->new_ptr<Assign_t>();
8323 assign->values.push_back(value); 8342 assign->values.push_back(value);
8324 auto assignment = x->new_ptr<ExpListAssign_t>(); 8343 auto assignment = x->new_ptr<ExpListAssign_t>();
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index 44baced..fccb6fb 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -547,7 +547,7 @@ YueParser::YueParser() {
547 547
548 Assign = '=' >> space >> Seperator >> ( 548 Assign = '=' >> space >> Seperator >> (
549 With | If | Switch | TableBlock | 549 With | If | Switch | TableBlock |
550 Exp >> *(space >> set(",;") >> space >> Exp) 550 (SpreadListExp | Exp) >> *(space >> set(",;") >> space >> (SpreadListExp | Exp))
551 ); 551 );
552 552
553 UpdateOp = 553 UpdateOp =