diff options
| -rwxr-xr-x | doc/docs/doc/README.md | 38 | ||||
| -rwxr-xr-x | doc/docs/zh/doc/README.md | 38 | ||||
| -rw-r--r-- | spec/inputs/lists.yue | 10 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc.lua | 84 | ||||
| -rw-r--r-- | spec/outputs/codes_from_doc_zh.lua | 84 | ||||
| -rw-r--r-- | spec/outputs/lists.lua | 49 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 47 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 2 |
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 | ||
| 598 | You can also use the spread operator `...` to append all elements from one list to another: | ||
| 599 | |||
| 600 | ```moonscript | ||
| 601 | tbA = [1, 2, 3] | ||
| 602 | tbB = [4, 5, 6] | ||
| 603 | tbA[] = ...tbB | ||
| 604 | -- tbA is now [1, 2, 3, 4, 5, 6] | ||
| 605 | ``` | ||
| 606 | <YueDisplay> | ||
| 607 | <pre> | ||
| 608 | tbA = [1, 2, 3] | ||
| 609 | tbB = [4, 5, 6] | ||
| 610 | tbA[] = ...tbB | ||
| 611 | -- tbA is now [1, 2, 3, 4, 5, 6] | ||
| 612 | </pre> | ||
| 613 | </YueDisplay> | ||
| 614 | |||
| 598 | ### Table Spreading | 615 | ### Table Spreading |
| 599 | 616 | ||
| 600 | You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals. | 617 | You 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 | ||
| 2485 | In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect: | ||
| 2486 | |||
| 2487 | ```moonscript | ||
| 2488 | data = | ||
| 2489 | a: {1,2,3} | ||
| 2490 | b: {4,5,6} | ||
| 2491 | |||
| 2492 | flat = [...v for k,v in pairs data] | ||
| 2493 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 2494 | ``` | ||
| 2495 | <YueDisplay> | ||
| 2496 | <pre> | ||
| 2497 | data = | ||
| 2498 | a: {1,2,3} | ||
| 2499 | b: {4,5,6} | ||
| 2500 | |||
| 2501 | flat = [...v for k,v in pairs data] | ||
| 2502 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 2503 | </pre> | ||
| 2504 | </YueDisplay> | ||
| 2505 | |||
| 2468 | The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause. | 2506 | The 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 | ||
| 2470 | Using multiple for clauses is the same as using nested loops: | 2508 | Using 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 | ||
| 600 | tbA = [1, 2, 3] | ||
| 601 | tbB = [4, 5, 6] | ||
| 602 | tbA[] = ...tbB | ||
| 603 | -- tbA 现在为 [1, 2, 3, 4, 5, 6] | ||
| 604 | ``` | ||
| 605 | <YueDisplay> | ||
| 606 | <pre> | ||
| 607 | tbA = [1, 2, 3] | ||
| 608 | tbB = [4, 5, 6] | ||
| 609 | tbA[] = ...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 | ||
| 2448 | data = | ||
| 2449 | a: {1,2,3} | ||
| 2450 | b: {4,5,6} | ||
| 2451 | |||
| 2452 | flat = [...v for k,v in pairs data] | ||
| 2453 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 2454 | ``` | ||
| 2455 | <YueDisplay> | ||
| 2456 | <pre> | ||
| 2457 | data = | ||
| 2458 | a: {1,2,3} | ||
| 2459 | b: {4,5,6} | ||
| 2460 | |||
| 2461 | flat = [...v for k,v in pairs data] | ||
| 2462 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 2463 | </pre> | ||
| 2464 | </YueDisplay> | ||
| 2465 | |||
| 2428 | for和when子句可以根据需要进行链式操作。唯一的要求是推导式中至少要有一个for子句。 | 2466 | for和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 | ||
| 270 | do | ||
| 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 | |||
| 270 | nil | 280 | nil |
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() | |||
| 147 | end)()) | 147 | end)()) |
| 148 | local tab = { } | 148 | local tab = { } |
| 149 | tab[#tab + 1] = "Value" | 149 | tab[#tab + 1] = "Value" |
| 150 | local tbA = { | ||
| 151 | 1, | ||
| 152 | 2, | ||
| 153 | 3 | ||
| 154 | } | ||
| 155 | local tbB = { | ||
| 156 | 4, | ||
| 157 | 5, | ||
| 158 | 6 | ||
| 159 | } | ||
| 160 | local _len_0 = #tbA + 1 | ||
| 161 | for _index_0 = 1, #tbB do | ||
| 162 | local _elm_0 = tbB[_index_0] | ||
| 163 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 164 | end | ||
| 150 | local parts = { | 165 | local 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 |
| 1081 | end | 1096 | end |
| 1082 | doubled = _accum_0 | 1097 | doubled = _accum_0 |
| 1098 | local data = { | ||
| 1099 | a = { | ||
| 1100 | 1, | ||
| 1101 | 2, | ||
| 1102 | 3 | ||
| 1103 | }, | ||
| 1104 | b = { | ||
| 1105 | 4, | ||
| 1106 | 5, | ||
| 1107 | 6 | ||
| 1108 | } | ||
| 1109 | } | ||
| 1110 | local flat | ||
| 1111 | local _accum_0 = { } | ||
| 1112 | local _len_0 = 1 | ||
| 1113 | for 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 | ||
| 1123 | end | ||
| 1124 | flat = _accum_0 | ||
| 1083 | local x_coords = { | 1125 | local x_coords = { |
| 1084 | 4, | 1126 | 4, |
| 1085 | 5, | 1127 | 5, |
| @@ -2588,6 +2630,21 @@ print((function() | |||
| 2588 | end)()) | 2630 | end)()) |
| 2589 | local tab = { } | 2631 | local tab = { } |
| 2590 | tab[#tab + 1] = "Value" | 2632 | tab[#tab + 1] = "Value" |
| 2633 | local tbA = { | ||
| 2634 | 1, | ||
| 2635 | 2, | ||
| 2636 | 3 | ||
| 2637 | } | ||
| 2638 | local tbB = { | ||
| 2639 | 4, | ||
| 2640 | 5, | ||
| 2641 | 6 | ||
| 2642 | } | ||
| 2643 | local _len_0 = #tbA + 1 | ||
| 2644 | for _index_0 = 1, #tbB do | ||
| 2645 | local _elm_0 = tbB[_index_0] | ||
| 2646 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 2647 | end | ||
| 2591 | local parts = { | 2648 | local 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 |
| 3552 | end | 3609 | end |
| 3553 | doubled = _accum_0 | 3610 | doubled = _accum_0 |
| 3611 | local data = { | ||
| 3612 | a = { | ||
| 3613 | 1, | ||
| 3614 | 2, | ||
| 3615 | 3 | ||
| 3616 | }, | ||
| 3617 | b = { | ||
| 3618 | 4, | ||
| 3619 | 5, | ||
| 3620 | 6 | ||
| 3621 | } | ||
| 3622 | } | ||
| 3623 | local flat | ||
| 3624 | local _accum_0 = { } | ||
| 3625 | local _len_0 = 1 | ||
| 3626 | for 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 | ||
| 3636 | end | ||
| 3637 | flat = _accum_0 | ||
| 3554 | local x_coords = { | 3638 | local 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() | |||
| 147 | end)()) | 147 | end)()) |
| 148 | local tab = { } | 148 | local tab = { } |
| 149 | tab[#tab + 1] = "Value" | 149 | tab[#tab + 1] = "Value" |
| 150 | local tbA = { | ||
| 151 | 1, | ||
| 152 | 2, | ||
| 153 | 3 | ||
| 154 | } | ||
| 155 | local tbB = { | ||
| 156 | 4, | ||
| 157 | 5, | ||
| 158 | 6 | ||
| 159 | } | ||
| 160 | local _len_0 = #tbA + 1 | ||
| 161 | for _index_0 = 1, #tbB do | ||
| 162 | local _elm_0 = tbB[_index_0] | ||
| 163 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 164 | end | ||
| 150 | local parts = { | 165 | local 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 |
| 1075 | end | 1090 | end |
| 1076 | doubled = _accum_0 | 1091 | doubled = _accum_0 |
| 1092 | local data = { | ||
| 1093 | a = { | ||
| 1094 | 1, | ||
| 1095 | 2, | ||
| 1096 | 3 | ||
| 1097 | }, | ||
| 1098 | b = { | ||
| 1099 | 4, | ||
| 1100 | 5, | ||
| 1101 | 6 | ||
| 1102 | } | ||
| 1103 | } | ||
| 1104 | local flat | ||
| 1105 | local _accum_0 = { } | ||
| 1106 | local _len_0 = 1 | ||
| 1107 | for 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 | ||
| 1117 | end | ||
| 1118 | flat = _accum_0 | ||
| 1077 | local x_coords = { | 1119 | local x_coords = { |
| 1078 | 4, | 1120 | 4, |
| 1079 | 5, | 1121 | 5, |
| @@ -2582,6 +2624,21 @@ print((function() | |||
| 2582 | end)()) | 2624 | end)()) |
| 2583 | local tab = { } | 2625 | local tab = { } |
| 2584 | tab[#tab + 1] = "Value" | 2626 | tab[#tab + 1] = "Value" |
| 2627 | local tbA = { | ||
| 2628 | 1, | ||
| 2629 | 2, | ||
| 2630 | 3 | ||
| 2631 | } | ||
| 2632 | local tbB = { | ||
| 2633 | 4, | ||
| 2634 | 5, | ||
| 2635 | 6 | ||
| 2636 | } | ||
| 2637 | local _len_0 = #tbA + 1 | ||
| 2638 | for _index_0 = 1, #tbB do | ||
| 2639 | local _elm_0 = tbB[_index_0] | ||
| 2640 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 2641 | end | ||
| 2585 | local parts = { | 2642 | local 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 |
| 3540 | end | 3597 | end |
| 3541 | doubled = _accum_0 | 3598 | doubled = _accum_0 |
| 3599 | local data = { | ||
| 3600 | a = { | ||
| 3601 | 1, | ||
| 3602 | 2, | ||
| 3603 | 3 | ||
| 3604 | }, | ||
| 3605 | b = { | ||
| 3606 | 4, | ||
| 3607 | 5, | ||
| 3608 | 6 | ||
| 3609 | } | ||
| 3610 | } | ||
| 3611 | local flat | ||
| 3612 | local _accum_0 = { } | ||
| 3613 | local _len_0 = 1 | ||
| 3614 | for 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 | ||
| 3624 | end | ||
| 3625 | flat = _accum_0 | ||
| 3542 | local x_coords = { | 3626 | local 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 |
| 859 | end | 859 | end |
| 860 | do | ||
| 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 | ||
| 908 | end | ||
| 860 | return nil | 909 | return 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 | ||
| 444 | AST_NODE(Assign) | 444 | AST_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) |
| 448 | AST_END(Assign) | 448 | AST_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 | ||
| 81 | const std::string_view version = "0.29.7"sv; | 81 | const std::string_view version = "0.29.8"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class 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 = |
