diff options
-rwxr-xr-x | doc/docs/doc/README.md | 180 | ||||
-rwxr-xr-x | doc/docs/zh/doc/README.md | 182 | ||||
-rw-r--r-- | spec/inputs/cond.yue | 11 | ||||
-rw-r--r-- | spec/inputs/in_expression.yue | 25 | ||||
-rw-r--r-- | spec/inputs/lists.yue | 24 | ||||
-rw-r--r-- | spec/inputs/tables.yue | 20 | ||||
-rw-r--r-- | spec/inputs/unicode/cond.yue | 11 | ||||
-rw-r--r-- | spec/inputs/unicode/in_expression.yue | 21 | ||||
-rw-r--r-- | spec/outputs/cond.lua | 17 | ||||
-rw-r--r-- | spec/outputs/in_expression.lua | 31 | ||||
-rw-r--r-- | spec/outputs/lists.lua | 65 | ||||
-rw-r--r-- | spec/outputs/tables.lua | 83 | ||||
-rw-r--r-- | spec/outputs/unicode/cond.lua | 17 | ||||
-rw-r--r-- | spec/outputs/unicode/in_expression.lua | 31 | ||||
-rw-r--r-- | src/yuescript/yue_ast.cpp | 27 | ||||
-rw-r--r-- | src/yuescript/yue_ast.h | 34 | ||||
-rw-r--r-- | src/yuescript/yue_compiler.cpp | 497 | ||||
-rw-r--r-- | src/yuescript/yue_parser.cpp | 61 | ||||
-rw-r--r-- | src/yuescript/yue_parser.h | 10 |
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 | |||
394 | Comparisons can be arbitrarily chained: | ||
395 | |||
396 | ```moonscript | ||
397 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
398 | -- output: true | ||
399 | |||
400 | a = 5 | ||
401 | print 1 <= a <= 10 | ||
402 | -- output: true | ||
403 | ``` | ||
404 | <YueDisplay> | ||
405 | <pre> | ||
406 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
407 | -- output: true | ||
408 | |||
409 | a = 5 | ||
410 | print 1 <= a <= 10 | ||
411 | -- output: true | ||
412 | </pre> | ||
413 | </YueDisplay> | ||
414 | |||
415 | Note the evaluation behavior of chained comparisons: | ||
416 | |||
417 | ```moonscript | ||
418 | v = (x)-> | ||
419 | print x | ||
420 | x | ||
421 | |||
422 | print v(1) < v(2) <= v(3) | ||
423 | --[[ | ||
424 | output: | ||
425 | 2 | ||
426 | 1 | ||
427 | 3 | ||
428 | true | ||
429 | ]] | ||
430 | |||
431 | print v(1) > v(2) <= v(3) | ||
432 | --[[ | ||
433 | output: | ||
434 | 2 | ||
435 | 1 | ||
436 | false | ||
437 | ]] | ||
438 | ``` | ||
439 | <YueDisplay> | ||
440 | <pre> | ||
441 | v = (x)-> | ||
442 | print x | ||
443 | x | ||
444 | |||
445 | print v(1) < v(2) <= v(3) | ||
446 | --[[ | ||
447 | output: | ||
448 | 2 | ||
449 | 1 | ||
450 | 3 | ||
451 | true | ||
452 | ]] | ||
453 | |||
454 | print v(1) > v(2) <= v(3) | ||
455 | --[[ | ||
456 | output: | ||
457 | 2 | ||
458 | 1 | ||
459 | false | ||
460 | ]] | ||
461 | </pre> | ||
462 | </YueDisplay> | ||
463 | |||
464 | The 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 |
393 | The **[] =** operator is used to append values to tables. | 467 | The **[] =** 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 | |||
984 | This is best explained with examples. Here is how you would unpack the first two values from a table: | 1058 | This is best explained with examples. Here is how you would unpack the first two values from a table: |
985 | 1059 | ||
986 | ```moonscript | 1060 | ```moonscript |
987 | thing = {1, 2} | 1061 | thing = [1, 2] |
988 | 1062 | ||
989 | {a, b} = thing | 1063 | [a, b] = thing |
990 | print a, b | 1064 | print a, b |
991 | ``` | 1065 | ``` |
992 | <YueDisplay> | 1066 | <YueDisplay> |
993 | 1067 | ||
994 | <pre> | 1068 | <pre> |
995 | thing = {1, 2} | 1069 | thing = [1, 2] |
996 | 1070 | ||
997 | {a, b} = thing | 1071 | [a, b] = thing |
998 | print a, b | 1072 | print 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 | ||
1998 | Lua 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 | ||
2001 | some_values = [ 1, 2, 3, 4 ] | ||
2002 | list_with_one_element = [ 1, ] | ||
2003 | ``` | ||
2004 | <YueDisplay> | ||
2005 | <pre> | ||
2006 | some_values = [ 1, 2, 3, 4 ] | ||
2007 | list_with_one_element = [ 1, ] | ||
2008 | </pre> | ||
2009 | </YueDisplay> | ||
2010 | |||
1924 | ## Comprehensions | 2011 | ## Comprehensions |
1925 | 2012 | ||
1926 | Comprehensions 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. | 2013 | Comprehensions 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 | |||
1930 | The following creates a copy of the items table but with all the values doubled. | 2017 | The following creates a copy of the items table but with all the values doubled. |
1931 | 2018 | ||
1932 | ```moonscript | 2019 | ```moonscript |
1933 | items = { 1, 2, 3, 4 } | 2020 | items = [ 1, 2, 3, 4 ] |
1934 | doubled = [item * 2 for i, item in ipairs items] | 2021 | doubled = [item * 2 for i, item in ipairs items] |
1935 | ``` | 2022 | ``` |
1936 | <YueDisplay> | 2023 | <YueDisplay> |
1937 | <pre> | 2024 | <pre> |
1938 | items = { 1, 2, 3, 4 } | 2025 | items = [ 1, 2, 3, 4 ] |
1939 | doubled = [item * 2 for i, item in ipairs items] | 2026 | doubled = [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 | |||
1969 | Using multiple for clauses is the same as using nested loops: | 2056 | Using multiple for clauses is the same as using nested loops: |
1970 | 2057 | ||
1971 | ```moonscript | 2058 | ```moonscript |
1972 | x_coords = {4, 5, 6, 7} | 2059 | x_coords = [4, 5, 6, 7] |
1973 | y_coords = {9, 2, 3} | 2060 | y_coords = [9, 2, 3] |
1974 | 2061 | ||
1975 | points = [{x, y} for x in *x_coords \ | 2062 | points = [ [x, y] for x in *x_coords \ |
1976 | for y in *y_coords] | 2063 | for y in *y_coords] |
1977 | ``` | 2064 | ``` |
1978 | <YueDisplay> | 2065 | <YueDisplay> |
1979 | <pre> | 2066 | <pre> |
1980 | x_coords = {4, 5, 6, 7} | 2067 | x_coords = [4, 5, 6, 7] |
1981 | y_coords = {9, 2, 3} | 2068 | y_coords = [9, 2, 3] |
1982 | 2069 | ||
1983 | points = [{x, y} for x in *x_coords \ | 2070 | points = [ [x, y] for x in *x_coords \ |
1984 | for y in *y_coords] | 2071 | for 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"} | |||
2035 | The **\*** operator is also supported. Here we create a square root look up table for a few numbers. | 2122 | The **\*** operator is also supported. Here we create a square root look up table for a few numbers. |
2036 | 2123 | ||
2037 | ```moonscript | 2124 | ```moonscript |
2038 | numbers = {1, 2, 3, 4} | 2125 | numbers = [1, 2, 3, 4] |
2039 | sqrts = {i, math.sqrt i for i in *numbers} | 2126 | sqrts = {i, math.sqrt i for i in *numbers} |
2040 | ``` | 2127 | ``` |
2041 | <YueDisplay> | 2128 | <YueDisplay> |
2042 | <pre> | 2129 | <pre> |
2043 | numbers = {1, 2, 3, 4} | 2130 | numbers = [1, 2, 3, 4] |
2044 | sqrts = {i, math.sqrt i for i in *numbers} | 2131 | sqrts = {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 |
2406 | a = 5 | 2493 | a = 5 |
2407 | 2494 | ||
2408 | if a in [1, 10] | ||
2409 | print "a is in range from 1 to 10" | ||
2410 | |||
2411 | if a not in [1, 10] | ||
2412 | print "a is not in range from 1 to 10" | ||
2413 | |||
2414 | if a in (0, 11) | ||
2415 | print "a is between 0 and 11 with open intervals" | ||
2416 | |||
2417 | if a in {1, 3, 5, 7} | 2495 | if 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> |
2425 | a = 5 | 2503 | a = 5 |
2426 | 2504 | ||
2427 | if a in [1, 10] | ||
2428 | print "a is in range from 1 to 10" | ||
2429 | |||
2430 | if a not in [1, 10] | ||
2431 | print "a is not in range from 1 to 10" | ||
2432 | |||
2433 | if a in (0, 11) | ||
2434 | print "a is between 0 and 11 with open intervals" | ||
2435 | |||
2436 | if a in {1, 3, 5, 7} | 2505 | if 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 | |||
2654 | You can do range matching in a switch when clause using `In` expressions. | ||
2655 | |||
2656 | ```moonscript | ||
2657 | value = 5 | ||
2658 | |||
2659 | switch 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> | ||
2678 | value = 5 | ||
2679 | |||
2680 | switch 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 | ||
2701 | In 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. | 2723 | In 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 | ||
394 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
395 | -- 输出:true | ||
396 | |||
397 | a = 5 | ||
398 | print 1 <= a <= 10 | ||
399 | -- 输出:true | ||
400 | ``` | ||
401 | <YueDisplay> | ||
402 | <pre> | ||
403 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | ||
404 | -- 输出:true | ||
405 | |||
406 | a = 5 | ||
407 | print 1 <= a <= 10 | ||
408 | -- 输出:true | ||
409 | </pre> | ||
410 | </YueDisplay> | ||
411 | |||
412 | å¯ä»¥æ³¨æ„一下链å¼æ¯”较表达å¼çš„求值行为: | ||
413 | |||
414 | ```moonscript | ||
415 | v = (x)-> | ||
416 | print x | ||
417 | x | ||
418 | |||
419 | print v(1) < v(2) <= v(3) | ||
420 | --[[ | ||
421 | 输出: | ||
422 | 2 | ||
423 | 1 | ||
424 | 3 | ||
425 | true | ||
426 | ]] | ||
427 | |||
428 | print v(1) > v(2) <= v(3) | ||
429 | --[[ | ||
430 | 输出: | ||
431 | 2 | ||
432 | 1 | ||
433 | false | ||
434 | ]] | ||
435 | ``` | ||
436 | <YueDisplay> | ||
437 | <pre> | ||
438 | v = (x)-> | ||
439 | print x | ||
440 | x | ||
441 | |||
442 | print v(1) < v(2) <= v(3) | ||
443 | --[[ | ||
444 | 输出: | ||
445 | 2 | ||
446 | 1 | ||
447 | 3 | ||
448 | true | ||
449 | ]] | ||
450 | |||
451 | print 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 |
985 | thing = {1, 2} | 1059 | thing = [1, 2] |
986 | 1060 | ||
987 | {a, b} = thing | 1061 | [a, b] = thing |
988 | print a, b | 1062 | print a, b |
989 | ``` | 1063 | ``` |
990 | <YueDisplay> | 1064 | <YueDisplay> |
991 | 1065 | ||
992 | <pre> | 1066 | <pre> |
993 | thing = {1, 2} | 1067 | thing = [1, 2] |
994 | 1068 | ||
995 | {a, b} = thing | 1069 | [a, b] = thing |
996 | print a, b | 1070 | print 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 | ||
1958 | Lua的表åŒæ—¶å…·æœ‰æ•°ç»„éƒ¨åˆ†å’Œå“ˆå¸Œéƒ¨åˆ†ï¼Œä½†æœ‰æ—¶å€™ä½ ä¼šå¸Œæœ›åœ¨ä¹¦å†™Lua表时,对Lua表åšæ•°ç»„和哈希ä¸åŒç”¨æ³•çš„è¯ä¹‰åŒºåˆ†ã€‚然åŽä½ å¯ä»¥ç”¨ **[ ]** 而ä¸æ˜¯ **{ }** æ¥ç¼–写表示数组的 Lua 表,并且ä¸å…许在数组 Lua 表ä¸å†™å…¥ä»»ä½•é”®å€¼å¯¹ã€‚ | ||
1959 | |||
1960 | ```moonscript | ||
1961 | some_values = [ 1, 2, 3, 4 ] | ||
1962 | list_with_one_element = [ 1, ] | ||
1963 | ``` | ||
1964 | <YueDisplay> | ||
1965 | <pre> | ||
1966 | some_values = [ 1, 2, 3, 4 ] | ||
1967 | list_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 |
1893 | items = { 1, 2, 3, 4 } | 1980 | items = [ 1, 2, 3, 4 ] |
1894 | doubled = [item * 2 for i, item in ipairs items] | 1981 | doubled = [item * 2 for i, item in ipairs items] |
1895 | ``` | 1982 | ``` |
1896 | <YueDisplay> | 1983 | <YueDisplay> |
1897 | <pre> | 1984 | <pre> |
1898 | items = { 1, 2, 3, 4 } | 1985 | items = [ 1, 2, 3, 4 ] |
1899 | doubled = [item * 2 for i, item in ipairs items] | 1986 | doubled = [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 |
1932 | x_coords = {4, 5, 6, 7} | 2019 | x_coords = [4, 5, 6, 7] |
1933 | y_coords = {9, 2, 3} | 2020 | y_coords = [9, 2, 3] |
1934 | 2021 | ||
1935 | points = [{x, y} for x in *x_coords \ | 2022 | points = [ [x, y] for x in *x_coords \ |
1936 | for y in *y_coords] | 2023 | for y in *y_coords] |
1937 | ``` | 2024 | ``` |
1938 | <YueDisplay> | 2025 | <YueDisplay> |
1939 | <pre> | 2026 | <pre> |
1940 | x_coords = {4, 5, 6, 7} | 2027 | x_coords = [4, 5, 6, 7] |
1941 | y_coords = {9, 2, 3} | 2028 | y_coords = [9, 2, 3] |
1942 | 2029 | ||
1943 | points = [{x, y} for x in *x_coords \ | 2030 | points = [ [x, y] for x in *x_coords \ |
1944 | for y in *y_coords] | 2031 | for 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 |
1998 | numbers = {1, 2, 3, 4} | 2085 | numbers = [1, 2, 3, 4] |
1999 | sqrts = {i, math.sqrt i for i in *numbers} | 2086 | sqrts = {i, math.sqrt i for i in *numbers} |
2000 | ``` | 2087 | ``` |
2001 | <YueDisplay> | 2088 | <YueDisplay> |
2002 | <pre> | 2089 | <pre> |
2003 | numbers = {1, 2, 3, 4} | 2090 | numbers = [1, 2, 3, 4] |
2004 | sqrts = {i, math.sqrt i for i in *numbers} | 2091 | sqrts = {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 |
2367 | a = 5 | 2454 | a = 5 |
2368 | 2455 | ||
2369 | if a in [1, 10] | ||
2370 | print "a在1到10的范围内" | ||
2371 | |||
2372 | if a not in [1, 10] | ||
2373 | print "aä¸åœ¨1到10的范围内" | ||
2374 | |||
2375 | if a in (0, 11) | ||
2376 | print "a在0到11的开放区间内" | ||
2377 | |||
2378 | if a in {1, 3, 5, 7} | 2456 | if a in {1, 3, 5, 7} |
2379 | print "检查离散值的相ç‰æ€§" | 2457 | print "检查离散值的相ç‰æ€§" |
2380 | 2458 | ||
@@ -2385,15 +2463,6 @@ if a in list | |||
2385 | <pre> | 2463 | <pre> |
2386 | a = 5 | 2464 | a = 5 |
2387 | 2465 | ||
2388 | if a in [1, 10] | ||
2389 | print "a在1到10的范围内" | ||
2390 | |||
2391 | if a not in [1, 10] | ||
2392 | print "aä¸åœ¨1到10的范围内" | ||
2393 | |||
2394 | if a in (0, 11) | ||
2395 | print "a在0到11的开放区间内" | ||
2396 | |||
2397 | if a in {1, 3, 5, 7} | 2466 | if 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 | ||
2618 | value = 5 | ||
2619 | |||
2620 | switch 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> | ||
2639 | value = 5 | ||
2640 | |||
2641 | switch 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 | ||
229 | do | ||
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 | |||
229 | nil | 240 | nil |
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 | |
3 | a, b = x(...) not in [1, 3], 2 | ||
4 | |||
5 | d = (tb.x.y ...) not in [1, 3] | ||
6 | 3 | ||
7 | has = "foo" in { "bar", "foo" } | 4 | has = "foo" in { "bar", "foo" } |
8 | 5 | ||
9 | if a in {1} and b in {2, 3, 4} or c in [1, 10] | 6 | if a in {1} and b in {2, 3, 4} |
10 | print a, b, c | 7 | print a, b, c |
11 | 8 | ||
12 | switch val | 9 | if 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 | |||
25 | do return y not in (a, b) | ||
26 | 11 | ||
27 | do | 12 | do |
28 | exist = item in list | 13 | exist = item in list |
@@ -36,9 +21,11 @@ do | |||
36 | do | 21 | do |
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 | ||
44 | do | 31 | do |
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) -> | |||
67 | test = x 1,2,3,4,5 | 67 | test = x 1,2,3,4,5 |
68 | print thing for thing in *test | 68 | print thing for thing in *test |
69 | 69 | ||
70 | -> a = b for row in *rows | 70 | _ = -> a = b for row in *rows |
71 | 71 | ||
72 | 72 | with 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 | |||
86 | do | ||
87 | [a, b] = hello | ||
88 | [name = "nameless", job = "jobless"] = person | ||
89 | |||
90 | nil | ||
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 } | |||
40 | x = { 1,2, | 40 | x = { 1,2, |
41 | 4343, 343 ,343 } | 41 | 4343, 343 ,343 } |
42 | 42 | ||
43 | x = [ 1,2, | ||
44 | 4343, 343 ,343 ] | ||
43 | 45 | ||
44 | g, p = { | 46 | g, 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 | ||
57 | annother = [ | ||
58 | 1,2,3 | ||
59 | 3,4,5 | ||
60 | 6,7,8 | ||
61 | ] | ||
62 | |||
55 | yeah = { | 63 | yeah = { |
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 | ||
266 | tbMixA = [ | ||
267 | ...[i for i = 1, 10] | ||
268 | 11 | ||
269 | ] | ||
270 | |||
258 | tbMixB = { | 271 | tbMixB = { |
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 | ||
278 | tbMixB = [ | ||
279 | ... ... -- only the first item in vararg been accessed here | ||
280 | ... {...} | ||
281 | ... {......} | ||
282 | 1, 2, 3 | ||
283 | ] | ||
284 | |||
265 | const template = { | 285 | const 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 | ||
229 | do | ||
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 | |||
229 | nil | 240 | nil |
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 | ||
9 | if å˜é‡a in {1} and å˜é‡b in {2, 3, 4} or å˜é‡c in [1, 10] | 5 | if å˜é‡a in {1} and å˜é‡b in {2, 3, 4} |
10 | æ‰“å° å˜é‡a, å˜é‡b, å˜é‡c | 6 | æ‰“å° å˜é‡a, å˜é‡b, å˜é‡c |
11 | 7 | ||
12 | switch 值 | ||
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 | |||
25 | do return å˜é‡y not in (开始, 结æŸ) | ||
26 | |||
27 | do | 8 | do |
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 |
347 | end | 347 | end |
348 | do | ||
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 | ||
364 | end | ||
348 | return nil | 365 | return 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 |
4 | end)()) | 4 | end)()) |
5 | local a, b = (function(...) | ||
6 | local _val_0 = x(...) | ||
7 | return not (1 <= _val_0 and _val_0 <= 3) | ||
8 | end)(...), 2 | ||
9 | local d | ||
10 | do | ||
11 | local _val_0 = (tb.x.y(...)) | ||
12 | d = not (1 <= _val_0 and _val_0 <= 3) | ||
13 | end | ||
14 | local has | 5 | local has |
15 | do | 6 | do |
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 |
18 | end | 9 | end |
19 | if (1 == a) and (2 == b or 3 == b or 4 == b) or (function() | 10 | if (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 |
22 | end)() then | 13 | end)() then |
23 | print(a, b, c) | 14 | print(a, b, c) |
24 | end | 15 | end |
25 | do | 16 | do |
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 | ||
36 | end | ||
37 | do | ||
38 | local _val_0 = y | ||
39 | return not (a < _val_0 and _val_0 < b) | ||
40 | end | ||
41 | do | ||
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) |
275 | end | 275 | end |
276 | return 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 |
282 | end | 282 | end |
283 | do | ||
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 | ||
330 | end | ||
331 | do | ||
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 | ||
344 | end | ||
345 | return 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 | } |
55 | x = { | ||
56 | 1, | ||
57 | 2, | ||
58 | 4343, | ||
59 | 343, | ||
60 | 343 | ||
61 | } | ||
55 | local g, p = { | 62 | local 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 | } |
82 | annother = { | ||
83 | 1, | ||
84 | 2, | ||
85 | 3, | ||
86 | 3, | ||
87 | 4, | ||
88 | 5, | ||
89 | 6, | ||
90 | 7, | ||
91 | 8 | ||
92 | } | ||
75 | local yeah = { | 93 | local 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 |
437 | end | 455 | end |
456 | do | ||
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 | ||
476 | end | ||
438 | local tbMixB | 477 | local tbMixB |
439 | do | 478 | do |
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 |
491 | end | 530 | end |
531 | do | ||
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 | ||
574 | end | ||
492 | local template <const> = { | 575 | local 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 |
353 | end | 353 | end |
354 | do | ||
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 | ||
370 | end | ||
354 | return nil | 371 | return 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 |
4 | end)()) | 4 | end)()) |
5 | local _u53d8_u91cfa, _u53d8_u91cfb = (function(...) | ||
6 | local _val_0 = _u51fd_u6570x(...) | ||
7 | return not (1 <= _val_0 and _val_0 <= 3) | ||
8 | end)(...), 2 | ||
9 | local _u53d8_u91cfd | ||
10 | do | ||
11 | local _val_0 = (_u5bf9_u8c61["å—段x"]["å—段y"](...)) | ||
12 | _u53d8_u91cfd = not (1 <= _val_0 and _val_0 <= 3) | ||
13 | end | ||
14 | local _u5728_u7684 | 5 | local _u5728_u7684 |
15 | do | 6 | do |
16 | local _val_0 = "东" | 7 | local _val_0 = "东" |
17 | _u5728_u7684 = "东" == _val_0 or "西" == _val_0 | 8 | _u5728_u7684 = "东" == _val_0 or "西" == _val_0 |
18 | end | 9 | end |
19 | if (1 == _u53d8_u91cfa) and (2 == _u53d8_u91cfb or 3 == _u53d8_u91cfb or 4 == _u53d8_u91cfb) or (function() | 10 | if (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 |
22 | end)() then | 13 | end)() then |
23 | _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) | 14 | _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) |
24 | end | 15 | end |
25 | do | 16 | do |
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 | ||
36 | end | ||
37 | do | ||
38 | local _val_0 = _u53d8_u91cfy | ||
39 | return not (_u5f00_u59cb < _val_0 and _val_0 < _u7ed3_u675f) | ||
40 | end | ||
41 | do | ||
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 | } |
185 | std::string InRangeOpen_t::to_string(void*) const { | ||
186 | return {}; | ||
187 | } | ||
188 | std::string InRangeClose_t::to_string(void*) const { | ||
189 | return {}; | ||
190 | } | ||
191 | std::string NotIn_t::to_string(void*) const { | 185 | std::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 | } |
571 | std::string Comprehension_t::to_string(void* ud) const { | 565 | std::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 | } |
575 | std::string CompValue_t::to_string(void* ud) const { | 579 | std::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 { | |||
830 | std::string SpreadExp_t::to_string(void* ud) const { | 834 | std::string SpreadExp_t::to_string(void* ud) const { |
831 | return "..."s + exp->to_string(ud); | 835 | return "..."s + exp->to_string(ud); |
832 | } | 836 | } |
837 | std::string SpreadListExp_t::to_string(void* ud) const { | ||
838 | return "..."s + exp->to_string(ud); | ||
839 | } | ||
833 | std::string TableLit_t::to_string(void* ud) const { | 840 | std::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 | } |
1171 | std::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 | } | ||
1175 | std::string InDiscrete_t::to_string(void* ud) const { | 1178 | std::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; | |||
78 | class TableBlockIndent_t; | 78 | class TableBlockIndent_t; |
79 | class Macro_t; | 79 | class Macro_t; |
80 | class In_t; | 80 | class In_t; |
81 | class NormalDef_t; | ||
82 | class SpreadListExp_t; | ||
81 | } // namespace yue | 83 | } // namespace yue |
82 | 84 | ||
83 | AST_LEAF(Num) | 85 | AST_LEAF(Num) |
@@ -286,7 +288,7 @@ AST_NODE(SwitchList) | |||
286 | AST_END(SwitchList, "switch_list"sv) | 288 | AST_END(SwitchList, "switch_list"sv) |
287 | 289 | ||
288 | AST_NODE(SwitchCase) | 290 | AST_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) |
292 | AST_END(SwitchCase, "switch_case"sv) | 294 | AST_END(SwitchCase, "switch_case"sv) |
@@ -374,9 +376,10 @@ AST_NODE(Try) | |||
374 | AST_END(Try, "try"sv) | 376 | AST_END(Try, "try"sv) |
375 | 377 | ||
376 | AST_NODE(Comprehension) | 378 | AST_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) | ||
380 | AST_END(Comprehension, "comp"sv) | 383 | AST_END(Comprehension, "comp"sv) |
381 | 384 | ||
382 | AST_NODE(CompValue) | 385 | AST_NODE(CompValue) |
@@ -437,23 +440,9 @@ AST_END(BinaryOperator, "binary_op"sv) | |||
437 | AST_LEAF(UnaryOperator) | 440 | AST_LEAF(UnaryOperator) |
438 | AST_END(UnaryOperator, "unary_op"sv) | 441 | AST_END(UnaryOperator, "unary_op"sv) |
439 | 442 | ||
440 | AST_LEAF(InRangeOpen) | ||
441 | AST_END(InRangeOpen, "in_range_open"sv) | ||
442 | |||
443 | AST_LEAF(InRangeClose) | ||
444 | AST_END(InRangeClose, "in_range_close"sv) | ||
445 | |||
446 | AST_LEAF(NotIn) | 443 | AST_LEAF(NotIn) |
447 | AST_END(NotIn, "not_in"sv) | 444 | AST_END(NotIn, "not_in"sv) |
448 | 445 | ||
449 | AST_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) | ||
455 | AST_END(InRange, "in_range"sv) | ||
456 | |||
457 | AST_NODE(InDiscrete) | 446 | AST_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 | ||
463 | AST_NODE(In) | 452 | AST_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, ¬_, &item) | 455 | AST_MEMBER(In, ¬_, &item) |
467 | AST_END(In, "in"sv) | 456 | AST_END(In, "in"sv) |
468 | 457 | ||
@@ -666,6 +655,11 @@ AST_NODE(SpreadExp) | |||
666 | AST_MEMBER(SpreadExp, &exp) | 655 | AST_MEMBER(SpreadExp, &exp) |
667 | AST_END(SpreadExp, "spread_exp"sv) | 656 | AST_END(SpreadExp, "spread_exp"sv) |
668 | 657 | ||
658 | AST_NODE(SpreadListExp) | ||
659 | ast_ptr<true, Exp_t> exp; | ||
660 | AST_MEMBER(SpreadListExp, &exp) | ||
661 | AST_END(SpreadListExp, "spread_list_exp"sv) | ||
662 | |||
669 | AST_NODE(TableLit) | 663 | AST_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) |
678 | AST_END(TableLit, "table_lit"sv) | 672 | AST_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 | ||
77 | const std::string_view version = "0.19.6"sv; | 78 | const std::string_view version = "0.20.0"sv; |
78 | const std::string_view extension = "yue"sv; | 79 | const std::string_view extension = "yue"sv; |
79 | 80 | ||
80 | class CompileError : public std::logic_error { | 81 | class 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); |