aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xdoc/docs/doc/README.md180
-rwxr-xr-xdoc/docs/zh/doc/README.md182
-rw-r--r--spec/inputs/cond.yue11
-rw-r--r--spec/inputs/in_expression.yue25
-rw-r--r--spec/inputs/lists.yue24
-rw-r--r--spec/inputs/tables.yue20
-rw-r--r--spec/inputs/unicode/cond.yue11
-rw-r--r--spec/inputs/unicode/in_expression.yue21
-rw-r--r--spec/outputs/cond.lua17
-rw-r--r--spec/outputs/in_expression.lua31
-rw-r--r--spec/outputs/lists.lua65
-rw-r--r--spec/outputs/tables.lua83
-rw-r--r--spec/outputs/unicode/cond.lua17
-rw-r--r--spec/outputs/unicode/in_expression.lua31
-rw-r--r--src/yuescript/yue_ast.cpp27
-rw-r--r--src/yuescript/yue_ast.h34
-rw-r--r--src/yuescript/yue_compiler.cpp497
-rw-r--r--src/yuescript/yue_parser.cpp61
-rw-r--r--src/yuescript/yue_parser.h10
19 files changed, 913 insertions, 434 deletions
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
index c60330a..6662752 100755
--- a/doc/docs/doc/README.md
+++ b/doc/docs/doc/README.md
@@ -389,6 +389,80 @@ tb::func! if tb != nil
389</pre> 389</pre>
390</YueDisplay> 390</YueDisplay>
391 391
392### Chaining Comparisons
393
394Comparisons can be arbitrarily chained:
395
396```moonscript
397print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
398-- output: true
399
400a = 5
401print 1 <= a <= 10
402-- output: true
403```
404<YueDisplay>
405<pre>
406print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
407-- output: true
408
409a = 5
410print 1 <= a <= 10
411-- output: true
412</pre>
413</YueDisplay>
414
415Note the evaluation behavior of chained comparisons:
416
417```moonscript
418v = (x)->
419 print x
420 x
421
422print v(1) < v(2) <= v(3)
423--[[
424 output:
425 2
426 1
427 3
428 true
429]]
430
431print v(1) > v(2) <= v(3)
432--[[
433 output:
434 2
435 1
436 false
437]]
438```
439<YueDisplay>
440<pre>
441v = (x)->
442 print x
443 x
444
445print v(1) < v(2) <= v(3)
446--[[
447 output:
448 2
449 1
450 3
451true
452]]
453
454print v(1) > v(2) <= v(3)
455--[[
456 output:
457 2
458 1
459 false
460]]
461</pre>
462</YueDisplay>
463
464The middle expression is only evaluated once, rather than twice as it would be if the expression were written as `v(1) < v(2) and v(2) <= v(3)`. However, the order of evaluations in a chained comparison is undefined. It is strongly recommended not to use expressions with side effects (such as printing) in chained comparisons. If side effects are required, the short-circuit `and` operator should be used explicitly.
465
392### Table Appending 466### Table Appending
393The **[] =** operator is used to append values to tables. 467The **[] =** operator is used to append values to tables.
394 468
@@ -984,17 +1058,17 @@ Typically when you see a table literal, {1,2,3}, it is on the right hand side of
984This is best explained with examples. Here is how you would unpack the first two values from a table: 1058This is best explained with examples. Here is how you would unpack the first two values from a table:
985 1059
986```moonscript 1060```moonscript
987thing = {1, 2} 1061thing = [1, 2]
988 1062
989{a, b} = thing 1063[a, b] = thing
990print a, b 1064print a, b
991``` 1065```
992<YueDisplay> 1066<YueDisplay>
993 1067
994<pre> 1068<pre>
995thing = {1, 2} 1069thing = [1, 2]
996 1070
997{a, b} = thing 1071[a, b] = thing
998print a, b 1072print a, b
999</pre> 1073</pre>
1000</YueDisplay> 1074</YueDisplay>
@@ -1921,6 +1995,19 @@ t = {
1921</pre> 1995</pre>
1922</YueDisplay> 1996</YueDisplay>
1923 1997
1998Lua tables have both an array part and a hash part, but sometimes you want to make a semantic distinction between array and hash usage when writing Lua tables. Then you can write Lua table with **[ ]** instead of **{ }** to represent an array table and writing any key value pair in a list table won't be allowed.
1999
2000```moonscript
2001some_values = [ 1, 2, 3, 4 ]
2002list_with_one_element = [ 1, ]
2003```
2004<YueDisplay>
2005<pre>
2006some_values = [ 1, 2, 3, 4 ]
2007list_with_one_element = [ 1, ]
2008</pre>
2009</YueDisplay>
2010
1924## Comprehensions 2011## Comprehensions
1925 2012
1926Comprehensions provide a convenient syntax for constructing a new table by iterating over some existing object and applying an expression to its values. There are two kinds of comprehensions: list comprehensions and table comprehensions. They both produce Lua tables; list comprehensions accumulate values into an array-like table, and table comprehensions let you set both the key and the value on each iteration. 2013Comprehensions provide a convenient syntax for constructing a new table by iterating over some existing object and applying an expression to its values. There are two kinds of comprehensions: list comprehensions and table comprehensions. They both produce Lua tables; list comprehensions accumulate values into an array-like table, and table comprehensions let you set both the key and the value on each iteration.
@@ -1930,12 +2017,12 @@ Comprehensions provide a convenient syntax for constructing a new table by itera
1930The following creates a copy of the items table but with all the values doubled. 2017The following creates a copy of the items table but with all the values doubled.
1931 2018
1932```moonscript 2019```moonscript
1933items = { 1, 2, 3, 4 } 2020items = [ 1, 2, 3, 4 ]
1934doubled = [item * 2 for i, item in ipairs items] 2021doubled = [item * 2 for i, item in ipairs items]
1935``` 2022```
1936<YueDisplay> 2023<YueDisplay>
1937<pre> 2024<pre>
1938items = { 1, 2, 3, 4 } 2025items = [ 1, 2, 3, 4 ]
1939doubled = [item * 2 for i, item in ipairs items] 2026doubled = [item * 2 for i, item in ipairs items]
1940</pre> 2027</pre>
1941</YueDisplay> 2028</YueDisplay>
@@ -1969,18 +2056,18 @@ The for and when clauses can be chained as much as desired. The only requirement
1969Using multiple for clauses is the same as using nested loops: 2056Using multiple for clauses is the same as using nested loops:
1970 2057
1971```moonscript 2058```moonscript
1972x_coords = {4, 5, 6, 7} 2059x_coords = [4, 5, 6, 7]
1973y_coords = {9, 2, 3} 2060y_coords = [9, 2, 3]
1974 2061
1975points = [{x, y} for x in *x_coords \ 2062points = [ [x, y] for x in *x_coords \
1976for y in *y_coords] 2063for y in *y_coords]
1977``` 2064```
1978<YueDisplay> 2065<YueDisplay>
1979<pre> 2066<pre>
1980x_coords = {4, 5, 6, 7} 2067x_coords = [4, 5, 6, 7]
1981y_coords = {9, 2, 3} 2068y_coords = [9, 2, 3]
1982 2069
1983points = [{x, y} for x in *x_coords \ 2070points = [ [x, y] for x in *x_coords \
1984for y in *y_coords] 2071for y in *y_coords]
1985</pre> 2072</pre>
1986</YueDisplay> 2073</YueDisplay>
@@ -2035,12 +2122,12 @@ no_color = {k, v for k, v in pairs thing when k != "color"}
2035The **\*** operator is also supported. Here we create a square root look up table for a few numbers. 2122The **\*** operator is also supported. Here we create a square root look up table for a few numbers.
2036 2123
2037```moonscript 2124```moonscript
2038numbers = {1, 2, 3, 4} 2125numbers = [1, 2, 3, 4]
2039sqrts = {i, math.sqrt i for i in *numbers} 2126sqrts = {i, math.sqrt i for i in *numbers}
2040``` 2127```
2041<YueDisplay> 2128<YueDisplay>
2042<pre> 2129<pre>
2043numbers = {1, 2, 3, 4} 2130numbers = [1, 2, 3, 4]
2044sqrts = {i, math.sqrt i for i in *numbers} 2131sqrts = {i, math.sqrt i for i in *numbers}
2045</pre> 2132</pre>
2046</YueDisplay> 2133</YueDisplay>
@@ -2405,15 +2492,6 @@ You can write range checking code with an `in-expression`.
2405```moonscript 2492```moonscript
2406a = 5 2493a = 5
2407 2494
2408if a in [1, 10]
2409 print "a is in range from 1 to 10"
2410
2411if a not in [1, 10]
2412 print "a is not in range from 1 to 10"
2413
2414if a in (0, 11)
2415 print "a is between 0 and 11 with open intervals"
2416
2417if a in {1, 3, 5, 7} 2495if a in {1, 3, 5, 7}
2418 print "checking equality with discrete values" 2496 print "checking equality with discrete values"
2419 2497
@@ -2424,15 +2502,6 @@ if a in list
2424<pre> 2502<pre>
2425a = 5 2503a = 5
2426 2504
2427if a in [1, 10]
2428 print "a is in range from 1 to 10"
2429
2430if a not in [1, 10]
2431 print "a is not in range from 1 to 10"
2432
2433if a in (0, 11)
2434 print "a is between 0 and 11 with open intervals"
2435
2436if a in {1, 3, 5, 7} 2505if a in {1, 3, 5, 7}
2437 print "checking equality with discrete values" 2506 print "checking equality with discrete values"
2438 2507
@@ -2649,53 +2718,6 @@ switch item
2649</pre> 2718</pre>
2650</YueDisplay> 2719</YueDisplay>
2651 2720
2652### Range Matching
2653
2654You can do range matching in a switch when clause using `In` expressions.
2655
2656```moonscript
2657value = 5
2658
2659switch item
2660 -- range checking with closed interval
2661 when in [1, 3]
2662 print "1 <= value <= 3"
2663
2664 -- range checking with open and closed interval
2665 when in (6, 8]
2666 print "6 < value <= 8"
2667
2668 -- not in range checking
2669 when not in [1, 10)
2670 print "not (1 <= value < 10)"
2671
2672 -- checking discrete values
2673 when in {11, 21, 99}
2674 print "value is 11, 21 or 99"
2675```
2676<YueDisplay>
2677<pre>
2678value = 5
2679
2680switch item
2681 -- range checking with closed interval
2682 when in [1, 3]
2683 print "1 <= value <= 3"
2684
2685 -- range checking with open and closed interval
2686 when in (6, 8]
2687 print "6 < value <= 8"
2688
2689 -- not in range checking
2690 when not in [1, 10)
2691 print "not (1 <= value < 10)"
2692
2693 -- checking discrete values
2694 when in {11, 21, 99}
2695 print "value is 11, 21 or 99"
2696</pre>
2697</YueDisplay>
2698
2699## Object Oriented Programming 2721## Object Oriented Programming
2700 2722
2701In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the Yuescript code at first, then look into the Lua code if you wish to know the implementation details. 2723In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the Yuescript code at first, then look into the Lua code if you wish to know the implementation details.
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md
index 1d234a0..8a236c1 100755
--- a/doc/docs/zh/doc/README.md
+++ b/doc/docs/zh/doc/README.md
@@ -386,6 +386,80 @@ tb::func! if tb != nil
386</pre> 386</pre>
387</YueDisplay> 387</YueDisplay>
388 388
389### 链å¼æ¯”较
390
391您å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸­è¿›è¡Œæ¯”较表达å¼çš„链å¼ä¹¦å†™ï¼š
392
393```moonscript
394print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
395-- 输出:true
396
397a = 5
398print 1 <= a <= 10
399-- 输出:true
400```
401<YueDisplay>
402<pre>
403print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
404-- 输出:true
405
406a = 5
407print 1 <= a <= 10
408-- 输出:true
409</pre>
410</YueDisplay>
411
412å¯ä»¥æ³¨æ„一下链å¼æ¯”较表达å¼çš„求值行为:
413
414```moonscript
415v = (x)->
416 print x
417 x
418
419print v(1) < v(2) <= v(3)
420--[[
421 输出:
422 2
423 1
424 3
425 true
426]]
427
428print v(1) > v(2) <= v(3)
429--[[
430 输出:
431 2
432 1
433 false
434]]
435```
436<YueDisplay>
437<pre>
438v = (x)->
439 print x
440 x
441
442print v(1) < v(2) <= v(3)
443--[[
444 输出:
445 2
446 1
447 3
448 true
449]]
450
451print v(1) > v(2) <= v(3)
452--[[
453 输出:
454 2
455 1
456 false
457]]
458</pre>
459</YueDisplay>
460
461在上é¢çš„例å­é‡Œï¼Œä¸­é—´çš„表达å¼`v(2)`仅被计算一次,如果把表达å¼å†™æˆ`v(1) < v(2) and v(2) <= v(3)`çš„æ–¹å¼ï¼Œä¸­é—´çš„`v(2)`æ‰ä¼šè¢«è®¡ç®—两次。在链å¼æ¯”较中,求值的顺åºå¾€å¾€æ˜¯æœªå®šä¹‰çš„。所以强烈建议ä¸è¦åœ¨é“¾å¼æ¯”较中使用具有副作用(比如åšæ‰“å°æ“作)的表达å¼ã€‚如果需è¦ä½¿ç”¨æœ‰å‰¯ä½œç”¨çš„函数,应明确使用短路 `and` è¿ç®—符æ¥åšè¿žæŽ¥ã€‚
462
389### 表追加 463### 表追加
390 464
391**[] =** æ“作符用于å‘Lua表的最åŽæ’入值。 465**[] =** æ“作符用于å‘Lua表的最åŽæ’入值。
@@ -982,17 +1056,17 @@ do
982最好是通过示例æ¥è§£é‡Šã€‚以下是如何从表格中解包å‰ä¸¤ä¸ªå€¼çš„方法: 1056最好是通过示例æ¥è§£é‡Šã€‚以下是如何从表格中解包å‰ä¸¤ä¸ªå€¼çš„方法:
983 1057
984```moonscript 1058```moonscript
985thing = {1, 2} 1059thing = [1, 2]
986 1060
987{a, b} = thing 1061[a, b] = thing
988print a, b 1062print a, b
989``` 1063```
990<YueDisplay> 1064<YueDisplay>
991 1065
992<pre> 1066<pre>
993thing = {1, 2} 1067thing = [1, 2]
994 1068
995{a, b} = thing 1069[a, b] = thing
996print a, b 1070print a, b
997</pre> 1071</pre>
998</YueDisplay> 1072</YueDisplay>
@@ -1881,6 +1955,19 @@ t = {
1881</pre> 1955</pre>
1882</YueDisplay> 1956</YueDisplay>
1883 1957
1958Lua的表åŒæ—¶å…·æœ‰æ•°ç»„部分和哈希部分,但有时候你会希望在书写Lua表时,对Lua表åšæ•°ç»„和哈希ä¸åŒç”¨æ³•çš„语义区分。然åŽä½ å¯ä»¥ç”¨ **[ ]** 而ä¸æ˜¯ **{ }** æ¥ç¼–写表示数组的 Lua 表,并且ä¸å…许在数组 Lua 表中写入任何键值对。
1959
1960```moonscript
1961some_values = [ 1, 2, 3, 4 ]
1962list_with_one_element = [ 1, ]
1963```
1964<YueDisplay>
1965<pre>
1966some_values = [ 1, 2, 3, 4 ]
1967list_with_one_element = [ 1, ]
1968</pre>
1969</YueDisplay>
1970
1884## æŽ¨å¯¼å¼ 1971## 推导å¼
1885 1972
1886推导å¼ä¸ºæˆ‘们æ供了一ç§ä¾¿æ·çš„语法,通过é历现有对象并对其值应用表达å¼æ¥æž„造出新的表格。月之脚本有两ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生Lua表格;列表推导å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„的表格中,而表格推导å¼å…许您在æ¯æ¬¡é历时设置新表格的键和值。 1973推导å¼ä¸ºæˆ‘们æ供了一ç§ä¾¿æ·çš„语法,通过é历现有对象并对其值应用表达å¼æ¥æž„造出新的表格。月之脚本有两ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生Lua表格;列表推导å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„的表格中,而表格推导å¼å…许您在æ¯æ¬¡é历时设置新表格的键和值。
@@ -1890,12 +1977,12 @@ t = {
1890以下æ“作创建了一个items表的副本,但所有包å«çš„值都翻å€äº†ã€‚ 1977以下æ“作创建了一个items表的副本,但所有包å«çš„值都翻å€äº†ã€‚
1891 1978
1892```moonscript 1979```moonscript
1893items = { 1, 2, 3, 4 } 1980items = [ 1, 2, 3, 4 ]
1894doubled = [item * 2 for i, item in ipairs items] 1981doubled = [item * 2 for i, item in ipairs items]
1895``` 1982```
1896<YueDisplay> 1983<YueDisplay>
1897<pre> 1984<pre>
1898items = { 1, 2, 3, 4 } 1985items = [ 1, 2, 3, 4 ]
1899doubled = [item * 2 for i, item in ipairs items] 1986doubled = [item * 2 for i, item in ipairs items]
1900</pre> 1987</pre>
1901</YueDisplay> 1988</YueDisplay>
@@ -1929,18 +2016,18 @@ forå’Œwhenå­å¥å¯ä»¥æ ¹æ®éœ€è¦è¿›è¡Œé“¾å¼æ“作。唯一的è¦æ±‚是推导å
1929使用多个forå­å¥ä¸Žä½¿ç”¨å¤šé‡å¾ªçŽ¯çš„效果相åŒï¼š 2016使用多个forå­å¥ä¸Žä½¿ç”¨å¤šé‡å¾ªçŽ¯çš„效果相åŒï¼š
1930 2017
1931```moonscript 2018```moonscript
1932x_coords = {4, 5, 6, 7} 2019x_coords = [4, 5, 6, 7]
1933y_coords = {9, 2, 3} 2020y_coords = [9, 2, 3]
1934 2021
1935points = [{x, y} for x in *x_coords \ 2022points = [ [x, y] for x in *x_coords \
1936for y in *y_coords] 2023for y in *y_coords]
1937``` 2024```
1938<YueDisplay> 2025<YueDisplay>
1939<pre> 2026<pre>
1940x_coords = {4, 5, 6, 7} 2027x_coords = [4, 5, 6, 7]
1941y_coords = {9, 2, 3} 2028y_coords = [9, 2, 3]
1942 2029
1943points = [{x, y} for x in *x_coords \ 2030points = [ [x, y] for x in *x_coords \
1944for y in *y_coords] 2031for y in *y_coords]
1945</pre> 2032</pre>
1946</YueDisplay> 2033</YueDisplay>
@@ -1995,12 +2082,12 @@ no_color = {k, v for k, v in pairs thing when k != "color"}
1995**\***æ“作符在表格推导å¼ä¸­èƒ½ä½¿ç”¨ã€‚在下é¢çš„例å­é‡Œï¼Œæˆ‘们为几个数字创建了一个平方根查找表。 2082**\***æ“作符在表格推导å¼ä¸­èƒ½ä½¿ç”¨ã€‚在下é¢çš„例å­é‡Œï¼Œæˆ‘们为几个数字创建了一个平方根查找表。
1996 2083
1997```moonscript 2084```moonscript
1998numbers = {1, 2, 3, 4} 2085numbers = [1, 2, 3, 4]
1999sqrts = {i, math.sqrt i for i in *numbers} 2086sqrts = {i, math.sqrt i for i in *numbers}
2000``` 2087```
2001<YueDisplay> 2088<YueDisplay>
2002<pre> 2089<pre>
2003numbers = {1, 2, 3, 4} 2090numbers = [1, 2, 3, 4]
2004sqrts = {i, math.sqrt i for i in *numbers} 2091sqrts = {i, math.sqrt i for i in *numbers}
2005</pre> 2092</pre>
2006</YueDisplay> 2093</YueDisplay>
@@ -2361,20 +2448,11 @@ print "你真幸è¿ï¼" unless math.random! > 0.1
2361 2448
2362### èŒƒå›´è¡¨è¾¾å¼ 2449### 范围表达å¼
2363 2450
2364您å¯ä»¥ä½¿ç”¨èŒƒå›´è¡¨è¾¾å¼æ¥ç¼–写进行边界范围检查的代ç ã€‚ 2451您å¯ä»¥ä½¿ç”¨èŒƒå›´è¡¨è¾¾å¼æ¥ç¼–写进行范围检查的代ç ã€‚
2365 2452
2366```moonscript 2453```moonscript
2367a = 5 2454a = 5
2368 2455
2369if a in [1, 10]
2370 print "a在1到10的范围内"
2371
2372if a not in [1, 10]
2373 print "aä¸åœ¨1到10的范围内"
2374
2375if a in (0, 11)
2376 print "a在0到11的开放区间内"
2377
2378if a in {1, 3, 5, 7} 2456if a in {1, 3, 5, 7}
2379 print "检查离散值的相等性" 2457 print "检查离散值的相等性"
2380 2458
@@ -2385,15 +2463,6 @@ if a in list
2385<pre> 2463<pre>
2386a = 5 2464a = 5
2387 2465
2388if a in [1, 10]
2389 print "a在1到10的范围内"
2390
2391if a not in [1, 10]
2392 print "aä¸åœ¨1到10的范围内"
2393
2394if a in (0, 11)
2395 print "a在0到11的开放区间内"
2396
2397if a in {1, 3, 5, 7} 2466if a in {1, 3, 5, 7}
2398 print "检查离散值的相等性" 2467 print "检查离散值的相等性"
2399 2468
@@ -2610,53 +2679,6 @@ switch item
2610</pre> 2679</pre>
2611</YueDisplay> 2680</YueDisplay>
2612 2681
2613### 范围匹é…
2614
2615使用`in`范围匹é…表达å¼ï¼Œä½ å¯ä»¥åœ¨switchçš„whenå­å¥ä¸­è¿›è¡ŒèŒƒå›´åŒ¹é…的检查处ç†ã€‚
2616
2617```moonscript
2618value = 5
2619
2620switch item
2621 -- 使用闭区间进行范围检查
2622 when in [1, 3]
2623 print "1 <= value <= 3"
2624
2625 -- 使用开闭区间进行范围检查
2626 when in (6, 8]
2627 print "6 < value <= 8"
2628
2629 -- 检查ä¸åœ¨èŒƒå›´å†…
2630 when not in [1, 10)
2631 print "ä¸æ˜¯ (1 <= value < 10)"
2632
2633 -- 检查离散值
2634 when in {11, 21, 99}
2635 print "值是 11, 21 或 99"
2636```
2637<YueDisplay>
2638<pre>
2639value = 5
2640
2641switch item
2642 -- 使用闭区间进行范围检查
2643 when in [1, 3]
2644 print "1 <= value <= 3"
2645
2646 -- 使用开闭区间进行范围检查
2647 when in (6, 8]
2648 print "6 < value <= 8"
2649
2650 -- 检查ä¸åœ¨èŒƒå›´å†…
2651 when not in [1, 10)
2652 print "ä¸æ˜¯ (1 <= value < 10)"
2653
2654 -- 检查离散值
2655 when in {11, 21, 99}
2656 print "值是 11, 21 或 99"
2657</pre>
2658</YueDisplay>
2659
2660## é¢å‘对象编程 2682## é¢å‘对象编程
2661 2683
2662在以下的示例中,月之脚本生æˆçš„Lua代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç å±‚é¢çš„æ„义,然åŽå¦‚果您想知é“关于é¢å‘对象功能的实现细节,å†æŸ¥çœ‹Lua代ç ã€‚ 2684在以下的示例中,月之脚本生æˆçš„Lua代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç å±‚é¢çš„æ„义,然åŽå¦‚果您想知é“关于é¢å‘对象功能的实现细节,å†æŸ¥çœ‹Lua代ç ã€‚
diff --git a/spec/inputs/cond.yue b/spec/inputs/cond.yue
index 638b5c3..df7d78e 100644
--- a/spec/inputs/cond.yue
+++ b/spec/inputs/cond.yue
@@ -226,6 +226,17 @@ do
226 else 226 else
227 2 227 2
228 228
229do
230 condChain = 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
231
232 v = (x)->
233 print x
234 x
235
236 evaluation = v(1) < v(2) <= v(3)
237
238 evaluation = v(1) > v(2) <= v(3)
239
229nil 240nil
230 241
231 242
diff --git a/spec/inputs/in_expression.yue b/spec/inputs/in_expression.yue
index 6e923e1..6faff4e 100644
--- a/spec/inputs/in_expression.yue
+++ b/spec/inputs/in_expression.yue
@@ -1,28 +1,13 @@
1-a^2 in {1, 2, 3} |> f 1-a^2 in {1, 2, 3} |> f
2 2-a^2 in [1, 2, 3] |> f
3a, b = x(...) not in [1, 3], 2
4
5d = (tb.x.y ...) not in [1, 3]
6 3
7has = "foo" in { "bar", "foo" } 4has = "foo" in { "bar", "foo" }
8 5
9if a in {1} and b in {2, 3, 4} or c in [1, 10] 6if a in {1} and b in {2, 3, 4}
10 print a, b, c 7 print a, b, c
11 8
12switch val 9if a in [1,] and b in [2, 3, 4]
13 when 1, 2, 3 10 print a, b, c
14 print "1, 2, 3"
15
16 when not in (0, 100]
17 print "not (0 < val <= 100)"
18
19 when in [200, 300)
20 print "200 <= val < 300)"
21
22 when not in {333, 444, 555}
23 print "not 333, 444 or 555"
24
25do return y not in (a, b)
26 11
27do 12do
28 exist = item in list 13 exist = item in list
@@ -36,9 +21,11 @@ do
36do 21do
37 item = get! 22 item = get!
38 list = {1, 2, 3} 23 list = {1, 2, 3}
24 list = [1, 2, 3]
39 not_exist = item not in list 25 not_exist = item not in list
40 check item in list 26 check item in list
41 check item in {1, 2, 3} 27 check item in {1, 2, 3}
28 check item in [1, 2, 3]
42 check item(...) in {[1]: 1, [2]: 2, [3]: 3} 29 check item(...) in {[1]: 1, [2]: 2, [3]: 3}
43 30
44do 31do
diff --git a/spec/inputs/lists.yue b/spec/inputs/lists.yue
index 15eb9ab..921cae0 100644
--- a/spec/inputs/lists.yue
+++ b/spec/inputs/lists.yue
@@ -67,6 +67,24 @@ normal = (hello) ->
67test = x 1,2,3,4,5 67test = x 1,2,3,4,5
68print thing for thing in *test 68print thing for thing in *test
69 69
70-> a = b for row in *rows 70_ = -> a = b for row in *rows
71 71
72 72with tb
73 f [a] -- indexing
74 f [a,] -- list with one element
75 print v for v in *f[a,] -- table slicing in for-loop
76 f [] -- empty list
77 f[] = x -- table appending to f
78 [a] = x -- assign to tb[a]
79 [a,] = x -- list destructuring for x
80 [] = x -- table appending to tb
81 c = a in [1] -- check if a in tb[1]
82 c = a in [1,] -- check if a == 1
83 c = a in {1} -- check if a == 1
84 c = a in {1,} -- check if a == 1
85
86do
87 [a, b] = hello
88 [name = "nameless", job = "jobless"] = person
89
90nil
diff --git a/spec/inputs/tables.yue b/spec/inputs/tables.yue
index 0b5af46..53a53ae 100644
--- a/spec/inputs/tables.yue
+++ b/spec/inputs/tables.yue
@@ -40,6 +40,8 @@ ya = { 1,2,3, key: 100, 343, "hello", umm: 232 }
40x = { 1,2, 40x = { 1,2,
41 4343, 343 ,343 } 41 4343, 343 ,343 }
42 42
43x = [ 1,2,
44 4343, 343 ,343 ]
43 45
44g, p = { 46g, p = {
45 1,2, nowy: "yes", 3,4, 47 1,2, nowy: "yes", 3,4,
@@ -52,6 +54,12 @@ annother = {
52 6,7,8 54 6,7,8
53} 55}
54 56
57annother = [
58 1,2,3
59 3,4,5
60 6,7,8
61]
62
55yeah = { 63yeah = {
56 [232]: 3434, "helo" 64 [232]: 3434, "helo"
57 ice: "cake" 65 ice: "cake"
@@ -255,6 +263,11 @@ tbMixA = {
255 11 263 11
256} 264}
257 265
266tbMixA = [
267 ...[i for i = 1, 10]
268 11
269]
270
258tbMixB = { 271tbMixB = {
259 ... ... -- only the first item in vararg been accessed here 272 ... ... -- only the first item in vararg been accessed here
260 ... {...} 273 ... {...}
@@ -262,6 +275,13 @@ tbMixB = {
262 1, 2, 3 275 1, 2, 3
263} 276}
264 277
278tbMixB = [
279 ... ... -- only the first item in vararg been accessed here
280 ... {...}
281 ... {......}
282 1, 2, 3
283]
284
265const template = { 285const template = {
266 foo: "Hello" 286 foo: "Hello"
267 bar: "World" 287 bar: "World"
diff --git a/spec/inputs/unicode/cond.yue b/spec/inputs/unicode/cond.yue
index 362408c..fca6d60 100644
--- a/spec/inputs/unicode/cond.yue
+++ b/spec/inputs/unicode/cond.yue
@@ -226,6 +226,17 @@ do
226 else 226 else
227 2 227 2
228 228
229do
230 链å¼æ¯”较 = 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
231
232 值 = (输入)->
233 æ‰“å° è¾“å…¥
234 输入
235
236 求值 = 值(1) < 值(2) <= 值(3)
237
238 求值 = 值(1) > 值(2) <= 值(3)
239
229nil 240nil
230 241
231 242
diff --git a/spec/inputs/unicode/in_expression.yue b/spec/inputs/unicode/in_expression.yue
index efaca47..e068cbf 100644
--- a/spec/inputs/unicode/in_expression.yue
+++ b/spec/inputs/unicode/in_expression.yue
@@ -1,29 +1,10 @@
1-å˜é‡a^2 in {1, 2, 3} |> 函数 1-å˜é‡a^2 in {1, 2, 3} |> 函数
2 2
3å˜é‡a, å˜é‡b = 函数x(...) not in [1, 3], 2
4
5å˜é‡d = (对象.字段x.字段y ...) not in [1, 3]
6
7在的 = "东" in { "东", "西" } 3在的 = "东" in { "东", "西" }
8 4
9if å˜é‡a in {1} and å˜é‡b in {2, 3, 4} or å˜é‡c in [1, 10] 5if å˜é‡a in {1} and å˜é‡b in {2, 3, 4}
10 æ‰“å° å˜é‡a, å˜é‡b, å˜é‡c 6 æ‰“å° å˜é‡a, å˜é‡b, å˜é‡c
11 7
12switch 值
13 when 1, 2, 3
14 æ‰“å° "1, 2, 3"
15
16 when not in (0, 100]
17 æ‰“å° "éž (0 < 值 <= 100)"
18
19 when in [200, 300)
20 æ‰“å° "200 <= 值 < 300)"
21
22 when not in {333, 444, 555}
23 æ‰“å° "éž 333, 444 或 555"
24
25do return å˜é‡y not in (开始, 结æŸ)
26
27do 8do
28 存在 = 元素 in 表 9 存在 = 元素 in 表
29 检查 元素 in 表 10 检查 元素 in 表
diff --git a/spec/outputs/cond.lua b/spec/outputs/cond.lua
index 1f6aa63..651c14a 100644
--- a/spec/outputs/cond.lua
+++ b/spec/outputs/cond.lua
@@ -345,4 +345,21 @@ do
345 v = 2 345 v = 2
346 end 346 end
347end 347end
348do
349 local condChain = 1 < 2 and 2 <= 2 and 2 < 3 and 3 == 3 and 3 > 2 and 2 >= 1 and 1 == 1 and 1 < 3 and 3 ~= 5
350 local v
351 v = function(x)
352 print(x)
353 return x
354 end
355 local evaluation
356 do
357 local _cond_0 = v(2)
358 evaluation = v(1) < _cond_0 and _cond_0 <= v(3)
359 end
360 do
361 local _cond_0 = v(2)
362 evaluation = v(1) > _cond_0 and _cond_0 <= v(3)
363 end
364end
348return nil 365return nil
diff --git a/spec/outputs/in_expression.lua b/spec/outputs/in_expression.lua
index ddba69a..60802c9 100644
--- a/spec/outputs/in_expression.lua
+++ b/spec/outputs/in_expression.lua
@@ -2,43 +2,18 @@ f((function()
2 local _val_0 = -a ^ 2 2 local _val_0 = -a ^ 2
3 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0 3 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0
4end)()) 4end)())
5local a, b = (function(...)
6 local _val_0 = x(...)
7 return not (1 <= _val_0 and _val_0 <= 3)
8end)(...), 2
9local d
10do
11 local _val_0 = (tb.x.y(...))
12 d = not (1 <= _val_0 and _val_0 <= 3)
13end
14local has 5local has
15do 6do
16 local _val_0 = "foo" 7 local _val_0 = "foo"
17 has = "bar" == _val_0 or "foo" == _val_0 8 has = "bar" == _val_0 or "foo" == _val_0
18end 9end
19if (1 == a) and (2 == b or 3 == b or 4 == b) or (function() 10if (1 == a) and (function()
20 local _val_0 = c 11 local _val_0 = b
21 return 1 <= _val_0 and _val_0 <= 10 12 return 2 == _val_0 or 3 == _val_0 or 4 == _val_0
22end)() then 13end)() then
23 print(a, b, c) 14 print(a, b, c)
24end 15end
25do 16do
26 local _exp_0 = val
27 if 1 == _exp_0 or 2 == _exp_0 or 3 == _exp_0 then
28 print("1, 2, 3")
29 elseif not (0 < _exp_0 and _exp_0 <= 100) then
30 print("not (0 < val <= 100)")
31 elseif (200 <= _exp_0 and _exp_0 < 300) then
32 print("200 <= val < 300)")
33 elseif not (333 == _exp_0 or 444 == _exp_0 or 555 == _exp_0) then
34 print("not 333, 444 or 555")
35 end
36end
37do
38 local _val_0 = y
39 return not (a < _val_0 and _val_0 < b)
40end
41do
42 local exist 17 local exist
43 do 18 do
44 local _check_0 = list 19 local _check_0 = list
diff --git a/spec/outputs/lists.lua b/spec/outputs/lists.lua
index 581cc23..e6f306d 100644
--- a/spec/outputs/lists.lua
+++ b/spec/outputs/lists.lua
@@ -273,10 +273,73 @@ for _index_0 = 1, #test do
273 local thing = test[_index_0] 273 local thing = test[_index_0]
274 print(thing) 274 print(thing)
275end 275end
276return function() 276_ = function()
277 local _list_0 = rows 277 local _list_0 = rows
278 for _index_0 = 1, #_list_0 do 278 for _index_0 = 1, #_list_0 do
279 local row = _list_0[_index_0] 279 local row = _list_0[_index_0]
280 a = b 280 a = b
281 end 281 end
282end 282end
283do
284 local _with_0 = tb
285 f(_with_0[a])
286 f({
287 a
288 })
289 local _list_0 = f
290 for _index_0 = a, #_list_0 do
291 local v = _list_0[_index_0]
292 print(v)
293 end
294 f({ })
295 do
296 local _obj_0 = f
297 _obj_0[#_obj_0 + 1] = x
298 end
299 _with_0[a] = x
300 a = x[1]
301 _with_0[#_with_0 + 1] = x
302 do
303 local _check_0 = _with_0[1]
304 local _find_0 = false
305 for _index_0 = 1, #_check_0 do
306 local _item_0 = _check_0[_index_0]
307 if _item_0 == a then
308 _find_0 = true
309 break
310 end
311 end
312 c = _find_0
313 end
314 c = (1 == a)
315 c = (1 == a)
316 do
317 local _check_0 = {
318 1
319 }
320 local _find_0 = false
321 for _index_0 = 1, #_check_0 do
322 local _item_0 = _check_0[_index_0]
323 if _item_0 == a then
324 _find_0 = true
325 break
326 end
327 end
328 c = _find_0
329 end
330end
331do
332 a, b = hello[1], hello[2]
333 local name, job
334 do
335 local _obj_0 = person
336 name, job = _obj_0[1], _obj_0[2]
337 if name == nil then
338 name = "nameless"
339 end
340 if job == nil then
341 job = "jobless"
342 end
343 end
344end
345return nil
diff --git a/spec/outputs/tables.lua b/spec/outputs/tables.lua
index e9df1c4..f836d58 100644
--- a/spec/outputs/tables.lua
+++ b/spec/outputs/tables.lua
@@ -52,6 +52,13 @@ local x = {
52 343, 52 343,
53 343 53 343
54} 54}
55x = {
56 1,
57 2,
58 4343,
59 343,
60 343
61}
55local g, p = { 62local g, p = {
56 1, 63 1,
57 2, 64 2,
@@ -72,6 +79,17 @@ local annother = {
72 7, 79 7,
73 8 80 8
74} 81}
82annother = {
83 1,
84 2,
85 3,
86 3,
87 4,
88 5,
89 6,
90 7,
91 8
92}
75local yeah = { 93local yeah = {
76 [232] = 3434, 94 [232] = 3434,
77 "helo", 95 "helo",
@@ -435,6 +453,27 @@ do
435 _tab_0[#_tab_0 + 1] = 11 453 _tab_0[#_tab_0 + 1] = 11
436 tbMixA = _tab_0 454 tbMixA = _tab_0
437end 455end
456do
457 local _tab_0 = { }
458 local _obj_0
459 do
460 local _accum_0 = { }
461 local _len_0 = 1
462 for i = 1, 10 do
463 _accum_0[_len_0] = i
464 _len_0 = _len_0 + 1
465 end
466 _obj_0 = _accum_0
467 end
468 local _idx_0 = #_tab_0 + 1
469 for _index_0 = 1, #_obj_0 do
470 local _value_0 = _obj_0[_index_0]
471 _tab_0[_idx_0] = _value_0
472 _idx_0 = _idx_0 + 1
473 end
474 _tab_0[#_tab_0 + 1] = 11
475 tbMixA = _tab_0
476end
438local tbMixB 477local tbMixB
439do 478do
440 local _tab_0 = { } 479 local _tab_0 = { }
@@ -489,6 +528,50 @@ do
489 _tab_0[#_tab_0 + 1] = 3 528 _tab_0[#_tab_0 + 1] = 3
490 tbMixB = _tab_0 529 tbMixB = _tab_0
491end 530end
531do
532 local _tab_0 = { }
533 local _obj_0 = ...
534 local _idx_0 = #_tab_0 + 1
535 for _index_0 = 1, #_obj_0 do
536 local _value_0 = _obj_0[_index_0]
537 _tab_0[_idx_0] = _value_0
538 _idx_0 = _idx_0 + 1
539 end
540 local _obj_1 = {
541 ...
542 }
543 local _idx_1 = #_tab_0 + 1
544 for _index_0 = 1, #_obj_1 do
545 local _value_0 = _obj_1[_index_0]
546 _tab_0[_idx_1] = _value_0
547 _idx_1 = _idx_1 + 1
548 end
549 local _obj_2
550 do
551 local _tab_1 = { }
552 local _obj_3 = ...
553 local _idx_2 = 1
554 for _key_0, _value_0 in pairs(_obj_3) do
555 if _idx_2 == _key_0 then
556 _tab_1[#_tab_1 + 1] = _value_0
557 _idx_2 = _idx_2 + 1
558 else
559 _tab_1[_key_0] = _value_0
560 end
561 end
562 _obj_2 = _tab_1
563 end
564 local _idx_2 = #_tab_0 + 1
565 for _index_0 = 1, #_obj_2 do
566 local _value_0 = _obj_2[_index_0]
567 _tab_0[_idx_2] = _value_0
568 _idx_2 = _idx_2 + 1
569 end
570 _tab_0[#_tab_0 + 1] = 1
571 _tab_0[#_tab_0 + 1] = 2
572 _tab_0[#_tab_0 + 1] = 3
573 tbMixB = _tab_0
574end
492local template <const> = { 575local template <const> = {
493 foo = "Hello", 576 foo = "Hello",
494 bar = "World", 577 bar = "World",
diff --git a/spec/outputs/unicode/cond.lua b/spec/outputs/unicode/cond.lua
index f972dea..9a4ccb9 100644
--- a/spec/outputs/unicode/cond.lua
+++ b/spec/outputs/unicode/cond.lua
@@ -351,4 +351,21 @@ do
351 _u53d8_u91cfv = 2 351 _u53d8_u91cfv = 2
352 end 352 end
353end 353end
354do
355 local _u94fe_u5f0f_u6bd4_u8f83 = 1 < 2 and 2 <= 2 and 2 < 3 and 3 == 3 and 3 > 2 and 2 >= 1 and 1 == 1 and 1 < 3 and 3 ~= 5
356 local _u503c
357 _u503c = function(_u8f93_u5165)
358 _u6253_u5370(_u8f93_u5165)
359 return _u8f93_u5165
360 end
361 local _u6c42_u503c
362 do
363 local _cond_0 = _u503c(2)
364 _u6c42_u503c = _u503c(1) < _cond_0 and _cond_0 <= _u503c(3)
365 end
366 do
367 local _cond_0 = _u503c(2)
368 _u6c42_u503c = _u503c(1) > _cond_0 and _cond_0 <= _u503c(3)
369 end
370end
354return nil 371return nil
diff --git a/spec/outputs/unicode/in_expression.lua b/spec/outputs/unicode/in_expression.lua
index 62aad05..7c584f3 100644
--- a/spec/outputs/unicode/in_expression.lua
+++ b/spec/outputs/unicode/in_expression.lua
@@ -2,43 +2,18 @@ _u51fd_u6570((function()
2 local _val_0 = -_u53d8_u91cfa ^ 2 2 local _val_0 = -_u53d8_u91cfa ^ 2
3 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0 3 return 1 == _val_0 or 2 == _val_0 or 3 == _val_0
4end)()) 4end)())
5local _u53d8_u91cfa, _u53d8_u91cfb = (function(...)
6 local _val_0 = _u51fd_u6570x(...)
7 return not (1 <= _val_0 and _val_0 <= 3)
8end)(...), 2
9local _u53d8_u91cfd
10do
11 local _val_0 = (_u5bf9_u8c61["字段x"]["字段y"](...))
12 _u53d8_u91cfd = not (1 <= _val_0 and _val_0 <= 3)
13end
14local _u5728_u7684 5local _u5728_u7684
15do 6do
16 local _val_0 = "东" 7 local _val_0 = "东"
17 _u5728_u7684 = "东" == _val_0 or "西" == _val_0 8 _u5728_u7684 = "东" == _val_0 or "西" == _val_0
18end 9end
19if (1 == _u53d8_u91cfa) and (2 == _u53d8_u91cfb or 3 == _u53d8_u91cfb or 4 == _u53d8_u91cfb) or (function() 10if (1 == _u53d8_u91cfa) and (function()
20 local _val_0 = _u53d8_u91cfc 11 local _val_0 = _u53d8_u91cfb
21 return 1 <= _val_0 and _val_0 <= 10 12 return 2 == _val_0 or 3 == _val_0 or 4 == _val_0
22end)() then 13end)() then
23 _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) 14 _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc)
24end 15end
25do 16do
26 local _exp_0 = _u503c
27 if 1 == _exp_0 or 2 == _exp_0 or 3 == _exp_0 then
28 _u6253_u5370("1, 2, 3")
29 elseif not (0 < _exp_0 and _exp_0 <= 100) then
30 _u6253_u5370("éž (0 < 值 <= 100)")
31 elseif (200 <= _exp_0 and _exp_0 < 300) then
32 _u6253_u5370("200 <= 值 < 300)")
33 elseif not (333 == _exp_0 or 444 == _exp_0 or 555 == _exp_0) then
34 _u6253_u5370("éž 333, 444 或 555")
35 end
36end
37do
38 local _val_0 = _u53d8_u91cfy
39 return not (_u5f00_u59cb < _val_0 and _val_0 < _u7ed3_u675f)
40end
41do
42 local _u5b58_u5728 17 local _u5b58_u5728
43 do 18 do
44 local _check_0 = _u8868 19 local _check_0 = _u8868
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp
index ed34274..6126f71 100644
--- a/src/yuescript/yue_ast.cpp
+++ b/src/yuescript/yue_ast.cpp
@@ -182,12 +182,6 @@ std::string ConstValue_t::to_string(void* ud) const {
182 auto info = reinterpret_cast<YueFormat*>(ud); 182 auto info = reinterpret_cast<YueFormat*>(ud);
183 return info->convert(this); 183 return info->convert(this);
184} 184}
185std::string InRangeOpen_t::to_string(void*) const {
186 return {};
187}
188std::string InRangeClose_t::to_string(void*) const {
189 return {};
190}
191std::string NotIn_t::to_string(void*) const { 185std::string NotIn_t::to_string(void*) const {
192 return {}; 186 return {};
193} 187}
@@ -569,8 +563,18 @@ std::string Try_t::to_string(void* ud) const {
569 return join(temp, "\n"sv); 563 return join(temp, "\n"sv);
570} 564}
571std::string Comprehension_t::to_string(void* ud) const { 565std::string Comprehension_t::to_string(void* ud) const {
572 auto valueStr = value->to_string(ud); 566 str_list temp;
573 return '[' + (valueStr[0] == '[' ? " "s : ""s) + valueStr + ' ' + forLoop->to_string(ud) + ']'; 567 for (const auto& item : items.objects()) {
568 temp.push_back(item->to_string(ud));
569 }
570 if (temp.size() > 0) {
571 temp.front().insert(0, temp.front()[0] == '[' ? " "s : ""s);
572 }
573 if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) {
574 return '[' + join(temp, ", "sv) + ']';
575 } else {
576 return '[' + join(temp, " "sv) + ']';
577 }
574} 578}
575std::string CompValue_t::to_string(void* ud) const { 579std::string CompValue_t::to_string(void* ud) const {
576 return value->to_string(ud); 580 return value->to_string(ud);
@@ -830,6 +834,9 @@ std::string Invoke_t::to_string(void* ud) const {
830std::string SpreadExp_t::to_string(void* ud) const { 834std::string SpreadExp_t::to_string(void* ud) const {
831 return "..."s + exp->to_string(ud); 835 return "..."s + exp->to_string(ud);
832} 836}
837std::string SpreadListExp_t::to_string(void* ud) const {
838 return "..."s + exp->to_string(ud);
839}
833std::string TableLit_t::to_string(void* ud) const { 840std::string TableLit_t::to_string(void* ud) const {
834 auto info = reinterpret_cast<YueFormat*>(ud); 841 auto info = reinterpret_cast<YueFormat*>(ud);
835 if (values.empty()) { 842 if (values.empty()) {
@@ -1168,10 +1175,6 @@ std::string UnaryExp_t::to_string(void* ud) const {
1168 } 1175 }
1169 return line; 1176 return line;
1170} 1177}
1171std::string InRange_t::to_string(void* ud) const {
1172 auto valueStr = openValue->to_string(ud);
1173 return (open.is<InRangeOpen_t>() ? "("s : "["s + (valueStr[0] == '[' ? " "s : ""s)) + valueStr + ", "s + closeValue->to_string(ud) + (close.is<InRangeOpen_t>() ? ')' : ']');
1174}
1175std::string InDiscrete_t::to_string(void* ud) const { 1178std::string InDiscrete_t::to_string(void* ud) const {
1176 str_list temp; 1179 str_list temp;
1177 for (auto value : values.objects()) { 1180 for (auto value : values.objects()) {
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h
index a02f548..2136849 100644
--- a/src/yuescript/yue_ast.h
+++ b/src/yuescript/yue_ast.h
@@ -78,6 +78,8 @@ class InvokeArgs_t;
78class TableBlockIndent_t; 78class TableBlockIndent_t;
79class Macro_t; 79class Macro_t;
80class In_t; 80class In_t;
81class NormalDef_t;
82class SpreadListExp_t;
81} // namespace yue 83} // namespace yue
82 84
83AST_LEAF(Num) 85AST_LEAF(Num)
@@ -286,7 +288,7 @@ AST_NODE(SwitchList)
286AST_END(SwitchList, "switch_list"sv) 288AST_END(SwitchList, "switch_list"sv)
287 289
288AST_NODE(SwitchCase) 290AST_NODE(SwitchCase)
289 ast_sel<true, SwitchList_t, In_t> condition; 291 ast_ptr<true, SwitchList_t> condition;
290 ast_sel<true, Block_t, Statement_t> body; 292 ast_sel<true, Block_t, Statement_t> body;
291 AST_MEMBER(SwitchCase, &condition, &body) 293 AST_MEMBER(SwitchCase, &condition, &body)
292AST_END(SwitchCase, "switch_case"sv) 294AST_END(SwitchCase, "switch_case"sv)
@@ -374,9 +376,10 @@ AST_NODE(Try)
374AST_END(Try, "try"sv) 376AST_END(Try, "try"sv)
375 377
376AST_NODE(Comprehension) 378AST_NODE(Comprehension)
377 ast_sel<true, Exp_t, /*non-syntax-rule*/ Statement_t> value; 379 ast_ptr<true, Seperator_t> sep;
378 ast_ptr<true, CompInner_t> forLoop; 380 ast_sel_list<false, NormalDef_t, SpreadListExp_t, CompInner_t,
379 AST_MEMBER(Comprehension, &value, &forLoop) 381 /*non-syntax-rule*/ Statement_t> items;
382 AST_MEMBER(Comprehension, &sep, &items)
380AST_END(Comprehension, "comp"sv) 383AST_END(Comprehension, "comp"sv)
381 384
382AST_NODE(CompValue) 385AST_NODE(CompValue)
@@ -437,23 +440,9 @@ AST_END(BinaryOperator, "binary_op"sv)
437AST_LEAF(UnaryOperator) 440AST_LEAF(UnaryOperator)
438AST_END(UnaryOperator, "unary_op"sv) 441AST_END(UnaryOperator, "unary_op"sv)
439 442
440AST_LEAF(InRangeOpen)
441AST_END(InRangeOpen, "in_range_open"sv)
442
443AST_LEAF(InRangeClose)
444AST_END(InRangeClose, "in_range_close"sv)
445
446AST_LEAF(NotIn) 443AST_LEAF(NotIn)
447AST_END(NotIn, "not_in"sv) 444AST_END(NotIn, "not_in"sv)
448 445
449AST_NODE(InRange)
450 ast_sel<true, InRangeOpen_t, InRangeClose_t> open;
451 ast_ptr<true, Exp_t> openValue;
452 ast_ptr<true, Exp_t> closeValue;
453 ast_sel<true, InRangeOpen_t, InRangeClose_t> close;
454 AST_MEMBER(InRange, &open, &openValue, &closeValue, &close)
455AST_END(InRange, "in_range"sv)
456
457AST_NODE(InDiscrete) 446AST_NODE(InDiscrete)
458 ast_ptr<true, Seperator_t> sep; 447 ast_ptr<true, Seperator_t> sep;
459 ast_list<true, Exp_t> values; 448 ast_list<true, Exp_t> values;
@@ -462,7 +451,7 @@ AST_END(InDiscrete, "in_discrete"sv)
462 451
463AST_NODE(In) 452AST_NODE(In)
464 ast_ptr<false, NotIn_t> not_; 453 ast_ptr<false, NotIn_t> not_;
465 ast_sel<true, InRange_t, InDiscrete_t, Exp_t> item; 454 ast_sel<true, InDiscrete_t, Exp_t> item;
466 AST_MEMBER(In, &not_, &item) 455 AST_MEMBER(In, &not_, &item)
467AST_END(In, "in"sv) 456AST_END(In, "in"sv)
468 457
@@ -666,6 +655,11 @@ AST_NODE(SpreadExp)
666 AST_MEMBER(SpreadExp, &exp) 655 AST_MEMBER(SpreadExp, &exp)
667AST_END(SpreadExp, "spread_exp"sv) 656AST_END(SpreadExp, "spread_exp"sv)
668 657
658AST_NODE(SpreadListExp)
659 ast_ptr<true, Exp_t> exp;
660 AST_MEMBER(SpreadListExp, &exp)
661AST_END(SpreadListExp, "spread_list_exp"sv)
662
669AST_NODE(TableLit) 663AST_NODE(TableLit)
670 ast_ptr<true, Seperator_t> sep; 664 ast_ptr<true, Seperator_t> sep;
671 ast_sel_list<false, 665 ast_sel_list<false,
@@ -673,7 +667,7 @@ AST_NODE(TableLit)
673 MetaVariablePairDef_t, MetaNormalPairDef_t, 667 MetaVariablePairDef_t, MetaNormalPairDef_t,
674 VariablePair_t, NormalPair_t, Exp_t, 668 VariablePair_t, NormalPair_t, Exp_t,
675 MetaVariablePair_t, MetaNormalPair_t, 669 MetaVariablePair_t, MetaNormalPair_t,
676 /*non-syntax-rule*/ TableBlockIndent_t> values; 670 /*non-syntax-rule*/ TableBlockIndent_t, SpreadListExp_t> values;
677 AST_MEMBER(TableLit, &sep, &values) 671 AST_MEMBER(TableLit, &sep, &values)
678AST_END(TableLit, "table_lit"sv) 672AST_END(TableLit, "table_lit"sv)
679 673
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp
index 5b9770d..d32d9c1 100644
--- a/src/yuescript/yue_compiler.cpp
+++ b/src/yuescript/yue_compiler.cpp
@@ -15,6 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
15#include <unordered_map> 15#include <unordered_map>
16#include <unordered_set> 16#include <unordered_set>
17#include <vector> 17#include <vector>
18#include <variant>
18 19
19#include "yuescript/yue_compiler.h" 20#include "yuescript/yue_compiler.h"
20#include "yuescript/yue_parser.h" 21#include "yuescript/yue_parser.h"
@@ -74,7 +75,7 @@ static std::unordered_set<std::string> Metamethods = {
74 "close"s // Lua 5.4 75 "close"s // Lua 5.4
75}; 76};
76 77
77const std::string_view version = "0.19.6"sv; 78const std::string_view version = "0.20.0"sv;
78const std::string_view extension = "yue"sv; 79const std::string_view extension = "yue"sv;
79 80
80class CompileError : public std::logic_error { 81class CompileError : public std::logic_error {
@@ -1148,6 +1149,10 @@ private:
1148 auto simpleValue = static_cast<SimpleValue_t*>(item); 1149 auto simpleValue = static_cast<SimpleValue_t*>(item);
1149 if (simpleValue->value.is<TableLit_t>()) { 1150 if (simpleValue->value.is<TableLit_t>()) {
1150 return true; 1151 return true;
1152 } else if (auto comp = simpleValue->value.as<Comprehension_t>()) {
1153 if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) {
1154 return true;
1155 }
1151 } 1156 }
1152 return false; 1157 return false;
1153 } 1158 }
@@ -1195,6 +1200,28 @@ private:
1195 return false; 1200 return false;
1196 } 1201 }
1197 1202
1203 bool isConditionChainingOperator(const std::string& op) {
1204 return op == "=="sv || op == "~="sv || op == "!="sv ||
1205 op == "<"sv || op == "<="sv || op == ">"sv || op == ">="sv;
1206 }
1207
1208 bool isConditionChaining(Exp_t* exp) {
1209 int conditionChaining = 0;
1210 for (const auto& opValue_ : exp->opValues.objects()) {
1211 auto opValue = static_cast<ExpOpValue_t*>(opValue_);
1212 auto op = _parser.toString(opValue->op);
1213 if (isConditionChainingOperator(op)) {
1214 conditionChaining++;
1215 if (conditionChaining > 1) {
1216 return true;
1217 }
1218 } else {
1219 conditionChaining = 0;
1220 }
1221 }
1222 return false;
1223 }
1224
1198 UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) { 1225 UnaryExp_t* unaryGeneratingAnonFunc(Exp_t* exp) {
1199 if (!exp) return nullptr; 1226 if (!exp) return nullptr;
1200 BLOCK_START 1227 BLOCK_START
@@ -1440,10 +1467,10 @@ private:
1440 case id<CompInner_t>(): { 1467 case id<CompInner_t>(): {
1441 auto compInner = appendix->item.to<CompInner_t>(); 1468 auto compInner = appendix->item.to<CompInner_t>();
1442 auto comp = x->new_ptr<Comprehension_t>(); 1469 auto comp = x->new_ptr<Comprehension_t>();
1443 comp->forLoop.set(compInner);
1444 auto stmt = x->new_ptr<Statement_t>(); 1470 auto stmt = x->new_ptr<Statement_t>();
1445 stmt->content.set(statement->content); 1471 stmt->content.set(statement->content);
1446 comp->value.set(stmt); 1472 comp->items.push_back(stmt);
1473 comp->items.push_back(compInner);
1447 auto simpleValue = x->new_ptr<SimpleValue_t>(); 1474 auto simpleValue = x->new_ptr<SimpleValue_t>();
1448 simpleValue->value.set(comp); 1475 simpleValue->value.set(comp);
1449 auto exp = newExp(simpleValue, x); 1476 auto exp = newExp(simpleValue, x);
@@ -2032,6 +2059,10 @@ private:
2032 transformUnaryExp(unary, out, ExpUsage::Assignment, expList); 2059 transformUnaryExp(unary, out, ExpUsage::Assignment, expList);
2033 out.back().insert(0, preDefine); 2060 out.back().insert(0, preDefine);
2034 return; 2061 return;
2062 } else if (isConditionChaining(exp)) {
2063 auto expList = assignment->expList.get();
2064 transformExp(exp, out, ExpUsage::Assignment, expList);
2065 return;
2035 } 2066 }
2036 auto singleVal = singleValueFrom(exp); 2067 auto singleVal = singleValueFrom(exp);
2037 BREAK_IF(!singleVal); 2068 BREAK_IF(!singleVal);
@@ -2320,12 +2351,15 @@ private:
2320 case id<Exp_t>(): { 2351 case id<Exp_t>(): {
2321 auto item = singleValueFrom(node)->item.get(); 2352 auto item = singleValueFrom(node)->item.get();
2322 if (!item) throw CompileError("invalid destructure value"sv, node); 2353 if (!item) throw CompileError("invalid destructure value"sv, node);
2323 auto tbA = item->get_by_path<TableLit_t>(); 2354 if (auto tbA = item->get_by_path<TableLit_t>()) {
2324 if (tbA) {
2325 tableItems = &tbA->values.objects(); 2355 tableItems = &tbA->values.objects();
2326 } else { 2356 } else if (auto tbB = item->get_by_path<Comprehension_t>()) {
2327 auto tbB = ast_cast<SimpleTable_t>(item); 2357 if (tbB->items.size() == 2 && ast_is<CompInner_t>(tbB->items.back())) {
2328 if (tbB) tableItems = &tbB->pairs.objects(); 2358 throw CompileError("invalid destructure value"sv, tbB);
2359 }
2360 tableItems = &tbB->items.objects();
2361 } else if (auto tbC = ast_cast<SimpleTable_t>(item)) {
2362 tableItems = &tbC->pairs.objects();
2329 } 2363 }
2330 break; 2364 break;
2331 } 2365 }
@@ -2340,15 +2374,23 @@ private:
2340 break; 2374 break;
2341 } 2375 }
2342 case id<TableLit_t>(): { 2376 case id<TableLit_t>(): {
2343 auto table = ast_cast<TableLit_t>(node); 2377 auto table = static_cast<TableLit_t*>(node);
2344 tableItems = &table->values.objects(); 2378 tableItems = &table->values.objects();
2345 break; 2379 break;
2346 } 2380 }
2347 case id<SimpleTable_t>(): { 2381 case id<SimpleTable_t>(): {
2348 auto table = ast_cast<SimpleTable_t>(node); 2382 auto table = static_cast<SimpleTable_t*>(node);
2349 tableItems = &table->pairs.objects(); 2383 tableItems = &table->pairs.objects();
2350 break; 2384 break;
2351 } 2385 }
2386 case id<Comprehension_t>(): {
2387 auto table = static_cast<Comprehension_t*>(node);
2388 if (table->items.size() == 2 && ast_is<CompInner_t>(table->items.back())) {
2389 throw CompileError("invalid destructure value"sv, table);
2390 }
2391 tableItems = &table->items.objects();
2392 break;
2393 }
2352 default: YUEE("AST node mismatch", node); break; 2394 default: YUEE("AST node mismatch", node); break;
2353 } 2395 }
2354 if (!tableItems) throw CompileError("invalid destructure value"sv, node); 2396 if (!tableItems) throw CompileError("invalid destructure value"sv, node);
@@ -2370,8 +2412,9 @@ private:
2370 } 2412 }
2371 auto value = singleValueFrom(pair); 2413 auto value = singleValueFrom(pair);
2372 auto item = value->item.get(); 2414 auto item = value->item.get();
2373 if (ast_is<SimpleTable_t>(item) || item->get_by_path<TableLit_t>()) { 2415 ast_node* subExp = ast_cast<SimpleTable_t>(item);
2374 auto subPairs = destructFromExp(pair, varDefOnly, optional); 2416 if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) {
2417 auto subPairs = destructFromExp(subExp, varDefOnly, optional);
2375 if (!subPairs.empty()) { 2418 if (!subPairs.empty()) {
2376 if (defVal) { 2419 if (defVal) {
2377 throw CompileError("default value is not supported here"sv, defVal); 2420 throw CompileError("default value is not supported here"sv, defVal);
@@ -2448,8 +2491,9 @@ private:
2448 if (auto exp = np->value.as<Exp_t>()) { 2491 if (auto exp = np->value.as<Exp_t>()) {
2449 if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); 2492 if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp);
2450 auto item = singleValueFrom(exp)->item.get(); 2493 auto item = singleValueFrom(exp)->item.get();
2451 if (ast_is<SimpleTable_t>(item) || item->get_by_path<TableLit_t>()) { 2494 ast_node* subExp = ast_cast<SimpleTable_t>(item);
2452 auto subPairs = destructFromExp(exp, varDefOnly, optional); 2495 if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) {
2496 auto subPairs = destructFromExp(subExp, varDefOnly, optional);
2453 if (!subPairs.empty()) { 2497 if (!subPairs.empty()) {
2454 if (defVal) { 2498 if (defVal) {
2455 throw CompileError("default value is not supported here"sv, defVal); 2499 throw CompileError("default value is not supported here"sv, defVal);
@@ -2602,8 +2646,19 @@ private:
2602 if (!value) { 2646 if (!value) {
2603 throw CompileError("invalid destructure"sv, expr); 2647 throw CompileError("invalid destructure"sv, expr);
2604 } 2648 }
2605 ast_node* destructNode = value->get_by_path<SimpleValue_t, TableLit_t>(); 2649 ast_node* destructNode = value->item.as<SimpleTable_t>();
2606 if (destructNode || (destructNode = value->item.as<SimpleTable_t>())) { 2650 if (!destructNode) {
2651 if (auto sVal = value->item.as<SimpleValue_t>()) {
2652 if (auto tab = sVal->value.as<TableLit_t>()) {
2653 destructNode = tab;
2654 } else if (auto comp = sVal->value.as<Comprehension_t>()) {
2655 if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) {
2656 destructNode = comp;
2657 }
2658 }
2659 }
2660 }
2661 if (destructNode) {
2607 if (*j != nil) { 2662 if (*j != nil) {
2608 if (auto ssVal = simpleSingleValueFrom(*j)) { 2663 if (auto ssVal = simpleSingleValueFrom(*j)) {
2609 switch (ssVal->value->get_id()) { 2664 switch (ssVal->value->get_id()) {
@@ -2630,6 +2685,9 @@ private:
2630 case id<SimpleTable_t>(): 2685 case id<SimpleTable_t>():
2631 dlist = &static_cast<SimpleTable_t*>(destructNode)->pairs.objects(); 2686 dlist = &static_cast<SimpleTable_t*>(destructNode)->pairs.objects();
2632 break; 2687 break;
2688 case id<Comprehension_t>():
2689 dlist = &static_cast<Comprehension_t*>(destructNode)->items.objects();
2690 break;
2633 default: YUEE("AST node mismatch", destructNode); break; 2691 default: YUEE("AST node mismatch", destructNode); break;
2634 } 2692 }
2635 if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode); 2693 if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode);
@@ -3300,27 +3358,173 @@ private:
3300 transform_pipe_exp(exp->pipeExprs.objects(), out, usage, assignList); 3358 transform_pipe_exp(exp->pipeExprs.objects(), out, usage, assignList);
3301 return; 3359 return;
3302 } 3360 }
3303 if (usage != ExpUsage::Closure) {
3304 YUEE("invalid expression usage", exp);
3305 }
3306 if (exp->nilCoalesed) { 3361 if (exp->nilCoalesed) {
3362 if (usage != ExpUsage::Closure) {
3363 YUEE("invalid expression usage", exp);
3364 }
3307 transformNilCoalesedExp(exp, out, ExpUsage::Closure); 3365 transformNilCoalesedExp(exp, out, ExpUsage::Closure);
3308 return; 3366 return;
3309 } 3367 }
3310 str_list temp; 3368 str_list temp;
3311 transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure); 3369 std::list<std::pair<std::string, ast_list<true, UnaryExp_t>*>> chains;
3370 chains.emplace_back(std::string(), &exp->pipeExprs);
3371 int conditionChainCount = 0;
3372 str_list evalLines;
3373 auto checkChains = [&]() {
3374 std::optional<str_list> result;
3375 if (conditionChainCount > 1) {
3376 bool needWrapping = false;
3377 str_list conds;
3378 str_list preDefines;
3379 std::list<std::variant<std::string, ast_ptr<false, Exp_t>>> stack;
3380 for (const auto& item : chains) {
3381 if (!item.first.empty()) {
3382 stack.push_back(item.first);
3383 }
3384 auto node = item.second->front();
3385 bool checkEvalOnce = item != chains.front() && item != chains.back();
3386 if (checkEvalOnce) {
3387 std::string varName;
3388 if (item.second->size() == 1) {
3389 if (auto unary = singleUnaryExpFrom(node)) {
3390 if (auto value = singleValueFrom(unary)) {
3391 varName = singleVariableFrom(value, true);
3392 }
3393 if (varName.empty()) {
3394 if (auto sval = static_cast<Value_t*>(unary->expos.front())->item.as<SimpleValue_t>()) {
3395 if (ast_is<ConstValue_t, Num_t>(sval->value)) {
3396 auto condExp = unary->new_ptr<Exp_t>();
3397 condExp->pipeExprs.dup(*item.second);
3398 stack.push_back(condExp);
3399 goto reduce;
3400 }
3401 }
3402 }
3403 }
3404 }
3405 if (varName.empty() || !isLocal(varName)) {
3406 varName = getUnusedName("_cond_"sv);
3407 auto condExp = node->new_ptr<Exp_t>();
3408 condExp->pipeExprs.dup(*item.second);
3409 auto varExp = toAst<Exp_t>(varName, node);
3410 auto assignment = assignmentFrom(varExp, condExp, node);
3411 if (!needWrapping) {
3412 needWrapping = true;
3413 if (usage == ExpUsage::Closure) {
3414 pushFunctionScope();
3415 pushAnonVarArg();
3416 pushScope();
3417 } else if (usage == ExpUsage::Assignment) {
3418 pushScope();
3419 }
3420 }
3421 transformAssignment(assignment, preDefines);
3422 stack.push_back(varExp);
3423 goto reduce;
3424 }
3425 }
3426 {
3427 auto condExp = node->new_ptr<Exp_t>();
3428 condExp->pipeExprs.dup(*item.second);
3429 stack.push_back(condExp);
3430 }
3431 reduce:
3432 if (stack.size() == 3) {
3433 str_list tmp;
3434 auto one = std::get<ast_ptr<false, Exp_t>>(stack.front()).get();
3435 transformExp(one, tmp, ExpUsage::Closure);
3436 stack.pop_front();
3437 auto two = std::get<std::string>(stack.front());
3438 tmp.push_back(two);
3439 stack.pop_front();
3440 auto three = std::get<ast_ptr<false, Exp_t>>(stack.front()).get();
3441 transformExp(three, tmp, ExpUsage::Closure);
3442 conds.push_back(join(tmp, " "sv));
3443 }
3444 }
3445 auto condStr = join(conds, " and "sv);
3446 if (needWrapping && usage == ExpUsage::Closure) {
3447 str_list closureLines{anonFuncStart() + nll(exp)};
3448 closureLines.insert(closureLines.end(), preDefines.begin(), preDefines.end());
3449 closureLines.push_back(indent() + "return "s + condStr + nll(exp));
3450 popScope();
3451 closureLines.push_back(indent() + anonFuncEnd());
3452 temp.push_back(join(closureLines));
3453 popAnonVarArg();
3454 popFunctionScope();
3455 } else {
3456 temp.push_back(condStr);
3457 if (!preDefines.empty()) {
3458 evalLines.insert(evalLines.end(), preDefines.begin(), preDefines.end());
3459 if (usage == ExpUsage::Assignment) {
3460 popScope();
3461 }
3462 }
3463 }
3464 } else {
3465 for (const auto& item : chains) {
3466 if (!item.first.empty()) {
3467 temp.push_back(item.first);
3468 }
3469 transform_pipe_exp(item.second->objects(), temp, ExpUsage::Closure);
3470 }
3471 }
3472 conditionChainCount = 0;
3473 chains.clear();
3474 };
3475 str_list preDefines;
3312 for (auto _opValue : exp->opValues.objects()) { 3476 for (auto _opValue : exp->opValues.objects()) {
3313 auto opValue = static_cast<ExpOpValue_t*>(_opValue); 3477 auto opValue = static_cast<ExpOpValue_t*>(_opValue);
3314 transformBinaryOperator(opValue->op, temp); 3478 transformBinaryOperator(opValue->op, temp);
3315 transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure); 3479 auto op = temp.back();
3480 temp.pop_back();
3481 if (isConditionChainingOperator(op)) {
3482 conditionChainCount++;
3483 chains.emplace_back(op, &opValue->pipeExprs);
3484 } else {
3485 checkChains();
3486 temp.push_back(op);
3487 transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure);
3488 }
3489 }
3490 checkChains();
3491 auto condStr = join(temp, " "sv);
3492 switch (usage) {
3493 case ExpUsage::Closure: {
3494 out.push_back(condStr);
3495 break;
3496 }
3497 case ExpUsage::Assignment: {
3498 auto assignment = exp->new_ptr<ExpListAssign_t>();
3499 assignment->expList.set(assignList);
3500 auto assign = exp->new_ptr<Assign_t>();
3501 assign->values.push_back(toAst<Exp_t>(condStr, exp));
3502 assignment->action.set(assign);
3503 if (evalLines.empty()) {
3504 transformAssignment(assignment, out);
3505 } else {
3506 evalLines.push_front(indent() + "do"s + nll(exp));
3507 evalLines.push_front(getPreDefineLine(assignment));
3508 pushScope();
3509 transformAssignment(assignment, evalLines);
3510 popScope();
3511 evalLines.push_back(indent() + "end"s + nlr(exp));
3512 out.push_back(join(evalLines));
3513 }
3514 break;
3515 }
3516 case ExpUsage::Return: {
3517 evalLines.push_back(indent() + "return "s + condStr + nll(exp));
3518 out.push_back(join(evalLines));
3519 break;
3520 }
3521 default: YUEE("invalid expression usage", exp); break;
3316 } 3522 }
3317 out.push_back(join(temp, " "sv));
3318 } 3523 }
3319 3524
3320 void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) { 3525 void transformNilCoalesedExp(Exp_t* exp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool nilBranchOnly = false) {
3321 auto x = exp; 3526 auto x = exp;
3322 str_list temp; 3527 str_list temp;
3323 std::string prefix;
3324 auto left = exp->new_ptr<Exp_t>(); 3528 auto left = exp->new_ptr<Exp_t>();
3325 if (exp->opValues.empty()) { 3529 if (exp->opValues.empty()) {
3326 left->pipeExprs.dup(exp->pipeExprs); 3530 left->pipeExprs.dup(exp->pipeExprs);
@@ -3328,20 +3532,16 @@ private:
3328 if (usage != ExpUsage::Closure) { 3532 if (usage != ExpUsage::Closure) {
3329 YUEE("invalid expression usage", exp); 3533 YUEE("invalid expression usage", exp);
3330 } 3534 }
3331 transform_pipe_exp(exp->pipeExprs.objects(), temp, ExpUsage::Closure); 3535 auto last = static_cast<ExpOpValue_t*>(exp->opValues.back());
3332 auto last = exp->opValues.objects().back(); 3536 left->pipeExprs.dup(last->pipeExprs);
3333 for (auto _opValue : exp->opValues.objects()) { 3537
3334 auto opValue = static_cast<ExpOpValue_t*>(_opValue); 3538 auto startExp = x->new_ptr<Exp_t>();
3335 transformBinaryOperator(opValue->op, temp); 3539 startExp->pipeExprs.dup(exp->pipeExprs);
3336 if (opValue == last) { 3540 startExp->opValues.dup(exp->opValues);
3337 left->pipeExprs.dup(opValue->pipeExprs); 3541 startExp->opValues.pop_back();
3338 } else { 3542 transformExp(startExp, temp, ExpUsage::Closure);
3339 transform_pipe_exp(opValue->pipeExprs.objects(), temp, ExpUsage::Closure); 3543 transformBinaryOperator(last->op, temp);
3340 } 3544 temp.back() = " "s + temp.back() + " "s;
3341 }
3342 prefix = join(temp, " "sv) + ' ';
3343 temp.clear();
3344 temp.push_back(prefix);
3345 } 3545 }
3346 std::string* funcStart = nullptr; 3546 std::string* funcStart = nullptr;
3347 if (usage == ExpUsage::Closure) { 3547 if (usage == ExpUsage::Closure) {
@@ -4303,6 +4503,9 @@ private:
4303 } else if (auto unary = unaryGeneratingAnonFunc(exp)) { 4503 } else if (auto unary = unaryGeneratingAnonFunc(exp)) {
4304 transformUnaryExp(unary, out, ExpUsage::Return); 4504 transformUnaryExp(unary, out, ExpUsage::Return);
4305 return; 4505 return;
4506 } else if (isConditionChaining(exp)) {
4507 transformExp(exp, out, ExpUsage::Return);
4508 return;
4306 } 4509 }
4307 } 4510 }
4308 if (auto singleValue = singleValueFrom(valueList)) { 4511 if (auto singleValue = singleValueFrom(valueList)) {
@@ -5791,6 +5994,24 @@ private:
5791 return; 5994 return;
5792 } 5995 }
5793 } 5996 }
5997 auto discrete = unary_exp->inExp->item.to<InDiscrete_t>();
5998 if (usage == ExpUsage::Closure && discrete->values.size() == 1) {
5999 str_list tmp;
6000 transformExp(static_cast<Exp_t*>(discrete->values.front()), tmp, ExpUsage::Closure);
6001 tmp.push_back(" == "s);
6002 auto newUnaryExp = x->new_ptr<UnaryExp_t>();
6003 newUnaryExp->ops.dup(unary_exp->ops);
6004 newUnaryExp->expos.dup(unary_exp->expos);
6005 transformUnaryExp(newUnaryExp, tmp, ExpUsage::Closure);
6006 tmp.push_back(")"s);
6007 if (unary_exp->inExp->not_) {
6008 tmp.push_front("not ("s);
6009 } else {
6010 tmp.push_front("("s);
6011 }
6012 out.push_back(join(tmp));
6013 return;
6014 }
5794 if (varName.empty()) { 6015 if (varName.empty()) {
5795 str_list temp; 6016 str_list temp;
5796 if (usage == ExpUsage::Closure) { 6017 if (usage == ExpUsage::Closure) {
@@ -5809,54 +6030,32 @@ private:
5809 auto assignExp = toAst<Exp_t>(newVar, x); 6030 auto assignExp = toAst<Exp_t>(newVar, x);
5810 auto assignment = assignmentFrom(assignExp, exp, x); 6031 auto assignment = assignmentFrom(assignExp, exp, x);
5811 transformAssignment(assignment, temp); 6032 transformAssignment(assignment, temp);
5812 if (auto range = unary_exp->inExp->item.as<InRange_t>()) { 6033
5813 str_list tmp; 6034 str_list tmp;
5814 transformExp(range->openValue, tmp, ExpUsage::Closure); 6035 for (auto exp : discrete->values.objects()) {
5815 transformExp(range->closeValue, tmp, ExpUsage::Closure); 6036 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure);
5816 if (usage == ExpUsage::Assignment) { 6037 }
5817 str_list tmpList; 6038 if (usage == ExpUsage::Assignment) {
5818 transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure); 6039 str_list tmpList;
5819 _buf << indent() << tmpList.back() << " = "sv; 6040 transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure);
5820 } else { 6041 _buf << indent() << tmpList.back() << " = "sv;
5821 _buf << indent() << "return "sv;
5822 }
5823 if (unary_exp->inExp->not_) {
5824 _buf << "not ("sv;
5825 }
5826 _buf << tmp.front() << (range->open.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << newVar << " and "sv << newVar << (range->close.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << tmp.back();
5827 if (unary_exp->inExp->not_) {
5828 _buf << ")"sv;
5829 }
5830 _buf << nll(x);
5831 temp.push_back(clearBuf());
5832 } else { 6042 } else {
5833 auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); 6043 _buf << indent() << "return "sv;
5834 str_list tmp; 6044 }
5835 for (auto exp : discrete->values.objects()) { 6045 if (unary_exp->inExp->not_) {
5836 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure); 6046 _buf << "not ("sv;
5837 } 6047 }
5838 if (usage == ExpUsage::Assignment) { 6048 for (const auto& exp : tmp) {
5839 str_list tmpList; 6049 _buf << exp << " == "sv << newVar;
5840 transformExp(static_cast<Exp_t*>(assignList->exprs.front()), tmpList, ExpUsage::Closure); 6050 if (exp != tmp.back()) {
5841 _buf << indent() << tmpList.back() << " = "sv; 6051 _buf << " or "sv;
5842 } else {
5843 _buf << indent() << "return "sv;
5844 }
5845 if (unary_exp->inExp->not_) {
5846 _buf << "not ("sv;
5847 }
5848 for (const auto& exp : tmp) {
5849 _buf << exp << " == "sv << newVar;
5850 if (exp != tmp.back()) {
5851 _buf << " or "sv;
5852 }
5853 }
5854 if (unary_exp->inExp->not_) {
5855 _buf << ")"sv;
5856 } 6052 }
5857 _buf << nll(x);
5858 temp.push_back(clearBuf());
5859 } 6053 }
6054 if (unary_exp->inExp->not_) {
6055 _buf << ")"sv;
6056 }
6057 _buf << nll(x);
6058 temp.push_back(clearBuf());
5860 if (usage == ExpUsage::Closure) { 6059 if (usage == ExpUsage::Closure) {
5861 temp.push_front(anonFuncStart() + nll(x)); 6060 temp.push_front(anonFuncStart() + nll(x));
5862 popScope(); 6061 popScope();
@@ -5872,35 +6071,22 @@ private:
5872 out.push_back(join(temp)); 6071 out.push_back(join(temp));
5873 } 6072 }
5874 } else { 6073 } else {
5875 if (auto range = unary_exp->inExp->item.as<InRange_t>()) { 6074 str_list tmp;
5876 str_list tmp; 6075 for (auto exp : discrete->values.objects()) {
5877 transformExp(range->openValue, tmp, ExpUsage::Closure); 6076 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure);
5878 transformExp(range->closeValue, tmp, ExpUsage::Closure); 6077 }
5879 if (unary_exp->inExp->not_) { 6078 if (unary_exp->inExp->not_) {
5880 _buf << "not "sv; 6079 _buf << "not "sv;
5881 } 6080 }
5882 _buf << '(' << tmp.front() << (range->open.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << varName << " and "sv << varName << (range->close.is<InRangeOpen_t>() ? " < "sv : " <= "sv) << tmp.back(); 6081 _buf << '(';
5883 _buf << ')'; 6082 for (const auto& exp : tmp) {
5884 out.push_back(clearBuf()); 6083 _buf << exp << " == "sv << varName;
5885 } else { 6084 if (exp != tmp.back()) {
5886 auto discrete = unary_exp->inExp->item.to<InDiscrete_t>(); 6085 _buf << " or "sv;
5887 str_list tmp;
5888 for (auto exp : discrete->values.objects()) {
5889 transformExp(static_cast<Exp_t*>(exp), tmp, ExpUsage::Closure);
5890 }
5891 if (unary_exp->inExp->not_) {
5892 _buf << "not "sv;
5893 }
5894 _buf << '(';
5895 for (const auto& exp : tmp) {
5896 _buf << exp << " == "sv << varName;
5897 if (exp != tmp.back()) {
5898 _buf << " or "sv;
5899 }
5900 } 6086 }
5901 _buf << ')';
5902 out.push_back(clearBuf());
5903 } 6087 }
6088 _buf << ')';
6089 out.push_back(clearBuf());
5904 } 6090 }
5905 return; 6091 return;
5906 } 6092 }
@@ -5945,7 +6131,7 @@ private:
5945 6131
5946 bool hasSpreadExp(const node_container& items) { 6132 bool hasSpreadExp(const node_container& items) {
5947 for (auto item : items) { 6133 for (auto item : items) {
5948 if (ast_is<SpreadExp_t>(item)) return true; 6134 if (ast_is<SpreadExp_t, SpreadListExp_t>(item)) return true;
5949 } 6135 }
5950 return false; 6136 return false;
5951 } 6137 }
@@ -5968,11 +6154,11 @@ private:
5968 std::string tableVar = getUnusedName("_tab_"sv); 6154 std::string tableVar = getUnusedName("_tab_"sv);
5969 forceAddToScope(tableVar); 6155 forceAddToScope(tableVar);
5970 auto it = values.begin(); 6156 auto it = values.begin();
5971 if (ast_is<SpreadExp_t>(*it)) { 6157 if (ast_is<SpreadExp_t, SpreadListExp_t>(*it)) {
5972 temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); 6158 temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x));
5973 } else { 6159 } else {
5974 auto initialTab = x->new_ptr<TableLit_t>(); 6160 auto initialTab = x->new_ptr<TableLit_t>();
5975 while (it != values.end() && !ast_is<SpreadExp_t>(*it)) { 6161 while (it != values.end() && !ast_is<SpreadExp_t, SpreadListExp_t>(*it)) {
5976 initialTab->values.push_back(*it); 6162 initialTab->values.push_back(*it);
5977 ++it; 6163 ++it;
5978 } 6164 }
@@ -6007,6 +6193,28 @@ private:
6007 transformForEach(forEach, temp); 6193 transformForEach(forEach, temp);
6008 break; 6194 break;
6009 } 6195 }
6196 case id<SpreadListExp_t>(): {
6197 auto spread = static_cast<SpreadListExp_t*>(item);
6198 std::string indexVar = getUnusedName("_idx_"sv);
6199 std::string valueVar = getUnusedName("_value_"sv);
6200 auto objVar = singleVariableFrom(spread->exp, true);
6201 if (objVar.empty()) {
6202 objVar = getUnusedName("_obj_");
6203 auto assignment = toAst<ExpListAssign_t>(objVar + "=nil"s, item);
6204 auto assign = assignment->action.to<Assign_t>();
6205 assign->values.clear();
6206 assign->values.push_back(spread->exp);
6207 transformAssignment(assignment, temp);
6208 }
6209 forceAddToScope(indexVar);
6210 temp.push_back(indent() + "local "s + indexVar + " = #"s + tableVar + " + 1"s + nll(item));
6211 _buf << "for "sv << valueVar << " in *"sv << objVar
6212 << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar
6213 << "\n\t"sv << indexVar << "+=1"sv;
6214 auto forEach = toAst<ForEach_t>(clearBuf(), item);
6215 transformForEach(forEach, temp);
6216 break;
6217 }
6010 case id<VariablePair_t>(): 6218 case id<VariablePair_t>():
6011 case id<VariablePairDef_t>(): { 6219 case id<VariablePairDef_t>(): {
6012 if (auto pair = ast_cast<VariablePairDef_t>(item)) { 6220 if (auto pair = ast_cast<VariablePairDef_t>(item)) {
@@ -6374,7 +6582,7 @@ private:
6374 void transformCompCommon(Comprehension_t* comp, str_list& out) { 6582 void transformCompCommon(Comprehension_t* comp, str_list& out) {
6375 str_list temp; 6583 str_list temp;
6376 auto x = comp; 6584 auto x = comp;
6377 auto compInner = comp->forLoop.get(); 6585 auto compInner = static_cast<CompInner_t*>(comp->items.back());
6378 for (auto item : compInner->items.objects()) { 6586 for (auto item : compInner->items.objects()) {
6379 switch (item->get_id()) { 6587 switch (item->get_id()) {
6380 case id<CompForEach_t>(): 6588 case id<CompForEach_t>():
@@ -6391,9 +6599,9 @@ private:
6391 default: YUEE("AST node mismatch", item); break; 6599 default: YUEE("AST node mismatch", item); break;
6392 } 6600 }
6393 } 6601 }
6394 if (auto stmt = comp->value.as<Statement_t>()) { 6602 if (auto stmt = ast_cast<Statement_t>(comp->items.front())) {
6395 transformStatement(stmt, temp); 6603 transformStatement(stmt, temp);
6396 } else if (auto exp = comp->value.as<Exp_t>()) { 6604 } else if (auto exp = ast_cast<Exp_t>(comp->items.front())) {
6397 auto expList = x->new_ptr<ExpList_t>(); 6605 auto expList = x->new_ptr<ExpList_t>();
6398 expList->exprs.push_back(exp); 6606 expList->exprs.push_back(exp);
6399 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 6607 auto expListAssign = x->new_ptr<ExpListAssign_t>();
@@ -6414,6 +6622,48 @@ private:
6414 6622
6415 void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 6623 void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
6416 auto x = comp; 6624 auto x = comp;
6625 if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) {
6626 auto tableLit = x->new_ptr<TableLit_t>();
6627 tableLit->values.dup(comp->items);
6628 switch (usage) {
6629 case ExpUsage::Assignment: {
6630 auto simpleValue = x->new_ptr<SimpleValue_t>();
6631 simpleValue->value.set(tableLit);
6632 auto exp = newExp(simpleValue, x);
6633 auto assignment = x->new_ptr<ExpListAssign_t>();
6634 assignment->expList.set(assignList);
6635 auto assign = x->new_ptr<Assign_t>();
6636 assign->values.push_back(exp);
6637 assignment->action.set(assign);
6638 transformAssignment(assignment, out);
6639 break;
6640 }
6641 case ExpUsage::Return: {
6642 auto simpleValue = x->new_ptr<SimpleValue_t>();
6643 simpleValue->value.set(tableLit);
6644 auto exp = newExp(simpleValue, x);
6645 auto returnNode = x->new_ptr<Return_t>();
6646 auto expList = x->new_ptr<ExpListLow_t>();
6647 expList->exprs.push_back(exp);
6648 returnNode->valueList.set(expList);
6649 transformReturn(returnNode, out);
6650 break;
6651 }
6652 case ExpUsage::Closure:
6653 transformTableLit(tableLit, out);
6654 break;
6655 default:
6656 YUEE("invalid comprehension usage", comp);
6657 break;
6658 }
6659 return;
6660 }
6661 auto def = ast_cast<NormalDef_t>(comp->items.front());
6662 if (!def || def->defVal) {
6663 throw CompileError("invalid comprehension expression", comp->items.front());
6664 }
6665 auto value = def->item.get();
6666 auto compInner = static_cast<CompInner_t*>(comp->items.back());
6417 switch (usage) { 6667 switch (usage) {
6418 case ExpUsage::Closure: 6668 case ExpUsage::Closure:
6419 pushFunctionScope(); 6669 pushFunctionScope();
@@ -6431,7 +6681,6 @@ private:
6431 std::string lenVar = getUnusedName("_len_"sv); 6681 std::string lenVar = getUnusedName("_len_"sv);
6432 addToScope(accumVar); 6682 addToScope(accumVar);
6433 addToScope(lenVar); 6683 addToScope(lenVar);
6434 auto compInner = comp->forLoop.get();
6435 for (auto item : compInner->items.objects()) { 6684 for (auto item : compInner->items.objects()) {
6436 switch (item->get_id()) { 6685 switch (item->get_id()) {
6437 case id<CompForEach_t>(): 6686 case id<CompForEach_t>():
@@ -6451,7 +6700,7 @@ private:
6451 { 6700 {
6452 auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); 6701 auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x);
6453 auto assign = x->new_ptr<Assign_t>(); 6702 auto assign = x->new_ptr<Assign_t>();
6454 assign->values.push_back(comp->value); 6703 assign->values.push_back(value);
6455 auto assignment = x->new_ptr<ExpListAssign_t>(); 6704 auto assignment = x->new_ptr<ExpListAssign_t>();
6456 assignment->expList.set(assignLeft); 6705 assignment->expList.set(assignLeft);
6457 assignment->action.set(assign); 6706 assignment->action.set(assign);
@@ -8830,19 +9079,7 @@ private:
8830 std::string tabCheckVar; 9079 std::string tabCheckVar;
8831 for (auto branch_ : branches) { 9080 for (auto branch_ : branches) {
8832 auto branch = static_cast<SwitchCase_t*>(branch_); 9081 auto branch = static_cast<SwitchCase_t*>(branch_);
8833 if (auto inExp = branch->condition.as<In_t>()) { 9082 auto valueList = static_cast<SwitchList_t*>(branch->condition.get());
8834 auto unary = branch->new_ptr<UnaryExp_t>();
8835 unary->expos.push_back(toAst<Value_t>(objVar, branch));
8836 unary->inExp.set(inExp);
8837 transformUnaryExp(unary, temp, ExpUsage::Closure);
8838 temp.back() = indent() + (firstBranch ? "if "s : "elseif "s) + temp.back() + " then"s + nll(branch);
8839 pushScope();
8840 transform_plain_body(branch->body, temp, usage, assignList);
8841 popScope();
8842 firstBranch = false;
8843 continue;
8844 }
8845 auto valueList = branch->condition.to<SwitchList_t>();
8846 if (auto value = singleValueFrom(valueList); 9083 if (auto value = singleValueFrom(valueList);
8847 value && (value->item.is<SimpleTable_t>() || value->get_by_path<SimpleValue_t, TableLit_t>())) { 9084 value && (value->item.is<SimpleTable_t>() || value->get_by_path<SimpleValue_t, TableLit_t>())) {
8848 if (!firstBranch) { 9085 if (!firstBranch) {
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp
index c818098..8ceee9a 100644
--- a/src/yuescript/yue_parser.cpp
+++ b/src/yuescript/yue_parser.cpp
@@ -109,6 +109,11 @@ YueParser::YueParser() {
109 return false; 109 return false;
110 }); 110 });
111 111
112 table_key_pair_error = pl::user(true_(), [](const item_t& item) {
113 throw ParserError("can not put hash pair in a list"sv, item.begin);
114 return false;
115 });
116
112 #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) 117 #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut)
113 118
114 #define key(str) (expr(str) >> not_alpha_num) 119 #define key(str) (expr(str) >> not_alpha_num)
@@ -342,7 +347,7 @@ YueParser::YueParser() {
342 with_exp = ExpList >> -(space >> Assign); 347 with_exp = ExpList >> -(space >> Assign);
343 348
344 With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); 349 With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do");
345 SwitchCase = key("when") >> space >> (disable_chain_rule(disable_arg_table_block_rule(SwitchList)) | In) >> space >> body_with("then"); 350 SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then");
346 switch_else = key("else") >> space >> body; 351 switch_else = key("else") >> space >> body;
347 352
348 switch_block = 353 switch_block =
@@ -449,7 +454,37 @@ YueParser::YueParser() {
449 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; 454 CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block;
450 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; 455 Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock;
451 456
452 Comprehension = '[' >> not_('[') >> space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']'; 457 list_value =
458 and_(
459 VariablePairDef |
460 NormalPairDef |
461 MetaVariablePairDef |
462 MetaNormalPairDef
463 ) >> table_key_pair_error |
464 SpreadListExp |
465 NormalDef;
466
467 list_value_list = +(space >> ',' >> space >> list_value);
468
469 list_lit_line = (
470 push_indent_match >> (space >> list_value >> -list_value_list >> pop_indent | pop_indent)
471 ) | (
472 space
473 );
474
475 list_lit_lines = space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ',');
476
477 Comprehension = '[' >> not_('[') >>
478 Seperator >> space >> (
479 disable_for_rule(list_value) >> space >> (
480 CompInner >> space >> ']' |
481 (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> ']'
482 ) |
483 list_lit_lines >> white >> ']' |
484 white >> ']' >> not_(space >> '=')
485 );
486
487 (space >> disable_for_rule(Exp) >> space >> CompInner >> space >> ']');
453 CompValue = ',' >> space >> Exp; 488 CompValue = ',' >> space >> Exp;
454 TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); 489 TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error);
455 490
@@ -479,12 +514,11 @@ YueParser::YueParser() {
479 expo_value = exponential_operator >> *space_break >> space >> Value; 514 expo_value = exponential_operator >> *space_break >> space >> Value;
480 expo_exp = Value >> *(space >> expo_value); 515 expo_exp = Value >> *(space >> expo_value);
481 516
482 InRangeOpen = true_();
483 InRangeClose = true_();
484 NotIn = true_(); 517 NotIn = true_();
485 InRange = ('(' >> InRangeOpen | '[' >> InRangeClose) >> space >> Exp >> space >> ',' >> space >> Exp >> space >> (')' >> InRangeOpen | ']' >> InRangeClose); 518 InDiscrete =
486 InDiscrete = '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) >> space >> '}'; 519 '[' >> Seperator >> space >> exp_not_tab >> (+(space >> ',' >> space >> exp_not_tab) | space >> ',') >> space >> ']' |
487 In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InRange | InDiscrete | and_(key("not")) >> confusing_unary_not_error | Exp); 520 '{' >> Seperator >> space >> exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) >> space >> '}';
521 In = -(key("not") >> NotIn >> space) >> key("in") >> space >> (InDiscrete | and_(key("not")) >> confusing_unary_not_error | Exp);
488 522
489 UnaryOperator = 523 UnaryOperator =
490 '-' >> not_(set(">=") | space_one) | 524 '-' >> not_(set(">=") | space_one) |
@@ -635,7 +669,7 @@ YueParser::YueParser() {
635 space >> ',' >> 669 space >> ',' >>
636 space >> (Exp | DefaultValue) >> 670 space >> (Exp | DefaultValue) >>
637 space >> (',' >> space >> Exp | DefaultValue) >> 671 space >> (',' >> space >> Exp | DefaultValue) >>
638 space >> ']'; 672 space >> (']' | slice_expression_error);
639 673
640 Invoke = Seperator >> ( 674 Invoke = Seperator >> (
641 fn_args | 675 fn_args |
@@ -646,6 +680,7 @@ YueParser::YueParser() {
646 ); 680 );
647 681
648 SpreadExp = "..." >> space >> Exp; 682 SpreadExp = "..." >> space >> Exp;
683 SpreadListExp = "..." >> space >> Exp;
649 684
650 table_value = 685 table_value =
651 VariablePairDef | 686 VariablePairDef |
@@ -667,8 +702,7 @@ YueParser::YueParser() {
667 702
668 TableLit = 703 TableLit =
669 space >> '{' >> Seperator >> 704 space >> '{' >> Seperator >>
670 -(space >> table_value_list) >> 705 -(space >> table_value_list >> -(space >> ',')) >>
671 -(space >> ',') >>
672 -table_lit_lines >> 706 -table_lit_lines >>
673 white >> '}'; 707 white >> '}';
674 708
@@ -834,7 +868,7 @@ YueParser::YueParser() {
834 }); 868 });
835 869
836 InvokeArgs = 870 InvokeArgs =
837 not_(set("-~")) >> space >> Seperator >> ( 871 not_(set("-~") | "[]") >> space >> Seperator >> (
838 Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | 872 Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) |
839 arg_table_block | 873 arg_table_block |
840 leading_spaces_error 874 leading_spaces_error
@@ -852,6 +886,11 @@ YueParser::YueParser() {
852 return false; 886 return false;
853 }); 887 });
854 888
889 slice_expression_error = pl::user(true_(), [](const item_t& item) {
890 throw ParserError("syntax error in slice expression"sv, item.begin);
891 return false;
892 });
893
855 SimpleValue = 894 SimpleValue =
856 TableLit | ConstValue | If | Switch | Try | With | 895 TableLit | ConstValue | If | Switch | Try | With |
857 ClassDecl | ForEach | For | While | Do | 896 ClassDecl | ForEach | For | While | Do |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h
index 7864300..8156ae2 100644
--- a/src/yuescript/yue_parser.h
+++ b/src/yuescript/yue_parser.h
@@ -136,9 +136,11 @@ private:
136 NONE_AST_RULE(indentation_error); 136 NONE_AST_RULE(indentation_error);
137 NONE_AST_RULE(braces_expression_error); 137 NONE_AST_RULE(braces_expression_error);
138 NONE_AST_RULE(brackets_expression_error); 138 NONE_AST_RULE(brackets_expression_error);
139 NONE_AST_RULE(slice_expression_error);
139 NONE_AST_RULE(export_expression_error); 140 NONE_AST_RULE(export_expression_error);
140 NONE_AST_RULE(invalid_interpolation_error); 141 NONE_AST_RULE(invalid_interpolation_error);
141 NONE_AST_RULE(confusing_unary_not_error); 142 NONE_AST_RULE(confusing_unary_not_error);
143 NONE_AST_RULE(table_key_pair_error);
142 144
143 NONE_AST_RULE(inc_exp_level); 145 NONE_AST_RULE(inc_exp_level);
144 NONE_AST_RULE(dec_exp_level); 146 NONE_AST_RULE(dec_exp_level);
@@ -202,6 +204,10 @@ private:
202 NONE_AST_RULE(for_key); 204 NONE_AST_RULE(for_key);
203 NONE_AST_RULE(for_args); 205 NONE_AST_RULE(for_args);
204 NONE_AST_RULE(for_in); 206 NONE_AST_RULE(for_in);
207 NONE_AST_RULE(list_value);
208 NONE_AST_RULE(list_value_list);
209 NONE_AST_RULE(list_lit_line);
210 NONE_AST_RULE(list_lit_lines);
205 NONE_AST_RULE(comp_clause); 211 NONE_AST_RULE(comp_clause);
206 NONE_AST_RULE(chain); 212 NONE_AST_RULE(chain);
207 NONE_AST_RULE(chain_list); 213 NONE_AST_RULE(chain_list);
@@ -352,6 +358,7 @@ private:
352 AST_RULE(ExistentialOp); 358 AST_RULE(ExistentialOp);
353 AST_RULE(TableAppendingOp); 359 AST_RULE(TableAppendingOp);
354 AST_RULE(SpreadExp); 360 AST_RULE(SpreadExp);
361 AST_RULE(SpreadListExp);
355 AST_RULE(TableLit); 362 AST_RULE(TableLit);
356 AST_RULE(TableBlock); 363 AST_RULE(TableBlock);
357 AST_RULE(TableBlockIndent); 364 AST_RULE(TableBlockIndent);
@@ -388,10 +395,7 @@ private:
388 AST_RULE(ConstValue); 395 AST_RULE(ConstValue);
389 AST_RULE(UnaryValue); 396 AST_RULE(UnaryValue);
390 AST_RULE(UnaryExp); 397 AST_RULE(UnaryExp);
391 AST_RULE(InRangeOpen);
392 AST_RULE(InRangeClose);
393 AST_RULE(NotIn); 398 AST_RULE(NotIn);
394 AST_RULE(InRange);
395 AST_RULE(InDiscrete); 399 AST_RULE(InDiscrete);
396 AST_RULE(In); 400 AST_RULE(In);
397 AST_RULE(ExpListAssign); 401 AST_RULE(ExpListAssign);